forked from drone/command-center-dashboard

罗广辉
2025-04-21 2800fa4f32f3900509cb4d6eefaf2bfaf54efdd7
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
/*
 * @Author: GuLiMmo 2820890765@qq.com
 * @Date: 2024-03-22 14:17:13
 * @LastEditors: GuLiMmo 2820890765@qq.com
 * @LastEditTime: 2024-04-17 11:12:20
 * @FilePath: /bigScreen/src/utils/cesium/common.js
 * @Description:
 */
import * as Cesium from 'cesium'
import JsZip from 'jszip'
import _ from 'lodash'
import axios from 'axios'
import { analyzeKmzFile, XMLToJSON } from './kmz'
import { getCenterPoint, getLnglatDist, getShortestDistance } from './mapUtil'
 
// 图斑航线计算
export const polygonRoutePlanning = (polygonList, startPostion) => {
    // 起始点位
    const { longitude, latitude } = startPostion
    // 计算中心点
    const polygonCenterArr = polygonList.map(polygon => {
        const newPolygon = [...new Set(polygon.map(lnglat => lnglat.join(',')))]
        return {
            center: getCenterPoint(polygon),
            polygon: newPolygon.map(item => item.split(',')),
        }
    })
    // 机场到中心点的距离排序
    const airportDistanceArr = polygonCenterArr.sort((prev, next) => {
        const prevDistance = getLnglatDist(longitude, latitude, prev.center.lng, prev.center.lat)
        const nextDistance = getLnglatDist(longitude, latitude, next.center.lng, next.center.lat)
        return prevDistance - nextDistance
    })
 
    const sortPolygon = []
    function getFirstPolygon(arr, start) {
        const { slongitude, slatitude } = start
        // 机场到中心点的距离排序
        const airportDistanceArr = arr.sort((prev, next) => {
            const prevDistance = getLnglatDist(slongitude, slatitude, prev.center.lng, prev.center.lat)
            const nextDistance = getLnglatDist(slongitude, slatitude, next.center.lng, next.center.lat)
            return prevDistance - nextDistance
        })
        const polygon = _.cloneDeep(airportDistanceArr[0])
        if (polygon === void 0) return
        sortPolygon.push(polygon)
        airportDistanceArr.splice(0, 1)
        if (airportDistanceArr.length > 0) {
            getFirstPolygon(airportDistanceArr, {
                slongitude: polygon.center.lng,
                slatitude: polygon.center.lat,
            })
        }
    }
    getFirstPolygon(polygonCenterArr, {
        slongitude: longitude,
        slatitude: latitude,
    })
    // 计算图斑内点位飞行顺序
    let result = [[longitude, latitude]]
    sortPolygon.forEach((item, index) => {
        const { polygon } = item
        // 取出当前图斑之前最后一个点
        const prevPolygon = result[result.length - 1]
        const [slng, slat] = prevPolygon
        const nextPolygon = airportDistanceArr[index + 1]
        // 求出距离上一个点最近的点,作为第一个点
        const sequence = polygon.sort((prev, next) => {
            const [prevLng, prevLat] = prev
            const [nextLng, nextLat] = next
            const prevDistance = getLnglatDist(slng, slat, prevLng, prevLat)
            const nextDistance = getLnglatDist(slng, slat, nextLng, nextLat)
            return prevDistance - nextDistance
        })
        // 第一个点位
        const firstLnglat = [...sequence[0]]
        // 去除第一个点位
        const cloneSequence = _.cloneDeep(sequence)
        cloneSequence.splice(0, 1)
        if (nextPolygon) {
            // 获取两个经纬度组两个最近的点位
            const { index: lnglatIndex } = getShortestDistance(cloneSequence, nextPolygon.polygon)
            const lastLnglat = _.cloneDeep(cloneSequence[lnglatIndex[0]])
            // 删除飞行的最后一个点
            cloneSequence.splice(lnglatIndex[0], 1)
            const centerLnglatList = cloneSequence.sort((prev, next) => {
                const [prevLng, prevLat] = prev
                const [nextLng, nextLat] = next
                const prevDistance = getLnglatDist(longitude, latitude, prevLng, prevLat)
                const nextDistance = getLnglatDist(longitude, latitude, nextLng, nextLat)
                return prevDistance - nextDistance
            })
            result = [...result, firstLnglat, ...centerLnglatList, lastLnglat]
        } else {
            // const last = polygon.sort((prev, next) => {
            //   const [prevLng, prevLat] = prev;
            //   const [nextLng, nextLat] = next;
            //   const prevDistance = getLnglatDist(longitude, latitude, prevLng, prevLat);
            //   const nextDistance = getLnglatDist(longitude, latitude, nextLng, nextLat);
            //   return prevDistance - nextDistance;
            // });
            result = [...result, ...sequence]
            // result = [...result, ...last]
        }
    })
    return result
}
 
