From 06a7756f5df918ed44016a6860c4bde246a76f54 Mon Sep 17 00:00:00 2001
From: shuishen <1109946754@qq.com>
Date: Mon, 24 Nov 2025 09:43:10 +0800
Subject: [PATCH] feat:GSD可见光,相对被射面距离,安全起飞高度(相对起飞高度),测区方向,航线方向,完成动作,拍照方式,旁向重叠率,航向重叠率等处理

---
 js/modules/axis-manager.js |  189 +++++++++++++++++++++++++++++++++++++++++++++--
 1 files changed, 181 insertions(+), 8 deletions(-)

diff --git a/js/modules/axis-manager.js b/js/modules/axis-manager.js
index 5be9609..4143e7d 100644
--- a/js/modules/axis-manager.js
+++ b/js/modules/axis-manager.js
@@ -33,6 +33,10 @@
     this.centerVectorYC = null
     this.centerVectorZC = null
     this.dashLineList = []
+    this.flip = { x: false, y: false, z: false }
+    this.editingEnabled = false
+    this.interaction = { type: null, axis: null }
+    this.outlineEntity = null
 
     this.planeCtx = { activeShape: null, polygonPositionList: [], centerPoint: null }
     this.axisModelUris = { axisX: 'gltf/green-arrows.gltf', axisY: 'gltf/red-arrows.gltf', axisZ: 'gltf/blue-arrows.gltf' }
@@ -50,6 +54,31 @@
     }
   }
 
