/*
|
* @Author: shuishen 1109946754@qq.com
|
* @Date: 2025-04-19 14:24:34
|
* @LastEditors: shuishen 1109946754@qq.com
|
* @LastEditTime: 2025-04-19 19:00:36
|
* @FilePath: \command-center-dashboard\src\hooks\useTaskWayline\useTaskWayline.js
|
* @Description:
|
*
|
* Copyright (c) 2025 by shuishen, All Rights Reserved.
|
*/
|
import lineImg from '@/assets/images/arrow-right-blue.png'
|
import rwqfdImg from '@/assets/images/signMachineNest/rwqfd.png'
|
import endPointImg from '@/assets/images/EndPointicon.png'
|
|
import { analyzeKmzFile, removeTextKey, XMLToJSON } from '@/utils/cesium/kmz'
|
import { flyVisual } from '@/utils/cesium/mapUtil'
|
import ImageTrailMaterial from '@/utils/cesium/ImageTrailMaterial'
|
|
import * as Cesium from 'cesium'
|
import { Cartesian3 } from 'cesium'
|
import aircraftGltf from '@/assets/gltf/aircraft.gltf'
|
import CreateFrustum from '@/utils/cesium/frustum/CreateFrustum'
|
|
export function useTaskWayline () {
|
let viewer = null
|
let deviceOsdInfo = null
|
let taskWatch = null
|
let deviceWatch = null
|
|
// 解析kmz文件
|
const parsingFiles = async url => {
|
const res = await analyzeKmzFile(`${url}?_t=${new Date().getTime()}`)
|
const waylinesXML = await res.fileInfoObj['wpmz/waylines.wpml']
|
const waylinesXMLJSON = XMLToJSON(waylinesXML)?.['Document']
|
const waylinesXMLObj = removeTextKey(waylinesXMLJSON.Folder)
|
if (!waylinesXMLObj.Placemark.length) return
|
const allPoint = waylinesXMLObj.Placemark.map(item => item.Point.coordinates.split(','))
|
flyVisual(allPoint, viewer)
|
drawWayline(waylinesXMLObj)
|
}
|
|
const drawWayline = lineObj => {
|
const positions = lineObj.Placemark.map(item => {
|
const [lon, lat] = item.Point.coordinates.split(',')
|
return Cartesian3.fromDegrees(Number(lon), Number(lat))
|
})
|
|
removeEntitys()
|
|
// 起点
|
viewer.entities.add({
|
id: 'drone-job-wayline-start',
|
position: positions[0],
|
billboard: {
|
image: new Cesium.ConstantProperty(rwqfdImg),
|
width: 70,
|
height: 70,
|
},
|
})
|
|
// 终点
|
viewer.entities.add({
|
id: 'drone-job-wayline-end',
|
position: positions[positions.length - 1],
|
billboard: {
|
image: new Cesium.ConstantProperty(endPointImg),
|
width: 30,
|
height: 30,
|
verticalOrigin: Cesium.VerticalOrigin.BOTTOM, // 底部对齐
|
},
|
})
|
|
// 路径线
|
viewer.entities.add({
|
id: 'drone-job-wayline-polyline',
|
polyline: {
|
width: 4,
|
positions: positions,
|
material: new ImageTrailMaterial({
|
color: { alpha: 1, blue: 1, green: 1, red: 1 },
|
speed: 20,
|
image: lineImg,
|
repeat: { x: Math.floor(40), y: 1 },
|
}),
|
clampToGround: false,
|
},
|
})
|
}
|
|
|
|
|
let viewInfoFrustum
|
// 设置视椎
|
const setCreateFrustum = (host) => {
|
if (!host) return
|
viewInfoFrustum?.clear()
|
|
const attitude_head = 180 + host?.attitude_head
|
const gimbal_pitch = 90 - Number(host?.payloads[0]?.gimbal_pitch) || 0
|
|
viewInfoFrustum = new CreateFrustum(viewer, {
|
position: {
|
longitude: host?.longitude,
|
latitude: host?.latitude,
|
altitude: host?.height,
|
},
|
width: 30,
|
height: 30,
|
fov: 20.0,
|
near: 3.0,
|
far: 250.0,
|
roll: gimbal_pitch,
|
pitch: 0,
|
heading: attitude_head,
|
})
|
}
|
|
function setAircraftGltf () {
|
const host = deviceOsdInfo.value?.data?.host
|
|
const aircraftEntity = viewer?.entities.getById('aircraftGltf')
|
const position = Cesium.Cartesian3.fromDegrees(host?.longitude, host?.latitude, host?.height)
|
if (aircraftEntity) {
|
aircraftEntity.position = new Cesium.ConstantPositionProperty(position)
|
return
|
}
|
|
let entity = viewer?.entities.add({
|
id: 'aircraftGltf',
|
position,
|
label: {},
|
model: {
|
uri: aircraftGltf, // 或 .glb
|
scale: 1.0, // 缩放比例
|
minimumPixelSize: 64, // 最小像素尺寸(保证模型远处可见)
|
maximumScale: 128, // 最大缩放(可选)
|
},
|
})
|
|
const homeDistance = Math.floor(host?.home_distance) || 0
|
const distance = 1
|
const arrivalTime = 1
|
const totalDistance = 1
|
const usedTime = 1
|
|
entity.label = new Cesium.LabelGraphics({
|
text: `距离机场水平距离:${homeDistance}m\n距离下一个航点:${Math.round(
|
distance,
|
)}m\n预计到达下一航点时间:${arrivalTime}\n本次飞行时间:${usedTime}\n本次航线平面里程:${Math.round(
|
totalDistance,
|
)}m`,
|
font: '13px monospace',
|
showBackground: true,
|
horizontalOrigin: Cesium.HorizontalOrigin.CENTER,
|
verticalOrigin: Cesium.VerticalOrigin.BOTTOM,
|
disableDepthTestDistance: Number.POSITIVE_INFINITY,
|
pixelOffset: new Cesium.Cartesian2(0, -40),
|
show: true,
|
})
|
}
|
|
const mapEntityRemove = () => {
|
viewInfoFrustum?.clear()
|
|
viewer?.entities.removeById('aircraftGltf')
|
}
|
|
const removeEntitys = () => {
|
const entitiesIDs = viewer?.entities.values.map(i => i.id)
|
|
Array.isArray(entitiesIDs) && entitiesIDs.forEach(item => {
|
item.includes('drone-job-wayline-') && viewer?.entities.removeById(item)
|
})
|
}
|
|
const init = (v, wsInfo, taskDetails) => {
|
console.log(v, wsInfo, taskDetails)
|
|
viewer = v
|
deviceOsdInfo = computed(() => wsInfo.value?.device_osd)
|
|
taskWatch?.()
|
|
taskWatch = watch(taskDetails,
|
() => {
|
if (taskDetails.value?.way_lines?.length) {
|
parsingFiles(taskDetails.value.way_lines[0].url)
|
}
|
},
|
{ immediate: true }
|
)
|
|
deviceWatch?.()
|
|
deviceWatch = watch(deviceOsdInfo, () => {
|
const host = deviceOsdInfo.value?.data?.host
|
|
if (!host) return
|
|
if ([14, 0].includes(host?.mode_code)) {
|
mapEntityRemove()
|
return
|
}
|
|
setCreateFrustum(host)
|
setAircraftGltf()
|
}
|
)
|
}
|
|
onBeforeUnmount(() => {
|
mapEntityRemove()
|
removeEntitys()
|
|
taskWatch?.()
|
deviceWatch?.()
|
})
|
|
return {
|
init,
|
removeEntitys,
|
mapEntityRemove,
|
}
|
}
|