From f4d452c1967e5a223148df4b4c33ee460aa56b71 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E4=B8=A5=E4=BA=89=E9=B8=A3?= Date: Tue, 25 Feb 2025 15:59:30 +0800 Subject: [PATCH] =?UTF-8?q?feat:=E6=96=B0=E5=A2=9E=E6=9C=AA=E5=AE=8C?= =?UTF-8?q?=E6=88=90=E7=9A=84=E5=8D=AB=E6=98=9F=E9=80=9A=E4=BF=A1=E8=BD=BD?= =?UTF-8?q?=E8=8D=B7?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/hooks/entity.ts | 2 + src/js/Beam.js | 242 ++++++++++++++++++ src/js/Wave.js | 98 ------- src/js/satelliteEntity.js | 20 ++ src/main.ts | 2 +- .../Gantt/components/Gantt/hooks/gantt.ts | 20 +- src/views/Payload/Communication.jsx | 1 - src/views/Satellite/hooks/satellite.ts | 56 +++- 8 files changed, 329 insertions(+), 112 deletions(-) create mode 100644 src/js/Beam.js delete mode 100644 src/js/Wave.js diff --git a/src/hooks/entity.ts b/src/hooks/entity.ts index 905d01c61..3c7bb896e 100644 --- a/src/hooks/entity.ts +++ b/src/hooks/entity.ts @@ -5,6 +5,7 @@ const baseMap = new Map() const mubiaoMap = new Map() const mubiaoConicMap = new Map() const satelliteMap = new Map() +const satelliteBeamMap = new Map() const mbPayloadShowMap = reactive(new Map()) // const satDetectingPayloadMap = reactive(new Map()) @@ -17,6 +18,7 @@ export const useEntity = () => { mubiaoMap, mubiaoConicMap, satelliteMap, + satelliteBeamMap, mbPayloadShowMap, // satDetectingPayloadMap, // satCommunicationPayloadMap, diff --git a/src/js/Beam.js b/src/js/Beam.js new file mode 100644 index 000000000..3b3af84b8 --- /dev/null +++ b/src/js/Beam.js @@ -0,0 +1,242 @@ +class BeamPrimitiveMaterialProperty { + constructor(option) { + this.opts = { + color: Cesium.Color.RED, + duration: 2000, + time: new Date().getTime(), + repeat: 30, + offset: 0, + thickness: 0.3, + } + this.opts = Object.assign(this.opts, option) + this._definitionChanged = new Cesium.Event() + this._color = undefined + this._colorSubscription = undefined + this.color = this.opts.color + this.duration = this.opts.duration + this._time = this.opts.time + } +} + +Object.defineProperties(BeamPrimitiveMaterialProperty.prototype, { + isConstant: { + get: function () { + return false + }, + }, + definitionChanged: { + get: function () { + return this._definitionChanged + }, + }, +}) + +BeamPrimitiveMaterialProperty.prototype.getType = function (time) { + return 'BeamPrimitive' +} + +BeamPrimitiveMaterialProperty.prototype.getValue = function (time, result) { + if (!Cesium.defined(result)) { + result = {} + } + result.color = Cesium.Property.getValueOrClonedDefault( + this._color, + time, + Cesium.Color.WHITE, + result.color + ) + result.time = + ((new Date().getTime() - this._time) % this.duration) / this.duration / 10 + result.repeat = this.opts.repeat + result.offset = this.opts.offset + result.thickness = this.opts.thickness + return result +} + +BeamPrimitiveMaterialProperty.prototype.equals = function (other) { + return ( + this === other || + (other instanceof BeamPrimitiveMaterialProperty && + Cesium.Property.equals(this._color, other._color)) + ) +} + +Cesium.BeamPrimitiveMaterialProperty = BeamPrimitiveMaterialProperty +Cesium.Material.BeamPrimitiveType = 'BeamPrimitive' +Cesium.Material.BeamPrimitiveSource = + 'uniform vec4 color;\n\ + uniform float repeat;\n\ + uniform float offset;\n\ + uniform float thickness;\n\ + czm_material czm_getMaterial(czm_materialInput materialInput){\n\ + czm_material material = czm_getDefaultMaterial(materialInput);\n\ + float sp = 1.0/repeat;\n\ + vec2 st = materialInput.st;\n\ + float dis = distance(st, vec2(0.5));\n\ + float m = mod(dis + offset-time, sp);\n\ + float a = step(sp*(1.0-thickness), m); \n\ + material.diffuse = color.rgb;\n\ + material.alpha = a * color.a;\n\ + return material;\n\ + }' + +Cesium.Material._materialCache.addMaterial(Cesium.Material.BeamPrimitiveType, { + fabric: { + type: Cesium.Material.BeamPrimitiveType, + uniforms: { + color: new Cesium.Color(1.0, 0.0, 0.0, 0.5), + time: 0, + repeat: 30, + offset: 0, + thickness: 0.3, + }, + source: Cesium.Material.BeamPrimitiveSource, + }, + translucent: function (material) { + return true + }, +}) + +export class Beam { + constructor(opt) { + this.topEntity = opt.topEntity + this.bottomEntity = opt.bottomEntity + this.color = opt.color || '#00dcff82' + this.topRadius = opt.topRadius || 0 + this.bottomRadius = opt.bottomRadius || 10000 + this.duration = opt.duration || 2000 + this.repeat = opt.repeat || 160 + + this.centerPoint = null + this.distance = null + this.beamEntity = null + + this._listener = null + } + + create() { + const cylinder = viewer.entities.add({ + // name: 'Red cone', + position: this.centerPoint, + // orientation: null, + cylinder: { + topRadius: 0, + bottomRadius: 10000, + length: this.distance, + topSurface: true, //新增参数,控制顶部是否渲染 + bottomSurface: true, //新增参数,控制底部是否渲染 + material: new Cesium.BeamPrimitiveMaterialProperty({ + color: Cesium.Color.fromCssColorString(this.color), + thickness: 0.2, + duration: this.duration, + repeat: this.repeat, + }), + }, + }) + this.beamEntity = cylinder + + this._listener = (scene, time) => { + if (!this.beamEntity) { + return + } + let topPosition = Cesium.Property.getValueOrUndefined( + this.topEntity.position, + time, + new Cesium.Cartesian3() + ) + let bottomPosition = this.bottomEntity.position + console.log(bottomPosition, 'bottomPosition') + this.centerPoint = this._getCenterPoint(topPosition, bottomPosition) + console.log(this.centerPoint, 'centerPoint') + this.beamEntity.position = this.centerPoint + this.distance = this._getDistance(topPosition, bottomPosition) + this.beamEntity.cylinder.length = this.distance + + console.log(this.distance) + const orientation = this._getOrientation(topPosition, bottomPosition) + + this.beamEntity.orientation = orientation + } + + viewer.scene.preRender.addEventListener(this._listener) + } + + _getCenterPoint(t, b) { + this.centerPoint = Cesium.Cartesian3.lerp( + t, + b, + 0.5, + new Cesium.Cartesian3() + ) + } + + _getDistance(t, b) { + this.distance = Cesium.Cartesian3.distance(t, b) + } + + _getOrientation(t, b) { + let m = this._getModelMatrix(t, b) + let hpr = this._getHeadingPitchRoll(m) + hpr.pitch = hpr.pitch + Cesium.Math.PI / 2 + Cesium.Math.PI + let orientation = Cesium.Transforms.headingPitchRollQuaternion(t, hpr) + return orientation + } + + _getModelMatrix(pointA, pointB) { + //向量AB + const vector2 = Cesium.Cartesian3.subtract( + pointB, + pointA, + new Cesium.Cartesian3() + ) + //归一化 + const normal = Cesium.Cartesian3.normalize(vector2, new Cesium.Cartesian3()) + //旋转矩阵 + const rotationMatrix3 = + Cesium.Transforms.rotationMatrixFromPositionVelocity( + pointA, + normal, + Cesium.Ellipsoid.WGS84 + ) + const modelMatrix4 = Cesium.Matrix4.fromRotationTranslation( + rotationMatrix3, + pointA + ) + return modelMatrix4 + } + + _getHeadingPitchRoll(m) { + const m1 = Cesium.Transforms.eastNorthUpToFixedFrame( + Cesium.Matrix4.getTranslation(m, new Cesium.Cartesian3()), + Cesium.Ellipsoid.WGS84, + new Cesium.Matrix4() + ) + // 矩阵相除 + const m3 = Cesium.Matrix4.multiply( + Cesium.Matrix4.inverse(m1, new Cesium.Matrix4()), + m, + new Cesium.Matrix4() + ) + // 旋转矩阵 + const mat3 = Cesium.Matrix4.getMatrix3(m3, new Cesium.Matrix3()) + // 计算四元数 + const q = Cesium.Quaternion.fromRotationMatrix(mat3) + // 计算旋转角(弧度) + const hpr = Cesium.HeadingPitchRoll.fromQuaternion(q) + return hpr + } + + remove() { + if (this.entity) { + viewer.entities.remove(this.entity) + this._removeListener() + } + } + + _removeListener() { + if (this._listener) { + viewer.scene.preRender.removeEventListener(this._listener) + } + this._listener = null + } +} diff --git a/src/js/Wave.js b/src/js/Wave.js deleted file mode 100644 index efe16a8bf..000000000 --- a/src/js/Wave.js +++ /dev/null @@ -1,98 +0,0 @@ -class WavePrimitiveMaterialProperty { - constructor(option) { - this.opts = { - color: Cesium.Color.RED, - duration: 2000, - time: new Date().getTime(), - repeat: 30, - offset: 0, - thickness: 0.3, - } - this.opts = Object.assign(this.opts, option) - this._definitionChanged = new Cesium.Event() - this._color = undefined - this._colorSubscription = undefined - this.color = this.opts.color - this.duration = this.opts.duration - this._time = this.opts.time - } -} - -Object.defineProperties(WavePrimitiveMaterialProperty.prototype, { - isConstant: { - get: function () { - return false - }, - }, - definitionChanged: { - get: function () { - return this._definitionChanged - }, - }, -}) - -WavePrimitiveMaterialProperty.prototype.getType = function (time) { - return 'WavePrimitive' -} - -WavePrimitiveMaterialProperty.prototype.getValue = function (time, result) { - if (!Cesium.defined(result)) { - result = {} - } - result.color = Cesium.Property.getValueOrClonedDefault( - this._color, - time, - Cesium.Color.WHITE, - result.color - ) - result.time = - ((new Date().getTime() - this._time) % this.duration) / this.duration / 10 - result.repeat = this.opts.repeat - result.offset = this.opts.offset - result.thickness = this.opts.thickness - return result -} - -WavePrimitiveMaterialProperty.prototype.equals = function (other) { - return ( - this === other || - (other instanceof WavePrimitiveMaterialProperty && - Cesium.Property.equals(this._color, other._color)) - ) -} - -Cesium.wavePrimitiveProperty = WavePrimitiveMaterialProperty -Cesium.Material.wavePrimitiveType = 'WavePrimitive' -Cesium.Material.wavePrimitiveSource = - 'uniform vec4 color;\n\ - uniform float repeat;\n\ - uniform float offset;\n\ - uniform float thickness;\n\ - czm_material czm_getMaterial(czm_materialInput materialInput){\n\ - czm_material material = czm_getDefaultMaterial(materialInput);\n\ - float sp = 1.0/repeat;\n\ - vec2 st = materialInput.st;\n\ - float dis = distance(st, vec2(0.5));\n\ - float m = mod(dis + offset-time, sp);\n\ - float a = step(sp*(1.0-thickness), m); \n\ - material.diffuse = color.rgb;\n\ - material.alpha = a * color.a;\n\ - return material;\n\ - }' - -Cesium.Material._materialCache.addMaterial(Cesium.Material.wavePrimitiveType, { - fabric: { - type: Cesium.Material.wavePrimitiveType, - uniforms: { - color: new Cesium.Color(1.0, 0.0, 0.0, 0.5), - time: 0, - repeat: 30, - offset: 0, - thickness: 0.3, - }, - source: Cesium.Material.wavePrimitiveSource, - }, - translucent: function (material) { - return true - }, -}) diff --git a/src/js/satelliteEntity.js b/src/js/satelliteEntity.js index 2cda28756..cb545f0b6 100644 --- a/src/js/satelliteEntity.js +++ b/src/js/satelliteEntity.js @@ -26,6 +26,8 @@ class SatelliteEntity { this._sensorAngle = 30 this._sensorType = 'conic' this._listener = null + // this._beam = false + // this.beamEntityMap = new Map() } get sensorType() { return this._sensorType @@ -85,6 +87,20 @@ class SatelliteEntity { } } + // get beam() { + // return this._beam + // } + // set beam(showBeam) { + // this._beam = showBeam + // if (showBeam) { + // if (!this.beamEntityMap.has()) { + // this.createBeam(this.entity) + // } + // } else { + // this.removeBeam() + // } + // } + _checkTle(tle) { let elements = tle.split('\n') if (elements.length !== 3) { @@ -521,6 +537,10 @@ class SatelliteEntity { this._listener = null } } + + // createBeam() { + + // } destroy() { this.removeSensor() viewer.entities.remove(this.entity) diff --git a/src/main.ts b/src/main.ts index 45593b1ee..7fd6565fe 100644 --- a/src/main.ts +++ b/src/main.ts @@ -11,7 +11,7 @@ import 'normalize.css' import 'virtual:windi.css' import './js/polylineTrail.js' -import './js/Wave.js' +import './js/Beam.js' import Loading from '@/components/Loading/Loading' // import { Viewer } from "cesium"; diff --git a/src/views/Gantt/components/Gantt/hooks/gantt.ts b/src/views/Gantt/components/Gantt/hooks/gantt.ts index 40dbbb723..951aa6b4f 100644 --- a/src/views/Gantt/components/Gantt/hooks/gantt.ts +++ b/src/views/Gantt/components/Gantt/hooks/gantt.ts @@ -94,19 +94,19 @@ const useGantt = ({ router, route }: GanttParams) => { lineWidth: 1, lineDash: [4, 2], }, - scales: getTimeScales('month'), + scales: getTimeScales('day'), }, - minDate: '2023-11-14', + minDate: '2024-11-14', maxDate: '2024-12-30', markLine: [ - // { - // date: '2024-07-29', - // style: { - // lineWidth: 1, - // lineColor: 'blue', - // lineDash: [8, 4], - // }, - // }, + { + date: '2024-07-29', + style: { + lineWidth: 1, + lineColor: 'blue', + lineDash: [8, 4], + }, + }, // { // date: '2024-08-17', // style: { diff --git a/src/views/Payload/Communication.jsx b/src/views/Payload/Communication.jsx index 207ce2f84..cbe331a21 100644 --- a/src/views/Payload/Communication.jsx +++ b/src/views/Payload/Communication.jsx @@ -1,4 +1,3 @@ -import { defineExpose } from 'vue' import { NDataTable, NButton, diff --git a/src/views/Satellite/hooks/satellite.ts b/src/views/Satellite/hooks/satellite.ts index 84aed587e..f57448e19 100644 --- a/src/views/Satellite/hooks/satellite.ts +++ b/src/views/Satellite/hooks/satellite.ts @@ -3,6 +3,7 @@ import { difference } from 'lodash' import { useEntity } from '@/hooks/entity' import { useTree } from '@/utils/tree' import { getSatellite } from '@/api/Satellite' +import { Beam } from '@/js/Beam' // import CreateFrustum from '@/js/Sensor' @@ -21,7 +22,8 @@ const { filterTreeNodeByField } = useTree() const satelliteList = ref([]) const checkedKeys = ref>([]) -const { satelliteMap, showOrHideLoad, satellitePayloadShowMap } = useEntity() +const { mubiaoMap, satelliteMap, satelliteBeamMap, satellitePayloadShowMap } = + useEntity() const showPoint = ref(true) function showPointUnderSat(id?: string) { @@ -72,6 +74,8 @@ export function useSatellite() { (satellite.sensorAngle = satPayload.detectingPayload.angle) satPayload.detectingPayload.show && (satellite.sensor = true) } + + createSatelliteCommunicationPayload(id) }, 1000) // viewer.clock.multiplier = 100 @@ -119,6 +123,54 @@ export function useSatellite() { } } +function createSatelliteCommunicationPayload(satId: string) { + if ( + !satelliteMap.has(satId) || + !satellitePayloadShowMap.get(satId)?.communicationPayload || + satellitePayloadShowMap.get(satId)?.communicationPayload?.show + ) { + return + } + + removeSatelliteCommunicationPayload(satId) + // console.log(satellitePayloadShowMap.get(id)?.communicationPayload) + satellitePayloadShowMap + .get(satId) + ?.communicationPayload?.target.forEach((mbId: string) => { + console.log(mbId, 'mbId') + if (mubiaoMap.has(mbId)) { + const beam = new Beam({ + topEntity: satelliteMap.get(satId), + bottomEntity: mubiaoMap.get(mbId), + }) + + beam.create() + + console.log(beam) + + if (!satelliteBeamMap.has(satId)) { + satelliteBeamMap.set(satId, new Map()) + } + + const beamMap = satelliteBeamMap.get(satId) + beamMap.set(mbId, beam) + } + }) +} + +function removeSatelliteCommunicationPayload(satId: string) { + if (!satelliteBeamMap.has(satId)) { + return + } + const beamMap = satelliteBeamMap.get(satId) + ;[...beamMap.keys()].forEach((mbId: string) => { + beamMap.get(mbId)?.remove() + beamMap.delete(mbId) + }) + + satelliteBeamMap.delete(satId) +} + // function filterTreeNodeByField({ // treeData, // params, @@ -175,7 +227,7 @@ function getAllNodesToPayload() { ? { ...detectingPayload, show: detectingShow } : null, communicationPayload: communicationPayload - ? { ...communicationPayload, show: communicationShow } + ? { target: communicationPayload, show: communicationShow } : null, }) }