diff --git a/debug/tags.html b/debug/tags.html index 3fe0db70..70291a2e 100644 --- a/debug/tags.html +++ b/debug/tags.html @@ -14,6 +14,7 @@
+ @@ -79,14 +80,14 @@ var createdIndex = 0; - function createOutlineTag(geometry) { + function createOutlineTag(geometry, text) { createdIndex += 1; var id = "created" + createdIndex; var options = { editable: true, lineColor: 0x00FFFF, lineWidth: 1, - text: "Rectangle", + text: text, textColor: 0x00FFFF, }; @@ -114,7 +115,9 @@ tagComponent.on(Mapillary.TagComponent.TagComponent.geometrycreated, function(geometry) { if (geometry instanceof Mapillary.TagComponent.RectGeometry) { - createOutlineTag(geometry); + createOutlineTag(geometry, "Rectangle"); + } else if (geometry instanceof Mapillary.TagComponent.PolygonGeometry) { + createOutlineTag(geometry, "Polygon"); } else if (geometry instanceof Mapillary.TagComponent.PointGeometry) { createSpotTag(geometry); } diff --git a/src/component/tag/TagComponent.ts b/src/component/tag/TagComponent.ts index 62545a14..eca36484 100644 --- a/src/component/tag/TagComponent.ts +++ b/src/component/tag/TagComponent.ts @@ -12,6 +12,8 @@ import { ITagConfiguration, PointGeometry, OutlineCreateTag, + PolygonGeometry, + RectGeometry, Tag, TagCreator, TagDOMRenderer, @@ -413,7 +415,8 @@ export class TagComponent extends Component { .flatMapLatest( (configuration: ITagConfiguration): rx.Observable => { return configuration.creating && - configuration.createType === "rect" ? + configuration.createType === "rect" || + configuration.createType === "polygon" ? this._validBasicClick$.take(1) : rx.Observable.empty(); }) @@ -468,7 +471,11 @@ export class TagComponent extends Component { camera, transform); - tag.geometry.setVertex2d(3, basic, transform); + if (tag.geometry instanceof RectGeometry) { + tag.geometry.setVertex2d(3, basic, transform); + } else if (tag.geometry instanceof PolygonGeometry) { + tag.geometry.setVertex2d((tag.geometry).polygon.length - 2, basic, transform); + } }); this._addPointSubscription = this._creating$ @@ -621,7 +628,7 @@ export class TagComponent extends Component { this._container.spriteService.spriteAtlas$, this._tags$.startWith([]), this._tagChanged$.startWith(null), - this._tagCreator.tag$.startWith(null), + this._tagCreator.tag$.merge(this._createGeometryChanged$).startWith(null), (rc: RenderCamera, atlas: ISpriteAtlas, tags: Tag[], tag: Tag, createTag: OutlineCreateTag): [RenderCamera, ISpriteAtlas, Tag[], Tag, OutlineCreateTag] => { return [rc, atlas, tags, tag, createTag]; diff --git a/src/component/tag/TagCreator.ts b/src/component/tag/TagCreator.ts index 7e60c5f7..e33f7c07 100644 --- a/src/component/tag/TagCreator.ts +++ b/src/component/tag/TagCreator.ts @@ -5,6 +5,7 @@ import * as rx from "rx"; import { GeometryType, OutlineCreateTag, + PolygonGeometry, RectGeometry, } from "../../Component"; @@ -56,6 +57,14 @@ export class TagCreator { coordinate[1], ]); + return new OutlineCreateTag(geometry); + } else if (type === "polygon") { + let geometry: PolygonGeometry = new PolygonGeometry([ + [coordinate[0], coordinate[1]], + [coordinate[0], coordinate[1]], + [coordinate[0], coordinate[1]], + ]); + return new OutlineCreateTag(geometry); } diff --git a/src/component/tag/tag/OutlineCreateTag.ts b/src/component/tag/tag/OutlineCreateTag.ts index 8f8fd284..6d7cd434 100644 --- a/src/component/tag/tag/OutlineCreateTag.ts +++ b/src/component/tag/tag/OutlineCreateTag.ts @@ -4,7 +4,11 @@ import * as rx from "rx"; import * as THREE from "three"; import * as vd from "virtual-dom"; -import {VertexGeometry, RectGeometry} from "../../../Component"; +import { + PolygonGeometry, + RectGeometry, + VertexGeometry, +} from "../../../Component"; import {Transform} from "../../../Geo"; export class OutlineCreateTag { @@ -64,41 +68,117 @@ export class OutlineCreateTag { vd.VNode[] { let vNodes: vd.VNode[] = []; - let polygonPoints3d: number[][] = this._geometry.getVertices3d(transform); - let abort: (e: MouseEvent) => void = (e: MouseEvent): void => { + e.stopPropagation(); this._aborted$.onNext(this); }; - let topLeftCameraSpace: THREE.Vector3 = this._convertToCameraSpace(polygonPoints3d[1], matrixWorldInverse); - if (topLeftCameraSpace.z < 0) { - let centerCanvas: number[] = this._projectToCanvas(topLeftCameraSpace, projectionMatrix); - let centerCss: string[] = centerCanvas.map((coord: number): string => { return (100 * coord) + "%"; }); + if (this._geometry instanceof RectGeometry) { + let topLeftPoint3d: number[] = this._geometry.getVertex3d(1, transform); - let pointProperties: vd.createProperties = { - style: { background: "#FFFFFF", left: centerCss[0], position: "absolute", top: centerCss[1] }, - }; + let topLeftCameraSpace: THREE.Vector3 = this._convertToCameraSpace(topLeftPoint3d, matrixWorldInverse); + if (topLeftCameraSpace.z < 0) { + let centerCanvas: number[] = this._projectToCanvas(topLeftCameraSpace, projectionMatrix); + let centerCss: string[] = centerCanvas.map((coord: number): string => { return (100 * coord) + "%"; }); - let completerProperties: vd.createProperties = { - onclick: abort, - style: { left: centerCss[0], position: "absolute", top: centerCss[1] }, - }; + let pointProperties: vd.createProperties = { + style: { background: "#FFFFFF", left: centerCss[0], position: "absolute", top: centerCss[1] }, + }; - vNodes.push(vd.h("div.TagInteractor", completerProperties, [])); - vNodes.push(vd.h("div.TagVertex", pointProperties, [])); + let completerProperties: vd.createProperties = { + onclick: abort, + style: { left: centerCss[0], position: "absolute", top: centerCss[1] }, + }; + + vNodes.push(vd.h("div.TagInteractor", completerProperties, [])); + vNodes.push(vd.h("div.TagVertex", pointProperties, [])); + } + } else if (this._geometry instanceof PolygonGeometry) { + let polygonGeometry: PolygonGeometry = this._geometry; + + if (polygonGeometry.polygon.length > 3) { + let lastVertex3d: number[] = this._geometry.getVertex3d(polygonGeometry.polygon.length - 3, transform); + + let lastCameraSpace: THREE.Vector3 = this._convertToCameraSpace(lastVertex3d, matrixWorldInverse); + if (lastCameraSpace.z < 0) { + let centerCanvas: number[] = this._projectToCanvas(lastCameraSpace, projectionMatrix); + let centerCss: string[] = centerCanvas.map((coord: number): string => { return (100 * coord) + "%"; }); + + let remove: (e: MouseEvent) => void = (e: MouseEvent): void => { + e.stopPropagation(); + polygonGeometry.removeVertex2d(polygonGeometry.polygon.length - 3); + }; + + let completerProperties: vd.createProperties = { + onclick: remove, + style: { left: centerCss[0], position: "absolute", top: centerCss[1] }, + }; + + vNodes.push(vd.h("div.TagInteractor", completerProperties, [])); + } + } + + let firstVertex3d: number[] = this._geometry.getVertex3d(0, transform); + let firstCameraSpace: THREE.Vector3 = this._convertToCameraSpace(firstVertex3d, matrixWorldInverse); + if (firstCameraSpace.z < 0) { + let centerCanvas: number[] = this._projectToCanvas(firstCameraSpace, projectionMatrix); + let centerCss: string[] = centerCanvas.map((coord: number): string => { return (100 * coord) + "%"; }); + + let firstOnclick: (e: MouseEvent) => void = polygonGeometry.polygon.length > 4 ? + (e: MouseEvent): void => { + e.stopPropagation(); + polygonGeometry.removeVertex2d(polygonGeometry.polygon.length - 2); + this._created$.onNext(this); + } : + abort; + + let completerProperties: vd.createProperties = { + onclick: firstOnclick, + style: { left: centerCss[0], position: "absolute", top: centerCss[1] }, + }; + + let firstClass: string = polygonGeometry.polygon.length > 4 ? + "TagCompleter" : + "TagInteractor"; + + vNodes.push(vd.h("div." + firstClass, completerProperties, [])); + } + + let vertices3d: number[][] = this._geometry.getVertices3d(transform); + vertices3d.splice(-2, 2); + + for (let vertex of vertices3d) { + let vertexCameraSpace: THREE.Vector3 = this._convertToCameraSpace(vertex, matrixWorldInverse); + if (vertexCameraSpace.z < 0) { + let centerCanvas: number[] = this._projectToCanvas(vertexCameraSpace, projectionMatrix); + let centerCss: string[] = centerCanvas.map((coord: number): string => { return (100 * coord) + "%"; }); + + let pointProperties: vd.createProperties = { + style: { background: "#FFFFFF", left: centerCss[0], position: "absolute", top: centerCss[1] }, + }; + + vNodes.push(vd.h("div.TagVertex", pointProperties, [])); + } + } } return vNodes; } public addPoint(point: number[]): void { - let rectGeometry: RectGeometry = this._geometry; + if (this._geometry instanceof RectGeometry) { + let rectGeometry: RectGeometry = this._geometry; - if (!rectGeometry.validate(point)) { - return; + if (!rectGeometry.validate(point)) { + return; + } + + this._created$.onNext(this); + } else if (this._geometry instanceof PolygonGeometry) { + let polygonGeometry: PolygonGeometry = this._geometry; + + polygonGeometry.addVertex2d(point); } - - this._created$.onNext(this); } private _getPositions(polygon3d: number[][]): Float32Array { diff --git a/styles/TagComponent.css b/styles/TagComponent.css index d5c0e182..15ccae18 100644 --- a/styles/TagComponent.css +++ b/styles/TagComponent.css @@ -49,6 +49,7 @@ } .TagInteractor, +.TagCompleter, .TagSpotInteractor { transform: translate(-50%, -50%); pointer-events: all; @@ -58,10 +59,15 @@ opacity: 0; } +.TagCompleter { + background: limegreen; +} + .TagInteractor { background: orangered; } +.TagCompleter:hover, .TagInteractor:hover { opacity: 0.6; }