GuLiMmo
2024-03-19 aec00ecc093be803860c8675cbe1c4c776a7cb4e
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
import * as Cesium from 'cesium'
import { analyzeKmzFile, getKmlParams } from '/@/utils/cesium/kmz'
import { getPolylineLength, createTriangleMarker } from '/@/utils/cesium/mapUtils'
import ImageTrailMaterial from '/@/utils/cesium/ImageTrailMaterial'
import { ref } from 'vue'
import { cesiumOperation } from '/@/hooks/use-cesium-tsa'
import { XMLToJSON } from './kmz'
const { addPolyline, getEntityById, removeAllDataSource, removeAllPoint } = cesiumOperation()
 
const getResource = (name: string) => {
  return new URL(`/src/assets/icons/${name}`, import.meta.url).href
}
 
interface waylineDetails {
  title: string
  value: number | string
}
interface eventParmas {
  key: string
  name: string
  distinguish?: string
  icon?: string
}
interface tragetPoint {
  position: Cesium.Cartesian3
  isUseGlobalHeight: boolean
  eventList: eventParmas[] | null
}
 
interface action {
  key: string
  name: string
  icon?: string
}
// 对应事件
const actionList: eventParmas[] = [
  {
    key: 'takePhoto',
    name: '单拍',
    icon: getResource('waylinetool/camera.png'),
  },
  {
    key: 'startRecord',
    name: '开始录像',
    icon: getResource('waylinetool/camera-on.png'),
  },
  {
    key: 'stopRecord',
    name: '结束录像',
    icon: getResource('waylinetool/camera-off.png'),
  },
  {
    key: 'time',
    name: '开始等时间隔拍照',
    icon: getResource('waylinetool/shoot1.png'),
  },
  {
    key: 'distance',
    name: '开始等距间隔拍照',
    icon: getResource('waylinetool/shoot2.png'),
  },
  {
    key: 'zoom',
    name: '变焦',
    icon: getResource('waylinetool/fd.png'),
  },
  {
    key: 'gimbalRotate',
    distinguish: 'Yaw',
    name: '云台俯仰角',
    icon: getResource('waylinetool/holderyaw.png'),
  },
  {
    key: 'gimbalYawRotate',
    name: '云台偏航角',
    distinguish: 'pitch',
    icon: getResource('waylinetool/holdertilt.png'),
  },
  {
    key: 'rotateYaw',
    name: '飞行器偏航',
    icon: getResource('waylinetool/droneyaw.png'),
  },
  {
    key: 'hover',
    name: '悬停等待',
    icon: getResource('waylinetool/xt.png'),
  },
]
 
const waylinePointsEvent = ref<tragetPoint[]>([])
// 路线详情
const waylineDetails = reactive<waylineDetails[]>([
  {
    title: '航线长度',
    value: '0',
  },
  {
    title: '预计执行时间',
    value: '0',
  },
  {
    title: '航点',
    value: 0,
  },
  {
    title: '照片',
    value: 0,
  },
])
// kml中的全部实体
const kmlEntities = ref<Cesium.Entity[]>([])
 
const selectPointIndex = ref<number | null>(null)
 
