吉安感知网项目-前端
shuishen
2026-02-03 89380e6260a75d1d3b94de687ebcc2f50d50659d
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
import * as Cesium from 'cesium'
import { MapTooltip } from './MapTooltip'
import { DrawPolygon } from './DrawPolygon'
/**
 * 飞到中心点并且所有点在可视范围
 *  @param positionsData 二维数组,每项为 [lon, lat] 或 三维数组 [lon, lat, height]
 *  @param viewer Cesium.Viewer 实例
 *  @param multiple 缩放倍数-默认为4
 *  @param pitch 俯仰角-默认为-90
 */
function flyVisual({ positionsData, viewer, multiple = 4, pitch = -90 }) {
    if (!Array.isArray(positionsData) || positionsData.length === 0) return
 
    // 如果是一个点,加两个点方便后续生成外包围盒
    if (positionsData.length === 1) {
        const [lon, lat, height = 0] = positionsData[0]
        positionsData = [
            [lon + 0.001, lat + 0.001, height],
            [lon - 0.001, lat - 0.001, height],
            [lon, lat, height],
        ]
    }
    const positions = positionsData.map(([lon, lat, height = 0]) =>
        Cesium.Cartesian3.fromDegrees(Number(lon), Number(lat), Number(height || 0))
    )
 
    // 计算最高高度和中心点经纬度
    let maxHeight = -Infinity
    let sumLon = 0,
        sumLat = 0
    for (const [lon, lat, height] of positionsData) {
        sumLon += Number(lon)
        sumLat += Number(lat)
        maxHeight = Math.max(maxHeight, Number(height || 0))
    }
    const centerLon = sumLon / positionsData.length
    const centerLat = sumLat / positionsData.length
    const boundingSphere = Cesium.BoundingSphere.fromPoints(positions)
    // 暂时飞向 BoundingSphere
    viewer.camera.flyToBoundingSphere(Cesium.BoundingSphere.fromPoints(positions), {
        duration: 0,
        offset: {
            heading: Cesium.Math.toRadians(0),
            pitch: Cesium.Math.toRadians(pitch),
            range: boundingSphere.radius * multiple,
        },
        complete: () => {
            // 飞行完成后检查相机高度是否小于最高点
            const cameraHeight = Cesium.Cartographic.fromCartesian(viewer.camera.position).height
            if (cameraHeight < maxHeight) {
                viewer.camera.flyTo({
                    destination: Cesium.Cartesian3.fromDegrees(centerLon, centerLat, maxHeight + 100), // 加100米缓冲
                    duration: 1.5,
                    orientation: {
                        heading: viewer.camera.heading,
                        pitch: viewer.camera.pitch,
                        roll: viewer.camera.roll,
                    },
                })
            }
        },
    })
}
 
// 批量获取点数组经纬度对应高度信息
const getPointPositionsHeight = (data, viewer, droneHeight = null) => {
    return new Promise((resolve, reject) => {
        if (!data || !data.length) {
            resolve([])
            return
        }
        // 假设 viewer 已经初始化并且 terrainProvider 是有效的
        const terrainProvider = viewer?.terrainProvider
        // 创建 Cartographic 对象
        const cartographics = data.map(item => {
            const { lng, lat } = item
            return Cesium.Cartographic.fromDegrees(Number(lng), Number(lat))
        })
        // 获取地形数据的Promise
        const promise = Cesium.sampleTerrainMostDetailed(terrainProvider, cartographics)
        // 使用 Cesium.when 处理 Promise
        promise
            .then(function (updatedPositions) {
                //  是一个数组,包含更新后的 Cartographic 对象
                const newPosition = updatedPositions.map((item, index) => {
                    const longitude = Cesium.Math.toDegrees(item.longitude)
                    const latitude = Cesium.Math.toDegrees(item.latitude)
                    let pointData = {
                        ...data[index],
                        longitude,
                        latitude,
                        ASL: Number(item.height),
                        customHeight: Number(item.height),
                    }
                    if (droneHeight) pointData.TH = Number(item.height) + Number(droneHeight)
                    return pointData
                })
                resolve(newPosition)
            })
            .catch(function (error) {
                console.log('获取高程时发生错误:', error)
                resolve(data.map(item => ({ ...item, ASL: 0, customHeight: 0, longitude: item.lng, latitude: item.lat })))
            })
    })
}
 
export { MapTooltip, flyVisual, getPointPositionsHeight, DrawPolygon }