export const getWaylineFilePoints = async fileUrl => {
    const fileRes = await analyzeKmzFile(fileUrl)
    const waylineContent = await fileRes['fileInfoObj']?.['wpmz/waylines.wpml']
    const xml = XMLToJSON(waylineContent)
    const placemarkArr = xml?.Document?.Folder.Placemark
    const points = placemarkArr.map(placemark => {
        const lnglat = placemark.Point.coordinates?.['#text'].split(',')
        return {
            longitude: lnglat[0],
            latitude: lnglat[1],
        }
    })
    return points
}
 
// 传入方向,计算移动点位经纬度
export function movePosition(lon, lat, heading, direction) {
    // 计算朝向角度的弧度值(Cesium 是基于地理坐标系,heading=0 指向正北)
    const headingRad = Cesium.Math.toRadians(heading)
    const moveStep = 0.00005 // 移动步长
    let newLon = lon
    let newLat = lat
 
    switch (direction) {
        case 'W': // 向前(heading 方向)
            newLon += moveStep * Math.sin(headingRad)
            newLat += moveStep * Math.cos(headingRad)
            break
 
        case 'S': // 向后(反方向)
            newLon -= moveStep * Math.sin(headingRad)
            newLat -= moveStep * Math.cos(headingRad)
            break
 
        case 'D': // 向右(heading + 90°)
            newLon += moveStep * Math.cos(headingRad)
            newLat -= moveStep * Math.sin(headingRad)
            break
 
        case 'A': // 向左(heading - 90°)
            newLon -= moveStep * Math.cos(headingRad)
            newLat += moveStep * Math.sin(headingRad)
            break
 
        default:
            console.warn('无效方向')
            return null
    }
 
    return { longitude: newLon, latitude: newLat }
}
 
/**
 * 添加蓝色滤镜
 * @param options
 * @param viewer
 * @param layer
 */
export const addBlueFilter = (options, viewer, layer) => {
    if (layer){
        layer.brightness = 0.6    // 亮度(默认值)
        layer.contrast = 1.8     // 对比度(负值降低对比度)
        layer.hue = 1           // 色相(弧度值,3.0可能导致紫色)
        layer.saturation = 0    // 增加饱和度强化蓝色
        layer.gamma = 0.3         // 伽马校正(小于1.0使颜色更鲜艳)
    }
 
    const { bInvertColor, bFilterColor, filterColor } = options
 
    const color = new Cesium.Color.fromCssColorString(filterColor)
    const filterRGB = [
        Math.round(color.red * 255),
        Math.round(color.green * 255),
        Math.round(color.blue * 255)
    ]
    let fragShader = viewer.scene.globe._surfaceShaderSet.baseFragmentShaderSource.sources
    for (let i = 0; i < fragShader.length; i++) {
        const strS = 'color = czm_saturation(color, textureSaturation);\n#endif\n'
        let strT = 'color = czm_saturation(color, textureSaturation);\n#endif\n'
        if (bInvertColor) {
            strT += `
          color.r = 1.0 - color.r;
          color.g = 1.0 - color.g;
          color.b = 1.0 - color.b;
        `
        }
        if (bFilterColor) {
            strT += `
          color.r = color.r * ${filterRGB[0]}.0/255.0;
          color.g = color.g * ${filterRGB[1]}.0/255.0;
          color.b = color.b * ${filterRGB[2]}.0/255.0;
        `
        }
        fragShader[i] = fragShader[i].replace(strS, strT)
    }
}