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
|
}
|
}
|