diff --git a/src/arrow/attack-arrow.ts b/src/arrow/attack-arrow.ts index 0126e94..711256e 100644 --- a/src/arrow/attack-arrow.ts +++ b/src/arrow/attack-arrow.ts @@ -2,7 +2,7 @@ import Base from '../base'; import * as Utils from '../utils'; // @ts-ignore import { Cartesian3 } from 'cesium'; -import { PolygonStyle } from '../interface'; +import { PolygonStyle, Shape } from '../interface'; export default class AttackArrow extends Base { points: Cartesian3[] = []; @@ -26,7 +26,7 @@ export default class AttackArrow extends Base { this.onDoubleClick(); } - getType(): 'polygon' | 'line' { + getType(): Shape { return 'polygon'; } diff --git a/src/arrow/curved-arrow.ts b/src/arrow/curved-arrow.ts index 8c1b936..377d9b1 100644 --- a/src/arrow/curved-arrow.ts +++ b/src/arrow/curved-arrow.ts @@ -2,7 +2,7 @@ import * as Utils from '../utils'; import Base from '../base'; // @ts-ignore import { Cartesian3 } from 'cesium'; -import { LineStyle } from '../interface'; +import { LineStyle, Shape } from '../interface'; export default class CurvedArrow extends Base { points: Cartesian3[] = []; @@ -20,7 +20,7 @@ export default class CurvedArrow extends Base { this.onDoubleClick(); } - getType(): 'polygon' | 'line' { + getType(): Shape { return 'line'; } diff --git a/src/arrow/double-arrow.ts b/src/arrow/double-arrow.ts index 38ed574..97688e3 100644 --- a/src/arrow/double-arrow.ts +++ b/src/arrow/double-arrow.ts @@ -2,7 +2,7 @@ import Base from '../base'; import * as Utils from '../utils'; // @ts-ignore import { Cartesian3 } from 'cesium'; -import { PolygonStyle } from '../interface'; +import { PolygonStyle, Shape } from '../interface'; type Position = [number, number]; export default class DoubleArrow extends Base { @@ -35,7 +35,7 @@ export default class DoubleArrow extends Base { this.setState('drawing'); } - getType(): 'polygon' | 'line' { + getType(): Shape { return 'polygon'; } diff --git a/src/arrow/fine-arrow.ts b/src/arrow/fine-arrow.ts index 67540e1..96fa00e 100644 --- a/src/arrow/fine-arrow.ts +++ b/src/arrow/fine-arrow.ts @@ -2,7 +2,7 @@ import Base from '../base'; import * as Utils from '../utils'; // @ts-ignore import { Cartesian3 } from 'cesium'; -import { PolygonStyle } from '../interface'; +import { PolygonStyle, Shape } from '../interface'; export default class FineArrow extends Base { points: Cartesian3[] = []; @@ -27,7 +27,7 @@ export default class FineArrow extends Base { this.setState('drawing'); } - getType(): 'polygon' | 'line' { + getType(): Shape { return 'polygon'; } diff --git a/src/arrow/straight-arrow.ts b/src/arrow/straight-arrow.ts index 3c3bce4..5f94476 100644 --- a/src/arrow/straight-arrow.ts +++ b/src/arrow/straight-arrow.ts @@ -2,7 +2,7 @@ import * as Utils from '../utils'; import Base from '../base'; // @ts-ignore import { Cartesian3 } from 'cesium'; -import { LineStyle } from '../interface'; +import { LineStyle, Shape } from '../interface'; export default class StraightArrow extends Base { points: Cartesian3[] = []; @@ -17,7 +17,7 @@ export default class StraightArrow extends Base { this.setState('drawing'); } - getType(): 'polygon' | 'line' { + getType(): Shape { return 'line'; } diff --git a/src/assets/tag_active.png b/src/assets/tag_active.png new file mode 100644 index 0000000..9eeb1fa Binary files /dev/null and b/src/assets/tag_active.png differ diff --git a/src/assets/tag_default.png b/src/assets/tag_default.png new file mode 100644 index 0000000..e1ffa0b Binary files /dev/null and b/src/assets/tag_default.png differ diff --git a/src/base.ts b/src/base.ts index 1e3444c..f601b30 100644 --- a/src/base.ts +++ b/src/base.ts @@ -5,27 +5,32 @@ import { GeometryStyle, PolygonStyle, LineStyle, + TagStyle, EventType, EventListener, VisibleAnimationOpts, GrowthAnimationOpts, + Shape } from './interface'; import EventDispatcher from './events'; import cloneDeep from 'lodash.clonedeep'; // import merge from 'lodash.merge'; import * as Utils from './utils'; +import TagDefault from './assets/tag_default.png'; +import TagActive from './assets/tag_active.png'; export default class Base { cesium: typeof CesiumTypeOnly; viewer: CesiumTypeOnly.Viewer; eventHandler: CesiumTypeOnly.ScreenSpaceEventHandler; polygonEntity: CesiumTypeOnly.Entity; + tagEntity: CesiumTypeOnly.Entity; geometryPoints: CesiumTypeOnly.Cartesian3[] = []; state: State = 'drawing'; controlPoints: CesiumTypeOnly.EntityCollection = []; controlPointsEventHandler: CesiumTypeOnly.ScreenSpaceEventHandler; lineEntity: CesiumTypeOnly.Entity; - type!: 'polygon' | 'line'; + type!: Shape; freehand!: boolean; style: GeometryStyle | undefined; outlineEntity: CesiumTypeOnly.Entity; @@ -71,6 +76,16 @@ export default class Base { }, style, ); + }else if(this.type === 'tag') { + this.style = Object.assign( + { + image: TagDefault, + activeImage: TagActive, + width: 32, + height: 32, + }, + style, + ); } //Cache the initial settings to avoid modification of properties due to reference type assignment. this.styleCache = cloneDeep(this.style); @@ -189,7 +204,7 @@ export default class Base { this.setState('edit'); this.addControlPoints(); this.draggable(); - const entity = this.polygonEntity || this.lineEntity; + const entity = this.polygonEntity || this.lineEntity || this.tagEntity; this.entityId = entity.id; /** * "I've noticed that CallbackProperty can lead to significant performance issues. @@ -260,6 +275,22 @@ export default class Base { } } + drawTag() { + const style = this.style as TagStyle; + if (!this.tagEntity) { + this.tagEntity = this.viewer.entities.add({ + position: this.geometryPoints[0], + billboard: { + image: style.image, + width: style.width, + height: style.height, + } + }); + } else { + this.tagEntity.position = this.geometryPoints[0]; + } + } + drawLine() { if (!this.lineEntity) { const style = this.style as LineStyle; @@ -824,6 +855,7 @@ export default class Base { this.polygonEntity = null; this.outlineEntity = null; this.lineEntity = null; + if (this.points.length <= 2) this.removeTempLine(); } else if (this.type === 'line') { this.viewer.entities.remove(this.lineEntity); } @@ -863,7 +895,7 @@ export default class Base { //Abstract method that must be implemented by subclasses. } - getType(): 'polygon' | 'line' { + getType(): Shape { return 'polygon'; //Abstract method that must be implemented by subclasses. } diff --git a/src/index.ts b/src/index.ts index fc66fd0..78814ea 100644 --- a/src/index.ts +++ b/src/index.ts @@ -17,6 +17,7 @@ import Triangle from './polygon/triangle'; import Polygon from './polygon/polygon'; import Circle from './polygon/circle'; import Sector from './polygon/sector'; +import Tag from './tag/tag'; import { GeometryStyle } from './interface'; import * as CesiumTypeOnly from 'cesium'; @@ -41,6 +42,7 @@ const CesiumPlot: any = { Polygon, Circle, Sector, + Tag, }; type CreateGeometryFromDataOpts = { @@ -61,8 +63,10 @@ CesiumPlot.createGeometryFromData = (cesium: any, viewer: any, opts: CreateGeome geometry.setGeometryPoints(geometryPoints); if (geometry.type == 'polygon') { geometry.drawPolygon(); - } else { + } else if (geometry.type == 'line'){ geometry.drawLine(); + }else if (geometry.type == 'tag'){ + geometry.drawTag(); } geometry.finishDrawing(); geometry.onClick(); diff --git a/src/interface.ts b/src/interface.ts index b4eb0f6..5896f5a 100644 --- a/src/interface.ts +++ b/src/interface.ts @@ -12,8 +12,15 @@ export type LineStyle = { lineWidth?: number; }; +export type TagStyle = { + image?: string; + activeImage?: string; + width?: number; + height?: number; + }; + export type State = 'drawing' | 'edit' | 'static' | 'animating' | 'hidden'; -export type GeometryStyle = PolygonStyle | LineStyle; +export type GeometryStyle = PolygonStyle | LineStyle | TagStyle; export type EventType = 'drawStart' | 'drawUpdate' | 'drawEnd' | 'editEnd' | 'editStart'; export type EventListener = (eventData?: any) => void; @@ -29,3 +36,5 @@ export type GrowthAnimationOpts = { delay: number; callback: Function; }; + +export type Shape = 'polygon' | 'line' | 'tag'; \ No newline at end of file diff --git a/src/line/curve.ts b/src/line/curve.ts index c093399..17ab317 100644 --- a/src/line/curve.ts +++ b/src/line/curve.ts @@ -2,7 +2,7 @@ import * as Utils from '../utils'; import Base from '../base'; // @ts-ignore import { Cartesian3 } from 'kmap-3d-engine'; -import { LineStyle } from '../interface'; +import { LineStyle, Shape } from '../interface'; export default class Curve extends Base { points: Cartesian3[] = []; @@ -18,7 +18,7 @@ export default class Curve extends Base { this.onDoubleClick(); } - getType(): 'polygon' | 'line' { + getType(): Shape { return 'line'; } diff --git a/src/line/freehand-line.ts b/src/line/freehand-line.ts index 775ee3d..45f30d9 100644 --- a/src/line/freehand-line.ts +++ b/src/line/freehand-line.ts @@ -1,7 +1,7 @@ import Base from '../base'; // @ts-ignore import { Cartesian3 } from 'cesium'; -import { PolygonStyle } from '../interface'; +import { PolygonStyle, Shape } from '../interface'; export default class FreehandLine extends Base { points: Cartesian3[] = []; @@ -14,7 +14,7 @@ export default class FreehandLine extends Base { this.setState('drawing'); } - getType(): 'polygon' | 'line' { + getType(): Shape { return 'line'; } diff --git a/src/polygon/circle.ts b/src/polygon/circle.ts index 6cd438e..eda10bf 100644 --- a/src/polygon/circle.ts +++ b/src/polygon/circle.ts @@ -3,7 +3,7 @@ import * as Utils from '../utils'; // @ts-ignore import { Cartesian3 } from 'cesium'; -import { PolygonStyle } from '../interface'; +import { PolygonStyle, Shape } from '../interface'; export default class Circle extends Base { points: Cartesian3[] = []; @@ -16,7 +16,7 @@ export default class Circle extends Base { this.setState('drawing'); } - getType(): 'polygon' | 'line' { + getType(): Shape { return 'polygon'; } diff --git a/src/polygon/ellipse.ts b/src/polygon/ellipse.ts index 432a0c8..fdd15ee 100644 --- a/src/polygon/ellipse.ts +++ b/src/polygon/ellipse.ts @@ -3,7 +3,7 @@ import * as Utils from '../utils'; // @ts-ignore import { Cartesian3 } from 'cesium'; -import { PolygonStyle } from '../interface'; +import { PolygonStyle, Shape } from '../interface'; export default class Ellipse extends Base { points: Cartesian3[] = []; @@ -16,7 +16,7 @@ export default class Ellipse extends Base { this.setState('drawing'); } - getType(): 'polygon' | 'line' { + getType(): Shape { return 'polygon'; } diff --git a/src/polygon/freehand-polygon.ts b/src/polygon/freehand-polygon.ts index a947c5d..36389ee 100644 --- a/src/polygon/freehand-polygon.ts +++ b/src/polygon/freehand-polygon.ts @@ -1,7 +1,7 @@ import Base from '../base'; // @ts-ignore import { Cartesian3 } from 'cesium'; -import { PolygonStyle } from '../interface'; +import { PolygonStyle, Shape } from '../interface'; export default class FreehandPolygon extends Base { points: Cartesian3[] = []; @@ -14,7 +14,7 @@ export default class FreehandPolygon extends Base { this.setState('drawing'); } - getType(): 'polygon' | 'line' { + getType(): Shape { return 'polygon'; } diff --git a/src/polygon/lune.ts b/src/polygon/lune.ts index aba5689..fc7cc9d 100644 --- a/src/polygon/lune.ts +++ b/src/polygon/lune.ts @@ -2,7 +2,7 @@ import Base from '../base'; import * as Utils from '../utils'; // @ts-ignore import { Cartesian3 } from 'cesium'; -import { PolygonStyle } from '../interface'; +import { PolygonStyle, Shape } from '../interface'; export default class Lune extends Base { points: Cartesian3[] = []; @@ -15,7 +15,7 @@ export default class Lune extends Base { this.setState('drawing'); } - getType(): 'polygon' | 'line' { + getType(): Shape { return 'polygon'; } diff --git a/src/polygon/polygon.ts b/src/polygon/polygon.ts index 3d447b5..e4b18a1 100644 --- a/src/polygon/polygon.ts +++ b/src/polygon/polygon.ts @@ -2,7 +2,7 @@ import Base from '../base'; // @ts-ignore import { Cartesian3 } from 'cesium'; -import { PolygonStyle } from '../interface'; +import { PolygonStyle, Shape } from '../interface'; export default class Polygon extends Base { points: Cartesian3[] = []; @@ -14,7 +14,7 @@ export default class Polygon extends Base { this.onDoubleClick(); } - getType(): 'polygon' | 'line' { + getType(): Shape { return 'polygon'; } @@ -22,17 +22,73 @@ export default class Polygon extends Base { * Add points only on click events */ addPoint(cartesian: Cartesian3) { - this.points.push(cartesian); + let endPoint = cartesian; + if (this.points.length > 2) { + endPoint = this.getEndPoint(cartesian); + } + this.points.push(endPoint); if (this.points.length === 1) { this.onMouseMove(); } + if (this.points.length > 2 && this.comparePositions(this.points[0], endPoint)) { + this.finishDrawing(); + } + } + + /** + * backout the last point + */ + removePoint() { + if (this.points.length > 0) { + this.points.pop(); + this.setGeometryPoints(this.points); + if (this.points.length === 2) { + this.addTempLine(); + } else { + this.removeTempLine(); + this.drawPolygon(); + } + if(this.points.length === 0) { + this.removeMoveListener(); + } + } + } + + /** + * Compare whether the positions of two points are equal. + */ + comparePositions(point1: Cartesian3, point2: Cartesian3) { + const lnglat1 = this.cartesianToLnglat(point1); + const lnglat2 = this.cartesianToLnglat(point2); + return lnglat1[0] === lnglat2[0] && lnglat1[1] === lnglat2[1]; + } + + /** + * Calculate the distance between two points + */ + calculateDistance(point1: Cartesian3, point2: Cartesian3) { + return this.cesium.Cartesian3.distance(point1, point2); + } + + /** + * get end point + */ + getEndPoint(cartesian: Cartesian3) { + let endPoint = cartesian; + let distance = this.calculateDistance(this.points[0], cartesian); + if (distance < 100) endPoint = this.points[0]; + return endPoint; } /** * Draw a shape based on mouse movement points during the initial drawing. */ updateMovingPoint(cartesian: Cartesian3) { - const tempPoints = [...this.points, cartesian]; + let endPoint = cartesian; + if (this.points.length > 2) { + endPoint = this.getEndPoint(cartesian); + } + const tempPoints = [...this.points, endPoint]; this.setGeometryPoints(tempPoints); if (tempPoints.length === 2) { this.addTempLine(); diff --git a/src/polygon/rectangle.ts b/src/polygon/rectangle.ts index 21c68a3..5d1172f 100644 --- a/src/polygon/rectangle.ts +++ b/src/polygon/rectangle.ts @@ -2,7 +2,7 @@ import Base from '../base'; // @ts-ignore import { Cartesian3 } from 'cesium'; -import { PolygonStyle } from '../interface'; +import { PolygonStyle, Shape } from '../interface'; export default class Rectangle extends Base { points: Cartesian3[] = []; @@ -13,7 +13,7 @@ export default class Rectangle extends Base { this.setState('drawing'); } - getType(): 'polygon' | 'line' { + getType(): Shape { return 'polygon'; } diff --git a/src/polygon/sector.ts b/src/polygon/sector.ts index f169c9d..7176f83 100644 --- a/src/polygon/sector.ts +++ b/src/polygon/sector.ts @@ -2,7 +2,7 @@ import Base from '../base'; // @ts-ignore import { Cartesian3 } from 'cesium'; import * as Utils from '../utils'; -import { PolygonStyle } from '../interface'; +import { PolygonStyle, Shape } from '../interface'; export default class Sector extends Base { points: Cartesian3[] = []; @@ -13,7 +13,7 @@ export default class Sector extends Base { this.setState('drawing'); } - getType(): 'polygon' | 'line' { + getType(): Shape { return 'polygon'; } diff --git a/src/polygon/triangle.ts b/src/polygon/triangle.ts index b886e96..8c752f2 100644 --- a/src/polygon/triangle.ts +++ b/src/polygon/triangle.ts @@ -2,7 +2,7 @@ import Base from '../base'; // @ts-ignore import { Cartesian3 } from 'cesium'; -import { PolygonStyle } from '../interface'; +import { PolygonStyle, Shape } from '../interface'; export default class Triangle extends Base { points: Cartesian3[] = []; @@ -13,7 +13,7 @@ export default class Triangle extends Base { this.setState('drawing'); } - getType(): 'polygon' | 'line' { + getType(): Shape { return 'polygon'; } diff --git a/src/tag/tag.ts b/src/tag/tag.ts new file mode 100644 index 0000000..8b7cb1e --- /dev/null +++ b/src/tag/tag.ts @@ -0,0 +1,85 @@ +import Base from '../base'; +import { Shape, TagStyle } from '../interface'; +import { Cartesian3 } from 'cesium'; + +export default class Tag extends Base { + points: Cartesian3[] = []; + + constructor(cesium: any, viewer: any, style?: TagStyle) { + super(cesium, viewer, style); + this.cesium = cesium; + this.setState('drawing'); + this.onMouseMove(); + } + getType(): Shape { + return 'tag'; + } + /** + * Draw a shape based on mouse movement points during the initial drawing. + */ + updateMovingPoint(cartesian: Cartesian3) { + this.setGeometryPoints([cartesian]); + this.drawTag(); + } + + onClick() { + this.eventHandler = new this.cesium.ScreenSpaceEventHandler(this.viewer.canvas); + this.eventHandler.setInputAction((evt: any) => { + const pickedObject = this.viewer.scene.pick(evt.position); + const hitEntities = this.cesium.defined(pickedObject) && pickedObject.id instanceof this.cesium.Entity; + const activeEntity = this.tagEntity; + if (this.state === 'drawing') { + this.finishDrawing(); + } else if (this.state === 'edit') { + if (!hitEntities || activeEntity.id !== pickedObject.id.id) { + this.tagEntity.billboard.image = this.style.image; + this.setState('static'); + this.removeControlPoints(); + this.disableDrag(); + this.eventDispatcher.dispatchEvent('editEnd', this.getPoints()); + } + } else if (this.state === 'static') { + if (hitEntities && activeEntity.id === pickedObject.id.id) { + this.tagEntity.billboard.image = this.style.activeImage; + this.setState('edit'); + this.draggable(); + this.eventDispatcher.dispatchEvent('editStart'); + } + } + }, this.cesium.ScreenSpaceEventType.LEFT_CLICK); + } + + draggable() { + let dragging = false; + this.dragEventHandler = new this.cesium.ScreenSpaceEventHandler(this.viewer.canvas); + this.dragEventHandler.setInputAction((event: any) => { + const pickRay = this.viewer.scene.camera.getPickRay(event.position); + if (pickRay) { + const pickedObject = this.viewer.scene.pick(event.position); + if (this.cesium.defined(pickedObject) && pickedObject.id instanceof this.cesium.Entity) { + const clickedEntity = pickedObject.id; + if (this.isCurrentEntity(clickedEntity.id)) { + dragging = true; + this.viewer.scene.screenSpaceCameraController.enableRotate = false; + } + } + } + }, this.cesium.ScreenSpaceEventType.LEFT_DOWN); + this.dragEventHandler.setInputAction((event: any) => { + if (dragging) { + console.log(666, event); + const cartesian = this.pixelToCartesian(event.endPosition); + console.log(cartesian, this.state); + this.tagEntity.position = cartesian; + } + }, this.cesium.ScreenSpaceEventType.MOUSE_MOVE); + this.dragEventHandler.setInputAction(() => { + dragging = false; + this.viewer.scene.screenSpaceCameraController.enableRotate = true; + }, this.cesium.ScreenSpaceEventType.LEFT_UP); + } + /** + * tag not need to add control points + */ + addControlPoints() { } +} \ No newline at end of file