517 lines
14 KiB
TypeScript
517 lines
14 KiB
TypeScript
// src/composables/useDrawingManager.ts
|
||
import { ref, reactive,watch} from 'vue';
|
||
import type { DrawingTool, DrawingResult, DrawingInfo, DrawingOptions, CircleOptions, PolygonOptions } from './DrawingTool';
|
||
|
||
export function useDrawingManager(drawingTool: any) { // 修改参数类型为 any 或 Ref<DrawingTool | null>
|
||
const isDrawing = ref(false);
|
||
const currentDrawingType = ref<'circle' | 'polygon' | null>(null);
|
||
const drawings = reactive(new Map<string, DrawingResult>());
|
||
const selectedDrawing = ref<string | null>(null);
|
||
const drawingInfo = ref<DrawingInfo | null>(null);
|
||
|
||
// 绘图选项
|
||
const drawingOptions = reactive<{
|
||
circle: CircleOptions;
|
||
polygon: PolygonOptions;
|
||
}>({
|
||
circle: {
|
||
color: Cesium.Color.YELLOW.withAlpha(0.3),
|
||
outlineColor: Cesium.Color.YELLOW,
|
||
outlineWidth: 2,
|
||
fill: true,
|
||
height: 0,
|
||
extrudedHeight: 1000
|
||
},
|
||
polygon: {
|
||
color: Cesium.Color.CYAN.withAlpha(0.3),
|
||
outlineColor: Cesium.Color.CYAN,
|
||
outlineWidth: 2,
|
||
fill: true,
|
||
height: 0,
|
||
extrudedHeight: 1000,
|
||
closePath: true
|
||
}
|
||
});
|
||
|
||
// // 初始化点击回调 - 使用 watch 来确保 drawingTool 已初始化
|
||
// import { watch } from 'vue';
|
||
|
||
watch(() => drawingTool?.value, (newTool) => {
|
||
if (newTool) {
|
||
newTool.setCallbacks({
|
||
onClick: (result: DrawingResult, info: DrawingInfo) => {
|
||
handleDrawingClick(result, info);
|
||
}
|
||
});
|
||
}
|
||
}, { immediate: true });
|
||
|
||
// 处理绘图点击
|
||
const handleDrawingClick = (result: DrawingResult, info: DrawingInfo): void => {
|
||
selectedDrawing.value = result.id;
|
||
drawingInfo.value = info;
|
||
|
||
// 高亮显示
|
||
if (drawingTool?.value) {
|
||
drawingTool.value.highlightDrawing(result.id, true);
|
||
}
|
||
|
||
console.log('Drawing clicked:', info);
|
||
};
|
||
|
||
// 开始绘制圆形
|
||
const startCircleDrawing = (): void => {
|
||
const tool = drawingTool?.value;
|
||
if (!tool) return;
|
||
|
||
tool.setCallbacks({
|
||
onStart: () => {
|
||
isDrawing.value = true;
|
||
currentDrawingType.value = 'circle';
|
||
drawingInfo.value = null;
|
||
},
|
||
onComplete: (result: DrawingResult) => {
|
||
isDrawing.value = false;
|
||
currentDrawingType.value = null;
|
||
drawings.set(result.id, result);
|
||
selectedDrawing.value = result.id;
|
||
drawingInfo.value = result.info;
|
||
},
|
||
onCancel: () => {
|
||
isDrawing.value = false;
|
||
currentDrawingType.value = null;
|
||
},
|
||
onClick: (result: DrawingResult, info: DrawingInfo) => {
|
||
handleDrawingClick(result, info);
|
||
}
|
||
});
|
||
|
||
tool.startDrawingCircle(drawingOptions.circle);
|
||
};
|
||
|
||
// 开始绘制多边形
|
||
const startPolygonDrawing = (): void => {
|
||
const tool = drawingTool?.value;
|
||
if (!tool) return;
|
||
|
||
tool.setCallbacks({
|
||
onStart: () => {
|
||
isDrawing.value = true;
|
||
currentDrawingType.value = 'polygon';
|
||
drawingInfo.value = null;
|
||
},
|
||
onComplete: (result: DrawingResult) => {
|
||
isDrawing.value = false;
|
||
currentDrawingType.value = null;
|
||
drawings.set(result.id, result);
|
||
selectedDrawing.value = result.id;
|
||
drawingInfo.value = result.info;
|
||
},
|
||
onCancel: () => {
|
||
isDrawing.value = false;
|
||
currentDrawingType.value = null;
|
||
},
|
||
onClick: (result: DrawingResult, info: DrawingInfo) => {
|
||
handleDrawingClick(result, info);
|
||
}
|
||
});
|
||
|
||
tool.startDrawingPolygon(drawingOptions.polygon);
|
||
};
|
||
|
||
// 取消绘制
|
||
const cancelDrawing = (): void => {
|
||
const tool = drawingTool?.value;
|
||
if (tool) {
|
||
tool.cancelDrawing();
|
||
isDrawing.value = false;
|
||
currentDrawingType.value = null;
|
||
}
|
||
};
|
||
|
||
// 选择图形
|
||
const selectDrawing = (id: string): void => {
|
||
const tool = drawingTool?.value;
|
||
if (selectedDrawing.value === id) {
|
||
deselectDrawing();
|
||
return;
|
||
}
|
||
|
||
if (selectedDrawing.value && tool) {
|
||
tool.highlightDrawing(selectedDrawing.value, false);
|
||
}
|
||
|
||
selectedDrawing.value = id;
|
||
const drawing = drawings.get(id);
|
||
if (drawing && tool) {
|
||
tool.highlightDrawing(id, true);
|
||
drawingInfo.value = drawing.info;
|
||
}
|
||
};
|
||
|
||
// 取消选择
|
||
const deselectDrawing = (): void => {
|
||
const tool = drawingTool?.value;
|
||
if (selectedDrawing.value && tool) {
|
||
tool.highlightDrawing(selectedDrawing.value, false);
|
||
}
|
||
selectedDrawing.value = null;
|
||
drawingInfo.value = null;
|
||
};
|
||
|
||
// 移除图形
|
||
const removeDrawing = (id: string): void => {
|
||
const tool = drawingTool?.value;
|
||
if (tool && tool.removeDrawing(id)) {
|
||
drawings.delete(id);
|
||
if (selectedDrawing.value === id) {
|
||
deselectDrawing();
|
||
}
|
||
}
|
||
};
|
||
|
||
// 清除所有图形
|
||
const clearAllDrawings = (): void => {
|
||
const tool = drawingTool?.value;
|
||
if (tool) {
|
||
tool.clearAllDrawings();
|
||
drawings.clear();
|
||
deselectDrawing();
|
||
}
|
||
};
|
||
|
||
// 飞向图形
|
||
// const flyToDrawing = (id: string): void => {
|
||
// const tool = drawingTool?.value;
|
||
// if (tool) {
|
||
// tool.flyToDrawing(id);
|
||
// }
|
||
// };
|
||
|
||
/**
|
||
* 飞向图形
|
||
*/
|
||
const flyToDrawing = (id: string): void => {
|
||
const tool = getTool();
|
||
console.log('=== flyToDrawing 被调用 ===');
|
||
console.log('目标ID:', id);
|
||
console.log('工具是否存在:', !!tool);
|
||
console.log('空域是否存在:', drawings.has(id));
|
||
|
||
if (!tool) {
|
||
console.error('❌ 绘图工具未初始化');
|
||
return;
|
||
}
|
||
|
||
if (!drawings.has(id)) {
|
||
console.error('❌ 空域不存在:', id);
|
||
return;
|
||
}
|
||
|
||
console.log('✅ 开始执行飞向操作...');
|
||
|
||
// 尝试不同的飞向方法
|
||
try {
|
||
// 方法1: 使用改进版本
|
||
tool.flyToDrawingImproved(id, 2);
|
||
|
||
// 或者方法2: 使用简单版本
|
||
// tool.flyToDrawingSimple(id, 2);
|
||
|
||
// 或者方法3: 使用原始版本
|
||
// tool.flyToDrawing(id, 2);
|
||
|
||
} catch (error) {
|
||
console.error('❌ 飞向操作失败:', error);
|
||
}
|
||
};
|
||
|
||
/**
|
||
* 飞向选中空域
|
||
*/
|
||
const flyToSelectedDrawing = (): void => {
|
||
console.log('=== flyToSelectedDrawing 被调用 ===');
|
||
console.log('当前选中的空域:', selectedDrawing.value);
|
||
|
||
if (!selectedDrawing.value) {
|
||
console.error('❌ 请先选择一个空域');
|
||
return;
|
||
}
|
||
|
||
flyToDrawing(selectedDrawing.value);
|
||
};
|
||
|
||
|
||
/**
|
||
* 导出选中空域信息为文本
|
||
*/
|
||
const exportSelectedDrawingAsText = (): string => {
|
||
console.log('=== exportSelectedDrawingAsText 开始执行 ===');
|
||
const tool = getTool();
|
||
console.log('工具状态:', !!tool);
|
||
console.log('选中空域:', selectedDrawing.value);
|
||
|
||
if (!tool) {
|
||
console.error('❌ 绘图工具未初始化');
|
||
return '';
|
||
}
|
||
if (!selectedDrawing.value) {
|
||
console.error('❌ 请先选择一个空域');
|
||
return '';
|
||
}
|
||
|
||
try {
|
||
const text = tool.exportDrawingInfoAsText(selectedDrawing.value);
|
||
console.log('导出的文本内容:', text);
|
||
return text;
|
||
} catch (error) {
|
||
console.error('❌ 导出空域信息时发生错误:', error);
|
||
return '';
|
||
}
|
||
};
|
||
|
||
/**
|
||
* 导出所有空域信息
|
||
*/
|
||
const exportAllDrawingsAsText = (): string => {
|
||
console.log('=== exportAllDrawingsAsText 开始执行 ===');
|
||
const tool = getTool();
|
||
|
||
if (!tool) {
|
||
console.error('❌ 绘图工具未初始化');
|
||
return '';
|
||
}
|
||
if (drawings.size === 0) {
|
||
console.warn('⚠️ 当前没有绘制任何空域');
|
||
return '';
|
||
}
|
||
|
||
let text = `=== 空域信息汇总 (共 ${drawings.size} 个) ===\n\n`;
|
||
|
||
drawings.forEach((drawing, id) => {
|
||
try {
|
||
const drawingText = tool.exportDrawingInfoAsText(id);
|
||
text += drawingText + '\n\n' + '='.repeat(50) + '\n\n';
|
||
} catch (error) {
|
||
console.error(`导出空域 ${id} 时发生错误:`, error);
|
||
text += `空域 ${id} 导出失败\n\n` + '='.repeat(50) + '\n\n';
|
||
}
|
||
});
|
||
|
||
console.log('导出的所有空域文本内容:', text);
|
||
return text;
|
||
};
|
||
|
||
// 更新绘图选项
|
||
const updateDrawingOptions = (type: 'circle' | 'polygon', options: Partial<DrawingOptions>): void => {
|
||
drawingOptions[type] = { ...drawingOptions[type], ...options };
|
||
};
|
||
|
||
// 导出图形数据
|
||
const exportDrawings = (): any[] => {
|
||
const tool = drawingTool?.value;
|
||
if (tool) {
|
||
return tool.exportDrawings();
|
||
}
|
||
return [];
|
||
};
|
||
|
||
// 导入图形数据
|
||
const importDrawings = (data: any[]): void => {
|
||
const tool = drawingTool?.value;
|
||
if (tool) {
|
||
tool.importDrawings(data);
|
||
data.forEach(item => {
|
||
drawings.set(item.id, item as DrawingResult);
|
||
});
|
||
}
|
||
};
|
||
|
||
// 获取绘图状态文本
|
||
const getDrawingStatus = (): string => {
|
||
if (!isDrawing.value) return '准备就绪';
|
||
|
||
if (currentDrawingType.value === 'circle') {
|
||
return '绘制圆形: 点击确定圆心,再次点击确定半径,右键完成';
|
||
} else if (currentDrawingType.value === 'polygon') {
|
||
return '绘制多边形: 点击添加顶点,右键完成绘制,ESC取消';
|
||
}
|
||
|
||
return '绘制中...';
|
||
};
|
||
|
||
// 格式化坐标显示
|
||
const formatCoordinate = (coord: { longitude: number; latitude: number; height: number }): string => {
|
||
return `经度: ${coord.longitude.toFixed(6)}\n纬度: ${coord.latitude.toFixed(6)}\n高程: ${coord.height.toFixed(2)}米`;
|
||
};
|
||
|
||
// 获取绘图信息显示文本
|
||
const getDrawingInfoText = (): string => {
|
||
if (!drawingInfo.value) return '';
|
||
|
||
const info = drawingInfo.value;
|
||
|
||
if (info.type === 'circle') {
|
||
const center = info.properties.center;
|
||
return `⭕ 圆形空域信息\n\n` +
|
||
`📍 圆心坐标:\n${formatCoordinate(center)}\n\n` +
|
||
`📏 半径: ${(info.radius! / 1000).toFixed(3)} km\n` +
|
||
`📐 直径: ${(info.radius! * 2 / 1000).toFixed(3)} km\n` +
|
||
`🔄 周长: ${(info.properties.circumference / 1000).toFixed(3)} km\n` +
|
||
`📊 面积: ${(info.area / 1000000).toFixed(3)} km²`;
|
||
} else {
|
||
const bounds = info.properties.bounds;
|
||
const center = info.properties.center;
|
||
const boundaryPoints = info.properties.boundaryPoints;
|
||
|
||
let text = `🔷 多边形空域信息\n\n` +
|
||
`📍 中心点:\n${formatCoordinate(center)}\n\n` +
|
||
`🗺️ 边界范围:\n` +
|
||
`北: ${bounds.north.toFixed(6)}\n` +
|
||
`南: ${bounds.south.toFixed(6)}\n` +
|
||
`东: ${bounds.east.toFixed(6)}\n` +
|
||
`西: ${bounds.west.toFixed(6)}\n\n` +
|
||
`📏 尺寸:\n` +
|
||
`宽度: ${(info.properties.width / 1000).toFixed(3)} km\n` +
|
||
`高度: ${(info.properties.height / 1000).toFixed(3)} km\n` +
|
||
`周长: ${(info.properties.perimeter / 1000).toFixed(3)} km\n` +
|
||
`面积: ${(info.area / 1000000).toFixed(3)} km²\n\n` +
|
||
`📍 边界顶点 (${boundaryPoints.length}个):\n`;
|
||
|
||
// 添加前几个顶点信息,避免信息过长
|
||
boundaryPoints.slice(0, 6).forEach((point, index) => {
|
||
text += `顶点${index + 1}: ${point.longitude.toFixed(6)}, ${point.latitude.toFixed(6)}\n`;
|
||
});
|
||
|
||
if (boundaryPoints.length > 6) {
|
||
text += `... 还有 ${boundaryPoints.length - 6} 个顶点`;
|
||
}
|
||
|
||
return text;
|
||
}
|
||
};
|
||
|
||
|
||
const printSelectedDrawingInfo = (): void => {
|
||
console.log('printSelectedDrawingInfo 被调用');
|
||
console.log('drawingTool:', drawingTool);
|
||
console.log('selectedDrawing:', selectedDrawing.value);
|
||
|
||
const tool = getTool();
|
||
if (!tool) {
|
||
console.error('绘图工具未找到');
|
||
return;
|
||
}
|
||
if (!selectedDrawing.value) {
|
||
console.error('没有选中的空域');
|
||
return;
|
||
}
|
||
|
||
console.log('开始打印空域信息...');
|
||
tool.printDrawingInfo(selectedDrawing.value);
|
||
};
|
||
|
||
|
||
/**
|
||
* 打印选中空域信息
|
||
*/
|
||
// const printSelectedDrawingInfo = (): void => {
|
||
// const tool = getTool();
|
||
// if (!tool || !selectedDrawing.value) {
|
||
// console.warn('请先选择一个空域');
|
||
// return;
|
||
// }
|
||
// console.log('=== 打印选中空域信息 ===');
|
||
// tool.printDrawingInfo(selectedDrawing.value);
|
||
// };
|
||
|
||
// 辅助函数:安全地访问 drawingTool
|
||
const getTool = () => {
|
||
return drawingTool?.value;
|
||
};
|
||
|
||
/**
|
||
* 打印所有空域信息
|
||
*/
|
||
const printAllDrawingsInfo = (): void => {
|
||
const tool = getTool();
|
||
if (!tool) {
|
||
console.warn('绘图工具未初始化');
|
||
return;
|
||
}
|
||
console.log('=== 打印所有空域信息 ===');
|
||
tool.printAllDrawingsInfo();
|
||
};
|
||
|
||
/**
|
||
* 打印指定空域信息
|
||
*/
|
||
const printDrawingInfo = (id: string): void => {
|
||
const tool = getTool();
|
||
if (!tool) {
|
||
console.warn('绘图工具未初始化');
|
||
return;
|
||
}
|
||
console.log(`=== 打印空域信息: ${id} ===`);
|
||
tool.printDrawingInfo(id);
|
||
};
|
||
|
||
/**
|
||
* 获取选中空域的JSON信息
|
||
*/
|
||
const getSelectedDrawingJSON = (): any => {
|
||
const tool = getTool();
|
||
if (!tool || !selectedDrawing.value) return null;
|
||
return tool.getDrawingInfoJSON(selectedDrawing.value);
|
||
};
|
||
|
||
/**
|
||
* 获取所有空域的JSON信息
|
||
*/
|
||
const getAllDrawingsJSON = (): any[] => {
|
||
const tool = getTool();
|
||
if (!tool) return [];
|
||
return tool.getAllDrawingsInfoJSON();
|
||
};
|
||
|
||
/**
|
||
* 导出选中空域信息为文本
|
||
*/
|
||
// const exportSelectedDrawingAsText = (): string => {
|
||
// const tool = getTool();
|
||
// if (!tool || !selectedDrawing.value) return '';
|
||
// return tool.exportDrawingInfoAsText(selectedDrawing.value);
|
||
// };
|
||
|
||
|
||
return {
|
||
isDrawing,
|
||
currentDrawingType,
|
||
drawings,
|
||
selectedDrawing,
|
||
drawingInfo,
|
||
drawingOptions,
|
||
startCircleDrawing,
|
||
startPolygonDrawing,
|
||
cancelDrawing,
|
||
selectDrawing,
|
||
deselectDrawing,
|
||
removeDrawing,
|
||
clearAllDrawings,
|
||
flyToDrawing,
|
||
updateDrawingOptions,
|
||
exportDrawings,
|
||
importDrawings,
|
||
getDrawingStatus,
|
||
getDrawingInfoText,
|
||
formatCoordinate,
|
||
// 新增的打印方法
|
||
printSelectedDrawingInfo,
|
||
printAllDrawingsInfo,
|
||
printDrawingInfo,
|
||
getSelectedDrawingJSON,
|
||
getAllDrawingsJSON,
|
||
exportSelectedDrawingAsText,
|
||
flyToSelectedDrawing
|
||
};
|
||
}
|