<template>
|
<div style="display: flex; justify-content: space-between;">
|
<!-- 第一个按钮:选取断面点 -->
|
<el-tooltip placement="top" show-after="1000">
|
<template #content>
|
断面分析功能说明:
|
<br /><br />
|
🔹 点击按钮切换状态:
|
<br />
|
- 白色:关闭拾取功能(不可选点)
|
<br />
|
- 黄色:开启拾取功能(可点击地图选择2个断面点)
|
<br /><br />
|
🔹 使用流程:
|
<br />
|
1. 点击按钮切换为黄色 ➜ 开始拾取坐标点
|
<br />
|
2. 在地图上点击选择 2 个断面点(如需修改,可重新点击)
|
<br /><br />
|
⚠️ 温馨提示:
|
<br />
|
每次只能分析一条沟渠的断面,多个断面可能导致计算异常;
|
<br />
|
使用完毕请将按钮切回白色,避免影响其他功能。
|
</template>
|
<div @click="initPickHandler" :class="{ active: isPicking }">
|
<img v-if="!isPicking" src="@/assets/img/timeline/断面.png" style="width: 26px;height: 26px;" />
|
<img v-else src="@/assets/img/timeline/已断面.png" style="width: 26px;height: 26px;" />
|
</div>
|
</el-tooltip>
|
|
<!-- 第二个按钮:上传并分析断面 -->
|
<el-tooltip placement="top" show-after="1000">
|
<template #content>
|
上传并分析断面数据:
|
<br /><br />
|
📌 条件限制:
|
<br />
|
仅当成功选择 2 个断面点后才可点击
|
<br /><br />
|
🔁 功能说明:
|
<br />
|
点击后将对当前断面进行分析,稍等片刻即可在图表区域查看结果
|
<br /><br />
|
⚠️ 注意事项:
|
<br />
|
该功能仅支持单条沟渠分析,多个断面可能导致计算不稳定或出错
|
</template>
|
<div @click="confirmPoints" :class="{ disabled: !isReadyForUpload }">
|
<img v-if="!isUploaded" src="@/assets/img/timeline/上传.png" style="width: 26px;height: 26px;" />
|
<img v-else src="@/assets/img/timeline/已上传.png" style="width: 26px;height: 26px;" />
|
</div>
|
</el-tooltip>
|
|
<!-- 第三个按钮:清除所有点和分析结果 -->
|
<el-tooltip placement="top" show-after="1000">
|
<template #content>
|
清除所有断面点及分析结果:
|
<br /><br />
|
🔁 功能说明:
|
<br />
|
点击后将移除地图上的所有断面点以及相关分析图表
|
<br /><br />
|
⚠️ 温馨提示:
|
<br />
|
此操作会清空当前分析进度,请确认后再执行
|
</template>
|
<div @click="clearPoints">
|
<img src="@/assets/img/timeline/清除.png" style="width: 26px;height: 26px;" />
|
</div>
|
</el-tooltip>
|
</div>
|
</template>
|
|
<script setup>
|
import { ElMessage } from 'element-plus';
|
import { ref, onMounted, defineExpose } from "vue";
|
import { getCrossSection } from '@/api/trApi.js'; // 假设你有真实接口
|
import { useSimStore } from '@/store/simulation';
|
import { storeToRefs } from 'pinia';
|
const simStore = useSimStore();
|
const { selectedScheme } = storeToRefs(simStore);
|
const viewer = window.viewer;
|
let selectedSchemeId = selectedScheme.value.id
|
|
let pickedPointsCross = ref([]);
|
let pickHandlerCross = null;
|
let isWallCreated = ref(false); // 新增状态变量,标记墙体是否已创建
|
let isPicking = ref(false); // 是否正在拾取点
|
const isUploaded = ref(false); // 控制是否已上传
|
|
// 获取断面坐标
|
function getPickPosition(windowPosition) {
|
if (!viewer) return null;
|
viewer.scene.globe.depthTestAgainstTerrain = true;
|
const cartesian = viewer.scene.pickPosition(windowPosition);
|
if (!cartesian) return null;
|
const cartographic = Cesium.Cartographic.fromCartesian(cartesian);
|
const longitude = Cesium.Math.toDegrees(cartographic.longitude);
|
const latitude = Cesium.Math.toDegrees(cartographic.latitude);
|
const terrainHeight = viewer.scene.globe.getHeight(cartographic);
|
if (!terrainHeight) return null;
|
const positionWithTerrainHeight = Cesium.Cartesian3.fromRadians(
|
cartographic.longitude,
|
cartographic.latitude,
|
terrainHeight
|
);
|
return {
|
cartesian: positionWithTerrainHeight,
|
longitude,
|
latitude
|
};
|
}
|
|
// 选取两个断面点坐标并绘制断面截面
|
function addPointToViewer(point) {
|
if (pickedPointsCross.value.length >= 2) {
|
for (const id of pickedEntitiesIds.value) {
|
viewer.entities.remove(viewer.entities.getById(id));
|
}
|
pickedPointsCross.value = [];
|
pickedEntitiesIds.value = [];
|
isWallCreated.value = false;
|
isUploaded.value = false;
|
}
|
pickedPointsCross.value.push(point);
|
drawPointOnMap(point);
|
if (pickedPointsCross.value.length === 2) {
|
drawWall(pickedPointsCross.value[0], pickedPointsCross.value[1]);
|
isWallCreated.value = true; // 设置为已创建墙体
|
}
|
}
|
|
let pickedEntitiesIds = ref([]); // 用于存储创建的点和墙的ID
|
|
// 绘制两个断面点坐标,并记录其ID
|
function drawPointOnMap(point) {
|
const entity = viewer.entities.add({
|
position: point.cartesian,
|
point: {
|
color: Cesium.Color.RED,
|
outlineColor: Cesium.Color.YELLOW,
|
outlineWidth: 2,
|
pixelSize: 8,// 圆点半径大小
|
distanceDisplayCondition: new Cesium.DistanceDisplayCondition(0, 5000),
|
|
}
|
});
|
pickedEntitiesIds.value.push(entity.id); // 记录实体ID
|
}
|
|
// 创建断面截面,并记录其ID
|
function drawWall(startPoint, endPoint) {
|
const entity = viewer.entities.add({
|
wall: {
|
positions: [startPoint.cartesian, endPoint.cartesian],
|
material: Cesium.Color.YELLOW,
|
heightReference: Cesium.HeightReference.RELATIVE_TO_GROUND,
|
distanceDisplayCondition: new Cesium.DistanceDisplayCondition(0, 5000),
|
|
}
|
});
|
pickedEntitiesIds.value.push(entity.id); // 记录实体ID
|
// 同时绘制模拟点
|
drawSimulationPoint(startPoint, endPoint);
|
}
|
|
// 新增:绘制模拟点(圆柱 + label)
|
function drawSimulationPoint(start, end) {
|
// 计算中点(经纬度平均值)
|
const midLon = (start.longitude + end.longitude) / 2;
|
const midLat = (start.latitude + end.latitude) / 2;
|
const terrainHeight = viewer.scene.globe.getHeight(
|
Cesium.Cartographic.fromDegrees(midLon, midLat)
|
);
|
|
const cylinderBottomHeight = 0;
|
const cylinderTopHeight = terrainHeight + 100;
|
const cartesianBottom = viewer.scene.globe.ellipsoid.cartographicToCartesian(
|
Cesium.Cartographic.fromDegrees(midLon, midLat, cylinderBottomHeight)
|
);
|
const CrosscylinderEntity = viewer.entities.add({
|
position: cartesianBottom,
|
cylinder: {
|
length: 100.0,
|
topRadius: 1.0,
|
bottomRadius: 1.0,
|
material: Cesium.Color.YELLOW,
|
outline: true,
|
outlineColor: Cesium.Color.YELLOW,
|
slices: 64,
|
heightReference: Cesium.HeightReference.RELATIVE_TO_GROUND,
|
distanceDisplayCondition: new Cesium.DistanceDisplayCondition(0, 5000)
|
}
|
});
|
const labelHeight = cylinderTopHeight + 10;
|
const cartesianLabel = viewer.scene.globe.ellipsoid.cartographicToCartesian(
|
Cesium.Cartographic.fromDegrees(midLon, midLat, labelHeight)
|
);
|
|
const CrosslabelEntity = viewer.entities.add({
|
position: cartesianLabel,
|
label: {
|
text: '断面截面模拟点',
|
font: 'bold 14pt monospace',
|
style: Cesium.LabelStyle.FILL_AND_OUTLINE,
|
fillColor: Cesium.Color.YELLOW,
|
outlineColor: Cesium.Color.BLACK,
|
outlineWidth: 2,
|
verticalOrigin: Cesium.VerticalOrigin.CENTER,
|
horizontalOrigin: Cesium.HorizontalOrigin.CENTER,
|
backgroundColor: Cesium.Color.fromCssColorString('rgba(0,0,0,0.7)'),
|
backgroundPadding: new Cesium.Cartesian2(10, 10),
|
showBackground: true,
|
scale: 1,
|
distanceDisplayCondition: new Cesium.DistanceDisplayCondition(0, 5000),
|
pixelOffsetScaleByDistance: new Cesium.NearFarScalar(100, 1.0, 5000, 0.3),
|
heightReference: Cesium.HeightReference.NONE // 使用绝对高度
|
}
|
});
|
pickedEntitiesIds.value.push(CrosscylinderEntity.id);
|
pickedEntitiesIds.value.push(CrosslabelEntity.id);
|
}
|
function clearPoints() {
|
for (const id of pickedEntitiesIds.value) {
|
viewer.entities.remove(viewer.entities.getById(id));
|
}
|
pickedPointsCross.value = [];
|
pickedEntitiesIds.value = [];
|
isWallCreated.value = false;
|
isUploaded.value = false;
|
if (pickHandlerCross) {
|
pickHandlerCross.destroy();
|
pickHandlerCross = null;
|
}
|
isPicking.value = false;
|
console.log('这里发送请求,清空郭楠的echarts2');
|
|
}
|
function initPickHandler() {
|
if (isPicking.value) {
|
if (pickHandlerCross) {
|
pickHandlerCross.destroy();
|
pickHandlerCross = null;
|
}
|
isPicking.value = false;
|
// isUploaded.value = false;
|
|
ElMessage.info('已关闭--断面截面--拾取点坐标功能!');
|
return;
|
}
|
ElMessage.success(`开始--断面截面--拾取坐标功能,请点击地图选择点位!选取完请及时关闭,避免影响其他功能!`);
|
isPicking.value = true;
|
if (!viewer?.scene?.canvas) return;
|
if (pickHandlerCross) {
|
pickHandlerCross.destroy();
|
pickHandlerCross = null;
|
}
|
pickHandlerCross = new Cesium.ScreenSpaceEventHandler(viewer.scene.canvas);
|
|
const clickAction = (movement) => {
|
const position = getPickPosition(movement.position);
|
if (position) {
|
addPointToViewer(position);
|
}
|
};
|
|
pickHandlerCross.setInputAction(clickAction, Cesium.ScreenSpaceEventType.LEFT_CLICK);
|
}
|
async function confirmPoints() {
|
console.log(selectedSchemeId,'这里拿的是方案的数据');
|
|
if (pickedPointsCross.value.length < 2) {
|
ElMessage.warning('请先选择两个点后再进行确认!');
|
return;
|
}
|
|
const point1 = pickedPointsCross.value[0];
|
const point2 = pickedPointsCross.value[1];
|
console.log(point1,point2);
|
|
console.log('第一个点信息:', {
|
longitude: point1.longitude,
|
latitude: point1.latitude,
|
cartesian: point1.cartesian
|
});
|
|
console.log('第二个点信息:', {
|
longitude: point2.longitude,
|
latitude: point2.latitude,
|
cartesian: point2.cartesian
|
});
|
const startPoint = `${point1.longitude},${point1.latitude}`;
|
const endPoint = `${point2.longitude},${point2.latitude}`;
|
const result = await getCrossSectionInfo(startPoint, endPoint);
|
console.log(result,'这里是郭楠需要的断面数据');
|
|
isUploaded.value = true;
|
ElMessage.success('正在进行--断面截面--数据分析上传,请稍等...');
|
|
}
|
// 获取真实数据
|
function getCrossSectionInfo(a, b) {
|
const params = {
|
startPoint: a,
|
endPoint: b,
|
id: selectedSchemeId
|
};
|
return getCrossSection(params).then(data => {
|
if (data && data.code === 200) {
|
return data.data; // 返回原始数据数组
|
} else {
|
return [];
|
}
|
}).catch(error => {
|
console.error('获取数据时发生错误:', error);
|
ElMessage.warning('数据有误,请联系管理员或重新进行模拟!');
|
return [];
|
});
|
}
|
defineExpose({
|
clearPoints
|
});
|
</script>
|