From d87242f609a6ebaba6f2b45b2c0b41f961e92d4b Mon Sep 17 00:00:00 2001
From: GuLiMmo <2820890765@qq.com>
Date: Fri, 01 Mar 2024 20:16:00 +0800
Subject: [PATCH] update
---
src/hooks/use-cesium-tsa.ts | 24 ++
src/pages/page-web/projects/components/route-edit/index.vue | 373 +++++++++++++++++++++++++++++++++++++++++++---
src/pages/page-web/projects/wayline.vue | 2
src/components/cesiumMap/cesium.vue | 1
src/utils/cesium/kmz.ts | 2
src/pages/page-web/projects/components/route-edit/components/setting.vue | 41 ++++
src/utils/cesium/mapUtils.ts | 1
7 files changed, 412 insertions(+), 32 deletions(-)
diff --git a/src/components/cesiumMap/cesium.vue b/src/components/cesiumMap/cesium.vue
index 771efdb..390d7c7 100644
--- a/src/components/cesiumMap/cesium.vue
+++ b/src/components/cesiumMap/cesium.vue
@@ -151,6 +151,7 @@
<style scoped lang="scss">
.cesium {
+ position: relative;
:deep(.cesium-viewer-bottom) {
display: none !important;
}
diff --git a/src/hooks/use-cesium-tsa.ts b/src/hooks/use-cesium-tsa.ts
index bc22c3b..a25ff3b 100644
--- a/src/hooks/use-cesium-tsa.ts
+++ b/src/hooks/use-cesium-tsa.ts
@@ -184,7 +184,7 @@
}
})
}
- // 添加点击事件
+ // 添加左键点击事件
let leftClickHandler: Cesium.ScreenSpaceEventHandler
const addClickEvent = (sid: string, cb: Function) => {
if (leftClickHandler) {
@@ -198,9 +198,25 @@
}
}, Cesium.ScreenSpaceEventType.LEFT_CLICK)
}
- // 移除事件
+ // 移除左键事件
const removeClickEvent = () => {
leftClickHandler.removeInputAction(Cesium.ScreenSpaceEventType.LEFT_CLICK)
+ }
+
+ let rightClickHandler: Cesium.ScreenSpaceEventHandler
+ const addRightClick = (sid: string, cb: Function) => {
+ if (leftClickHandler) {
+ removeRightClickEvent()
+ }
+ rightClickHandler = new Cesium.ScreenSpaceEventHandler(viewer?.scene.canvas)
+ rightClickHandler.setInputAction(function (click: { position: Cesium.Cartesian2 }) {
+ const pick = viewer?.scene.pick(click.position)
+ cb(click, pick, viewer, handler)
+ }, Cesium.ScreenSpaceEventType.RIGHT_CLICK)
+ }
+ // 移除右键事件
+ const removeRightClickEvent = () => {
+ rightClickHandler.removeInputAction(Cesium.ScreenSpaceEventType.RIGHT_CLICK)
}
// 添加线段
@@ -356,6 +372,8 @@
loadGeoJson,
removeAllDataSource,
addClickEvent,
- removeClickEvent
+ removeClickEvent,
+ addRightClick,
+ removeRightClickEvent
}
}
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 19832fc..1548230 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
@@ -20,6 +20,16 @@
<a-switch />
</div>
</div>
+ <div class="height-mode common">
+ <div class="title">航线高度模式</div>
+ <div class="mode-box">
+ <a-radio-group button-style="solid">
+ <a-radio-button value="a">绝对高度</a-radio-button>
+ <a-radio-button value="b">相对起飞高度</a-radio-button>
+ <a-radio-button value="c">相对地面高度</a-radio-button>
+ </a-radio-group>
+ </div>
+ </div>
</div>
</template>
<slot name="show"></slot>
@@ -31,6 +41,9 @@
const getResource = (name: string) => {
return new URL(`/src/assets/icons/${name}`, import.meta.url).href
}
+
+const waylineSetting = reactive({})
+
</script>
<style lang="scss" scoped>
@@ -74,6 +87,32 @@
display: flex;
.title {
font-weight: bold;
+ margin-right: auto;
+ }
+ }
+ }
+ .height-mode {
+ .mode-box {
+ margin-top: 10px;
+ :deep() {
+ .ant-radio-group {
+ display: flex;
+ .ant-radio-button-wrapper {
+ flex: 1;
+ text-align: center;
+ background-color: #3c3c3c;
+ border: 1px solid #101010;
+ color: #fff;
+ font-weight: bold;
+ border: 0;
+ &::before {
+ background-color: #101010;
+ }
+ &-checked {
+ background-color: #409eff !important;
+ }
+ }
+ }
}
}
}
@@ -99,5 +138,3 @@
}
}
</style>
-今日情况
-航线展示:照片计算 (已完成)
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 d45b13b..0d6b76a 100644
--- a/src/pages/page-web/projects/components/route-edit/index.vue
+++ b/src/pages/page-web/projects/components/route-edit/index.vue
@@ -7,7 +7,7 @@
</template>
返回
</a-button>
- <!-- <setting>
+ <setting>
<template #show>
<a-button type="text" class="setting-btn">
<div class="router-setting">
@@ -20,7 +20,7 @@
</div>
</a-button>
</template>
- </setting> -->
+ </setting>
</div>
<div class="wayline-info">
<div
@@ -32,7 +32,11 @@
</div>
</div>
<ul class="point-list">
- <li v-for="(item, index) in tragetPointArr" :key="index">
+ <li
+ v-for="(item, index) in tragetPointArr"
+ :key="index"
+ :class="{ 'active-point': index == selectPointIndex }"
+ @click="pointSelect(item, index)">
<div class="graph">
<div class="left"></div>
<div class="right">{{ index + 1 }}</div>
@@ -56,7 +60,7 @@
</template>
<script setup lang="ts">
-import _ from 'lodash'
+import _, { divide } from 'lodash'
import * as Cesium from 'cesium'
import setting from './components/setting.vue'
import { ref, reactive, defineEmits, defineProps, watch, onMounted } from 'vue'
@@ -70,11 +74,17 @@
const { appContext }: any = getCurrentInstance()
const global = appContext.config.globalProperties
-const { removeAllPoint, getEntityById, addPolyline } = cesiumOperation()
+const {
+ removeAllPoint,
+ getEntityById,
+ addPolyline,
+ addRightClick,
+ removeRightClickEvent,
+} = cesiumOperation()
interface waylineDetails {
title: string
- value: string | number
+ value: number | string
}
interface eventParmas {
key: string
@@ -167,6 +177,9 @@
| null
| any = null
+let mouseRightClickEvent: any = null
+
+// 初始化KML,判断当中存在多少事件
const initKML = () => {
analyzeKmzFile(filePath.value).then((kmlRes) => {
// 所有航点
@@ -213,6 +226,15 @@
}
}
})
+ // 判断一共有多少个拍照模式
+ const actionFunc = getKmlParams(point, true, {
+ name: 'actionActuatorFunc',
+ findRegx: 'takePhoto',
+ mode: 'g',
+ })
+ if (actionFunc) {
+ ;(waylineDetails[3] as any).value++
+ }
})
tragetPointArr.value[index].eventList = eventArr
}
@@ -248,6 +270,11 @@
.then((res: any) => {
kmlDataSource = res
createMapMarker(kmlDataSource)
+ initKML()
+ if (!mouseRightClickEvent) {
+ // 添加右键事件
+ addMapPointEvent()
+ }
})
}
@@ -276,14 +303,24 @@
},
])
// 样式
-const createMapMarker = async (dataSource: {
- entities: { values: { _children: any }[] }
- show: boolean
-}) => {
- const ellipsoid = global.$viewer.scene.globe.ellipsoid
- kmlEntity.value = dataSource.entities.values
- dataSource.show = true
- const kmlEntityArr = dataSource.entities.values[0]._children
+const kmlEntities = ref<Cesium.Entity[]>([])
+const ellipsoid = global.$viewer.scene.globe.ellipsoid
+const createMapMarker = async (
+ dataSource:
+ | {
+ entities: { values: { _children: any }[] }
+ show: boolean
+ }
+ | any,
+ entitiesList: Cesium.Entity[] = [],
+) => {
+ dataSource.show = false
+ let kmlEntityArr = [...entitiesList]
+ // kmlEntity.value = dataSource.entities.values
+ if (dataSource) {
+ kmlEntityArr = dataSource.entities.values[0]._children
+ kmlEntities.value = kmlEntityArr
+ }
const cartesianArr: any[] = []
let btmStartPoint = null
// 获取所有的点位
@@ -294,9 +331,15 @@
findRegx: '([\\s\\S]*?)',
mode: 'g',
})
+ // 获取当前航线全局速度
+ const getGlobalSpeed: any = getKmlParams(kmlRes, true, {
+ name: 'autoFlightSpeed',
+ findRegx: '([\\s\\S]*?)',
+ })
+ const speed = Number(getGlobalSpeed[1])
// 修改点位样式信息等
for (let i = 0; i < kmlEntityArr.length; i++) {
- const entity = kmlEntityArr[i]
+ const entity: any = kmlEntityArr[i]
// 将cartographic3D坐标转换为正常坐标
const c3Position = entity.position._value
const c2Postion = ellipsoid.cartesianToCartographic(c3Position)
@@ -305,12 +348,20 @@
// 获取当前航点中的值
const point = points[i]
const getPointHeight: any = getKmlParams(point, true, {
+ name: 'ellipsoidHeight',
+ findRegx: '([\\s\\S]*?)',
+ })
+ const getHaeHeight: any = getKmlParams(point, true, {
name: 'height',
findRegx: '([\\s\\S]*?)',
})
- console.log(getPointHeight[0])
- const height = 100
- entity.position = Cesium.Cartesian3.fromDegrees(longitude, latitude, height)
+ const AslHeight = Number(getPointHeight[1])
+ const HeaHeight = Number(getHaeHeight[1])
+ entity.position = Cesium.Cartesian3.fromDegrees(
+ longitude,
+ latitude,
+ AslHeight,
+ )
if (i === 0) {
btmStartPoint = Cesium.Cartesian3.fromDegrees(longitude, latitude, 0)
}
@@ -322,6 +373,15 @@
entity.billboard = new Cesium.BillboardGraphics({
image: billboard,
pixelOffset: new Cesium.Cartesian2(0, -20),
+ })
+ entity.label = new Cesium.LabelGraphics({
+ text: `ASL:${Math.round(AslHeight)}m\nHAE:${Math.round(HeaHeight)}m`,
+ font: '13px monospace',
+ showBackground: true,
+ horizontalOrigin: Cesium.HorizontalOrigin.CENTER,
+ verticalOrigin: Cesium.VerticalOrigin.BOTTOM,
+ disableDepthTestDistance: Number.POSITIVE_INFINITY,
+ pixelOffset: new Cesium.Cartesian2(0, -40),
})
// 修改点的信息
entity.point = new Cesium.PointGraphics({
@@ -336,7 +396,7 @@
positions: Cesium.Cartesian3.fromDegreesArrayHeights([
longitude,
latitude,
- height,
+ AslHeight,
longitude,
latitude,
0,
@@ -347,6 +407,7 @@
}),
},
})
+ // 获取虚线中心点
cartesianArr.push(entity.position._value)
tragetPointArr.value[i] = {
position: entity.position._value,
@@ -379,14 +440,25 @@
clampToGround: false, // 关闭贴地效果,保留高度
},
})
+ dataSource.show = true
const lineEntity = getEntityById('entityLine')
- const polylineLength = getPolylineLength(lineEntity).toFixed(1) || 0
+ // 获取距离
+ const polylineLength: any = getPolylineLength(lineEntity).toFixed(1) || 0
waylineDetails[0].value = polylineLength + 'm'
+ // 航点数
waylineDetails[2].value = cartesianArr.length
+ // 计算时间
+ const sportTime = polylineLength / speed
+ // 判断有没有超过一分钟
+ const time = sportTime / 60
+ waylineDetails[1].value =
+ Math.trunc(time) + ' m ' + Math.round((time % 1) * 60) + ' s'
global.$viewer.flyTo(lineEntity, {
offset: new Cesium.HeadingPitchRange(0, -90, 300),
})
}
+
+// const createPointOrPolyline = () => {}
// 创建广告牌
const createBillboard = (title: string | number, color: string) => {
@@ -408,14 +480,256 @@
return billboard
}
+// 选择点位
+let prevPointEntity: any = null
+let nextPointEntity: any = null
+// 选中的点
+const selectPointIndex = ref<string | number | any>(null)
+const pointSelect = (value: tragetPoint, index: number) => {
+ removeCesiumChildDom(popupDom)
+ if (selectPointIndex.value === index) {
+ global.$viewer.entities.remove(prevPointEntity)
+ global.$viewer.entities.remove(nextPointEntity)
+ kmlEntities.value.forEach((entity: Cesium.Entity | any, i: number) => {
+ entity.billboard.image = createBillboard(i + 1, '#61d396')
+ })
+ selectPointIndex.value = null
+ return
+ }
+ if (prevPointEntity) {
+ global.$viewer.entities.remove(prevPointEntity)
+ }
+ if (nextPointEntity) {
+ global.$viewer.entities.remove(nextPointEntity)
+ }
+ // 点击点相邻两个点的距离
+ const points = _.cloneDeep(tragetPointArr.value)
+ const currentPoint = points[index]?.position
+ const prevPoint = points[index - 1]?.position
+ const nextPoint = points[index + 1]?.position
+ if (prevPoint) {
+ // 获取中心点
+ const centerPoint = Cesium.Cartesian3.lerp(
+ currentPoint,
+ prevPoint,
+ 0.5,
+ new Cesium.Cartesian3(),
+ )
+ // 获取两个点之间的距离
+ let distance = Cesium.Cartesian3.distance(currentPoint, prevPoint)
+ distance = Math.round(distance)
+ prevPointEntity = createDistanceLabel(centerPoint, distance)
+ }
+ if (nextPoint) {
+ // 获取中心点
+ const centerPoint = Cesium.Cartesian3.lerp(
+ currentPoint,
+ nextPoint,
+ 0.5,
+ new Cesium.Cartesian3(),
+ )
+ // 获取两个点之间的距离
+ let distance = Cesium.Cartesian3.distance(currentPoint, nextPoint)
+ distance = Math.round(distance)
+ nextPointEntity = createDistanceLabel(centerPoint, distance)
+ }
+ // 更新点击点的样式
+ kmlEntities.value.forEach((entity: Cesium.Entity | any, i: number) => {
+ if (i === index) {
+ entity.billboard.image = createBillboard(index + 1, '#f3be4f')
+ } else {
+ entity.billboard.image = createBillboard(i + 1, '#61d396')
+ }
+ })
+ selectPointIndex.value = index
+}
+
+// 添加右键事件,弹出窗口
+const showCreatePointPopup = ref<boolean>(false)
+let popupDom: any = null
+const addMapPointEvent = () => {
+ mouseRightClickEvent = true
+ addRightClick('', (click: { position: Cesium.Cartesian2 }) => {
+ showCreatePointPopup.value = true
+ removeCesiumChildDom(popupDom)
+ const { position } = click
+ const { x, y } = position
+ const pointEvents = [
+ {
+ class: 'add-prev-point',
+ title: `在${Number(selectPointIndex.value) + 1}号航点前插入`,
+ },
+ {
+ class: 'add-next-point',
+ title: `在${Number(selectPointIndex.value) + 1}号航点前插入`,
+ },
+ ]
+ 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)`
+ // 添加点击事件
+ addMenuEvent(popupDom, position)
+ })
+}
+
+// 创建距离标签
+const createDistanceLabel = (position: Cesium.Cartesian3, dist: number) => {
+ return global.$viewer.entities.add({
+ position: position,
+ name: 'distance',
+ label: {
+ text: `${dist}m`,
+ font: '13px monospace',
+ showBackground: true,
+ horizontalOrigin: Cesium.HorizontalOrigin.CENTER,
+ verticalOrigin: Cesium.VerticalOrigin.BOTTOM,
+ disableDepthTestDistance: Number.POSITIVE_INFINITY,
+ pixelOffset: new Cesium.Cartesian2(0, -0),
+ },
+ })
+}
+
+// 创建右键弹窗
+const createPointPopupDom = (arr: any[] = []) => {
+ const pointPopup: HTMLDivElement | any = document.createElement('div')
+ pointPopup.className = 'point-popup'
+ arr.forEach((item) => {
+ const title: HTMLDivElement | any = document.createElement('div')
+ title.innerText = item.title
+ title.className = item.class
+ title.style = `
+ cursor: pointer;
+ padding: 5px 7px;
+ `
+ pointPopup.appendChild(title)
+ })
+ pointPopup.style = `
+ width: 'fit-content';
+ background-color: #232323;
+ position: absolute;
+ top: 0;
+ left: 0;
+ color: #fff;
+ `
+ 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 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,
+ height,
+ )
+ let entity: Cesium.Entity | any = null
+ 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,
+ }),
+ },
+ })
+ tragetPointArr.value.push({
+ position: createPointPosition,
+ eventList: [],
+ })
+ }
+ // clearCesiumMap()
+ // createMapMarker(undefined, [...kmlEntities.value, entity])
+ })
+}
+
+// 移除popup弹窗
+const removeCesiumChildDom = (dom: HTMLElement) => {
+ if (dom) {
+ global.$viewer.container.removeChild(dom)
+ popupDom = null
+ }
+}
+
const backPage = () => {
emits('backFn')
+}
+// 清空画布
+const clearCesiumMap = () => {
+ removeAllPoint()
+ global.$viewer.dataSources.removeAll()
+
+ removeCesiumChildDom(popupDom)
+
+ if (mouseRightClickEvent) {
+ removeRightClickEvent()
+ }
}
onMounted(() => {
// 清空画布
- removeAllPoint()
- global.$viewer.dataSources.removeAll()
+ clearCesiumMap()
initDrawRoute()
})
@@ -423,8 +737,7 @@
// if (kmlDataSource) {
// global.$viewer.dataSources.remove(kmlDataSource)
// }
- removeAllPoint()
- global.$viewer.dataSources.removeAll()
+ clearCesiumMap()
store.commit('SET_WAYLINE_INFO', {
isShow: false,
wayline: {},
@@ -495,6 +808,8 @@
.point-list {
padding: 0;
+ height: calc(100vh - 180px);
+ overflow: auto;
li {
cursor: pointer;
padding: 10px 0;
@@ -509,7 +824,7 @@
.left {
width: 0;
height: 0;
- border-top: 15px solid #2d8cf0;
+ border-top: 15px solid #61d396;
border-right: 10px solid transparent;
border-left: 10px solid transparent;
}
@@ -545,4 +860,12 @@
}
}
}
+.active-point {
+ background-color: #3c3c3c;
+ .graph {
+ .left {
+ border-top-color: #f3bf4e !important;
+ }
+ }
+}
</style>
diff --git a/src/pages/page-web/projects/wayline.vue b/src/pages/page-web/projects/wayline.vue
index 37771e5..ce39371 100644
--- a/src/pages/page-web/projects/wayline.vue
+++ b/src/pages/page-web/projects/wayline.vue
@@ -461,7 +461,7 @@
value: 0
},
])
-function createPointMarker (dataSource: { entities: { values: { _children: any }[] }; show: boolean }) {
+async function createPointMarker (dataSource: { entities: { values: { _children: any }[] }; show: boolean }) {
const ellipsoid = global.$viewer.scene.globe.ellipsoid
kmlEntity.value = dataSource.entities.values
dataSource.show = true
diff --git a/src/utils/cesium/kmz.ts b/src/utils/cesium/kmz.ts
index 3b2e345..47f3964 100644
--- a/src/utils/cesium/kmz.ts
+++ b/src/utils/cesium/kmz.ts
@@ -48,5 +48,5 @@
)
}
}
- return source.match(regx)
+ return source?.match(regx)
}
diff --git a/src/utils/cesium/mapUtils.ts b/src/utils/cesium/mapUtils.ts
index 97297d4..7ea2e20 100644
--- a/src/utils/cesium/mapUtils.ts
+++ b/src/utils/cesium/mapUtils.ts
@@ -23,6 +23,7 @@
return s * 1000
}
+// 获取限polyline长度
export function getPolylineLength (entity: any) {
let length = 0
--
Gitblit v1.9.3