一些技术路线测试,增加git,方便代码还原
shuishen
2025-11-24 37539b33023be5231f51c3f4d13ab477877ee9c4
feat:编辑模式等相关处理
2 files modified
130 ■■■■■ changed files
js/modules/axis-manager.js 119 ●●●●● patch | view | raw | blame | history
js/modules/edit-manager.js 11 ●●●●● patch | view | raw | blame | history
js/modules/axis-manager.js
@@ -36,6 +36,7 @@
    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' }
@@ -68,11 +69,14 @@
    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)
  }
  /**
@@ -83,6 +87,9 @@
    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
    }
  }
  /**
@@ -222,6 +229,7 @@
    } else {
      this.setControllerVisibility(this.editingEnabled)
    }
    this.setPolygonOutlineVisibility(this.editingEnabled)
  }
  /**
@@ -299,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)
  }
  /**
@@ -372,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)
@@ -383,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.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; 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) => {
@@ -403,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)
@@ -433,6 +461,7 @@
        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)
@@ -499,6 +528,7 @@
    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))
@@ -515,6 +545,14 @@
        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++) {
@@ -524,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)
@@ -618,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) {
@@ -831,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()
  }
}
js/modules/edit-manager.js
@@ -4,6 +4,10 @@
    this.entityFactory = entityFactory
    this.eventHub = eventHub
    this.labelManager = labelManager
    this.enableCornerDrag = false
    // 后续开启方式:如需恢复顶点拖拽控制点,在外层调用
    // editManager.setCornerDragEnabled(true)
    // 保持现有逻辑不变,避免再次修改核心代码
  }
  computeCenter (positions) {
@@ -74,11 +78,12 @@
    }, Cesium.ScreenSpaceEventType.LEFT_CLICK)
    editTriggerHandler.setInputAction((click) => {
      this.entityFactory.removeEntityLikeName('polygonEditPoint')
      if (!this.enableCornerDrag) return
      if (!isActivateEditRef.value) return
      const pickC = viewer.scene.pick(click.position)
      const rid = pickC && (pickC.id?.id || pickC.id || pickC.primitive?.id)
      if (String(rid) !== 'polygon') return
      this.entityFactory.removeEntityLikeName('polygonEditPoint')
      const positions = polygonPositionListRef.value
      positions.forEach((ele, index) => {
        viewer.entities.add({ name: 'polygonEditPoint', id: 'point' + index, position: ele, point: { color: new Cesium.Color(0, 1, 1, 0.9), pixelSize: 10 } })
@@ -124,4 +129,8 @@
      }, Cesium.ScreenSpaceEventType.LEFT_DOWN)
    }, Cesium.ScreenSpaceEventType.LEFT_CLICK)
  }
  // 开启/关闭顶点拖拽控制点(外层调用)
  // 使用方式:editManager.setCornerDragEnabled(true)
  setCornerDragEnabled (flag) { this.enableCornerDrag = !!flag }
}