吉安感知网项目-前端
chenyao
21 hours ago c567cbca3b78a7e06a827acbab56a46657e31aa1
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
import * as Cesium from 'cesium'
import { getPointPositionsHeight } from './mapUtil'
 
const DEVICE_RANGE_MATERIAL_TYPE = 'DeviceRangeEllipsoid'
let deviceRangeMaterialRegistered = false
 
export const registerDeviceRangeMaterial = () => {
    if (deviceRangeMaterialRegistered || !Cesium?.Material) return
    deviceRangeMaterialRegistered = true
    Cesium.Material._materialCache.addMaterial(DEVICE_RANGE_MATERIAL_TYPE, {
        fabric: {
            type: DEVICE_RANGE_MATERIAL_TYPE,
            uniforms: {
                color: new Cesium.Color(1.0, 0.0, 0.0, 0.7),
                speed: 3.0,
                globalAlpha: 0.9
            },
            source: `
                uniform vec4 color;
                uniform float speed;
                uniform float globalAlpha;
 
                czm_material czm_getMaterial(czm_materialInput materialInput)
                {
                czm_material material = czm_getDefaultMaterial(materialInput);
                vec2 st = materialInput.st;
                
                float time = fract(czm_frameNumber * speed / 1000.0);
 
                if (st.t < 0.5) {
                    discard;
                }
 
                float alphaMars3D = abs(smoothstep(0.5, 1.0, fract(-st.t - time)));
                alphaMars3D += 0.1;
 
                material.alpha = alphaMars3D * globalAlpha;
                material.diffuse = color.rgb;
 
                return material;
                }
            `,
        },
        translucent: () => true,
    })
}
 
export const createDeviceRangeMaterial = () => {
    registerDeviceRangeMaterial()
    return Cesium.Material.fromType(DEVICE_RANGE_MATERIAL_TYPE, {
        color: Cesium.Color.fromBytes(0, 255, 255, 155),
    })
}
 
export const getDeviceLngLat = device => {
    const lngRaw = device?.longitude ?? device?.lng ?? device?.lon
    const latRaw = device?.latitude ?? device?.lat
    const lng = Number(lngRaw)
    const lat = Number(latRaw)
    if (!Number.isFinite(lng) || !Number.isFinite(lat)) return null
    return { lng, lat }
}
 
export const normalizeDeviceRange = value => {
    const range = Number(value)
    if (!Number.isFinite(range) || range <= 0) return 2000
    return range
}
 
export const resolveDeviceTerrainHeight = async (viewer, position) => {
    if (!viewer || !position) return 0
    const lng = position.lng ?? position.longitude
    const lat = position.lat ?? position.latitude
    if (!Number.isFinite(Number(lng)) || !Number.isFinite(Number(lat))) return 0
    try {
        const results = await getPointPositionsHeight([{ lng: Number(lng), lat: Number(lat) }], viewer)
        const height = Number(results?.[0]?.ASL)
        return Number.isFinite(height) ? height : 0
    } catch (error) {
        return 0
    }
}
 
export const createDeviceRangePrimitiveWithHeight = (position, rangeMeters, height, material = null) => {
    if (!position || !Number.isFinite(rangeMeters)) return null
    const lng = position.lng ?? position.longitude
    const lat = position.lat ?? position.latitude
    if (!Number.isFinite(Number(lng)) || !Number.isFinite(Number(lat))) return null
    const center = Cesium.Cartesian3.fromDegrees(Number(lng), Number(lat), Number(height) || 0)
    const radii = new Cesium.Cartesian3(rangeMeters, rangeMeters, rangeMeters)
    const geometry = new Cesium.EllipsoidGeometry({
        radii,
        vertexFormat: Cesium.MaterialAppearance.MaterialSupport.TEXTURED?.vertexFormat
            || Cesium.VertexFormat.POSITION_AND_NORMAL,
    })
    const instance = new Cesium.GeometryInstance({
        geometry,
        modelMatrix: Cesium.Transforms.eastNorthUpToFixedFrame(center),
    })
    return new Cesium.Primitive({
        geometryInstances: instance,
        appearance: new Cesium.MaterialAppearance({
            material: material || createDeviceRangeMaterial(),
            closed: true,
            translucent: true,
            flat: true,
            faceForward: true,
        }),
        asynchronous: false
    })
}
 
export const createDeviceRangePrimitive = async (viewer, position, rangeMeters, material = null) => {
    if (!viewer) return null
    const height = await resolveDeviceTerrainHeight(viewer, position)
    return createDeviceRangePrimitiveWithHeight(position, rangeMeters, height, material)
}