From 247f401203a28cf2d36c48cb8e65fb286d76ddb4 Mon Sep 17 00:00:00 2001 From: ethan Date: Mon, 14 Aug 2023 17:47:59 +0800 Subject: [PATCH] shape editing --- examples/index.ts | 13 +++- src/arrow/fine-arrow.ts | 19 +++-- src/assets/circle_red.png | Bin 0 -> 891 bytes src/draw.ts | 153 +++++++++++++++++++++++++++++++++++--- src/interface.ts | 1 + 5 files changed, 164 insertions(+), 22 deletions(-) create mode 100644 src/assets/circle_red.png create mode 100644 src/interface.ts diff --git a/examples/index.ts b/examples/index.ts index dde4025..cb14b7e 100644 --- a/examples/index.ts +++ b/examples/index.ts @@ -1,8 +1,14 @@ import CesiumPlot from "../src"; +// import CesiumPlot from "../dist/CesiumPlot"; import * as Cesium from "./cesium/index"; -let raster = new Cesium.ArcGisMapServerImageryProvider({ - url: "https://services.arcgisonline.com/ArcGIS/rest/services/World_Imagery/MapServer", +// let raster = new Cesium.ArcGisMapServerImageryProvider({ +// url: "https://services.arcgisonline.com/ArcGIS/rest/services/World_Imagery/MapServer", +// }); + +let keda = new Cesium.UrlTemplateImageryProvider({ + url: "https://10.68.8.41:9043/kmap-server/gridMap/tile/{z}/{y}/{x}", + // url: 'http://10.68.8.58:8080/3d/dom2/{z}/{x}/{y}.png' }); const viewer = new Cesium.Viewer("cesiumContainer", { animation: false, @@ -16,7 +22,8 @@ const viewer = new Cesium.Viewer("cesiumContainer", { timeline: false, navigationHelpButton: false, baseLayerPicker: false, - imageryProvider: raster, + // imageryProvider: raster, + imageryProvider: keda, contextOptions: { requestWebgl2: true, }, diff --git a/src/arrow/fine-arrow.ts b/src/arrow/fine-arrow.ts index 09022cf..344f386 100644 --- a/src/arrow/fine-arrow.ts +++ b/src/arrow/fine-arrow.ts @@ -8,32 +8,33 @@ export default class FineArrow extends Draw { constructor(cesium: any, viewer: any, style: any) { super(cesium, viewer); this.cesium = cesium; - this.onClick(); + this.setState('drawing'); } /** * Add points only on click events */ addPoint(cartesian: Cartesian3) { - this.points.push(cartesian); - if (this.points.length === 1) { + this.points.push(); + if (this.points.length === 0) { + this.points[0] = cartesian; this.onMouseMove(); } if (this.points.length === 2) { const geometryPoints = this.createPolygon(this.points); this.setGeometryPoints(geometryPoints); this.addToMap(); - this.removeClickListener(); this.removeMoveListener(); + this.setState('static'); } } /** * Update the last point as the mouse moves. */ - updateMovingPoint(cartesian: Cartesian3) { - let tempPoints = [...this.points, cartesian]; - const geometryPoints = this.createPolygon(tempPoints); + updateMovingPoint(cartesian: Cartesian3, index: number) { + this.points[index] = cartesian; + const geometryPoints = this.createPolygon(this.points); this.setGeometryPoints(geometryPoints); this.addToMap(); } @@ -57,4 +58,8 @@ export default class FineArrow extends Draw { const cartesianPoints = this.cesium.Cartesian3.fromDegreesArray(points); return cartesianPoints; } + + getPoints() { + return this.points; + } } diff --git a/src/assets/circle_red.png b/src/assets/circle_red.png new file mode 100644 index 0000000000000000000000000000000000000000..653ce8fb02b6ab330bd3f542f5bffdbd6c43a29f GIT binary patch literal 891 zcmZXSdq`7p6vuz!GfOf9AC+K45322Vw>e$6!e*Op)Rvp`iJ9~6x?S?#ySD4*glJkp ziZO~Psg&@aM9A_*r3@;yND9o_jdo^ZA~0{`fWK>2u>^ zx5WYg;Op2$^!E0L)hTto|6ojN)YnUI(QB3)_Uu;kUMl&0i~ ztD~E-qbr^RB+*Y)6SdaQTMppq#>&Bbk?TxQ|-?b zBg4{DyTS{*{nVY}Ys#fpdtFNn%KdC*sWxhHm3cegI&v)L*3`Q*VK0lmyuac2AhvFJ zWGwZ*F}A0-&K*8#Sdp&&0LiscK3VTt558r$pe`0HW`QOt2aOYu5)y@o$Ph^tCaIK^ zrIUp00HGiWVn^4{!M_YFZ(*uDL4!m@$VHNnK`O`SZ^OZ_=Nhr$cyNQ0uM*s52Mu72 z(*dh_%3KW@)@-G5Fw|M-wBaVS@D$VrRb5CGWkSes7P?k!6WD5hzbE)!l7r(+wi>pQ zBvm|B!_u5Ul6lzV1d{t`5Mm~29TS>Ik{X(^+5{lUNPSq&VNyHcWg5Z67g_ zvX0O(EG>BKGzi@c?VL5Mr%?aTCY=dWKq4dLnNme2LHOG=hcFVqZcaW^M}u@(Mz&*R zp$+%S*YygFT2RGQ(mQNg fpwmG?S$bwL { - const cartesian = this.pixelToCartesian(evt.position); - this.addPoint(cartesian); + const pickedObject = this.viewer.scene.pick(evt.position); + const hitEntities = this.cesium.defined(pickedObject) && pickedObject.id instanceof CesiumTypeOnly.Entity; + if (this.state === 'drawing') { + // In the drawing state, the points clicked are key nodes of the shape, and they are saved in this.points. + const cartesian = this.pixelToCartesian(evt.position); + this.addPoint(cartesian); + } else if (this.state === 'edit') { + //In edit mode, exiting the edit state and deleting control points when clicking in the blank area. + if (!hitEntities) { + this.setState('static'); + this.removeControlPoints(); + } + } else if (this.state === 'static') { + if (hitEntities) { + const pickedEntity = pickedObject.id; + if (this.cesium.defined(pickedEntity.polygon)) { + // Hit PolygonGraphics geometry. + this.setState('edit'); + this.addControlPoints(); + } + } + } }, this.cesium.ScreenSpaceEventType.LEFT_CLICK); } onMouseMove() { this.eventHandler.setInputAction((evt) => { - const cartesian = this.pixelToCartesian(evt.endPosition); - const lnglat = this.cartesianToLnglat(cartesian); - const lastPoint = this.cartesianToLnglat(this.points[this.points.length - 1]); - const distance = Utils.MathDistance(lnglat, lastPoint); - if (distance < 0.0001) { - return false; - } - // Synchronize data to subclasses. - this.updateMovingPoint(cartesian); + this.drawingWhileMoving(evt.endPosition, 1); }, this.cesium.ScreenSpaceEventType.MOUSE_MOVE); } + drawingWhileMoving(position: CesiumTypeOnly.Cartesian2, index: number) { + const cartesian = this.pixelToCartesian(position); + const lnglat = this.cartesianToLnglat(cartesian); + const points = this.getPoints(); + const lastPoint = this.cartesianToLnglat(points[points.length - 1]); + const distance = Utils.MathDistance(lnglat, lastPoint); + if (distance < 0.0001) { + return false; + } + // Synchronize data to subclasses. + this.updateMovingPoint(cartesian, index); + } + removeClickListener() { this.eventHandler.removeInputAction(this.cesium.ScreenSpaceEventType.LEFT_CLICK); } @@ -61,6 +109,10 @@ export default class Draw { this.geometryPoints = geometryPoints; } + getGeometryPoints(): CesiumTypeOnly.Cartesian3[] { + return this.geometryPoints; + } + addToMap() { const callback = () => { return new this.cesium.PolygonHierarchy(this.geometryPoints); @@ -89,4 +141,81 @@ export default class Draw { const cartesian = this.viewer.scene.globe.pick(ray, this.viewer.scene); return cartesian; } + + /** + * Display key points when creating a shape, allowing dragging of these points to edit and generate new shapes. + */ + addControlPoints() { + const points = this.getPoints(); + this.controlPoints = points.map((position) => { + return this.viewer.entities.add({ + position, + billboard: { + image: './src/assets/circle_red.png', + }, + }); + }); + + let isDragging = false; + let draggedIcon: CesiumTypeOnly.Entity = null; + + this.controlPointsEventHandler = new this.cesium.ScreenSpaceEventHandler(this.viewer.canvas); + // Listen for left mouse button press events + this.controlPointsEventHandler.setInputAction((clickEvent) => { + const pickedObject = this.viewer.scene.pick(clickEvent.position); + + if (this.cesium.defined(pickedObject)) { + for (let i = 0; i < this.controlPoints.length; i++) { + if (pickedObject.id === this.controlPoints[i]) { + isDragging = true; + draggedIcon = this.controlPoints[i]; + draggedIcon.index = i; //Save the index of dragged points for dynamic updates during movement + break; + } + } + // Disable default camera interaction. + this.viewer.scene.screenSpaceCameraController.enableRotate = false; + } + }, this.cesium.ScreenSpaceEventType.LEFT_DOWN); + + // Listen for mouse movement events + this.controlPointsEventHandler.setInputAction((moveEvent) => { + if (isDragging && draggedIcon) { + const cartesian = this.viewer.camera.pickEllipsoid(moveEvent.endPosition, this.viewer.scene.globe.ellipsoid); + if (cartesian) { + draggedIcon.position.setValue(cartesian); + this.drawingWhileMoving(moveEvent.endPosition, draggedIcon.index); + } + } + }, this.cesium.ScreenSpaceEventType.MOUSE_MOVE); + + // Listen for left mouse button release events + this.controlPointsEventHandler.setInputAction(() => { + isDragging = false; + draggedIcon = null; + this.viewer.scene.screenSpaceCameraController.enableRotate = true; + }, this.cesium.ScreenSpaceEventType.LEFT_UP); + } + + removeControlPoints() { + this.controlPoints.forEach((entity: CesiumTypeOnly.Entity) => { + this.viewer.entities.remove(entity); + }); + this.controlPointsEventHandler.removeInputAction(this.cesium.ScreenSpaceEventType.LEFT_DOWN); + this.controlPointsEventHandler.removeInputAction(this.cesium.ScreenSpaceEventType.MOUSE_MOVE); + this.controlPointsEventHandler.removeInputAction(this.cesium.ScreenSpaceEventType.LEFT_UP); + } + + addPoint(cartesian: CesiumTypeOnly.Cartesian3) { + //Abstract method that must be implemented by subclasses. + } + + getPoints(): CesiumTypeOnly.Cartesian3[] { + //Abstract method that must be implemented by subclasses. + return this.cesium.Cartesian3(); + } + + updateMovingPoint(cartesian: CesiumTypeOnly.Cartesian3, index: number) { + //Abstract method that must be implemented by subclasses. + } } diff --git a/src/interface.ts b/src/interface.ts new file mode 100644 index 0000000..1ae5ef4 --- /dev/null +++ b/src/interface.ts @@ -0,0 +1 @@ +export type State = 'drawing' | 'edit' | 'static';