feature: 实时飞行高度与地形高度折线图绘制

devzpx
zhaipx 2 months ago
parent c5b665157c
commit 5548c7e57e

@ -298,7 +298,7 @@ export default class MeasureDistance {
}
/**
* 显示飞行航线
* 显示航线
* @param line Airline
*/
showAirLine(line){
@ -307,17 +307,34 @@ export default class MeasureDistance {
let coord = new Cartesian3.fromDegrees(line.points[i].lon,line.points[i].lat,line.points[i].alt)
degreesArr.push(coord)
}
if(line.isClose)
degreesArr.push(new Cartesian3.fromDegrees(line.points[0].lon,line.points[0].lat,line.points[0].alt))
let airlineEntity = new Cesium.Entity({
name: line.name,
id: line.name+line.totalDistance,
id: line.name + line.totalDistance,
polyline: {
positions: degreesArr,
width: 2,
width: 3,
material: Cesium.Color.ORANGE,
clampToGround: true,
},
clampToGround: false,
}
})
this.viewer.entities.add(airlineEntity)
for (let pt in degreesArr) {
let vertexEntity = new Cesium.Entity({
// id: "航点" + ,
position: pt,
point: {
color: Cesium.Color.FUCHSIA,
pixelSize: 6,
disableDepthTestDistance:99000000,
// heightReference:Cesium.HeightReference.CLAMP_TO_GROUND,
}
});
this.viewer.entities.add(vertexEntity)
}
}
addAirplaneEntity(modelPath,StrUavTypeID){
@ -334,7 +351,7 @@ export default class MeasureDistance {
return new Cesium.Transforms.headingPitchRollQuaternion(
new Cesium.Cartesian3.fromDegrees(this.dynamicData.lon, this.dynamicData.lat, this.dynamicData.alt),
new Cesium.HeadingPitchRoll(
Cesium.Math.toRadians(this.dynamicData.heading-90), // 0是正东顺时针增加
Cesium.Math.toRadians(this.dynamicData.heading-0), // 0调整该值不同模型的正方向不同
Cesium.Math.toRadians(0),
Cesium.Math.toRadians(0)
))
@ -342,8 +359,9 @@ export default class MeasureDistance {
model: {
uri: modelPath,
scale: 0.001,
minimumPixelSize: 100,
maximumScale: 2000,
maximumScale: 1,
runAnimations: true,
clampAnimations: true,
color: Cesium.Color.fromAlpha(Cesium.Color.RED, parseFloat(1.0)),

@ -45,7 +45,7 @@ function dataProcess_fromQT(websocketDataQT:any): UavDynamicInfo|null {
data.heading = websocketDataQT.pos.HeadAngle
data.lon = websocketDataQT.pos.lon
data.lat = websocketDataQT.pos.lat
data.alt = websocketDataQT.pos.height
data.alt = Number(websocketDataQT.pos.height) + useLayerStore().navi.hFactor
data.groundSpeed = websocketDataQT.pos.groundSpeed //km/h
useLayerStore().navi.currentRouteID = websocketDataQT.navi.currentRouteID
@ -53,8 +53,8 @@ function dataProcess_fromQT(websocketDataQT:any): UavDynamicInfo|null {
useLayerStore().navi.nextPoint = websocketDataQT.navi.nextPoint
useLayerStore().navi.distonext = websocketDataQT.navi.distonext
console.log(data.lon,data.lat, data.alt)
// console.log(data.lon,data.lat, data.alt)
//
return data.lon==0? null: data
}
@ -63,24 +63,23 @@ function dataProcess_fromQT_route(websocketDataQT:any): Airline|null {
code: 0, PtNum: 0, isClose: false, name: "", points: [], totalDistance: 0
}
if(!websocketDataQT.route) return null
data.PtNum = websocketDataQT.route.length
for (let i = 1; i < websocketDataQT.route.length; i++) {
data.PtNum = websocketDataQT.route.points.length
data.isClose = websocketDataQT.route.isClose
for (let i = 1; i < websocketDataQT.route.points.length; i++) {
let aPt: AirlinePoint = {alt: 0, ch1: 0, ch2: 0, lat: 0, lon: 0, nPt: 0, speed: 0}
aPt.lon = websocketDataQT.route[i].lon
aPt.lat = websocketDataQT.route[i].lat
aPt.alt = websocketDataQT.route[i].height
aPt.ch1 = websocketDataQT.route[i].ch1
aPt.ch2 = websocketDataQT.route[i].ch2
aPt.nPt = websocketDataQT.route[i].nPt
aPt.speed = websocketDataQT.route[i].nV
data.code = websocketDataQT.route[i].nL
aPt.lon = websocketDataQT.route.points[i].lon
aPt.lat = websocketDataQT.route.points[i].lat
aPt.alt = websocketDataQT.route.points[i].height
aPt.ch1 = websocketDataQT.route.points[i].ch1
aPt.ch2 = websocketDataQT.route.points[i].ch2
aPt.nPt = websocketDataQT.route.points[i].nPt
aPt.speed = websocketDataQT.route.points[i].nV
data.code = websocketDataQT.route.points[i].nL
data.points.push(aPt)
}
if(data.points[data.PtNum-2].ch1 ==2)
data.isClose = true
data.name = "lineID-" + data.code.toString()
console.log(data)
return data.PtNum==0? null: data
}

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

@ -1,21 +1,24 @@
<script setup lang="ts">
import {
drawEcharts_CollisionDetection,
drawEcharts_CollisionDetection2,
profileAnalyse
} from "@/utils/map/SpatialAnalysis.ts";
import {Cartesian3} from "cesium";
import {nextTick, onMounted} from "vue";
import {onMounted} from "vue";
import * as echarts from "echarts";
import {EChartsType} from "echarts";
import {useLayerStore} from "@/store/layerManagerStore.ts";
let l_store = useLayerStore()
let myChart: EChartsType = undefined
let uavDisArr: number[] = []
let uavHeightArr: number[] = []
let terrainArr: number[] = []
onMounted(()=>{
myChart = echarts.init(document.getElementById('detection-chart'))
// nextTick(()=>{
//
// })
})
const props = defineProps(['groundHeight'])
/**
* 绘制地形碰撞检测折线图
* @param height 飞机高度作为检测线
@ -26,19 +29,46 @@ const drawDetection = (height: number, currentPos:Cartesian3, nextPos: Cartesian
//
let res = profileAnalyse(window.viewer, [currentPos, nextPos], 10)
//
nextTick(()=>{
drawEcharts_CollisionDetection(myChart, res.distanceArray, res.elevationArray, height)
})
drawEcharts_CollisionDetection(myChart, res.distanceArray, res.elevationArray, height)
}
/**
* 绘制地形碰撞检测折线图
* @param uavH 飞机高度
* @param uavDis 飞机当前位置与上一位置的距离
* @param terrainH 飞机当前地面投影点的地形高度
*/
const drawDetection2 = (uavH: number, uavDis:number, terrainH: number) => {
if(uavDisArr.length == 0){
uavDisArr.push(Math.round(uavDis))
}
else{
uavDisArr.push(Math.round(uavDis + uavDisArr[uavDisArr.length - 1]))
}
uavHeightArr.push(Math.round(uavH))
terrainArr.push(Math.round(terrainH))
// ECharts
drawEcharts_CollisionDetection2(myChart, uavDisArr, terrainArr, uavHeightArr)
}
defineExpose({
drawDetection,
drawDetection2,
})
</script>
<template>
<div id="detection-chart"></div>
<n-space>
<span style="font-weight: bolder">
飞机对地高度{{props.groundHeight}}
</span>
<div id="detection-chart"></div>
</n-space>
</template>
<style scoped>

@ -9,7 +9,7 @@ import {RulerAlt} from '@vicons/carbon'
import {TerrainSharp} from '@vicons/material'
import {DrawPolygon} from '@vicons/fa'
import {useMessage} from 'naive-ui'
import {nextTick, ref} from "vue";
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";
@ -17,7 +17,7 @@ import LayerManager from "@/components/map/LayerManager.vue";
import CollisionDetection from "@/components/CollisionDetection.vue";
import {useLayerStore} from "@/store/layerManagerStore.ts";
import {Cartesian3} from "cesium";
import * as echarts from "echarts";
import {getDistance, getElevation} from "@/utils/map/geocomputation.ts";
const message = useMessage();
let SceneValue;
@ -26,13 +26,13 @@ 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;
@ -168,43 +168,54 @@ async function connectWebSocket() {
window.measureViewer.updateDynamicData(ycData)
//
if(!hasPlane.value){
window.measureViewer.addAirplaneEntity(store.models.defaultAirPlane, ycData.uavId + ycData.uavType)
window.measureViewer.addAirplaneEntity(store.models.fp98, ycData.uavId + ycData.uavType)
SceneValue.value = 'fallow'
hasPlane.value = true;
}
/************************测试代码(以下)******************/
// if(frameCount>50) { //(50)
// frameCount = 0
// //TODO:
// let cartesianTarget = Cartesian3.fromDegrees(114.6, 37.8)
// let cartesianCurr = Cartesian3.fromDegrees(ycData.lon, ycData.lat, ycData.alt)
// collisionDetection.value?.drawDetection(ycData.alt, cartesianCurr, cartesianTarget)
// }
/************************测试代码(以上)******************/
// (20)
if(lStore.navi.airlines.length>0 && frameCount>50){
console.log(frameCount)
// (50)
if(frameCount>50){
showDetection.value = true
frameCount = 0
lStore.navi.airlines.forEach(airline => {
if(airline.code === lStore.navi.currentRouteID){
let targetPos = airline.points[lStore.navi.nextPoint]
//TODO:
let cartesianTarget = Cartesian3.fromDegrees(targetPos.lon, targetPos.lat,targetPos.alt)
let cartesianCurr = Cartesian3.fromDegrees(ycData.lon, ycData.lat,ycData.alt)
collisionDetection.value?.drawDetection(ycData.alt, cartesianCurr, cartesianTarget)
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)
lStore.navi.airlines.push(routeData)
console.log(routeData)
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)
})
*/
}
}
};
}
@ -304,7 +315,7 @@ function manageLayer(){
</n-row>
</n-space>
<n-space id="detectionGraph" v-show="showDetection">
<CollisionDetection ref="collisionDetection"></CollisionDetection>
<CollisionDetection ref="collisionDetection" :groundHeight="groundHeight"></CollisionDetection>
</n-space>
<n-modal v-model:show="showModal"
@ -356,6 +367,6 @@ function manageLayer(){
width: 100rem;
height: 15rem;
border-radius: 7px;
background: rgba(21, 21, 21, 0.94);
background: rgba(255, 255, 255, 0.94);
}
</style>

@ -1,5 +1,5 @@
import {defineStore} from "pinia";
import {Airline} from "@/types/entityoptions.ts";
import {Airline, routeTerrain} from "@/types/entityoptions.ts";
type layer = {
lName: string
lId: string
@ -14,11 +14,13 @@ export const useLayerStore = defineStore('LayerStore', {
Layers: [] as layer[],
navi: {
airlines: [] as Airline[],
currentRouteID: undefined, //当前航线号
nextRouteID: undefined, //下一航线号
nextPoint: undefined, //下一航点号
distonext: undefined, //待飞距离
currentRouteID: -1, //当前航线号
nextRouteID: -1, //下一航线号
nextPoint: -1, //下一航点号
distonext: -1, //待飞距离
hFactor: 3 //高度修正数
},
routesTerrain: [] as routeTerrain[]
}
},
actions: {

@ -1,5 +1,7 @@
import {defineStore} from "pinia";
import cesiumAirPlane from "@/assets/models/Cesium_Air.glb";
import fp985Plane from "@/assets/models/FP-985.gltf";
import fp98Plane from "@/assets/models/fp-98.gltf";
export const useStaticStore = defineStore('staticOptions',{
state: ()=>{
@ -51,6 +53,8 @@ export const useStaticStore = defineStore('staticOptions',{
},
models: {
defaultAirPlane: cesiumAirPlane,
fp985: fp985Plane,
fp98: fp98Plane
},
hasPlane: false,
uav: {

@ -52,4 +52,10 @@ export type Airline = {
isClose: boolean,
totalDistance: number,
points: AirlinePoint[],
}
}
export type routeTerrain = {
routeID: number,
distanceArray: number[],
elevationArray: number[],
}

@ -8,10 +8,12 @@ import {getDistance, getElevation} from "@/utils/map/geocomputation.ts";
import {Cartesian3, Viewer} from "cesium";
import * as echarts from "echarts";
import {EChartsType} from "echarts";
import {Airline, AirlinePoint} from "@/types/entityoptions.ts";
type ProfileResult = {
distanceArray:number[],
elevationArray:number[],
}
/**
*
* @param viewer Viewer
@ -74,6 +76,36 @@ export function profileAnalyse(viewer: Viewer, polyline:Cartesian3[], interval:
return result
}
/**
* 线
* @param viewer Viewer
* @param route 线
* @param interval 线 m
* @return 线线
*/
export function profileAnalyse_promise(viewer: Viewer, route: Airline, interval: number){
return new Promise((resolve, reject) => {
let result: ProfileResult = { distanceArray:[], elevationArray:[] }
let polyline = []
//航线转为坐标点数组
route.points.forEach(point => {
polyline.push(Cartesian3.fromDegrees(point.lon, point.lat,point.alt))
})
let temp_dis = 0 //每两点之间的距离
for (let i = 0; i <= polyline.length - 2; i++) {
let temp = elevationProfile(viewer, polyline[i], polyline[i+1], interval)
result.elevationArray = result.elevationArray.concat(temp.elevationArray)
temp.distanceArray.forEach(distance => {
result.distanceArray.push(distance+temp_dis)
})
if(temp.distanceArray.length > 0){
temp_dis += temp.distanceArray[temp.distanceArray.length-1]
}
}
resolve(result)
})
}
/**
* <br>
* truefalseundefined
@ -394,6 +426,120 @@ export function drawEcharts_CollisionDetection(myChart: EChartsType, xData:numbe
}, false);
}
/**
*
* @param myChart ECharts
* @param xData x
* @param yData y线
* @param yData2 y2线
*/
export function drawEcharts_CollisionDetection2(myChart: EChartsType, xData:number[], yData:number[], yData2: number[]) {
// 绘制图表
myChart.setOption({
legend: {
show: true,
type: 'plain',
top: '5%',
data:[
{
name: '地表高度',
itemStyle: 'inherit',
lineStyle: 'inherit',
},
{
name: '飞机高度',
lineStyle: {
type: 'dotted',
width: 3,
color: '#f8364d'
},
itemStyle: {
fontSize: 18
}
}
]
},
tooltip: {
show: true,
trigger: 'axis',
axisPointer: {
type: 'cross'
},
formatter:'地表高度: {c0}<br>飞机高度: {c1}'
},
xAxis: {
data: xData,
name: '距离/米',
nameTextStyle: {
fontWeight:'bolder',
fontSize: 14
},
nameLocation: 'end',
axisLine:{
onZero: false,
show: true, // 是否显示坐标轴轴线
symbol: ['none', 'arrow'],
symbolSize: [7, 10]
},
axisLabel: {
formatter: '{value}',
margin: 5,
},
axisTick: {
show: true, // 是否显示坐标轴刻度
inside: true, // 坐标轴刻度是否朝内,默认朝外
alignWithLabel: true,
lineStyle: {
color: '#000000', //刻度线的颜色
type: 'solid', //坐标轴线线的类型solid实线类型dashed虚线类型dotted点状类型
},
}
},
yAxis: {
max: (value:any)=>{
return Math.floor(value.max * 1.01)
},
min: (value:any)=>{
return Math.floor(value.min * 0.99)
},
type: 'value',
name: '高度/米',
nameTextStyle: {
fontWeight:'bolder',
fontSize: 14
},
nameLocation: 'end',
position: 'left',
axisLabel: {
formatter: '{value}'
},
axisLine: {
show: true,
symbol: ['none', 'arrow'],
symbolSize: [7, 10]
}
},
series: [
{
name:'地表高度',
type: 'line',
data: yData,
areaStyle: {
color: '#37a5fb',
opacity: 0.5
},
},
{
name: '飞机高度',
type: 'line',
symbol: 'none',
color: 'red',
data: yData2,
}
]
}, false);
}
/**
* 线线

Loading…
Cancel
Save