吉安感知网项目-前端
罗广辉
2026-01-30 e696ff74ab21f80a3edd350176940a3e1cf65f3f
applications/drone-command/src/views/areaManage/partition/FormDiaLog.vue
@@ -234,7 +234,13 @@
import { fieldRules, geomAnalysis, getDictLabel } from '@ztzf/utils'
import CommonCesiumMap from '@/components/map-container/common-cesium-map.vue'
import { DrawManager, EditManager, buildEllipsePositions } from '@/utils/cesium/shapeTools'
import { cartesian3Convert, getPointPositionsHeight } from '@/utils/cesium/mapUtil'
import { cartesian3Convert } from '@/utils/cesium/mapUtil'
import {
   createDeviceRangePrimitive,
   getDeviceLngLat,
   normalizeDeviceRange,
   resolveDeviceTerrainHeight,
} from '@/utils/cesium/deviceRange'
import * as Cesium from 'cesium'
import { AREA_TYPE_STYLE_MAP, BUFFER_LEVEL_STYLES, DEFAULT_AREA_STYLE } from '@ztzf/constants'
import { fwPoliceStationListApi } from '@/views/areaManage/precinctInfo/precinctInfoApi'
@@ -294,7 +300,6 @@
let viewEntity
let shapeDisplaySource
const deviceRangePrimitiveMap = new Map()
let deviceRangeMaterialRegistered = false
const activeToolMode = ref('')
const rules = {
@@ -455,42 +460,6 @@
   return shapeDisplaySource
}
function registerDeviceRangeMaterial () {
   if (deviceRangeMaterialRegistered || !Cesium?.Material) return
   deviceRangeMaterialRegistered = true
   Cesium.Material._materialCache.addMaterial('DeviceRangeEllipsoid', {
      fabric: {
         type: 'DeviceRangeEllipsoid',
         uniforms: {
            color: new Cesium.Color(1.0, 0.0, 0.0, 0.7),
            speed: 3.0,
         },
         source: `
            uniform vec4 color;
            uniform float speed;
            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);
               float alpha = abs(smoothstep(0.5,1.,fract( -st.t - time)));
               alpha += .1;
               material.alpha = alpha;
               material.diffuse = color.rgb;
               return material;
            }
         `,
      },
      translucent: () => true,
   })
}
function createDeviceRangeMaterial () {
   registerDeviceRangeMaterial()
   return Cesium.Material.fromType('DeviceRangeEllipsoid', {
      color: Cesium.Color.fromBytes(0, 255, 255, 155),
   })
}
function clearDeviceRangePrimitives () {
   if (!viewer || !deviceRangePrimitiveMap.size) return
   for (const primitive of deviceRangePrimitiveMap.values()) {
@@ -499,67 +468,13 @@
   deviceRangePrimitiveMap.clear()
}
function normalizeDeviceRange (value) {
   const range = Number(value)
   if (!Number.isFinite(range) || range <= 0) return 2000
   return range
}
function 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 }
}
async function resolveDeviceTerrainHeight (position) {
   if (!viewer) return 0
   try {
      const results = await getPointPositionsHeight([{ lng: position.lng, lat: position.lat }], viewer)
      const height = Number(results?.[0]?.ASL)
      return Number.isFinite(height) ? height : 0
   } catch (error) {
      return 0
   }
}
async function createDeviceRangePrimitive (device) {
   if (!viewer) return null
   if (!device) return null
   const position = getDeviceLngLat(device)
   if (!position) return null
   const rangeMeters = normalizeDeviceRange(device.effectiveRangeKm)
   const centerHeight = await resolveDeviceTerrainHeight(position)
   const center = Cesium.Cartesian3.fromDegrees(position.lng, position.lat, centerHeight)
   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: createDeviceRangeMaterial(),
         closed: true,
         translucent: true,
         flat: true,
         faceForward: true,
      }),
      asynchronous: false
   })
}
async function renderDeviceRangeSingle (device) {
   if (!viewer) return
   clearDeviceRangePrimitives()
   const primitive = await createDeviceRangePrimitive(device)
   const position = getDeviceLngLat(device)
   if (!position) return
   const rangeMeters = normalizeDeviceRange(device.effectiveRangeKm)
   const primitive = await createDeviceRangePrimitive(viewer, position, rangeMeters)
   if (!primitive) return
   deviceRangePrimitiveMap.set(String(device?.id ?? Date.now()), primitive)
   viewer.scene.primitives.add(primitive)
@@ -582,7 +497,10 @@
   if (!pendingRows.length) return
   const primitives = await Promise.all(
      pendingRows.map(async row => {
         const primitive = await createDeviceRangePrimitive(row)
         const position = getDeviceLngLat(row)
         if (!position) return { row, primitive: null }
         const rangeMeters = normalizeDeviceRange(row.effectiveRangeKm)
         const primitive = await createDeviceRangePrimitive(viewer, position, rangeMeters)
         return { row, primitive }
      })
   )
@@ -598,8 +516,9 @@
   if (!viewer) return
   const position = getDeviceLngLat(device)
   if (!position) return
   const height = await resolveDeviceTerrainHeight(position)
   const destination = Cesium.Cartesian3.fromDegrees(position.lng, position.lat, height + device.effectiveRangeKm * 3)
   const height = await resolveDeviceTerrainHeight(viewer, position)
   const rangeMeters = normalizeDeviceRange(device?.effectiveRangeKm)
   const destination = Cesium.Cartesian3.fromDegrees(position.lng, position.lat, height + rangeMeters * 3)
   viewer.camera.flyTo({
      destination,
      orientation: {