+  setControllerVisibility (show) {
+    const s = !!show
+    if (this.axisEntyX) this.axisEntyX.show = s
+    if (this.axisEntyY) this.axisEntyY.show = s
+    if (this.axisEntyZ) this.axisEntyZ.show = s
+    if (this.sphereEntyX) this.sphereEntyX.show = s
+    if (this.sphereEntyY) this.sphereEntyY.show = s
+    if (this.sphereEntyZ) this.sphereEntyZ.show = s
+    if (this.overlayModels.axisX) this.overlayModels.axisX.show = s
+    if (this.overlayModels.axisY) this.overlayModels.axisY.show = s
+    if (this.overlayModels.axisZ) this.overlayModels.axisZ.show = s
+    if (this.overlayModels.sphereX) this.overlayModels.sphereX.show = s
+    if (this.overlayModels.sphereY) this.overlayModels.sphereY.show = s
+    if (this.overlayModels.sphereZ) this.overlayModels.sphereZ.show = s
+    if (!s) this.dashLineList.forEach(ele => { ele.show = false })
+    this.setPolygonOutlineVisibility(this.editingEnabled)
+  }
+
+  setEditingEnabled (flag) {
+    this.editingEnabled = !!flag
+    this.setControllerVisibility(this.editingEnabled)
+    this.setPolygonOutlineVisibility(this.editingEnabled)
+    this.setDistanceLabelsVisibility(this.editingEnabled)
+  }
+
   /**
    * 注入当前平面上下文(面实体、顶点列表、中心点)
    * @param {{activeShape:Cesium.Entity,polygonPositionList:Cesium.Cartesian3[],centerPoint:Cesium.Cartesian3}} ctx 上下文
@@ -57,6 +86,10 @@
   setPlaneContext (ctx) {
     this.planeCtx = ctx
     this.centerPoint = ctx.centerPoint
+    this.setEditingEnabled(true)
+    if (this.planeCtx && this.planeCtx.activeShape && this.planeCtx.activeShape.polygon) {
+      this.planeCtx.activeShape.polygon.outline = false
+    }
   }
 
   /**
@@ -129,9 +162,11 @@
     if (this.dashLineList[1]) { this.dashLineList[1].polyline.positions = g.dashY } else { this.dashLineList[1] = this.entityFactory.drawDashLine(g.dashY, 'dashY') }
     if (this.dashLineList[2]) { this.dashLineList[2].polyline.positions = g.dashZ } else { this.dashLineList[2] = this.entityFactory.drawDashLine(g.dashZ, 'dashZ') }
 
-    const qX = this._getAxisOrientation(g.centerPoint, g.centerVectorXC, this.axisLocalBasis.axisX)
+    const xDir = this.flip.x ? Cesium.Cartesian3.multiplyByScalar(g.centerVectorXC, -1, new Cesium.Cartesian3()) : g.centerVectorXC
+    const qX = this._getAxisOrientation(g.centerPoint, xDir, this.axisLocalBasis.axisX)
     const qY = this._getAxisOrientation(g.centerPoint, g.rotationNormalY, this.axisLocalBasis.axisY)
-    const qZ = this._getAxisOrientation(g.centerPoint, g.rotationNormalZ, this.axisLocalBasis.axisZ)
+    const zDir = this.flip.z ? Cesium.Cartesian3.multiplyByScalar(g.rotationNormalZ, -1, new Cesium.Cartesian3()) : g.rotationNormalZ
+    const qZ = this._getAxisOrientation(g.centerPoint, zDir, this.axisLocalBasis.axisZ)
     this.lastOrientation.axisX = qX
     this.lastOrientation.axisY = qY
     this.lastOrientation.axisZ = qZ
@@ -155,7 +190,8 @@
     }
     const qsX = this._getOrientationWithUp(g.centerPoint, g.refDirX, g.rotationNormalX, this.circleLocalBasis.sphereX)
     const qsY = this._getOrientationWithUp(g.centerPoint, g.refDirY, g.rotationNormalY, this.circleLocalBasis.sphereY)
-    const qsZ = this._getOrientationWithUp(g.centerPoint, g.refDirZ, g.rotationNormalZ, this.circleLocalBasis.sphereZ)
+    const zUp = this.flip.z ? Cesium.Cartesian3.multiplyByScalar(g.rotationNormalZ, -1, new Cesium.Cartesian3()) : g.rotationNormalZ
+    const qsZ = this._getOrientationWithUp(g.centerPoint, g.refDirZ, zUp, this.circleLocalBasis.sphereZ)
     this.lastOrientation.sphereX = qsX
     this.lastOrientation.sphereY = qsY
     this.lastOrientation.sphereZ = qsZ
@@ -188,6 +224,12 @@
     this.centerVectorXC = g.centerVectorXC
     this.centerVectorYC = g.centerVectorYC
     this.centerVectorZC = g.centerVectorZC
+    if (this.interaction && this.interaction.type === 'rotation' && this.interaction.axis) {
+      this.setRotationAxisFocus(this.interaction.axis)
+    } else {
+      this.setControllerVisibility(this.editingEnabled)
+    }
+    this.setPolygonOutlineVisibility(this.editingEnabled)
   }
 
   /**
@@ -196,6 +238,13 @@
   createAxisEntity (point1, point2, point3, point4) {
     const g = this.computeAxisGeometry(point1, point2, point3, point4)
     this.applyAxisGeometry(g)
+  }
+
+  setReversalMode (flag) {
+    this.flip.z = !!flag
+    this.flip.x = !!flag
+    const p = this.planeCtx.polygonPositionList
+    if (Array.isArray(p) && p.length >= 4) this.createAxisEntity(p[0], p[1], p[2], p[3])
   }
 
   /**
@@ -258,6 +307,7 @@
     this.dashLineList[0].polyline.positions = new Cesium.CallbackProperty(() => axisDashX, false)
     this.dashLineList[1].polyline.positions = new Cesium.CallbackProperty(() => axisDashY, false)
     this.dashLineList[2].polyline.positions = new Cesium.CallbackProperty(() => axisDashZ, false)
+    this.setPolygonOutlineVisibility(this.editingEnabled)
   }
 
   /**
@@ -321,6 +371,7 @@
     let translationController = this._translationController()
 
     masterController.setInputAction((e) => {
+      if (!this.editingEnabled) return
       const results = viewer.scene.drillPick(e.position)
       let hit = null
       let id = null
@@ -330,10 +381,10 @@
           if (!rid) continue
           const s = String(rid)
           if (s === 'polygon') continue
-          if (s.slice(0, 6) === 'sphere' || s.slice(0, 4) === 'axis') { hit = results[k]; id = rid; break }
+          if (s.slice(0, 6) === 'sphere' || s.slice(0, 4) === 'axis' || s === 'polygonOutline') { hit = results[k]; id = rid; break }
         }
       }
-      if (!hit || !id || !this.axisPosition[id]) return
+      if (!hit || !id) return
 
       moveDashLine = true
       eventHub.enableRotate(false)
@@ -341,13 +392,19 @@
 
       let isRotation = false
       let isTranslation = false
+      let isEdgeDrag = false
 
       if (id.slice(0, 6) === 'sphere') {
-        if (rotationController.startRotation(hit, this.centerPoint)) { isRotation = true; this._setDragRotationFocus(rotationController.state.currentAxis) }
+        if (rotationController.startRotation(hit, this.centerPoint)) { isRotation = true; this.interaction = { type: 'rotation', axis: rotationController.state.currentAxis }; this._setDragRotationFocus(rotationController.state.currentAxis) }
       } else if (id.slice(0, 4) === 'axis') {
-        if (translationController.startTranslation(hit, this.centerPoint)) { isTranslation = true; translationController.state.lastMousePosition = new Cesium.Cartesian2(e.position.x, e.position.y); this._setDragTranslationHighlight(translationController.state.currentAxis) }
+        if (translationController.startTranslation(hit, this.centerPoint)) { isTranslation = true; this.interaction = { type: 'translation', axis: translationController.state.currentAxis }; translationController.state.lastMousePosition = new Cesium.Cartesian2(e.position.x, e.position.y); this._setDragTranslationHighlight(translationController.state.currentAxis) }
+      } else if (id === 'polygonOutline') {
+        const p = this.planeCtx && this.planeCtx.polygonPositionList
+        if (!p || p.length < 4) return
+        if (!this._edgeController) this._edgeController = this._edgeDragController()
+        if (this._edgeController.startEdgeDrag(e.position, this.centerPoint, p)) { isEdgeDrag = true }
       }
-      if (!isRotation && !isTranslation) return
+      if (!isRotation && !isTranslation && !isEdgeDrag) return
       this.setDistanceLabelsVisibility(false)
 
       masterController.setInputAction((movement) => {
@@ -361,6 +418,19 @@
         } else if (isTranslation) {
           const distanceDelta = translationController.updateTranslation(mousePosition, this.centerPoint)
           if (Math.abs(distanceDelta) > 0.01) { this._setDragTranslationHighlight(translationController.state.currentAxis); this.translatePlaneByAxis(distanceDelta, translationController.state.currentAxis) }
+        } else if (isEdgeDrag) {
+          const delta = this._edgeController.updateEdgeDrag(mousePosition)
+          if (delta) {
+            const idx = this._edgeController.state.edgeIndex
+            const p = this.planeCtx.polygonPositionList
+            const a = idx === 0 ? 0 : idx === 1 ? 1 : idx === 2 ? 2 : 3
+            const b = idx === 0 ? 1 : idx === 1 ? 2 : idx === 2 ? 3 : 0
+            p[a] = Cesium.Cartesian3.add(p[a], delta, new Cesium.Cartesian3())
+            p[b] = Cesium.Cartesian3.add(p[b], delta, new Cesium.Cartesian3())
+            this.planeCtx.activeShape.polygon.hierarchy = new Cesium.CallbackProperty(() => new Cesium.PolygonHierarchy(p), false)
+            const g = this.computeAxisGeometry(p[0], p[1], p[2], p[3])
+            this.applyAxisGeometry(g)
+          }
         }
       }, Cesium.ScreenSpaceEventType.MOUSE_MOVE)
 
@@ -391,10 +461,13 @@
         this.bindHover()
         if (isRotation) rotationController.endRotation()
         if (isTranslation) translationController.endTranslation()
+        if (isEdgeDrag && this._edgeController) this._edgeController.endEdgeDrag()
+        this.interaction = { type: null, axis: null }
         if (typeof onUpdate === 'function') onUpdate(this.planeCtx.polygonPositionList)
         this.createAxisEntity(...this.planeCtx.polygonPositionList)
         this.updateDistanceLabels()
         this.setDistanceLabelsVisibility(true)
+        this.setControllerVisibility(this.editingEnabled)
       }, Cesium.ScreenSpaceEventType.LEFT_UP)
     }, Cesium.ScreenSpaceEventType.LEFT_DOWN)
   }
@@ -454,7 +527,32 @@
   bindHover () {
     const handler = this.eventHub.get('hover')
     handler.setInputAction((arg) => {
+      if (!this.editingEnabled) {
+        document.body.style.cursor = 'default'
+        this.axisEntyZ && (this.axisEntyZ.model.silhouetteSize = new Cesium.CallbackProperty(() => 0, false))
+        this.axisEntyX && (this.axisEntyX.model.silhouetteSize = new Cesium.CallbackProperty(() => 0, false))
+        this.axisEntyY && (this.axisEntyY.model.silhouetteSize = new Cesium.CallbackProperty(() => 0, false))
+        if (this.overlayModels.axisZ) this.overlayModels.axisZ.silhouetteSize = 0
+        if (this.overlayModels.axisX) this.overlayModels.axisX.silhouetteSize = 0
+        if (this.overlayModels.axisY) this.overlayModels.axisY.silhouetteSize = 0
+        this.sphereEntyX && (this.sphereEntyX.model.silhouetteSize = new Cesium.CallbackProperty(() => 0, false))
+        this.sphereEntyY && (this.sphereEntyY.model.silhouetteSize = new Cesium.CallbackProperty(() => 0, false))
+        this.sphereEntyZ && (this.sphereEntyZ.model.silhouetteSize = new Cesium.CallbackProperty(() => 0, false))
+        if (this.overlayModels.sphereX) this.overlayModels.sphereX.silhouetteSize = 0
+        if (this.overlayModels.sphereY) this.overlayModels.sphereY.silhouetteSize = 0
+        if (this.overlayModels.sphereZ) this.overlayModels.sphereZ.silhouetteSize = 0
+        this.dashLineList.forEach(ele => { ele.show = false })
+        return
+      }
       const results = this.viewer.scene.drillPick(arg.endPosition)
+      let onOutline = false
+      if (Array.isArray(results) && results.length > 0) {
+        for (let k = 0; k < results.length; k++) {
+          const rid0 = (results[k] && (results[k].id?.id || results[k].id || results[k].primitive?.id))
+          if (!rid0) continue
+          if (String(rid0) === 'polygonOutline') { onOutline = true; break }
+        }
+      }
       let id = null
       if (Array.isArray(results) && results.length > 0) {
         for (let k = 0; k < results.length; k++) {
@@ -464,6 +562,7 @@
           if (s.slice(0, 6) === 'sphere' || s.slice(0, 4) === 'axis') { id = rid; break }
         }
       }
+      document.body.style.cursor = onOutline ? 'all-scroll' : 'default'
       if (id) {
         this.axisEntyZ.model.silhouetteSize = new Cesium.CallbackProperty(() => (id === 'axisZ' ? 1 : 0), false)
         this.axisEntyX.model.silhouetteSize = new Cesium.CallbackProperty(() => (id === 'axisX' ? 1 : 0), false)
@@ -558,6 +657,24 @@
     if (this.dashLineList[0]) this.dashLineList[0].show = xOn
     if (this.dashLineList[1]) this.dashLineList[1].show = yOn
     if (this.dashLineList[2]) this.dashLineList[2].show = zOn
+  }
+
+  setPolygonOutlineVisibility (show) {
+    const posCb = new Cesium.CallbackProperty(() => {
+      const p = this.planeCtx && this.planeCtx.polygonPositionList
+      if (!p || p.length < 4) return []
+      return [p[0], p[1], p[2], p[3], p[0]]
+    }, false)
+    const editOn = !!show
+    const baseColor = Cesium.Color.fromCssColorString('#2987f0')
+    if (!this.outlineEntity) {
+      this.outlineEntity = this.viewer.entities.add({ id: 'polygonOutline', show: true, polyline: { positions: posCb, width: editOn ? 8 : 2, material: editOn ? new Cesium.PolylineOutlineMaterialProperty({ color: baseColor, outlineColor: Cesium.Color.WHITE, outlineWidth: 3 }) : baseColor, arcType: Cesium.ArcType.RHUMB, clampToGround: false } })
+    } else {
+      this.outlineEntity.show = true
+      this.outlineEntity.polyline.positions = posCb
+      this.outlineEntity.polyline.width = editOn ? 8 : 2
+      this.outlineEntity.polyline.material = editOn ? new Cesium.PolylineOutlineMaterialProperty({ color: baseColor, outlineColor: Cesium.Color.WHITE, outlineWidth: 3 }) : baseColor
+    }
   }
 
   _getAxisOrientation (centerPoint, dir, basis) {
@@ -771,4 +888,60 @@
     }
     return new TranslationController()
   }
+
+  _distanceToSegment (p, a, b) {
+    const ab = Cesium.Cartesian3.subtract(b, a, new Cesium.Cartesian3())
+    const ap = Cesium.Cartesian3.subtract(p, a, new Cesium.Cartesian3())
+    const ab2 = Cesium.Cartesian3.dot(ab, ab)
+    let t = ab2 > 0 ? Cesium.Cartesian3.dot(ap, ab) / ab2 : 0
+    t = Math.max(0, Math.min(1, t))
+    const proj = Cesium.Cartesian3.add(a, Cesium.Cartesian3.multiplyByScalar(ab, t, new Cesium.Cartesian3()), new Cesium.Cartesian3())
+    return Cesium.Cartesian3.magnitude(Cesium.Cartesian3.subtract(p, proj, new Cesium.Cartesian3()))
+  }
+
+  _closestEdgeIndex (point, positions) {
+    const d01 = this._distanceToSegment(point, positions[0], positions[1])
+    const d12 = this._distanceToSegment(point, positions[1], positions[2])
+    const d23 = this._distanceToSegment(point, positions[2], positions[3])
+    const d30 = this._distanceToSegment(point, positions[3], positions[0])
+    const arr = [d01, d12, d23, d30]
+    let idx = 0
+    let min = arr[0]
+    for (let i = 1; i < 4; i++) { if (arr[i] < min) { min = arr[i]; idx = i } }
+    return idx
+  }
+
+  _edgeDragController () {
+    const self = this
+    class EdgeDragController {
+      constructor() { this.state = { isDragging: false, plane: null, lastPoint: null, edgeIndex: 0 } }
+      startEdgeDrag (mousePosition, centerPoint, positions) {
+        const ray = self.viewer.camera.getPickRay(mousePosition); if (!ray) return false
+        let normal
+        if (self.centerVectorZC) normal = Cesium.Cartesian3.normalize(self.centerVectorZC, new Cesium.Cartesian3())
+        else {
+          const v1 = Cesium.Cartesian3.subtract(positions[1], positions[0], new Cesium.Cartesian3())
+          const v2 = Cesium.Cartesian3.subtract(positions[2], positions[1], new Cesium.Cartesian3())
+          normal = Cesium.Cartesian3.normalize(Cesium.Cartesian3.cross(v1, v2, new Cesium.Cartesian3()), new Cesium.Cartesian3())
+        }
+        const plane = Cesium.Plane.fromPointNormal(centerPoint, normal)
+        const p = Cesium.IntersectionTests.rayPlane(ray, plane); if (!p) return false
+        this.state.edgeIndex = self._closestEdgeIndex(p, positions)
+        this.state.plane = plane
+        this.state.lastPoint = p
+        this.state.isDragging = true
+        return true
+      }
+      updateEdgeDrag (mousePosition) {
+        if (!this.state.isDragging || !this.state.plane) return null
+        const ray = self.viewer.camera.getPickRay(mousePosition); if (!ray) return null
+        const p = Cesium.IntersectionTests.rayPlane(ray, this.state.plane); if (!p) return null
+        const delta = Cesium.Cartesian3.subtract(p, this.state.lastPoint, new Cesium.Cartesian3())
+        this.state.lastPoint = p
+        return delta
+      }
+      endEdgeDrag () { this.state = { isDragging: false, plane: null, lastPoint: null, edgeIndex: 0 } }
+    }
+    return new EdgeDragController()
+  }
 }
\ No newline at end of file

--
Gitblit v1.9.3