const useMapDraw = (
  dataSource: Cesium.DataSource | any,
  entitiesList: Cesium.Entity[] | any,
  fileUrl: string | any,
  global: any,
) => {
  const ellipsoid = global.$viewer.scene.globe.ellipsoid
  //  记录点位信息
  let cartesianArr: Cesium.Cartesian3[] = []
 
  // 绘制路线
  const drawWayline = async (entities?: Cesium.Entity[], kmlStr?: string) => {
    if (!entities && !kmlStr) {
      dataSource.show = false
    }
    let kmlEntityArr = entities || [...entitiesList]
    if (dataSource) {
      kmlEntityArr = dataSource.entities.values[0]._children
      kmlEntities.value = kmlEntityArr
    }
    // 获取所有点位
    let kmlRes = ''
    if (kmlStr) {
      removeAllDataSource()
      removeAllPoint()
      kmlRes = kmlStr
    } else {
      const fileRes = await analyzeKmzFile(fileUrl)
      kmlRes = await fileRes.fileInfoObj['wpmz/template.kml']
    }
    const kmlJson = XMLToJSON(kmlRes)
    // 所有航点
    const kmlPoints = kmlJson.Document.Folder.Placemark
    // 起飞点
    let btmStartPoint = null
    // 获取文件中的起飞点
    const startPointPosition = kmlJson.Document.missionConfig.takeOffRefPoint['#text'].split(',')
    btmStartPoint = Cesium.Cartesian3.fromDegrees(
      Number(startPointPosition[1]),
      Number(startPointPosition[0]),
      Number(startPointPosition[2]),
    )
    // 判断是否存在实体集
    if (entities) {
      cartesianArr = []
      waylinePointsEvent.value = []
    }
    // 修改点位样式
    for (let i = 0; i < kmlEntityArr.length; i++) {
      const entity: any = kmlEntityArr[i]
      // 将cartographic3D坐标转换为正常坐标
      const c3Position = entity.position._value
      const c2Postion = ellipsoid.cartesianToCartographic(c3Position)
      const longitude = Cesium.Math.toDegrees(c2Postion.longitude)
      const latitude = Cesium.Math.toDegrees(c2Postion.latitude)
      // 获取当前航点中的值
      const point = kmlPoints[i]
      const getHaeHeight = point.ellipsoidHeight['#text']
      const getPointHeight = point.height['#text']
      // 获取是否使用全局高度
      const isUseGlobalHeight = point?.useGlobalHeight ? point.useGlobalHeight['#text'] : 0
      const AslHeight = Number(getPointHeight)
      const HeaHeight = Number(getHaeHeight)
      entity.position = Cesium.Cartesian3.fromDegrees(longitude, latitude, AslHeight)
      // 创建广告牌信息
      const title = Number(i + 1) === 1 ? 'S' : i + 1
      let billboard = null
      if (isUseGlobalHeight) {
        billboard = createTriangleMarker(title, '#61d396')
      } else {
        billboard = createTriangleMarker(title, '#409eff')
      }
      // 修改id
      entity._id = 'tragetPoint' + i
      // 修改广告牌样式
      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),
        show: false,
      })
      // 修改点的信息
      entity.point = new Cesium.PointGraphics({
        pixelSize: 20,
        color: Cesium.Color.GHOSTWHITE,
        outlineColor: Cesium.Color.BLACK,
      })
      if (entities) {
        global.$viewer.entities.add(entity)
      }
      // 创建虚线
      addPolyline({
        id: 'dashLine' + i,
        polyline: {
          positions: Cesium.Cartesian3.fromDegreesArrayHeights([
            longitude,
            latitude,
            AslHeight,
            longitude,
            latitude,
            0,
          ]),
          width: 1,
          material: new Cesium.PolylineDashMaterialProperty({
            color: Cesium.Color.WHITE,
          }),
        },
      })
      cartesianArr.push(entity.position._value)
      // 当前航线点位事件信息等
      waylinePointsEvent.value.push({
        position: entity.position._value,
        isUseGlobalHeight,
        eventList: [],
      })
    }
    // 创建起飞位置
    global.$viewer.entities.add({
      id: 'dronePosition',
      position: btmStartPoint,
      billboard: {
        image: getResource('dock.png'),
        width: 36,
        height: 36,
      },
    })
    // 绘制链接线
    addPolyline({
      id: 'entityLine',
      polyline: {
        positions: [btmStartPoint, ...cartesianArr],
        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, // 关闭贴地效果,保留高度
      },
    })
    // 获取航线详情
    getWaylineDetails(kmlRes)
    if (!entities && !kmlStr) {
      dataSource.show = true
    }
    global.$viewer.flyTo(getEntityById('entityLine'), {
      offset: new Cesium.HeadingPitchRange(0, -90, 600),
    })
  }
  //   获取航线详情
  const getWaylineDetails = (kmlStr: string) => {
    // 获取当前航线全局速度
    const kmlJson = XMLToJSON(kmlStr).Document
    const getGlobalSpeed = kmlJson.Folder.autoFlightSpeed['#text']
    const speed = Number(getGlobalSpeed)
    const lineEntity = getEntityById('entityLine')
    // 获取距离
    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'
 
    // 获取事件
    getPointEvent(kmlStr || null)
  }
  // 获取航线点位事件
  const getPointEvent = async (kmlStr: string | null) => {
    let kmlRes = ''
    if (kmlStr) {
      kmlRes = kmlStr
    } else {
      const fileRes = await analyzeKmzFile(fileUrl)
      kmlRes = await fileRes.fileInfoObj['wpmz/template.kml']
    }
    const kmlJson = XMLToJSON(kmlRes).Document
    const points = kmlJson.Folder?.Placemark
    let takePhotoNum = 0
    points?.forEach((point: { actionGroup: any }, index: number) => {
      if (Reflect.has(point, 'actionGroup')) {
        const action = point.actionGroup.action
        if (Array.isArray(action)) {
          action.forEach((item) => {
            const { actionActuatorFunc } = item
            actionActuatorFunc?.['#text'] === 'takePhoto' && takePhotoNum++
            const actionObj: eventParmas | any = actionList.find((event) => actionActuatorFunc['#text'] === event.key)
            waylinePointsEvent.value[index].eventList?.push(actionObj)
          })
        } else {
          const { actionActuatorFunc } = action
          actionActuatorFunc['#text'] === 'takePhoto' && takePhotoNum++
          const actionObj: eventParmas | any = actionList.find((item) => actionActuatorFunc['#text'] === item.key)
          waylinePointsEvent.value[index].eventList?.push(actionObj)
        }
      }
    })
    waylineDetails[3].value = takePhotoNum
  }
  const clearWaylineData = () => {
    kmlEntities.value = []
    waylinePointsEvent.value = []
  }
 
  return {
    waylinePointsEvent,
    waylineDetails,
    kmlEntities,
    drawWayline,
    getWaylineDetails,
    clearWaylineData,
  }
}
 
export { waylinePointsEvent, waylineDetails, kmlEntities, selectPointIndex }
export default useMapDraw