| | |
| | | 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 } from '@/utils/cesium/mapUtil' |
| | | import { cartesian3Convert, getPointPositionsHeight } from '@/utils/cesium/mapUtil' |
| | | 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' |
| | |
| | | return { lng, lat } |
| | | } |
| | | |
| | | function createDeviceRangePrimitive (device) { |
| | | 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 center = Cesium.Cartesian3.fromDegrees(position.lng, position.lat, 0) |
| | | 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, |
| | |
| | | }) |
| | | } |
| | | |
| | | function renderDeviceRangeSingle (device) { |
| | | async function renderDeviceRangeSingle (device) { |
| | | if (!viewer) return |
| | | clearDeviceRangePrimitives() |
| | | const primitive = createDeviceRangePrimitive(device) |
| | | const primitive = await createDeviceRangePrimitive(device) |
| | | if (!primitive) return |
| | | deviceRangePrimitiveMap.set(String(device?.id ?? Date.now()), primitive) |
| | | viewer.scene.primitives.add(primitive) |
| | | } |
| | | |
| | | function renderDeviceRanges (rows) { |
| | | async function renderDeviceRanges (rows) { |
| | | if (!viewer) return |
| | | const selectedRows = Array.isArray(rows) ? rows : [] |
| | | const nextIds = new Set(selectedRows.map(row => String(row?.id))) |
| | |
| | | deviceRangePrimitiveMap.delete(id) |
| | | } |
| | | } |
| | | selectedRows.forEach(row => { |
| | | const pendingRows = selectedRows.filter(row => { |
| | | const id = String(row?.id) |
| | | if (!id || deviceRangePrimitiveMap.has(id)) return |
| | | const primitive = createDeviceRangePrimitive(row) |
| | | return id && !deviceRangePrimitiveMap.has(id) |
| | | }) |
| | | if (!pendingRows.length) return |
| | | const primitives = await Promise.all( |
| | | pendingRows.map(async row => { |
| | | const primitive = await createDeviceRangePrimitive(row) |
| | | return { row, primitive } |
| | | }) |
| | | ) |
| | | primitives.forEach(({ row, primitive }) => { |
| | | if (!primitive) return |
| | | const id = String(row?.id) |
| | | deviceRangePrimitiveMap.set(id, primitive) |
| | | viewer.scene.primitives.add(primitive) |
| | | }) |
| | | } |
| | | |
| | | async function flyToDevice (device) { |
| | | 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) |
| | | viewer.camera.flyTo({ |
| | | destination, |
| | | orientation: { |
| | | heading: viewer.camera.heading, |
| | | pitch: Cesium.Math.toRadians(-90), |
| | | roll: 0, |
| | | }, |
| | | duration: 0.6, |
| | | }) |
| | | } |
| | | |
| | |
| | | const ids = rows.map(item => item.id) |
| | | formData.value.deviceIds = ids.join(',') |
| | | renderDeviceRanges(rows) |
| | | const target = rows[rows.length - 1] |
| | | if (target) { |
| | | void flyToDevice(target) |
| | | } |
| | | } |
| | | |
| | | function handleDeviceRowClick (row) { |
| | | if (readonly.value) { |
| | | renderDeviceRangeSingle(row) |
| | | void flyToDevice(row) |
| | | return |
| | | } |
| | | renderDeviceRanges(selectedDeviceRows.value) |
| | | void flyToDevice(row) |
| | | } |
| | | |
| | | // 同步选择状态 |