| | |
| | | * - 外部订阅/通知机制 |
| | | */ |
| | | export class DrawPolygon { |
| | | constructor() { |
| | | constructor(options = {}) { |
| | | // 设备覆盖范围列表(经纬度 + 5000m半径) |
| | | this.deviceList = options.deviceList || [] |
| | | this.coverageRadius = 5000 |
| | | // 图斑预览模式标记 |
| | | this.isPureSpotPreview = false |
| | | // 是否删除测区 |
| | |
| | | this.handleLeftUp = this.handleLeftUp.bind(this) |
| | | this.handleMouseMove = this.handleMouseMove.bind(this) |
| | | this.handleLeftClick = this.handleLeftClick.bind(this) |
| | | this.handleDoubleClick = this.handleDoubleClick.bind(this) |
| | | this.handleRightClick = this.handleRightClick.bind(this) |
| | | |
| | | this.delPolygon = this.delPolygon.bind(this) |
| | |
| | | this.listeners = [] |
| | | // 绘制提示 tooltip |
| | | this.drawingTooltip = null |
| | | // 防止双击时第二次点击添加重复的点 |
| | | this._lastClickTime = 0 |
| | | } |
| | | |
| | | // 实体命名常量 |
| | |
| | | // 开始绘制 |
| | | startDrawing() { |
| | | this.drawingMode = true |
| | | this._lastClickTime = 0 |
| | | this.curPolygon = new Cesium.PolygonHierarchy() |
| | | |
| | | // 如果还没有 DataSource,就新建一个 |
| | |
| | | handleLeftUp() { |
| | | if (!(this.editingMode && this.curPolygon?.positions && this.draggedEntity)) return |
| | | |
| | | // 检查松手位置是否在设备覆盖范围内 |
| | | if (this.isDragging && !this.isWithinDeviceCoverage(this.curPolygon.positions[this.draggedEntity?.customData.ind])) { |
| | | ElMessage.warning('该位置不在设备覆盖范围内,请在设备5公里范围内绘制') |
| | | // 回弹到拖拽前的位置 |
| | | this.draggedEntity.position = this.currentDragPointPosition |
| | | this.curPolygon.positions[this.draggedEntity?.customData.ind] = this.currentDragPointPosition |
| | | this.isDragging = false |
| | | this.draggedEntity = null |
| | | this.enableMapControl() |
| | | this.rebuildMidPoints() |
| | | return |
| | | } |
| | | |
| | | if (this.currentDragPointIsValid && this.isDragging) { |
| | | // 更新点位置 |
| | | this.draggedEntity.position = this.currentDragPointPosition |
| | |
| | | return |
| | | } |
| | | |
| | | // 防止双击时第二次点击添加重复的点(双击触发顺序:click → click → dblclick) |
| | | const now = Date.now() |
| | | if (this._lastClickTime && (now - this._lastClickTime) < 300) { |
| | | return |
| | | } |
| | | this._lastClickTime = now |
| | | |
| | | // 添加新的点 |
| | | const cartesian = this.viewer.scene.pickPosition(click.position) |
| | | if (!cartesian) return |
| | | |
| | | // 检查点击位置是否在设备覆盖范围内 |
| | | if (!this.isWithinDeviceCoverage(cartesian)) { |
| | | ElMessage.warning('该位置不在设备覆盖范围内,请在设备5公里范围内绘制') |
| | | return |
| | | } |
| | | |
| | | let arr = [...this.curPolygon.positions] |
| | | arr.pop() |
| | |
| | | } |
| | | |
| | | this.addPosition(cartesian) |
| | | } |
| | | |
| | | // 鼠标双击(完成绘制) |
| | | handleDoubleClick() { |
| | | if (!this.drawingMode) return |
| | | // 双击时第一次 LEFT_CLICK 已经添加了一个点,所以至少需要 4 个点(3个有效点 + 1个跟踪点) |
| | | if (this.curPolygon.positions.length < 4) return |
| | | this.finishDrawing() |
| | | } |
| | | |
| | | // 鼠标右键点击(弹出菜单) |
| | |
| | | |
| | | const menuItems = |
| | | type === 'polygon' |
| | | ? [{ title: '删除测区', class: 'del-planar-polygon' }] |
| | | ? [{ title: '删除范围', class: 'del-planar-polygon' }] |
| | | : [{ title: '删除端点', class: 'del-planar-point' }] |
| | | |
| | | menuItems.forEach(item => { |
| | |
| | | const intersections = turf.kinks(poly) |
| | | |
| | | return intersections.features.length === 0 |
| | | } |
| | | |
| | | // 检查位置是否在任意设备的覆盖范围内(5km) |
| | | isWithinDeviceCoverage(cartesian) { |
| | | if (!this.deviceList || this.deviceList.length === 0) return true |
| | | const cartographic = Cesium.Cartographic.fromCartesian(cartesian) |
| | | const clickPoint = turf.point([Cesium.Math.toDegrees(cartographic.longitude), Cesium.Math.toDegrees(cartographic.latitude)]) |
| | | return this.deviceList |
| | | .filter(item => item.latitude) |
| | | .some(item => { |
| | | const rangePoint = turf.point([item.longitude, item.latitude]) |
| | | const distance = turf.distance(rangePoint, clickPoint, { units: 'kilometers' }) |
| | | return distance <= 5 |
| | | }) |
| | | } |
| | | // 初始化已有多边形 |
| | | async initPolygon(viewer, positions, isPurePreview = false) { |
| | |
| | | [Cesium.ScreenSpaceEventType.LEFT_UP, this.handleLeftUp], |
| | | [Cesium.ScreenSpaceEventType.MOUSE_MOVE, this.handleMouseMove], |
| | | [Cesium.ScreenSpaceEventType.LEFT_CLICK, this.handleLeftClick], |
| | | [Cesium.ScreenSpaceEventType.LEFT_DOUBLE_CLICK, this.handleDoubleClick], |
| | | [Cesium.ScreenSpaceEventType.RIGHT_CLICK, this.handleRightClick], |
| | | ] |
| | | |
| | |
| | | Cesium.ScreenSpaceEventType.LEFT_UP, |
| | | Cesium.ScreenSpaceEventType.MOUSE_MOVE, |
| | | Cesium.ScreenSpaceEventType.LEFT_CLICK, |
| | | Cesium.ScreenSpaceEventType.LEFT_DOUBLE_CLICK, |
| | | Cesium.ScreenSpaceEventType.RIGHT_CLICK, |
| | | ] |
| | | |