| | |
| | | <template> |
| | | <div style="display: flex; justify-content: space-between;"> |
| | | <div @click="initPickHandler"> |
| | | <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> |
| | | <div @click="confirmPoints"> |
| | | <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> |
| | | <div @click="clearPoints"> |
| | | <img src="@/assets/img/timeline/清除.png" style="width: 26px;height: 26px;" /> |
| | | </div> |
| | | <!-- 第一个按钮:选取断面点 --> |
| | | <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; |
| | |
| | | // 选取两个断面点坐标并绘制断面截面 |
| | | function addPointToViewer(point) { |
| | | if (pickedPointsCross.value.length >= 2) { |
| | | clearPoints(); |
| | | 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); |
| | |
| | | color: Cesium.Color.RED, |
| | | outlineColor: Cesium.Color.YELLOW, |
| | | outlineWidth: 2, |
| | | pixelSize: 8 // 圆点半径大小 |
| | | pixelSize: 8,// 圆点半径大小 |
| | | distanceDisplayCondition: new Cesium.DistanceDisplayCondition(0, 5000), |
| | | |
| | | } |
| | | }); |
| | | pickedEntitiesIds.value.push(entity.id); // 记录实体ID |
| | |
| | | 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 |
| | |
| | | |
| | | // 新增:绘制模拟点(圆柱 + 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 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 + 190; |
| | | const cartesianBottom = viewer.scene.globe.ellipsoid.cartographicToCartesian( |
| | | Cesium.Cartographic.fromDegrees(midLon, midLat, cylinderBottomHeight) |
| | | ); |
| | | const CrosscylinderEntity = viewer.entities.add({ |
| | | position: cartesianBottom, |
| | | cylinder: { |
| | | length: 190.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 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); |
| | | 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) { |
| | |
| | | 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) { |
| | |
| | | pickHandlerCross = null; |
| | | } |
| | | isPicking.value = false; |
| | | isUploaded.value = false; |
| | | // isUploaded.value = false; |
| | | |
| | | ElMessage.info('已关闭--断面截面--拾取点坐标功能!'); |
| | | return; |
| | | } |
| | |
| | | |
| | | pickHandlerCross.setInputAction(clickAction, Cesium.ScreenSpaceEventType.LEFT_CLICK); |
| | | } |
| | | function confirmPoints() { |
| | | 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: point2.latitude, |
| | | cartesian: point2.cartesian |
| | | }); |
| | | |
| | | isUploaded.value = true; |
| | | const startPoint = `${point1.longitude},${point1.latitude}`; |
| | | const endPoint = `${point2.longitude},${point2.latitude}`; |
| | | const result = await getCrossSectionInfo(startPoint, endPoint); |
| | | simStore.crossSection = result |
| | | 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 |
| | | }); |