| | |
| | | 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' } |
| | |
| | | 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) |
| | | } |
| | | |
| | | /** |
| | |
| | | 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 |
| | | } |
| | | } |
| | | |
| | | /** |
| | |
| | | } else { |
| | | this.setControllerVisibility(this.editingEnabled) |
| | | } |
| | | this.setPolygonOutlineVisibility(this.editingEnabled) |
| | | } |
| | | |
| | | /** |
| | |
| | | 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) |
| | | } |
| | | |
| | | /** |
| | |
| | | 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) |
| | |
| | | |
| | | 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) => { |
| | |
| | | } 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) |
| | | |
| | |
| | | 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) |
| | |
| | | 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)) |
| | |
| | | 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++) { |
| | |
| | | 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) |
| | |
| | | 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) { |
| | |
| | | } |
| | | 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() |
| | | } |
| | | } |