tcctyn-ui/src/components/CesiumMap/mixins/useDrawTool/drawCurvePolygon.js

133 lines
4.1 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import {
Cartesian3,
Entity,
CallbackProperty,
Color as CesiumColor,
ScreenSpaceEventType,
PolygonHierarchy,
HeightReference,
} from 'cesium'
import { createCurvePolygonPositions } from './draw/curvePolygonGraphic'
/**
* 绘制多边形的具体逻辑
* @param deps 绘制所需的依赖
* @returns Promise 绘制完成的所有点坐标数组
*/
export const drawCurvePolygon = (deps) => {
const { viewer, bus, position, status, registerAbort, globalAbort } = deps
// 如果在执行其它操作,则取消
globalAbort()
status.value = 'Drawing'
const featurePositions = []
// 临时多边形实体 (包含填充和边界线)
const tempPolygon = new Entity({
name: '__draw_temp_curve_polygon',
polygon: {
hierarchy: new CallbackProperty(() => {
const positions = [...featurePositions]
// 添加当前鼠标位置作为最后一个点,形成动态效果
if (
position.value &&
!position.value.equals(featurePositions[featurePositions.length - 1]) // 避免重复添加同一个点
) {
positions.push(position.value)
}
// 曲面需要至少2个点才能形成
if (positions.length < 2) {
return null
}
return new PolygonHierarchy(createCurvePolygonPositions(positions))
}, false),
heightReference: HeightReference.CLAMP_TO_GROUND,
material: CesiumColor.fromCssColorString('#ff0000').withAlpha(0.3),
},
// 绘制边界线,连接所有点和第一个点,形成闭合效果
polyline: {
positions: new CallbackProperty(() => {
const positions = [...featurePositions]
// 添加当前鼠标位置作为最后一个点
if (
position.value &&
!position.value.equals(featurePositions[featurePositions.length - 1])
) {
positions.push(position.value)
}
// 曲面需要至少2个点才能形成
if (positions.length < 2) {
return null
}
return createCurvePolygonPositions(positions)
}, false),
clampToGround: true,
width: 2,
material: CesiumColor.fromCssColorString('#ff0000'),
},
})
viewer.entities.add(tempPolygon)
return new Promise((resolve, reject) => {
// 清理资源
const dispose = () => {
registerAbort(null) // 取消注册当前的 abort 回调
status.value = 'Default'
viewer.entities.remove(tempPolygon)
bus.offScreen(ScreenSpaceEventType.LEFT_CLICK, handleAddPoint)
bus.offScreen(ScreenSpaceEventType.RIGHT_CLICK, handleCancelDraw)
bus.offScreen(ScreenSpaceEventType.LEFT_DOUBLE_CLICK, handleEndDraw)
}
// 取消绘制
const abort = (info) => {
dispose()
reject(info || '取消曲面绘制!')
}
// 左键加点
const handleAddPoint = () => {
if (position.value && !position.value.equals(featurePositions[featurePositions.length - 1])) {
featurePositions.push(position.value)
}
}
// 左键双击完成绘制
const handleEndDraw = () => {
// 双击时,如果鼠标位置与最后一个点不同,先添加当前点
handleAddPoint()
if (featurePositions.length < 2) {
// TODO: 替换为实际的错误提示方式
console.error('请保曲面至少有2个特征点')
return
}
dispose()
// 使用 setTimeout 避免立即 resolve 可能导致的事件冲突或其他问题
setTimeout(() => {
resolve(featurePositions)
}, 0)
}
// 右键取消绘制或删除最后一个点
const handleCancelDraw = () => {
if (featurePositions.length > 0) {
// 取消最后绘制的点
featurePositions.pop()
} else {
// 如果没有点,则取消整个绘制
abort()
}
}
// 注册当前的取消回调
registerAbort(abort)
// 绑定绘制相关事件
bus.onScreen(ScreenSpaceEventType.LEFT_CLICK, handleAddPoint)
bus.onScreen(ScreenSpaceEventType.RIGHT_CLICK, handleCancelDraw)
bus.onScreen(ScreenSpaceEventType.LEFT_DOUBLE_CLICK, handleEndDraw)
})
}