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) }) }