| | |
| | | createRadialGradientMaterial, |
| | | getTexturedVertexFormat, |
| | | } from './device-map-materials' |
| | | import { getPointPositionsHeight } from '@/utils/cesium/mapUtil' |
| | | import dzIcon from '@/assets/images/dataCockpit/map/dz-map-layer.png' |
| | | import yxIcon from '@/assets/images/dataCockpit/map/yx-map-layer.png' |
| | | |
| | | const CLUSTER_HEIGHT = 100000 |
| | | const DETAIL_HEIGHT = 10000 |
| | | const POLYGON_HEIGHT_M = 0.2 |
| | | |
| | | const props = defineProps({ |
| | | onlineDevices: { |
| | |
| | | let deviceRingFillPrimitives = [] |
| | | let defenseZonePrimitive = null |
| | | let defenseZoneOutlinePrimitive = null |
| | | let partitionPrimitive = null |
| | | let partitionOutlinePrimitive = null |
| | | let partitionFillPrimitives = [] |
| | | let partitionOutlinePrimitives = [] |
| | | let aggregationSource = null |
| | | let commandPostBillboardCollection = null |
| | | let droneTrackBillboardCollection = null |
| | |
| | | cockpitPrimitiveLayer.removeAll(false) |
| | | if (defenseZonePrimitive) cockpitPrimitiveLayer.add(defenseZonePrimitive) |
| | | if (defenseZoneOutlinePrimitive) cockpitPrimitiveLayer.add(defenseZoneOutlinePrimitive) |
| | | if (partitionPrimitive) cockpitPrimitiveLayer.add(partitionPrimitive) |
| | | if (partitionOutlinePrimitive) cockpitPrimitiveLayer.add(partitionOutlinePrimitive) |
| | | if (partitionFillPrimitives.length) { |
| | | partitionFillPrimitives.forEach(primitive => cockpitPrimitiveLayer.add(primitive)) |
| | | } |
| | | if (partitionOutlinePrimitives.length) { |
| | | partitionOutlinePrimitives.forEach(primitive => cockpitPrimitiveLayer.add(primitive)) |
| | | } |
| | | if (deviceRingFillPrimitives.length) { |
| | | deviceRingFillPrimitives.forEach(primitive => cockpitPrimitiveLayer.add(primitive)) |
| | | } |
| | |
| | | |
| | | const clearPartitionEntities = () => { |
| | | if (!viewer) return |
| | | if (partitionPrimitive) { |
| | | removeCockpitPrimitive(partitionPrimitive) |
| | | partitionPrimitive = null |
| | | if (partitionFillPrimitives.length) { |
| | | partitionFillPrimitives.forEach(primitive => removeCockpitPrimitive(primitive)) |
| | | partitionFillPrimitives = [] |
| | | } |
| | | if (partitionOutlinePrimitive) { |
| | | removeCockpitPrimitive(partitionOutlinePrimitive) |
| | | partitionOutlinePrimitive = null |
| | | if (partitionOutlinePrimitives.length) { |
| | | partitionOutlinePrimitives.forEach(primitive => removeCockpitPrimitive(primitive)) |
| | | partitionOutlinePrimitives = [] |
| | | } |
| | | } |
| | | |
| | |
| | | detailVisible.value = visible |
| | | if (defenseZonePrimitive) defenseZonePrimitive.show = visible |
| | | if (defenseZoneOutlinePrimitive) defenseZoneOutlinePrimitive.show = visible |
| | | if (partitionPrimitive) partitionPrimitive.show = visible |
| | | if (partitionOutlinePrimitive) partitionOutlinePrimitive.show = visible |
| | | if (partitionFillPrimitives.length) { |
| | | partitionFillPrimitives.forEach(primitive => { |
| | | primitive.show = visible |
| | | }) |
| | | } |
| | | if (partitionOutlinePrimitives.length) { |
| | | partitionOutlinePrimitives.forEach(primitive => { |
| | | primitive.show = visible |
| | | }) |
| | | } |
| | | if (commandPostBillboardCollection) commandPostBillboardCollection.show = visible |
| | | if (deviceBillboardCollection) deviceBillboardCollection.show = visible |
| | | if (deviceRingFillPrimitives.length) { |
| | |
| | | return list.map(item => Cesium.Cartesian3.fromDegrees(item.longitude, item.latitude)) |
| | | } |
| | | |
| | | const elevatePositions = async (positions, height = POLYGON_HEIGHT_M) => { |
| | | if (!Array.isArray(positions) || !positions.length) return [] |
| | | if (!viewer) return positions |
| | | const points = positions |
| | | .map(pos => { |
| | | const carto = Cesium.Cartographic.fromCartesian(pos) |
| | | if (!carto) return null |
| | | return { |
| | | lng: Cesium.Math.toDegrees(carto.longitude), |
| | | lat: Cesium.Math.toDegrees(carto.latitude), |
| | | } |
| | | }) |
| | | .filter(Boolean) |
| | | if (!points.length) return positions |
| | | const heights = await getPointPositionsHeight(points, viewer) |
| | | return heights.map(item => Cesium.Cartesian3.fromDegrees(item.longitude, item.latitude, (item.ASL ?? 0) + height)) |
| | | } |
| | | |
| | | const getAreaTypeStyle = areaType => { |
| | | return AREA_TYPE_STYLE_MAP?.[String(areaType)] || DEFAULT_AREA_STYLE |
| | | } |
| | | |
| | | const buildZonePrimitives = (zones, lineColor, fillColor1, fillColor2) => { |
| | | const buildZonePrimitives = async (zones, lineColor, fillColor1, fillColor2) => { |
| | | if (!viewer) return { primitive: null, outlinePrimitive: null } |
| | | const polygonInstances = [] |
| | | const lineInstances = [] |
| | | const positionGroups = [] |
| | | const texturedVertexFormat = getTexturedVertexFormat() |
| | | ; (zones || []).forEach((zone, index) => { |
| | | ; (zones || []).forEach(zone => { |
| | | if (!zone?.geom) return |
| | | const positions = getDefenseZonePositions(zone.geom) |
| | | if (!positions.length) return |
| | | const polygon = new Cesium.PolygonGeometry({ |
| | | polygonHierarchy: new Cesium.PolygonHierarchy(positions), |
| | | vertexFormat: texturedVertexFormat, |
| | | }) |
| | | polygonInstances.push( |
| | | new Cesium.GeometryInstance({ |
| | | geometry: polygon, |
| | | }) |
| | | ) |
| | | const linePositions = positions.length > 1 ? [...positions, positions[0]] : positions |
| | | lineInstances.push( |
| | | new Cesium.GeometryInstance({ |
| | | geometry: new Cesium.GroundPolylineGeometry({ |
| | | positions: linePositions, |
| | | width: 2, |
| | | }), |
| | | attributes: { |
| | | color: Cesium.ColorGeometryInstanceAttribute.fromColor( |
| | | Cesium.Color.fromCssColorString(lineColor) |
| | | ), |
| | | }, |
| | | }) |
| | | ) |
| | | positionGroups.push(positions) |
| | | }) |
| | | if (!positionGroups.length) return { primitive: null, outlinePrimitive: null } |
| | | const elevatedGroups = await Promise.all(positionGroups.map(group => elevatePositions(group))) |
| | | elevatedGroups.forEach(elevatedPositions => { |
| | | if (!elevatedPositions.length) return |
| | | const polygon = new Cesium.PolygonGeometry({ |
| | | polygonHierarchy: new Cesium.PolygonHierarchy(elevatedPositions), |
| | | perPositionHeight: true, |
| | | vertexFormat: texturedVertexFormat, |
| | | }) |
| | | polygonInstances.push( |
| | | new Cesium.GeometryInstance({ |
| | | geometry: polygon, |
| | | }) |
| | | ) |
| | | const linePositions = |
| | | elevatedPositions.length > 1 ? [...elevatedPositions, elevatedPositions[0]] : elevatedPositions |
| | | lineInstances.push( |
| | | new Cesium.GeometryInstance({ |
| | | geometry: new Cesium.PolylineGeometry({ |
| | | positions: linePositions, |
| | | width: 2, |
| | | }), |
| | | attributes: { |
| | | color: Cesium.ColorGeometryInstanceAttribute.fromColor( |
| | | Cesium.Color.fromCssColorString(lineColor) |
| | | ), |
| | | }, |
| | | }) |
| | | ) |
| | | }) |
| | | let primitive = null |
| | | if (polygonInstances.length) { |
| | | const baseColor1 = Cesium.Color.fromCssColorString(fillColor1) |
| | | const baseColor2 = Cesium.Color.fromCssColorString(fillColor2) |
| | | const material = createRadialGradientMaterial(baseColor1.withAlpha(0.64), baseColor2.withAlpha(0.64)) |
| | | primitive = new Cesium.GroundPrimitive({ |
| | | primitive = new Cesium.Primitive({ |
| | | geometryInstances: polygonInstances, |
| | | appearance: new Cesium.MaterialAppearance({ |
| | | material, |
| | |
| | | } |
| | | let outlinePrimitive = null |
| | | if (lineInstances.length) { |
| | | outlinePrimitive = new Cesium.GroundPolylinePrimitive({ |
| | | outlinePrimitive = new Cesium.Primitive({ |
| | | geometryInstances: lineInstances, |
| | | appearance: new Cesium.PolylineColorAppearance(), |
| | | }) |
| | |
| | | return { primitive, outlinePrimitive } |
| | | } |
| | | |
| | | const buildPartitionPrimitives = shapes => { |
| | | if (!viewer) return { primitive: null, outlinePrimitive: null } |
| | | const polygonInstances = [] |
| | | const lineInstances = [] |
| | | const vertexFormat = Cesium.PerInstanceColorAppearance.VERTEX_FORMAT |
| | | const buildPartitionPrimitives = async shapes => { |
| | | if (!viewer) return { primitives: [], outlinePrimitives: [] } |
| | | const vertexFormat = getTexturedVertexFormat() |
| | | const groups = new Map() |
| | | const tasks = [] |
| | | ; (shapes || []).forEach(shape => { |
| | | if (!shape?.positions || shape.positions.length < 3) return |
| | | const outlineColor = shape.outlineColor |
| | | const fillColor = shape.fillColor |
| | | const key = `${outlineColor.toCssColorString()}|${fillColor.toCssColorString()}` |
| | | if (!groups.has(key)) { |
| | | groups.set(key, { outlineColor, fillColor, polygonInstances: [], lineInstances: [] }) |
| | | } |
| | | const group = groups.get(key) |
| | | const positions = shape.positions |
| | | const polygon = new Cesium.PolygonGeometry({ |
| | | polygonHierarchy: new Cesium.PolygonHierarchy(positions), |
| | | vertexFormat, |
| | | tasks.push( |
| | | elevatePositions(positions).then(elevatedPositions => { |
| | | if (!elevatedPositions.length) return |
| | | const polygon = new Cesium.PolygonGeometry({ |
| | | polygonHierarchy: new Cesium.PolygonHierarchy(elevatedPositions), |
| | | perPositionHeight: true, |
| | | vertexFormat, |
| | | }) |
| | | group.polygonInstances.push( |
| | | new Cesium.GeometryInstance({ |
| | | geometry: polygon, |
| | | }) |
| | | ) |
| | | const linePositions = |
| | | elevatedPositions.length > 1 |
| | | ? [...elevatedPositions, elevatedPositions[0]] |
| | | : elevatedPositions |
| | | group.lineInstances.push( |
| | | new Cesium.GeometryInstance({ |
| | | geometry: new Cesium.PolylineGeometry({ |
| | | positions: linePositions, |
| | | width: 2, |
| | | }), |
| | | attributes: { |
| | | color: Cesium.ColorGeometryInstanceAttribute.fromColor(outlineColor), |
| | | }, |
| | | }) |
| | | ) |
| | | }) |
| | | ) |
| | | }) |
| | | |
| | | if (tasks.length) await Promise.all(tasks) |
| | | |
| | | const primitives = [] |
| | | const outlinePrimitives = [] |
| | | groups.forEach(group => { |
| | | if (group.polygonInstances.length) { |
| | | const material = createRadialGradientMaterial(group.outlineColor, group.fillColor, { |
| | | gamma: 1.7, |
| | | innerCutoff: 0, |
| | | }) |
| | | polygonInstances.push( |
| | | new Cesium.GeometryInstance({ |
| | | geometry: polygon, |
| | | attributes: { |
| | | color: Cesium.ColorGeometryInstanceAttribute.fromColor(shape.fillColor), |
| | | }, |
| | | }) |
| | | ) |
| | | const linePositions = positions.length > 1 ? [...positions, positions[0]] : positions |
| | | lineInstances.push( |
| | | new Cesium.GeometryInstance({ |
| | | geometry: new Cesium.GroundPolylineGeometry({ |
| | | positions: linePositions, |
| | | width: 2, |
| | | }), |
| | | attributes: { |
| | | color: Cesium.ColorGeometryInstanceAttribute.fromColor( |
| | | shape.outlineColor |
| | | ), |
| | | }, |
| | | }) |
| | | ) |
| | | }) |
| | | let primitive = null |
| | | if (polygonInstances.length) { |
| | | primitive = new Cesium.GroundPrimitive({ |
| | | geometryInstances: polygonInstances, |
| | | appearance: new Cesium.PerInstanceColorAppearance({ translucent: true, flat: true }), |
| | | }) |
| | | addCockpitPrimitive(primitive) |
| | | } |
| | | let outlinePrimitive = null |
| | | if (lineInstances.length) { |
| | | outlinePrimitive = new Cesium.GroundPolylinePrimitive({ |
| | | geometryInstances: lineInstances, |
| | | appearance: new Cesium.PolylineColorAppearance(), |
| | | }) |
| | | addCockpitPrimitive(outlinePrimitive) |
| | | } |
| | | return { primitive, outlinePrimitive } |
| | | const primitive = new Cesium.Primitive({ |
| | | geometryInstances: group.polygonInstances, |
| | | appearance: new Cesium.MaterialAppearance({ |
| | | material, |
| | | translucent: true, |
| | | }), |
| | | }) |
| | | addCockpitPrimitive(primitive) |
| | | primitives.push(primitive) |
| | | } |
| | | if (group.lineInstances.length) { |
| | | const outlinePrimitive = new Cesium.Primitive({ |
| | | geometryInstances: group.lineInstances, |
| | | appearance: new Cesium.PolylineColorAppearance(), |
| | | }) |
| | | addCockpitPrimitive(outlinePrimitive) |
| | | outlinePrimitives.push(outlinePrimitive) |
| | | } |
| | | }) |
| | | |
| | | return { primitives, outlinePrimitives } |
| | | } |
| | | |
| | | const parseGeomJson = geomJson => { |
| | |
| | | return shapes |
| | | } |
| | | |
| | | const renderDefenseZones = zones => { |
| | | const renderDefenseZones = async zones => { |
| | | if (!viewer) return |
| | | clearDefenseZoneEntities() |
| | | const result = buildZonePrimitives(zones, '#72F3FF', '#72F3FF', '#0A7C88') |
| | | const result = await buildZonePrimitives(zones, '#72F3FF', '#72F3FF', '#0A7C88') |
| | | defenseZonePrimitive = result.primitive |
| | | defenseZoneOutlinePrimitive = result.outlinePrimitive |
| | | if (defenseZonePrimitive) defenseZonePrimitive.show = detailVisible.value |
| | |
| | | reorderCockpitPrimitives() |
| | | } |
| | | |
| | | const renderPartitions = zones => { |
| | | const renderPartitions = async zones => { |
| | | if (!viewer) return |
| | | clearPartitionEntities() |
| | | const shapes = resolvePartitionShapes(zones) |
| | | const result = buildPartitionPrimitives(shapes) |
| | | partitionPrimitive = result.primitive |
| | | partitionOutlinePrimitive = result.outlinePrimitive |
| | | if (partitionPrimitive) partitionPrimitive.show = detailVisible.value |
| | | if (partitionOutlinePrimitive) partitionOutlinePrimitive.show = detailVisible.value |
| | | const result = await buildPartitionPrimitives(shapes) |
| | | partitionFillPrimitives = result.primitives |
| | | partitionOutlinePrimitives = result.outlinePrimitives |
| | | if (partitionFillPrimitives.length) { |
| | | partitionFillPrimitives.forEach(primitive => { |
| | | primitive.show = detailVisible.value |
| | | }) |
| | | } |
| | | if (partitionOutlinePrimitives.length) { |
| | | partitionOutlinePrimitives.forEach(primitive => { |
| | | primitive.show = detailVisible.value |
| | | }) |
| | | } |
| | | reorderCockpitPrimitives() |
| | | } |
| | | |
| | |
| | | if (!viewer) return |
| | | try { |
| | | const res = await fwDefenseZonePageApi({ current: 1, size: DEFAULT_ZONE_PAGE_SIZE }) |
| | | renderDefenseZones(res?.data?.data?.records ?? []) |
| | | await renderDefenseZones(res?.data?.data?.records ?? []) |
| | | } catch (error) { |
| | | renderDefenseZones([]) |
| | | await renderDefenseZones([]) |
| | | } |
| | | } |
| | | |
| | |
| | | if (!viewer) return |
| | | try { |
| | | const res = await fwAreaDivideListApi() |
| | | renderPartitions(res?.data?.data ?? []) |
| | | await renderPartitions(res?.data?.data ?? []) |
| | | } catch (error) { |
| | | renderPartitions([]) |
| | | await renderPartitions([]) |
| | | } |
| | | } |
| | | |