吉安感知网项目-前端
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
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
import { getAreaDataByAlgorithmKeysApi } from '@ztzf/apis'
import  * as Cesium from 'cesium'
import * as turf from '@turf/turf'
import L from 'leaflet'
import 'leaflet/dist/leaflet.css'
 
/**
 * 设置自定义识别区域--大屏
 * @returns {{}}
 */
export const useIdentificationArea = () => {
    let viewerObj
    async function setArea(ai_types,viewer) {
        if (!ai_types.length)return
        viewerObj = viewer
        removeArea()
        const res = await getAreaDataByAlgorithmKeysApi(ai_types)
        const list = res.data.data
        list
            .filter(item => item.geo_data)
            .forEach(item => {
                const parsed = JSON.parse(item.geo_data) // 转为数组
                const grouped = parsed.flat() // 再展开
 
                // 计算多边形质心
                let polygon = turf.polygon([parsed]);
                let center = turf.centerOfMass(polygon);
                const color = '#00ff06'
                viewerObj.entities?.add({
                    customType: 'identificationArea',
                    customInfo: {
                        ...item,
                    },
                    position: Cesium.Cartesian3.fromDegrees(center.geometry.coordinates[0], center.geometry.coordinates[1], 0),
                    label: {
                        text: item.name,
                        font: 'bold 12px Source Han Sans CN',
                        fillColor: Cesium.Color.WHITE,
                        verticalOrigin: Cesium.VerticalOrigin.BOTTOM,
                        disableDepthTestDistance: Number.POSITIVE_INFINITY,
                        scale: 1.0,
                    },
                    polygon: {
                        hierarchy: Cesium.Cartesian3.fromDegreesArray(grouped),
                        material: Cesium.Color.fromCssColorString(color).withAlpha(0.5),
                        classificationType: Cesium.ClassificationType.TERRAIN,
                    },
                    polyline: {
                        positions: Cesium.Cartesian3.fromDegreesArray([...grouped, grouped[0], grouped[1]]),
                        clampToGround: true,
                        width: 1.5,
                        material: Cesium.Color.fromCssColorString(color),
                    },
                })
            })
    }
    function removeArea() {
        const thisList = viewerObj?.entities?.values?.filter(item => item?.customType === 'identificationArea')
        thisList?.forEach(item => {
            viewerObj.entities.remove(item)
        })
    }
 
    onBeforeUnmount(()=>{
        removeArea()
    })
    return {
        setArea,
        removeArea
    }
}
 
 
/**
 * 设置自定义识别区域--h5
 * @returns {{}}
 */
export const useIdentificationAreaForApp = () => {
    // 初始化图层
    let mapLayerSource = null
    async function setArea(ai_types,viewer) {
        if (!ai_types.length) return
        // 清空所有图层
        if (mapLayerSource) {
            mapLayerSource.clearLayers();
        }
        mapLayerSource = viewer
        const res = await getAreaDataByAlgorithmKeysApi(ai_types)
        const list = res.data.data
 
        list
            .filter(item => item.geo_data)
            .forEach(item => {
                const parsed = JSON.parse(item.geo_data); // 转为数组
                const grouped = parsed.flat(); // 再展开
 
                // 3. 计算多边形质心
                const turfPolygon = turf.polygon([parsed]);
                const center = turf.centerOfMass(turfPolygon);
                const centerLatLng = [center.geometry.coordinates[1], center.geometry.coordinates[0]];
 
                const labelMarker = L.marker(centerLatLng, {
                    icon: L.divIcon({
                        className: 'polygon-label',
                        html: `
                            <div style="
                                color: #008013;
                                font-weight: bold;
                                font-size: 12px;
                                font-family: 'Source Han Sans CN', 'Source Han Sans CN';
                                white-space: nowrap;
                            ">
                                ${item.name || '未命名'}
                            </div>
                        `,
                        iconSize: null,    // 让div决定大小
                        iconAnchor: null   // 不需要锚点,用CSS transform居中
                    }),
                    interactive: false,    // 标签不参与交互
                    // zIndexOffset: 1000     // 确保标签在最上层
                });
 
                // 将坐标数组转换为 Leaflet 格式 [lat, lng, lat, lng...] -> [[lat, lng], [lat, lng]...]
                const latLngs = [];
                for (let i = 0; i < grouped.length; i += 2) {
                    latLngs.push([grouped[i + 1], grouped[i]]); // 注意:Leaflet 是 [lat, lng] 顺序
                }
 
                // 创建多边形(填充区域)
                const polygon = L.polygon(latLngs, {
                    color: '#00ff06',
                    fillColor: '#00ff06',
                    fillOpacity: 0.5,
                    weight: 0, // 隐藏多边形边框,使用折线作为边框
                });
 
                // 创建折线(边框)
                const polyline = L.polyline([...latLngs, latLngs[0]], { // 闭合多边形
                    color: '#00ff06',
                    weight: 1.5,
                    opacity: 1,
                    fill: false
                });
 
                // 将两个图层组合在一起
                const group = L.featureGroup([polygon, polyline, labelMarker]);
                // 添加到图层组
                mapLayerSource.addLayer(group);
            });
    }
    function removeArea() {
        if (mapLayerSource) {
            mapLayerSource.clearLayers();
        }
    }
 
    onBeforeUnmount(()=>{
        mapLayerSource.clearLayers();
    })
    return {
        setArea,
        removeArea
    }
}