feat(3d-situational-awareness): 增加对分级应急点和塌陷边界的支持

- 为城市、区域和其他应急点添加新图标
- 更新地图点击处理器以显示分级应急点详情
- 实现塌陷边界绘制,左右地图使用实线和虚线
- 修改标记添加功能,按级别处理应急点(城市、区域、其他)
This commit is contained in:
Zzc 2025-11-25 19:21:02 +08:00
parent 0303849072
commit 00468b053b
5 changed files with 245 additions and 10 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.1 KiB

View File

@ -127,6 +127,15 @@ export function useMapClickHandler({ tooltipComposable, icons, rangeCircleEntity
: icons.emergencyBaseIcon : icons.emergencyBaseIcon
} else if (type === 'reserveCenter' || type === 'presetPoint') { } else if (type === 'reserveCenter' || type === 'presetPoint') {
icon = type === 'reserveCenter' ? icons.reserveCenterIcon : icons.emergencyBaseIcon icon = type === 'reserveCenter' ? icons.reserveCenterIcon : icons.emergencyBaseIcon
} else if (type === 'city' || type === 'district' || type === 'other') {
// 新增:根据级别选择图标
if (type === 'city') {
icon = icons.cityEmergencyIcon
} else if (type === 'district') {
icon = icons.districtEmergencyIcon
} else {
icon = icons.otherEmergencyIcon
}
} }
if (icon) { if (icon) {
@ -285,6 +294,19 @@ export function useMapClickHandler({ tooltipComposable, icons, rangeCircleEntity
) )
supportVideo = true supportVideo = true
videoTitle = '预置点' videoTitle = '预置点'
} else if (type === 'city' || type === 'district' || type === 'other') {
// 新增:应急点(市级/区县级/其他)
const level = properties.level?.getValue() || '应急点'
title = `${level}应急点`
fields.push(
{ label: '名称', value: properties.name?.getValue() || '-' },
{ label: '级别', value: level },
{ label: '区县', value: properties.district?.getValue() || '-' },
{ label: '人员数量', value: properties.personnelCount?.getValue() || '-' },
{ label: '占地面积', value: properties.area?.getValue() || '-' }
)
supportVideo = true
videoTitle = `${level}应急点`
} }
return { return {

View File

@ -1,6 +1,7 @@
import { ref } from 'vue' import { ref } from 'vue'
import * as Cesium from 'cesium' import * as Cesium from 'cesium'
import { cesiumDataConfig } from '../config/cesiumData' import { cesiumDataConfig } from '../config/cesiumData'
import { collapseBoundaryData } from '../config/collapseBoundary'
// 图标导入 // 图标导入
import soldierIcon from '../assets/images/SketchPngfbec927027ff9e49207749ebaafd229429315341fda199251b6dfb1723ff17fb.png' import soldierIcon from '../assets/images/SketchPngfbec927027ff9e49207749ebaafd229429315341fda199251b6dfb1723ff17fb.png'
@ -8,6 +9,10 @@ import deviceIcon from '../assets/images/SketchPng860d54f2a31f5f441fc6a88081224f
import emergencyBaseIcon from '../assets/images/应急基地.png' import emergencyBaseIcon from '../assets/images/应急基地.png'
import emergencyCenterIcon from '../assets/images/应急中心icon定位.png' import emergencyCenterIcon from '../assets/images/应急中心icon定位.png'
import reserveCenterIcon from '../assets/images/储备中心.png' import reserveCenterIcon from '../assets/images/储备中心.png'
// 新增:根据级别的应急点图标
import cityEmergencyIcon from '../assets/images/市应急点.png'
import districtEmergencyIcon from '../assets/images/区县应急点.png'
import otherEmergencyIcon from '../assets/images/其他应急点.png'
// 默认高度偏移(米)- 与 WuRenJi 保持一致 // 默认高度偏移(米)- 与 WuRenJi 保持一致
const DEFAULT_HEIGHT_OFFSET = 100 const DEFAULT_HEIGHT_OFFSET = 100
@ -21,6 +26,8 @@ export function useMapMarkers() {
const markerEntities = ref([]) const markerEntities = ref([])
const emergencyResourceEntities = ref([]) // 应急资源标记由API数据动态生成 const emergencyResourceEntities = ref([]) // 应急资源标记由API数据动态生成
const reserveCenterEntities = ref([]) // 储备中心和预置点标记 const reserveCenterEntities = ref([]) // 储备中心和预置点标记
const collapseBoundaryEntity = ref(null) // 坍塌边界线实体(右侧实线)
const collapseBoundaryLeftEntity = ref(null) // 坍塌边界线实体(左侧虚线)
/** /**
* 获取塌陷区域的所有位置点 * 获取塌陷区域的所有位置点
@ -103,6 +110,187 @@ export function useMapMarkers() {
return Cesium.HeightReference.CLAMP_TO_GROUND return Cesium.HeightReference.CLAMP_TO_GROUND
} }
/**
* 绘制坍塌边界蓝色实线右侧地图
* 在右侧地图上显示灾后坍塌的边界轮廓
* @param {Cesium.Viewer} viewer
* @returns {Cesium.Entity | null} 返回创建的边界线实体
*/
const drawCollapseBoundary = (viewer) => {
if (!viewer) {
console.warn('[useMapMarkers] drawCollapseBoundary: viewer 为空')
return null
}
if (!Array.isArray(collapseBoundaryData) || collapseBoundaryData.length === 0) {
console.warn('[useMapMarkers] drawCollapseBoundary: 配置数据为空')
return null
}
// 清除旧的边界线(如果存在)
if (collapseBoundaryEntity.value) {
viewer.entities.remove(collapseBoundaryEntity.value)
collapseBoundaryEntity.value = null
}
// 转换坐标点
const positions = collapseBoundaryData.map(point =>
new Cesium.Cartesian3(point.x, point.y, point.z)
)
// 闭合线条(连接最后一个点到第一个点)
positions.push(positions[0])
console.log('[useMapMarkers] 右侧坍塌边界点位数量:', positions.length)
// 创建蓝色实线边界
const boundaryEntity = viewer.entities.add({
polyline: {
positions: positions,
width: 4, // 增加线宽,更明显
material: Cesium.Color.fromCssColorString('#1CA1FF').withAlpha(1.0), // 纯蓝色实线
clampToGround: true,
classificationType: Cesium.ClassificationType.BOTH, // 同时分类到地形和3D Tiles
zIndex: 1 // 提高层级
},
properties: new Cesium.PropertyBag({
type: 'collapseBoundary',
name: '坍塌边界(右侧实线)'
}),
show: true // 明确设置为显示
})
collapseBoundaryEntity.value = boundaryEntity
console.log('[useMapMarkers] 右侧坍塌边界蓝色实线绘制完成, entityId:', boundaryEntity.id)
// 强制渲染场景
viewer.scene.requestRender()
return boundaryEntity
}
/**
* 绘制坍塌边界蓝色虚线左侧地图
* 在左侧地图上显示灾前位置的虚线轮廓
* @param {HTMLElement} leftContainer - 左侧地图容器元素
* @returns {Cesium.Entity | null} 返回创建的边界线实体
*/
const drawCollapseBoundaryLeft = (leftContainer) => {
if (!leftContainer) {
console.warn('[useMapMarkers] drawCollapseBoundaryLeft: leftContainer 为空')
return null
}
// 获取左侧 viewer假设已经创建
const leftViewer = leftContainer._cesiumViewer
if (!leftViewer) {
console.warn('[useMapMarkers] drawCollapseBoundaryLeft: 左侧 viewer 未创建')
return null
}
if (!Array.isArray(collapseBoundaryData) || collapseBoundaryData.length === 0) {
console.warn('[useMapMarkers] drawCollapseBoundaryLeft: 配置数据为空')
return null
}
// 清除旧的边界线(如果存在)
if (collapseBoundaryLeftEntity.value) {
leftViewer.entities.remove(collapseBoundaryLeftEntity.value)
collapseBoundaryLeftEntity.value = null
}
// 转换坐标点
const positions = collapseBoundaryData.map(point =>
new Cesium.Cartesian3(point.x, point.y, point.z)
)
// 闭合线条(连接最后一个点到第一个点)
positions.push(positions[0])
console.log('[useMapMarkers] 左侧坍塌边界点位数量:', positions.length)
// 创建蓝色虚线边界
const boundaryEntity = leftViewer.entities.add({
polyline: {
positions: positions,
width: 4,
material: new Cesium.PolylineDashMaterialProperty({
color: Cesium.Color.fromCssColorString('#1CA1FF').withAlpha(1.0), // 蓝色
dashLength: 16.0, // 虚线段长度
dashPattern: 255.0 // 虚线模式
}),
clampToGround: true,
classificationType: Cesium.ClassificationType.BOTH,
zIndex: 1
},
properties: new Cesium.PropertyBag({
type: 'collapseBoundaryLeft',
name: '坍塌边界(左侧虚线)'
}),
show: true
})
collapseBoundaryLeftEntity.value = boundaryEntity
console.log('[useMapMarkers] 左侧坍塌边界蓝色虚线绘制完成, entityId:', boundaryEntity.id)
// 强制渲染场景
leftViewer.scene.requestRender()
return boundaryEntity
}
/**
* 清除坍塌边界线
* @param {Cesium.Viewer} viewer - 右侧 viewer
* @param {HTMLElement} leftContainer - 左侧地图容器可选
*/
const clearCollapseBoundary = (viewer, leftContainer = null) => {
// 清除右侧边界线
if (viewer && collapseBoundaryEntity.value) {
viewer.entities.remove(collapseBoundaryEntity.value)
collapseBoundaryEntity.value = null
console.log('[useMapMarkers] 右侧坍塌边界线已清除')
}
// 清除左侧边界线
if (leftContainer && collapseBoundaryLeftEntity.value) {
const leftViewer = leftContainer._cesiumViewer
if (leftViewer) {
leftViewer.entities.remove(collapseBoundaryLeftEntity.value)
collapseBoundaryLeftEntity.value = null
console.log('[useMapMarkers] 左侧坍塌边界线已清除')
}
}
}
/**
* 显示坍塌边界线
*/
const showCollapseBoundary = () => {
if (collapseBoundaryEntity.value) {
collapseBoundaryEntity.value.show = true
console.log('[useMapMarkers] 显示右侧坍塌边界线')
}
if (collapseBoundaryLeftEntity.value) {
collapseBoundaryLeftEntity.value.show = true
console.log('[useMapMarkers] 显示左侧坍塌边界线')
}
}
/**
* 隐藏坍塌边界线
*/
const hideCollapseBoundary = () => {
if (collapseBoundaryEntity.value) {
collapseBoundaryEntity.value.show = false
console.log('[useMapMarkers] 隐藏右侧坍塌边界线')
}
if (collapseBoundaryLeftEntity.value) {
collapseBoundaryLeftEntity.value.show = false
console.log('[useMapMarkers] 隐藏左侧坍塌边界线')
}
}
/** /**
* 绘制塌陷区域多边形 * 绘制塌陷区域多边形
* 这个函数不涉及高度采样直接使用配置中的绝对坐标 * 这个函数不涉及高度采样直接使用配置中的绝对坐标
@ -603,7 +791,7 @@ export function useMapMarkers() {
* @param {string} reserveData[].gl1Qxmc - 区县名称 * @param {string} reserveData[].gl1Qxmc - 区县名称
* @param {string} reserveData[].gl1Rysl - 人员数量 * @param {string} reserveData[].gl1Rysl - 人员数量
* @param {string} reserveData[].gl1Zdmj - 占地面积 * @param {string} reserveData[].gl1Zdmj - 占地面积
* @param {string} reserveData[].gl1Lx - 类型 (2=储备中心, 3=预置点) * @param {string} reserveData[].gl1Lx - 级别 (1=市级, 2=区县级, 3=其他)
* @param {Object} options - 配置选项 * @param {Object} options - 配置选项
* @param {number} [options.heightOffset=10] - 相对地面的高度偏移 * @param {number} [options.heightOffset=10] - 相对地面的高度偏移
* @returns {Promise<void>} * @returns {Promise<void>}
@ -641,27 +829,45 @@ export function useMapMarkers() {
false false
) )
// 根据类型选择图标和类型标识 // 根据级别选择图标和类型标识
// gl1Lx: 2=储备中心, 3=预置点 // gl1Lx: "1市级", "2区县级", "3其他" 或者可能只是 "1", "2", "3"
const itemType = String(item.gl1Lx).trim() const levelString = String(item.gl1Lx || '').trim()
const isReserveCenter = itemType === '2' let icon = otherEmergencyIcon // 默认使用其他应急点图标
const icon = isReserveCenter ? reserveCenterIcon : emergencyBaseIcon let type = 'other'
const type = isReserveCenter ? 'reserveCenter' : 'presetPoint' let levelName = '其他'
// 判断级别(兼容 "1市级" 和 "1" 两种格式)
if (levelString.startsWith('1') || levelString === '1') {
icon = cityEmergencyIcon
type = 'city'
levelName = '市级'
} else if (levelString.startsWith('2') || levelString === '2') {
icon = districtEmergencyIcon
type = 'district'
levelName = '区县级'
} else if (levelString.startsWith('3') || levelString === '3') {
icon = otherEmergencyIcon
type = 'other'
levelName = '其他'
}
console.log(`[useMapMarkers] 添加标记: ${item.gl1Yjllmc}, 级别: ${levelString} (${levelName})`)
const entity = viewer.entities.add({ const entity = viewer.entities.add({
position: result.position, position: result.position,
billboard: { billboard: {
image: icon, image: icon,
width: 48, width: 29,
height: 48, height: 32,
verticalOrigin: Cesium.VerticalOrigin.BOTTOM, verticalOrigin: Cesium.VerticalOrigin.BOTTOM,
heightReference: resolveBillboardHeightReference(result.samplingSucceeded), heightReference: resolveBillboardHeightReference(result.samplingSucceeded),
disableDepthTestDistance: Number.POSITIVE_INFINITY disableDepthTestDistance: Number.POSITIVE_INFINITY
}, },
properties: { properties: {
type, type,
level: levelName,
id: item.gl1Id, id: item.gl1Id,
name: item.gl1Yjllmc || (isReserveCenter ? '储备中心' : '预置点'), name: item.gl1Yjllmc || `${levelName}应急点`,
district: item.gl1Qxmc || '-', district: item.gl1Qxmc || '-',
personnelCount: item.gl1Rysl || '0', personnelCount: item.gl1Rysl || '0',
area: item.gl1Zdmj || '-' area: item.gl1Zdmj || '-'
@ -771,12 +977,19 @@ export function useMapMarkers() {
markerEntities, markerEntities,
emergencyResourceEntities, emergencyResourceEntities,
reserveCenterEntities, reserveCenterEntities,
collapseBoundaryEntity,
collapseBoundaryLeftEntity,
initializeMarkers, initializeMarkers,
clearMarkers, clearMarkers,
setMarkersSplitDirection, setMarkersSplitDirection,
hideMarkers, hideMarkers,
showMarkers, showMarkers,
drawCollapseArea, drawCollapseArea,
drawCollapseBoundary,
drawCollapseBoundaryLeft,
clearCollapseBoundary,
showCollapseBoundary,
hideCollapseBoundary,
addFixedMarkers, addFixedMarkers,
addRandomMarkers, addRandomMarkers,
addEmergencyResourceMarkers, addEmergencyResourceMarkers,