From a51171f691ec516929fbb29356ad9074d0439b6e Mon Sep 17 00:00:00 2001
From: GuLiMmo <2820890765@qq.com>
Date: Thu, 07 Mar 2024 17:32:45 +0800
Subject: [PATCH] update: 右键新增航线、事件编辑、kmz文件编辑
---
src/utils/cesium/use-map-draw.ts | 9 +
src/pages/page-web/projects/components/route-edit/index.vue | 212 +++++++++++++----------------------
src/utils/cesium/use-kmz-tsa.ts | 73 ++++++++++-
src/utils/cesium/kmz.ts | 16 ++
src/pages/page-web/projects/components/route-edit/components/setting.vue | 6
src/utils/cesium/mapUtils.ts | 31 +++-
6 files changed, 187 insertions(+), 160 deletions(-)
diff --git a/src/pages/page-web/projects/components/route-edit/components/setting.vue b/src/pages/page-web/projects/components/route-edit/components/setting.vue
index 4f75774..c898a23 100644
--- a/src/pages/page-web/projects/components/route-edit/components/setting.vue
+++ b/src/pages/page-web/projects/components/route-edit/components/setting.vue
@@ -86,7 +86,7 @@
<li @click="numberControls(true, 100, 'globalHeight')">+100</li>
<li @click="numberControls(true, 10, 'globalHeight')">+10</li>
<li>
- <span>{{ Number(folderSetting.globalHeight) }}</span> m
+ <span>{{ Math.round(folderSetting.globalHeight) }}</span> m
</li>
<li @click="numberControls(false, 100, 'globalHeight')">-100</li>
<li @click="numberControls(false, 10, 'globalHeight')">-10</li>
@@ -124,6 +124,7 @@
import useMapDraw from '/@/utils/cesium/use-map-draw'
import { getKmlParams } from '/@/utils/cesium/kmz'
import { cesiumOperation } from '/@/hooks/use-cesium-tsa'
+import { message } from 'ant-design-vue'
import type { missionConfig, payloadParam as payloadParamConfig, Folder } from '/@/utils/cesium/types/kml'
const { appContext }: any = getCurrentInstance()
const global = appContext.config.globalProperties
@@ -227,6 +228,9 @@
if (missionConfigSetting[key]) {
missionConfigSetting[key] -= computeVal
} else {
+ if (folderSetting[key] - computeVal <= 0) {
+ return message.warn('飞行高度较低!!!!')
+ }
folderSetting[key] -= computeVal
}
}
diff --git a/src/pages/page-web/projects/components/route-edit/index.vue b/src/pages/page-web/projects/components/route-edit/index.vue
index c568d50..ea4e04e 100644
--- a/src/pages/page-web/projects/components/route-edit/index.vue
+++ b/src/pages/page-web/projects/components/route-edit/index.vue
@@ -7,17 +7,14 @@
</template>
返回
</a-button>
- <div class="save-button">
+ <div class="save-button" @click="saveWaylineFile">
<SaveOutlined />
</div>
<setting v-model:loadCompleted="loadCompleted">
<template #show>
<a-button type="text" class="setting-btn">
<div class="router-setting">
- <img
- class="wayline-icon"
- :src="getResource('wayline.png')"
- alt="icon" />
+ <img class="wayline-icon" :src="getResource('wayline.png')" alt="icon" />
<span class="text">航线设置</span>
<CaretDownOutlined />
</div>
@@ -26,10 +23,7 @@
</setting>
</div>
<div class="wayline-info">
- <div
- class="info-box"
- v-for="(item, index) in waylineDetails"
- :key="index">
+ <div class="info-box" v-for="(item, index) in waylineDetails" :key="index">
<div class="title">{{ item.title }}</div>
<div class="info">{{ item.value }}</div>
</div>
@@ -45,10 +39,7 @@
<div class="right">{{ index + 1 }}</div>
</div>
<div class="graph-right">
- <div
- v-for="(event, index) in item.eventList"
- :key="index"
- class="s-event-icon">
+ <div v-for="(event, index) in item.eventList" :key="index" class="s-event-icon">
<a-tooltip placement="top">
<template #title>
{{ event.name }}
@@ -66,24 +57,23 @@
import _ from 'lodash'
import * as Cesium from 'cesium'
import setting from './components/setting.vue'
-import useKmzTsa from '/@/utils/cesium/use-kmz-tsa'
+import useKmzTsa, { kmlStr } from '/@/utils/cesium/use-kmz-tsa'
import { ref, reactive, defineEmits, defineProps, watch, onMounted } from 'vue'
import { ArrowLeftOutlined, CaretDownOutlined, SaveOutlined } from '@ant-design/icons-vue'
import { cesiumOperation } from '/@/hooks/use-cesium-tsa'
import { useMyStore } from '/@/store'
import ImageTrailMaterial from '/@/utils/cesium/ImageTrailMaterial'
-import useMapDraw from '/@/utils/cesium/use-map-draw'
+import useMapDraw, { kmlEntities as globalEntities } from '/@/utils/cesium/use-map-draw'
+import { getKmlParams } from '/@/utils/cesium/kmz'
+import { getHaeHeight } from '/@/utils/cesium/mapUtils'
const store = useMyStore()
const { appContext }: any = getCurrentInstance()
const global = appContext.config.globalProperties
-const {
- removeAllPoint,
- getEntityById,
- addPolyline,
- addRightClick,
- removeRightClickEvent,
-} = cesiumOperation()
+const kmzUtils = useKmzTsa()
+
+const { removeAllPoint, getEntityById, addPolyline, removeAllDataSource, addRightClick, removeRightClickEvent } =
+ cesiumOperation()
interface waylineDetails {
title: string
@@ -116,15 +106,12 @@
const tragetPointArr = ref<tragetPoint[]>([])
-let kmlDataSource:
- | { entities: { values: { _children: any }[] }; show: boolean }
- | null
- | any = null
+let kmlDataSource: { entities: { values: { _children: any }[] }; show: boolean } | null | any = null
let mouseRightClickEvent: any = null
// 绘制地图上的东西
-let mapDraw = null
+let mapDraw: any = null
// 航线详情
const waylineDetails = ref<waylineDetails[]>([])
// 样式
@@ -141,31 +128,29 @@
if (kmlDataSource) {
global.$viewer.dataSources.remove(kmlDataSource)
}
- global.$viewer.dataSources
- .add(Cesium.KmlDataSource.load(filePath.value, options))
- .then((res: any) => {
- kmlDataSource = res
- mapDraw = useMapDraw(kmlDataSource, [], filePath.value, global)
- const {
- drawWayline,
- waylineDetails: details,
- waylinePointsEvent,
- kmlEntities: entities,
- clearWaylineData
- } = mapDraw
- clearWaylineData()
- drawWayline()
- useKmzTsa().init(filePath.value).then(kmlRes => {
- loadCompleted.value = true
- })
- waylineDetails.value = details
- tragetPointArr.value = waylinePointsEvent.value
- kmlEntities.value = entities.value
- if (!mouseRightClickEvent) {
- // 添加右键事件
- addMapPointEvent()
- }
+ global.$viewer.dataSources.add(Cesium.KmlDataSource.load(filePath.value, options)).then((res: any) => {
+ kmlDataSource = res
+ mapDraw = useMapDraw(kmlDataSource, [], filePath.value, global)
+ const {
+ drawWayline,
+ waylineDetails: details,
+ waylinePointsEvent,
+ kmlEntities: entities,
+ clearWaylineData,
+ } = mapDraw
+ clearWaylineData()
+ drawWayline()
+ kmzUtils.init(filePath.value).then((kmlRes) => {
+ loadCompleted.value = true
})
+ waylineDetails.value = details
+ tragetPointArr.value = waylinePointsEvent.value
+ kmlEntities.value = entities.value
+ if (!mouseRightClickEvent) {
+ // 添加右键事件
+ addMapPointEvent()
+ }
+ })
}
// const createPointOrPolyline = () => {}
@@ -219,12 +204,7 @@
const nextPoint = points[index + 1]?.position
if (prevPoint) {
// 获取中心点
- const centerPoint = Cesium.Cartesian3.lerp(
- currentPoint,
- prevPoint,
- 0.5,
- new Cesium.Cartesian3(),
- )
+ const centerPoint = Cesium.Cartesian3.lerp(currentPoint, prevPoint, 0.5, new Cesium.Cartesian3())
// 获取两个点之间的距离
let distance = Cesium.Cartesian3.distance(currentPoint, prevPoint)
distance = Math.round(distance)
@@ -232,12 +212,7 @@
}
if (nextPoint) {
// 获取中心点
- const centerPoint = Cesium.Cartesian3.lerp(
- currentPoint,
- nextPoint,
- 0.5,
- new Cesium.Cartesian3(),
- )
+ const centerPoint = Cesium.Cartesian3.lerp(currentPoint, nextPoint, 0.5, new Cesium.Cartesian3())
// 获取两个点之间的距离
let distance = Cesium.Cartesian3.distance(currentPoint, nextPoint)
distance = Math.round(distance)
@@ -274,13 +249,8 @@
title: `在${Number(selectPointIndex.value) + 1}号航点前插入`,
},
]
- const defaultEvents = [
- { class: 'finally-point', title: '在最后航点新增航点' },
- ]
- const events =
- selectPointIndex.value !== null
- ? [...defaultEvents, ...pointEvents]
- : defaultEvents
+ const defaultEvents = [{ class: 'finally-point', title: '在最后航点新增航点' }]
+ const events = selectPointIndex.value !== null ? [...defaultEvents, ...pointEvents] : defaultEvents
popupDom = createPointPopupDom(events)
global.$viewer.container.appendChild(popupDom)
popupDom.style.transform = `translate3d(${x}px, ${y}px, 0)`
@@ -330,84 +300,53 @@
`
return pointPopup
}
+
// 给DOM添加点击事件
const addMenuEvent = (dom: HTMLElement, position: Cesium.Cartesian2) => {
dom.addEventListener('click', (e: any) => {
removeCesiumChildDom(popupDom)
const className = e.target.className
- const c3Position = global.$viewer.scene.globe.pick(
- global.$viewer.camera.getPickRay(position),
- global.$viewer.scene,
- )
+ const c3Position = global.$viewer.scene.globe.pick(global.$viewer.camera.getPickRay(position), global.$viewer.scene)
const c2Postion = ellipsoid.cartesianToCartographic(c3Position)
const longitude = Cesium.Math.toDegrees(c2Postion.longitude)
const latitude = Cesium.Math.toDegrees(c2Postion.latitude)
- const height = 70
- const createPointPosition = Cesium.Cartesian3.fromDegrees(
- longitude,
- latitude,
+ // 获取全局高度
+ const globalHeight: any = getKmlParams(kmlStr.value, true, {
+ name: 'globalHeight',
+ findRegx: '([\\s\\S]*?)',
+ })
+ const height = Number(globalHeight[1])
+ const createPointPosition = Cesium.Cartesian3.fromDegrees(longitude, latitude, height)
+ const entity: Cesium.Entity = global.$viewer.entities.add({
+ position: createPointPosition,
+ })
+ // 加入kml文件中
+ const setting = {
+ Point: {
+ coordinates: `${longitude},${latitude}`,
+ },
+ index: tragetPointArr.value.length,
height,
- )
- let entity: Cesium.Entity | any = null
+ ellipsoidHeight: height,
+ }
if (className === 'finally-point') {
- entity = global.$viewer.entities.add({
- position: createPointPosition,
- label: {
- text: 'ASL:70m',
- font: '13px monospace',
- showBackground: true,
- horizontalOrigin: Cesium.HorizontalOrigin.CENTER,
- verticalOrigin: Cesium.VerticalOrigin.BOTTOM,
- disableDepthTestDistance: Number.POSITIVE_INFINITY,
- pixelOffset: new Cesium.Cartesian2(0, -40),
- },
- billboard: {
- image: createBillboard(tragetPointArr.value.length + 1, '#61d396'),
- pixelOffset: new Cesium.Cartesian2(0, -20),
- },
- point: {
- pixelSize: 20,
- color: Cesium.Color.GHOSTWHITE,
- outlineColor: Cesium.Color.BLACK,
- },
- })
- const prePostion =
- tragetPointArr.value[tragetPointArr.value.length - 1].position
- const polylinePositions = [prePostion, createPointPosition]
- addPolyline({
- polyline: {
- positions: polylinePositions,
- width: 7,
- material: new ImageTrailMaterial({
- backgroundColor: Cesium.Color.fromBytes(96, 210, 149),
- image: getResource('arrow-right.png'),
- imageW: 7,
- duration: 0,
- animation: false,
- }),
- clampToGround: false, // 关闭贴地效果,保留高度
- },
- })
- addPolyline({
- polyline: {
- positions: Cesium.Cartesian3.fromDegreesArrayHeights([
- longitude,
- latitude,
- height,
- longitude,
- latitude,
- 0,
- ]),
- width: 1,
- material: new Cesium.PolylineDashMaterialProperty({
- color: Cesium.Color.WHITE,
- }),
- },
- })
+ removeAllDataSource()
+ removeAllPoint()
+ kmzUtils.writePoint(setting)
+ globalEntities.value.push(entity)
+ mapDraw.drawWayline(globalEntities.value, kmlStr.value)
tragetPointArr.value.push({
position: createPointPosition,
eventList: [],
})
+ }
+ if (className === 'add-prev-point') {
+ // console.log(1)
+ }
+ if (className === 'add-next-point') {
+ // const index = selectPointIndex.value
+ // globalEntities.value.splice(index, 0, entity)
+ // console.log()
}
// clearCesiumMap()
// createMapMarker(undefined, [...kmlEntities.value, entity])
@@ -437,6 +376,11 @@
}
}
+// 保存文件
+const saveWaylineFile = () => {
+ kmzUtils.save()
+}
+
onMounted(() => {
// 清空画布
clearCesiumMap()
diff --git a/src/utils/cesium/kmz.ts b/src/utils/cesium/kmz.ts
index ed14c43..fd1c3a8 100644
--- a/src/utils/cesium/kmz.ts
+++ b/src/utils/cesium/kmz.ts
@@ -2,6 +2,8 @@
import { mode } from 'crypto-js'
import JsZip from 'jszip'
+const noWmpl: string[] = ['Folder', 'Placemark', 'Point', 'coordinates']
+
/**
* @description: 读取kmz文件解析出kml文件
* @param {string} filePath 文件地址
@@ -15,7 +17,10 @@
.then((kmzZip) => {
// 通过文件名找到 KML 文件
const kmlFile = kmzZip.file(/\.kml$/i)[0]
- return kmlFile.async('text')
+ return {
+ file: kmzZip,
+ content: kmlFile.async('text')
+ }
})
}
@@ -47,11 +52,14 @@
if (Object.prototype.toString.call(settingParmas[key]) === '[object Object]') {
let parmaStr = ''
Object.keys(settingParmas[key]).forEach((v) => {
- parmaStr += `<wpml:${v}>${settingParmas[key][v]}</wpml:${v}>`
+ const xml = noWmpl.includes(key) ? `<${v}>${settingParmas[key][v]}</${v}>` : `<wpml:${v}>${settingParmas[key][v]}</wpml:${v}>`
+ parmaStr += xml
})
- paramGroup += `<wpml:${key}>${parmaStr}</wpml:${key}>`
+ const xml = noWmpl.includes(key) ? `<${key}>${parmaStr}</${key}>` : `<wpml:${key}>${parmaStr}</wpml:${key}>`
+ paramGroup += xml
} else {
- paramGroup += `<wpml:${key}>${settingParmas[key]}</wpml:${key}>`
+ const xml = noWmpl.includes(key) ? `<${key}>${settingParmas[key]}</${key}>` : `<wpml:${key}>${settingParmas[key]}</wpml:${key}>`
+ paramGroup += xml
}
})
return paramGroup
diff --git a/src/utils/cesium/mapUtils.ts b/src/utils/cesium/mapUtils.ts
index c84671c..ef5b8f6 100644
--- a/src/utils/cesium/mapUtils.ts
+++ b/src/utils/cesium/mapUtils.ts
@@ -1,11 +1,6 @@
import * as Cesium from 'cesium'
-export const getLngLatDistance = (
- lat1: number,
- lng1: number,
- lat2: number,
- lng2: number,
-) => {
+export const getLngLatDistance = (lat1: number, lng1: number, lat2: number, lng2: number) => {
const radLat1 = (lat1 * Math.PI) / 180.0
const radLat2 = (lat2 * Math.PI) / 180.0
const a = radLat1 - radLat2
@@ -13,10 +8,7 @@
let s =
2 *
Math.asin(
- Math.sqrt(
- Math.pow(Math.sin(a / 2), 2) +
- Math.cos(radLat1) * Math.cos(radLat2) * Math.pow(Math.sin(b / 2), 2),
- ),
+ Math.sqrt(Math.pow(Math.sin(a / 2), 2) + Math.cos(radLat1) * Math.cos(radLat2) * Math.pow(Math.sin(b / 2), 2)),
)
s = s * 6378.137 // EARTH_RADIUS;
s = Math.round(s * 10000) / 10000
@@ -63,3 +55,22 @@
ctx.closePath()
return billboard
}
+
+// 获取当前经纬度海拔
+export const getHaeHeight = (start: { longitude: number; latitude: number; height: number }, end: { longitude: number; latitude: number; height: number }) => {
+ const ellipsoid = Cesium.Ellipsoid.WGS84 // 选择合适的椭圆体模型
+ // const { longitude, latitude, height } = start
+ // const { longitude: endLng, latitude: endLat, height: endHeight } = end
+ // const startC3Position = new Cesium.Cartographic(longitude, latitude, height)
+ // const endC3Position = new Cesium.Cartographic(endLng, endLat, endHeight)
+ // const startCartesianPosition = ellipsoid.cartographicToCartesian(startC3Position)
+ // const endCartesianPosition = ellipsoid.cartographicToCartesian(endC3Position)
+ // // 计算两个位置之间的距离
+ // const distance = new Cesium.EllipsoidGeodesic(startCartesianPosition, endCartesianPosition, ellipsoid)
+ // return distance
+ const { longitude, latitude, height } = end
+ const cartographic = Cesium.Cartographic.fromDegrees(longitude, latitude, height)
+ const cartesianPosition = ellipsoid.cartographicToCartesian(cartographic)
+ const haeHeight = ellipsoid.cartesianToCartographic(cartesianPosition).height
+ return haeHeight
+}
diff --git a/src/utils/cesium/use-kmz-tsa.ts b/src/utils/cesium/use-kmz-tsa.ts
index a37e16e..2f49acf 100644
--- a/src/utils/cesium/use-kmz-tsa.ts
+++ b/src/utils/cesium/use-kmz-tsa.ts
@@ -1,11 +1,47 @@
-import { ref } from 'vue'
+import { ref, getCurrentInstance } from 'vue'
import { analyzeKmzFile, getKmlParams, generateKmlFormat } from '/@/utils/cesium/kmz'
+import { getLngLatAltitude } from './mapUtils'
+import JSZIP from 'jszip'
+import { saveAs } from 'file-saver'
+
+const JsZip = new JSZIP()
const kmlStr = ref('')
+const kmzFile = ref<any>(null)
+
+// 点位参数
+const placemark: any = {
+ Point: {
+ coordinates: '',
+ },
+ index: 0,
+ executeHeight: 80,
+ height: 80,
+ waypointSpeed: 10,
+ waypointHeadingParam: {
+ waypointHeadingMode: 'followWayline',
+ waypointHeadingAngle: 0,
+ waypointPoiPoint: '0.000000,0.000000,0.000000',
+ waypointHeadingPathMode: 'followBadArc',
+ waypointHeadingPoiIndex: 0,
+ },
+ waypointTurnParam: {
+ waypointTurnMode: 'toPointAndStopWithDiscontinuityCurvature',
+ waypointTurnDampingDist: 0.2,
+ },
+ useGlobalHeight: 1,
+ useGlobalSpeed: 1,
+ useGlobalHeadingParam: 1,
+ useGlobalTurnParam: 1,
+ useStraightLine: 1,
+ actionGroup: {},
+}
const useKmzTsa = () => {
const init = async (fileUrl: string, fileContent?: string) => {
- const kmzRes: string = await analyzeKmzFile(fileUrl)
+ const fileRes = await analyzeKmzFile(fileUrl)
+ kmzFile.value = fileRes.file
+ const kmzRes = await fileRes.content
if (fileContent) {
kmlStr.value = fileContent
return false
@@ -33,10 +69,26 @@
kmlStr.value = str
}
- const write = (settingParmas: any = {}, name?: string, isWpml?: boolean = false) => {}
-
- const del = () => {
+ // const write = (settingParmas: any = {}, name: string) => {
+ // }
+ const writePoint = (settingParmas: any = {}) => {
+ Object.keys(settingParmas).forEach((key: string) => {
+ placemark[key] = settingParmas[key]
+ })
+ const Placemark = `<Placemark>${generateKmlFormat(placemark)}</Placemark>`
+ const points: RegExpMatchArray = getKmlParams(kmlStr.value, false, {
+ name: 'Placemark',
+ findRegx: '([\\s\\S]*?)',
+ mode: 'g',
+ }) || ['']
+ const lastPoint = points[points.length - 1]
+ const index = kmlStr.value.indexOf(lastPoint)
+ const beforeStr = kmlStr.value.slice(0, index)
+ const afterStr = kmlStr.value.slice(index + lastPoint.length)
+ kmlStr.value = beforeStr + lastPoint + Placemark + afterStr
}
+
+ const del = () => {}
const edit = (settingParmas: any = {}, keyName?: string, isKeyWpml: boolean = false) => {
Object.keys(settingParmas).forEach((key: string) => {
@@ -50,7 +102,7 @@
const regxVal: any = getKmlParams(kmlStr.value, true, {
name: 'height',
findRegx: '([\\s\\S]*?)',
- mode: 'g'
+ mode: 'g',
})
regxVal.forEach((heightStr: string) => {
const rstr = generateKmlFormat({ height: settingParmas[key] })
@@ -66,13 +118,18 @@
}
const save = () => {
- console.log(kmlStr.value)
+ JsZip.file('wpmz/template.kml', kmlStr.value)
+ kmzFile.value.file('wpmz/template.kml', kmlStr.value)
+ JsZip.generateAsync({ type: 'blob' }).then((content) => {
+ saveAs(content, '新建航线-' + new Date().toLocaleString() + '.kmz')
+ })
}
return {
init,
create,
- write,
+ // write,
+ writePoint,
del,
edit,
save,
diff --git a/src/utils/cesium/use-map-draw.ts b/src/utils/cesium/use-map-draw.ts
index 3734bd9..c088045 100644
--- a/src/utils/cesium/use-map-draw.ts
+++ b/src/utils/cesium/use-map-draw.ts
@@ -123,7 +123,8 @@
let cartesianArr: Cesium.Cartesian3[] = []
// 绘制路线
- const drawWayline = async (entities: Cesium.Entity[], kmlStr: string) => {
+ const drawWayline = async (entities?: Cesium.Entity[], kmlStr?: string) => {
+ console.log(kmlStr)
if (!entities && !kmlStr) {
dataSource.show = false
}
@@ -137,7 +138,8 @@
if (kmlStr) {
kmlRes = kmlStr
} else {
- kmlRes = await analyzeKmzFile(fileUrl)
+ const fileRes = await analyzeKmzFile(fileUrl)
+ kmlRes = await fileRes.content
}
// 所有航点
kmlPoints = getKmlParams(kmlRes, false, {
@@ -293,7 +295,8 @@
if (kmlStr) {
kmlRes = kmlStr
} else {
- await analyzeKmzFile(fileUrl)
+ const fileRes = await analyzeKmzFile(fileUrl)
+ kmlRes = await fileRes.content
}
// 所有航点
const points = getKmlParams(kmlRes, false, {
--
Gitblit v1.9.3