<template>
|
<div class="custom-panel">
|
<div class="panel-content">
|
<!-- 开挖深度设置 -->
|
<el-form :model="form" label-width="80px">
|
<el-form-item label="请注意:">
|
<p>1、右击结束最后一个点 2、请按照同向顺序开挖</p>
|
</el-form-item>
|
<el-form-item label="开挖深度">
|
<el-input v-model="form.digDepth" placeholder="请输入开挖深度(m)" />
|
</el-form-item>
|
</el-form>
|
<!-- 按钮区域 -->
|
<div class="button-group">
|
<el-button type="primary" @click="handleDraw">绘制</el-button>
|
<el-button type="success" @click="handleConfirm">确认</el-button>
|
<el-button type="danger" @click="handleClear">清除</el-button>
|
</div>
|
</div>
|
</div>
|
</template>
|
|
<script setup>
|
import { ref, reactive, watch, defineEmits } from 'vue';
|
import { ElForm, ElFormItem, ElInput, ElButton, ElMessage } from 'element-plus';
|
const emit = defineEmits(['update-excavation-data']);
|
const form = reactive({
|
digDepth: '100'
|
});
|
let excavationInstance = null;
|
const currentPoints = reactive([]);
|
const isDrawing = ref(false);
|
let clickHandler = null;
|
const handleDraw = () => {
|
if (!window.viewer) {
|
console.error('Cesium Viewer 尚未初始化');
|
return;
|
}
|
|
const viewer = window.viewer;
|
|
// 清空之前的数据
|
currentPoints.splice(0, currentPoints.length);
|
isDrawing.value = true;
|
|
// 销毁旧的监听器
|
if (clickHandler) {
|
clickHandler.destroy();
|
}
|
|
// 立即创建开挖对象(不依赖初始点)
|
createExcavation();
|
|
// 开始监听点击事件
|
clickHandler = new Cesium.ScreenSpaceEventHandler(viewer.scene.canvas);
|
|
// 左击添加点
|
clickHandler.setInputAction((movement) => {
|
const cartesian = viewer.camera.pickEllipsoid(movement.position, viewer.scene.globe.ellipsoid);
|
if (cartesian) {
|
currentPoints.push(cartesian.clone());
|
}
|
}, Cesium.ScreenSpaceEventType.LEFT_CLICK);
|
|
// 右击结束绘制并保存最后一个点
|
clickHandler.setInputAction((movement) => {
|
const cartesian = viewer.camera.pickEllipsoid(movement.position, viewer.scene.globe.ellipsoid);
|
if (cartesian) {
|
currentPoints.push(cartesian.clone()); // 添加最后一个右击点
|
}
|
handleConfirm(); // 自动调用确认
|
}, Cesium.ScreenSpaceEventType.RIGHT_CLICK);
|
};
|
|
const createExcavation = () => {
|
const depth = parseFloat(form.digDepth);
|
if (!isNaN(depth)) {
|
excavationInstance = window.earthCtrl.analysis.createTerrainExcavation({
|
height: depth,
|
callback: function (a) {
|
},
|
});
|
}else{
|
ElMessage.warning('请输入有效的开挖深度!');
|
}
|
};
|
|
watch(
|
() => form.digDepth,
|
(newVal) => {
|
const num = parseFloat(newVal);
|
if (!isNaN(num) && excavationInstance) {
|
excavationInstance.setDeepth?.(num);
|
}
|
}
|
);
|
// 点击确认按钮(打印当前坐标点集合和深度)
|
const handleConfirm = () => {
|
if (currentPoints.length < 3) {
|
ElMessage.warning('请至少选择三个坐标点以构成多边形!');
|
return;
|
}
|
|
const depth = parseFloat(form.digDepth);
|
|
// 第一步:将笛卡尔坐标转为 [经度, 纬度] 数组
|
let coords = currentPoints.map(point => {
|
const cartographic = Cesium.Cartographic.fromCartesian(point);
|
const lon = Cesium.Math.toDegrees(cartographic.longitude).toFixed(6); // 经度
|
const lat = Cesium.Math.toDegrees(cartographic.latitude).toFixed(6); // 纬度
|
return [parseFloat(lon), parseFloat(lat)];
|
});
|
|
// 第二步:闭合多边形(如果首尾点不一致)
|
if (coords.length > 0 && (coords[0][0] !== coords[coords.length - 1][0] || coords[0][1] !== coords[coords.length - 1][1])) {
|
coords.push([...coords[0]]); // 添加第一个点到末尾
|
}
|
|
// 第三步:构造 WKT POLYGON 格式
|
const pointsStr = coords.map(p => p.join(' ')).join(', ');
|
const wkt = `POLYGON ((${pointsStr}))`;
|
|
// console.log(wkt);
|
|
// 第四步:构建返回结果
|
const result = {
|
geom: wkt,
|
depth: depth
|
};
|
console.log(result,'确认时,产生的地形修改数据');
|
|
emit('update-excavation-data', result);
|
ElMessage.success('实现开挖功能!');
|
};
|
const handleClear = () => {
|
isDrawing.value = false;
|
// 销毁点击事件监听器
|
if (clickHandler) {
|
clickHandler.destroy();
|
clickHandler = null;
|
}
|
// 清空临时点
|
currentPoints.splice(0, currentPoints.length);
|
// 移除开挖对象
|
if (excavationInstance) {
|
excavationInstance.removeFromMap?.();
|
excavationInstance = null;
|
}
|
};
|
</script>
|
|
<style scoped>
|
.custom-panel {
|
padding: 20px;
|
width: 290px;
|
background: url("@/assets/img/tools/plotting_new.png") no-repeat;
|
filter: opacity(83%);
|
background-size: 100% 100%;
|
box-sizing: border-box;
|
}
|
|
.panel-content {
|
display: flex;
|
flex-direction: column;
|
}
|
|
.button-group {
|
display: flex;
|
justify-content: space-around;
|
}
|
</style>
|