<!-- 文件描述:工具条 创建时间:2024/4/16 10:54 创建人:Zhaipeixiu --> <script setup> import {ChevronBack, CreateOutline, DuplicateSharp, EyeSharp, Layers, Settings} from '@vicons/ionicons5' import {RulerAlt} from '@vicons/carbon' import {TerrainSharp} from '@vicons/material' import {DrawPolygon} from '@vicons/fa' import {useMessage} from 'naive-ui' import {ref} from "vue"; import {useStaticStore} from "@/store/staticOptions.js"; import {dataProcess_fromQT, dataProcess_fromQT_route} from "@/assets/js/websocketProtocol.ts"; import SpatialAnalysis from "@/components/SpatialAnalysis.vue"; import LayerManager from "@/components/map/LayerManager.vue"; import CollisionDetection from "@/components/CollisionDetection.vue"; import {useLayerStore} from "@/store/layerManagerStore.ts"; import {Cartesian3} from "cesium"; import {getDistance, getElevation} from "@/utils/map/geocomputation.ts"; const message = useMessage(); let SceneValue; let showModal = ref(false); let showDetection = ref(false); let hasPlane = ref(false); let store = useStaticStore(); let lStore = useLayerStore(); let groundHeight = ref(-1) const spatialAnalyse = ref(null) const layerManager = ref(null) const collisionDetection = ref(null) SceneValue = ref('untrace'); let frameCount = 0 let lastPos = undefined; //飞机上一时点的坐标 function handleSceneSelect(key){ if(!hasPlane.value) return; if(key === 'untrace') { window.measureViewer.setNoTrack() }else if(key === 'fallow') { window.viewer.trackedEntity = window.viewer.entities.getById(store.uav.ModelIDinMap); } } let layerValue = ref('layer1'); let barIsOpen = ref(true); function handleEditSelect(key) { if(key === 'requestLine') { } else{ // 航线管理页面 } } function handleAnalyseSelect(key) { if(key === 'visibility') { store.analysisVars.analysisType = 2 //弹出参数窗口 spatialAnalyse.value?.openParamsDialog() } if(key === 'profile') { store.analysisVars.analysisType = 1 //弹出参数窗口 spatialAnalyse.value?.openParamsDialog() } } function handleDrawSelect(key) { if(key === 'clear') { if(window.measureViewer.clearDraw()){ message.warning('无可清除图形') } } else{ window.measureViewer.drawGraphics(key) } } // 测量菜单选中事件 function handleSelect(key) { if(key === 'distance') { measure(); } else if(key === 'area') { measureArea() }else if(key === 'clear') { measureEnd() } } async function handleFile() { const [fileHandle] = await window?.showOpenFilePicker({ types: [ { description: "kml/json", accept: {"text/kml": ['.kml', '.kmz', '.json', '.geojson']} } ] }) // 获取文件File对象 const file = await fileHandle?.getFile() console.group("获取到的文件") console.log(fileHandle) console.log(file.name) if(file.name.toLowerCase().endsWith('kml')||file.name.toLowerCase().endsWith('kmz')){ window.measureViewer.addKml(file) } else if(file.name.toLowerCase().endsWith('geojson')||file.name.toLowerCase().endsWith('json')||file.name.toLowerCase().endsWith('topojson')) { window.measureViewer.addJson(file) } } /** * 多点距离测量 */ function measure(){ window.measureViewer.clearDisEntity() window.measureViewer.activate() } /** * 清除面积测量和多点距离测量 */ function measureEnd(){ if(window.measureViewer.vertexEntities.length>0 || window.measureViewer.activeShapePoints.length>0){ window.measureViewer.deactivate() window.measureViewer.stopAreaMeasure() window.measureViewer.clearDisEntity() window.measureViewer.clearAreaEntity() window.measureViewer.viewer.scene.requestRender() }else{ message.warning('无可清除元素') } } /** * 面积测量 */ function measureArea() { window.measureViewer.clearAreaEntity() window.measureViewer.activateAreaMeasure(); } /** * 连接websocket * @returns {Promise<void>} */ async function connectWebSocket() { store.webskt.ws = new WebSocket('ws://'+store.webskt.ws_config.address+':'+store.webskt.ws_config.port); store.webskt.ws.onopen = function(event){ console.log("Connection open ..."); store.webskt.ws.send("hello QT!") } store.webskt.ws.onmessage = (event) => { //收到消息后的处理流程.... let sktData = JSON.parse(event.data) // console.log(sktData); frameCount++ if(sktData.type === 0){ let ycData = dataProcess_fromQT(sktData) if (ycData != null) { // 更新遥测数据(飞机位置) window.measureViewer.updateDynamicData(ycData) // 添加飞机三维图标 if(!hasPlane.value){ window.measureViewer.addAirplaneEntity(store.models.fp98, ycData.uavId + ycData.uavType) SceneValue.value = 'fallow' hasPlane.value = true; } console.log(frameCount) // 加载和更新碰撞检测图(50帧更新一次) if(frameCount>50){ showDetection.value = true frameCount = 0 let currentPos = Cartesian3.fromDegrees(ycData.lon, ycData.lat,ycData.alt) new Promise(resolve => { // 计算对地高度 m groundHeight.value = ycData.alt - getElevation(window.viewer, currentPos) // 计算当前点与上一点的距离 米 if(lastPos===undefined){ lastPos = currentPos; } let dis = getDistance(currentPos, lastPos) * 1000 lastPos = currentPos resolve(dis) }).then(res=>{ collisionDetection.value.drawDetection2(ycData.alt, res, ycData.alt-groundHeight.value) }) } } } if(sktData.type === 1){ let routeData = dataProcess_fromQT_route(sktData) if(routeData != null){ lStore.navi.airlines.push(routeData) lStore.navi.currentRouteID = routeData.code console.log(routeData) window.measureViewer.showAirLine(routeData) //计算航线的地形剖面,并存储到store中 // FIXME: 当前逻辑有待更新 /* profileAnalyse_promise(window.viewer, routeData,100).then((result) => { let routeTerr = {} routeTerr.routeID = routeData.code routeTerr.distanceArray = result.distanceArray routeTerr.elevationArray = result.elevationArray lStore.routesTerrain.push(routeTerr) }) */ } } }; } /** * 关闭websocket连接 */ function closeWS(){ if(store.webskt.ws){ store.webskt.ws.close(); } } function manageLayer(){ layerManager.value?.open_closeSidebar() } </script> <template> <n-space id="panel"> <n-row justify-content="space-between"> <n-tooltip placement="bottom" trigger="hover" > <template #trigger> <n-button tertiary type="warning" @click="manageLayer"> <template #icon> <n-icon><Layers/></n-icon> </template> </n-button> </template> <span> 图层管理 </span> </n-tooltip> <n-tooltip placement="bottom" trigger="hover"> <template #trigger> <n-button tertiary circle type="warning" @click="handleFile"> <template #icon> <n-icon><DuplicateSharp /></n-icon> </template> </n-button> </template> <span> 添加数据 </span> </n-tooltip> <n-dropdown :options="store.menuOptions.AnalyzeOptions" @select="handleAnalyseSelect"> <n-button tertiary type="warning"> <template #icon> <n-icon><TerrainSharp/></n-icon> </template> </n-button> </n-dropdown> <n-dropdown :options="store.menuOptions.EditOptions" @select="handleEditSelect"> <n-button tertiary circle type="warning"> <template #icon> <n-icon><CreateOutline/></n-icon> </template> </n-button> </n-dropdown> <n-dropdown :options="store.menuOptions.MeasureOptions" @select="handleSelect"> <n-button tertiary type="warning"> <template #icon> <n-icon><RulerAlt/></n-icon> </template> </n-button> </n-dropdown> <n-dropdown :options="store.menuOptions.DrawOptions" @select="handleDrawSelect"> <n-button tertiary circle type="warning"> <template #icon> <n-icon><DrawPolygon/></n-icon> </template> </n-button> </n-dropdown> <n-tooltip placement="bottom" trigger="hover"> <template #trigger> <n-button tertiary type="warning" @click="showModal = true"> <template #icon> <n-icon><Settings/></n-icon> </template> </n-button> </template> <span> WebSocket配置 </span> </n-tooltip> <n-popselect v-model:value="SceneValue" :options="store.menuOptions.sceneOptions" @update:value="handleSceneSelect" size="medium"> <!-- :disabled="!hasPlane" --> <n-button tertiary circle type="warning"> <template #icon> <n-icon><EyeSharp/></n-icon> </template> </n-button> </n-popselect> <n-button tertiary circle type="warning"> <template #icon> <!-- ChevronBack,ChevronForward,--> <n-icon><ChevronBack/></n-icon> </template> </n-button> </n-row> </n-space> <n-space id="detectionGraph" v-show="showDetection"> <CollisionDetection ref="collisionDetection" :groundHeight="groundHeight"></CollisionDetection> </n-space> <n-modal v-model:show="showModal" style="width: 30%" :mask-closable="false" preset="dialog" title=""> <template #header> <div>WebsSocket配置</div> </template> <div style="margin: 2rem 2rem .5rem 1rem"> <n-space> <n-form ref="formRef" :model="store.webskt.ws_config" label-placement="left" label-width="auto" require-mark-placement="right-hanging"> <n-form-item label="服务器地址"> <n-input v-model:value="store.webskt.ws_config.address" placeholder="127.0.0.1"/> </n-form-item> <n-form-item label="端口号"> <n-input-number v-model:value="store.webskt.ws_config.port" placeholder=8000 /> </n-form-item> </n-form> </n-space> <n-space justify="center"> <n-button @click="connectWebSocket" type="primary" size="small">开启通信</n-button> <!-- <n-button @click=" sendMessage" type="primary" size="small">发消息</n-button>--> <n-button @click="closeWS" type="warning" size="small">关闭通信</n-button> </n-space> </div> </n-modal> <SpatialAnalysis ref="spatialAnalyse"></SpatialAnalysis> <LayerManager ref="layerManager"></LayerManager> </template> <style scoped> #panel{ position: absolute; top: 10px; left: 2px; border-radius: 7px; background: rgba(21, 21, 21, 0.94); } #detectionGraph{ position: absolute; bottom: 2rem; width: 100rem; height: 15rem; border-radius: 7px; background: rgba(255, 255, 255, 0.94); } </style>