From de9d1a4db5557e874a30fd4ca43a7dbf4d8c841b 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 10:43:57 +0800 Subject: [PATCH] =?UTF-8?q?=E6=96=B0=E5=A2=9E=E8=BD=BD=E8=8D=B7=E7=9A=84?= =?UTF-8?q?=E5=88=A0=E9=99=A4=E3=80=81=E5=92=8C=E4=BF=AF=E4=BB=B0=E8=A7=92?= =?UTF-8?q?=E8=BE=90=E5=B0=84=E8=B7=9D=E7=A6=BB=E7=AD=89=E5=8F=82=E6=95=B0?= =?UTF-8?q?=E3=80=81=E4=BF=AE=E6=94=B9=E8=BD=A8=E8=BF=B9=E6=9B=B2=E7=BA=BF?= =?UTF-8?q?=E3=80=81jb=E5=88=86=E7=B1=BB=E5=92=8C=E9=A2=9C=E8=89=B2?= =?UTF-8?q?=E7=AD=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- package-lock.json | 11 ++ package.json | 1 + public/baseConfig.js | 16 ++- public/images/icons/10-5900-0-航空母舰.png | Bin 0 -> 3401 bytes public/images/icons/10-5900-0-航空母舰.svg | 1 + public/images/icons/10-6000-0-巡洋舰.png | Bin 0 -> 3423 bytes public/images/icons/10-6000-0-巡洋舰.svg | 1 + public/images/icons/10-6100-0-驱逐舰.png | Bin 0 -> 3383 bytes public/images/icons/10-6100-0-驱逐舰.svg | 1 + public/images/icons/10-6200-0-护卫舰.png | Bin 0 -> 3335 bytes public/images/icons/10-7200-0-歼击机.png | Bin 0 -> 3642 bytes public/images/icons/10-7200-0-歼击机.svg | 1 + public/images/icons/10-7400-0-轰炸机.png | Bin 0 -> 3692 bytes public/images/icons/10-7600-0-侦察机.png | Bin 0 -> 3631 bytes public/images/icons/10-7600-0-侦察机.svg | 1 + src/hooks/entity.ts | 86 +++++++++++-- src/js/Wave.js | 98 ++++++++++++++ src/js/satelliteEntity.js | 25 +++- src/main.ts | 1 + src/utils/pos.js | 27 ++++ src/views/Content/index.vue | 2 +- .../Daodan/components/hooks/testHooks.jsx | 29 +++-- .../Gantt/components/Gantt/hooks/gantt.ts | 56 +++++--- .../components/HisTrajectory/hooks/mbTraj.ts | 35 +++-- .../MultiHisTrajectory/hooks/multiMbTraj.ts | 52 ++++++-- src/views/Mubiao/hooks/mubiao.ts | 19 ++- src/views/Mubiao/hooks/mubiaoDetail.jsx | 33 ++++- src/views/Payload/Detection.jsx | 121 +++++++++++------- src/views/Satellite/components/SatDetail.jsx | 42 +++++- src/views/Satellite/hooks/satellite.ts | 2 + 30 files changed, 521 insertions(+), 140 deletions(-) create mode 100644 public/images/icons/10-5900-0-航空母舰.png create mode 100644 public/images/icons/10-5900-0-航空母舰.svg create mode 100644 public/images/icons/10-6000-0-巡洋舰.png create mode 100644 public/images/icons/10-6000-0-巡洋舰.svg create mode 100644 public/images/icons/10-6100-0-驱逐舰.png create mode 100644 public/images/icons/10-6100-0-驱逐舰.svg create mode 100644 public/images/icons/10-6200-0-护卫舰.png create mode 100644 public/images/icons/10-7200-0-歼击机.png create mode 100644 public/images/icons/10-7200-0-歼击机.svg create mode 100644 public/images/icons/10-7400-0-轰炸机.png create mode 100644 public/images/icons/10-7600-0-侦察机.png create mode 100644 public/images/icons/10-7600-0-侦察机.svg create mode 100644 src/js/Wave.js diff --git a/package-lock.json b/package-lock.json index b5c2eb5cb..202595801 100644 --- a/package-lock.json +++ b/package-lock.json @@ -21,6 +21,7 @@ "chroma-js": "^3.1.2", "dayjs": "^1.11.13", "echarts": "^5.5.1", + "es-toolkit": "^1.32.0", "lodash": "^4.17.21", "maplibre-gl": "^5.0.1", "moment-timezone": "^0.5.46", @@ -10047,6 +10048,16 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/es-toolkit": { + "version": "1.32.0", + "resolved": "https://registry.npmmirror.com/es-toolkit/-/es-toolkit-1.32.0.tgz", + "integrity": "sha512-ZfSfHP1l6ubgW/B/FRtqb9bYdMvI6jizbOSfbwwJNcOQ1QE6TFsC3jpQkZ900uUPSR3t3SU5Ds7UWKnYz+uP8Q==", + "license": "MIT", + "workspaces": [ + "docs", + "benchmarks" + ] + }, "node_modules/esbuild": { "version": "0.24.2", "resolved": "https://registry.npmmirror.com/esbuild/-/esbuild-0.24.2.tgz", diff --git a/package.json b/package.json index ce79c347f..377e4addc 100644 --- a/package.json +++ b/package.json @@ -24,6 +24,7 @@ "chroma-js": "^3.1.2", "dayjs": "^1.11.13", "echarts": "^5.5.1", + "es-toolkit": "^1.32.0", "lodash": "^4.17.21", "maplibre-gl": "^5.0.1", "moment-timezone": "^0.5.46", diff --git a/public/baseConfig.js b/public/baseConfig.js index 9ab8ddd58..6d2aacfed 100644 --- a/public/baseConfig.js +++ b/public/baseConfig.js @@ -24,21 +24,27 @@ window['settings'] = { model: './models/雷达.glb', }, }, + mbCountryDict: { + 美国: '#fff', + 中国: '#d00', + 日本: '#dd0', + 韩国: '#00d', + }, mbDict: { 甲: { - icon: './images/icons/飞机.png', + icon: './images/icons/10-7600-0-侦察机.svg', color: '#d00', model: './models/IDF.glb', - payload: 'conic', + payload: 'airplaneConic', }, 乙: { - icon: './images/icons/舰船.png', - color: '#dd0', + icon: './images/icons/10-5900-0-航空母舰.svg', + color: '#ff0', model: './models/驱逐舰2.glb', payload: 'radar', }, 丙: { - icon: './images/icons/舰船.png', + icon: './images/icons/10-6100-0-驱逐舰.svg', color: '#dd0', model: './models/驱逐舰2.glb', payload: 'radar', diff --git a/public/images/icons/10-5900-0-航空母舰.png b/public/images/icons/10-5900-0-航空母舰.png new file mode 100644 index 0000000000000000000000000000000000000000..b48cfbddd09b8690545d3f88f62d2879c551906d GIT binary patch literal 3401 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 \ No newline at end of file diff --git a/public/images/icons/10-6000-0-巡洋舰.png b/public/images/icons/10-6000-0-巡洋舰.png new file mode 100644 index 0000000000000000000000000000000000000000..28003077a31a2d3f27776de3f958b9cd1587762e GIT binary patch literal 3423 zcmV-l4WROgP)pPO=&|zP*7-ZbZ>KLZ*U+5Lu!Sk^o_Z5E4Meg@_7P6crJiNL9pw)e1;Xm069{HJUZAPk55R%$-RIA z6-eL&AQ0xu!e<4=008gy@A0LT~suv4>S3ILP<0Bm`DLLvaF4FK%)Nj?Pt*r}7;7Xa9z9H|HZjR63e zC`Tj$K)V27Re@400>HumpsYY5E(E}?0f1SyGDiY{y#)Yvj#!WnKwtoXnL;eg03bL5 z07D)V%>y7z1E4U{zu>7~aD})?0RX_umCct+(lZpemCzb@^6=o|A>zVpu|i=NDG+7} zl4`aK{0#b-!z=TL9Wt0BGO&T{GJWpjryhdijfaIQ&2!o}p04JRKYg3k&Tf zVxhe-O!X z{f;To;xw^bEES6JSc$k$B2CA6xl)ltA<32E66t?3@gJ7`36pmX0IY^jz)rRYwaaY4 ze(nJRiw;=Qb^t(r^DT@T3y}a2XEZW-_W%Hszxj_qD**t_m!#tW0KDiJT&R>6OvVTR z07RgHDzHHZ48atvzz&?j9lXF70$~P3Knx_nJP<+#`N z#-MZ2bTkiLfR>_b(HgWKJ%F~Nr_oF3b#wrIijHG|(J>BYjM-sajE6;FiC7vY#};Gd zST$CUHDeuEH+B^pz@B062qXfFfD`NpUW5?BY=V%GM_5c)L#QR}BeW8_2v-S%gfYS= zB9o|3v?Y2H`NVi)In3rTB8+ej^> zQ=~r95NVuDChL%G$=>7$vVg20myx%S50Foi`^m%Pw-h?Xh~i8Mq9jtJloCocWk2Nv zrJpiFnV_ms&8eQ$2&#xWpIS+6pmtC%Q-`S&GF4Q#^mhymh7E(qNMa}%YZ-ePrx>>xFPTiH1=E+A$W$=bG8>s^ zm=Bn5Rah$aDtr}@$`X}2l~$F0mFKEdRdZE8)p@E5RI61Ft6o-prbbn>P~)iy)E2AN zsU20jsWz_8Qg>31P|s0cqrPALg8E|(vWA65poU1JRAaZs8I2(p#xiB`SVGovRs-uS zYnV-9TeA7=Om+qP8+I>yOjAR1s%ETak!GFdam@h^# z)@rS0t$wXH+Irf)+G6c;?H29p+V6F6oj{!|o%K3xI`?%6x;DB|x`n#ibhIR?(H}Q3Gzd138Ei2)WAMz7W9Vy`X}HnwgyEn!VS)>mv$8&{hQn>w4zwy3R}t;BYlZQm5)6pty=DfLrs+A-|>>;~;Q z_F?uV_HFjh9n2gO9o9Q^JA86v({H5aB!kjoO6 zc9$1ZZKsN-Zl8L~mE{`ly3)1N^`o1+o7}D0ZPeY&J;i;i`%NyJ8_8Y6J?}yE@b_5a zam?eLr<8@mESk|3$_SkmS{wQ>%qC18))9_|&j{ZT zes8AvOzF(F2#DZEY>2oYX&IRp`F#{ADl)1r>QS^)ba8a|EY_^#S^HO&t^Rgqwv=MZThqqEWH8 zxJo>d=ABlR_Bh=;eM9Tw|Ih34~oTE|= zX_mAr*D$vzw@+p(E0Yc6dFE}(8oqt`+R{gE3x4zjX+Sb3_cYE^= zgB=w+-tUy`ytONMS8KgRef4hA?t0j zufM;t32jm~jUGrkaOInTZ`zyfns>EuS}G30LFK_G-==(f<51|K&cocp&EJ`SxAh3? zNO>#LI=^+SEu(FqJ)ynt=!~PC9bO$rzPJB=?=j6w@a-(u02P7 zaQ)#(uUl{HW%tYNS3ItC^iAtK(eKlL`f9+{bJzISE?u8_z3;~C8@FyI-5j_jy7l;W z_U#vU3hqqYU3!mrul&B+{ptt$59)uk{;_4iZQ%G|z+lhASr6|H35TBkl>gI*;nGLU zN7W-nBaM%pA0HbH8olyl&XeJ%vZoWz%6?Y=dFykl=imL}`%BMQ{Mhgd`HRoLu6e2R za__6DuR6yg#~-}Tc|Gx_{H@O0eebyMy5GmWADJlpK>kqk(fVV@r_fLLKIeS?{4e)} z^ZO;zpECde03c&XQcVB=dL;k=fP(-4`Tqa_faw4Lbua(`>RI+y?e7jKeZ#YO-C z0*pySK~#9!?AA{xl7lEx z5<}YBR?3BojP|04rlo0(Xv?;{Hey;M#mv0-FxgG^z|JVUJ%>-!qs7 z_gAT|_EJ_B_{PnR_UQog^9Q7)Kx8B&Cc?_f1ZintFu>7~j?K*h9FE>cWqbQIE|(db z%|U)XjE#K^J>c;09eO?JbkNy(&cMJ|nwvfN{X#>-6@7hQ0AXoKSX_Ku78ZoPJ;7!Z zy1Kq&v+aZqaCsSx(FidyP*dZ@6DN?Cf;k0d#ktU^WYdg@ViV zaKzf0aCj(WWeIh4LR;Gz)6+o$=I8g(>7b|x*4EzN>xJ=gVSnFr4`8(lX0woyA#80u z4B&7G$;pAA@8}2-z+yQkEDQuyA@BL4Ez*CeF=$CQW<`5D_LP zZ&&4lgn*`|-_Jgu7L& \ No newline at end of file diff --git a/public/images/icons/10-6100-0-驱逐舰.png b/public/images/icons/10-6100-0-驱逐舰.png new file mode 100644 index 0000000000000000000000000000000000000000..a941cd5b3184dd348642634f95f90730f5b07378 GIT binary patch literal 3383 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 \ No newline at end of file diff --git a/public/images/icons/10-6200-0-护卫舰.png b/public/images/icons/10-6200-0-护卫舰.png new file mode 100644 index 0000000000000000000000000000000000000000..afa628eb3c656404b4e1014b36c2866a3a99573f GIT binary patch literal 3335 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 R%76d>002ovPDHLkV1hZlR`>t_ literal 0 HcmV?d00001 diff --git a/public/images/icons/10-7200-0-歼击机.png b/public/images/icons/10-7200-0-歼击机.png new file mode 100644 index 0000000000000000000000000000000000000000..e6804fe50d2de533be9d06aeb5e93cc725b14ae8 GIT binary patch literal 3642 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 M07*qoM6N<$g7r)Hr2qf` literal 0 HcmV?d00001 diff --git a/public/images/icons/10-7200-0-歼击机.svg b/public/images/icons/10-7200-0-歼击机.svg new file mode 100644 index 000000000..a3050572b --- /dev/null +++ b/public/images/icons/10-7200-0-歼击机.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/public/images/icons/10-7400-0-轰炸机.png b/public/images/icons/10-7400-0-轰炸机.png new file mode 100644 index 0000000000000000000000000000000000000000..5228a50fb13bc46dac1c66236410f69ec4f04edb GIT binary patch literal 3692 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 KMNUMnLSTZG^cFk- literal 0 HcmV?d00001 diff --git a/public/images/icons/10-7600-0-侦察机.png b/public/images/icons/10-7600-0-侦察机.png new file mode 100644 index 0000000000000000000000000000000000000000..d2087ec85a7f9cf59ce05f741ac46e857a57a2e5 GIT binary patch literal 3631 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 B-K+or literal 0 HcmV?d00001 diff --git a/public/images/icons/10-7600-0-侦察机.svg b/public/images/icons/10-7600-0-侦察机.svg new file mode 100644 index 000000000..7e7329db8 --- /dev/null +++ b/public/images/icons/10-7600-0-侦察机.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/hooks/entity.ts b/src/hooks/entity.ts index 3e0665981..905d01c61 100644 --- a/src/hooks/entity.ts +++ b/src/hooks/entity.ts @@ -77,17 +77,21 @@ async function getHisTraj({ return { points, posArray, timeArray } } -function getMBEntityOpt({ +async function getMBEntityOpt({ id, targetType, + country, extendInfo, }: { id: string targetType: string + country: string extendInfo?: { detectingPayload: Record } }) { const mubiaoDict = window.settings.mbDict[targetType] + const countryColor = window.settings.mbCountryDict[country] + // console.log(country, countryColor) let ellipsoid if (extendInfo) { const { @@ -98,7 +102,7 @@ function getMBEntityOpt({ maximumClock, radius, } = extendInfo.detectingPayload - if (radius) { + if (maximumClock || minimumClock || minimumCone) { ellipsoid = { ellipsoid: { show: mbPayloadShowMap.get(id)?.detectingPayload?.show || false, @@ -122,11 +126,17 @@ function getMBEntityOpt({ } } } + const image = await getImageByColor({ + img: mubiaoDict.icon, + color: countryColor, + }) + // console.log(image.img, (+image.height / +image.width) * 30) return { label: { text: `${id}`, font: '12pt sans-serif', - fillColor: Cesium.Color.YELLOW, + fillColor: Cesium.Color.fromCssColorString(countryColor), + // fillColor: Cesium.Color.YELLOW, outlineColor: Cesium.Color.BLACK, outlineWidth: 2, style: Cesium.LabelStyle.FILL_AND_OUTLINE, @@ -141,10 +151,12 @@ function getMBEntityOpt({ }, billboard: { show: !iconOrModel.value, - image: mubiaoDict.icon, - width: 30, - height: 30, - color: Cesium.Color.fromCssColorString(mubiaoDict.color), + image: image.img, + // image: mubiaoDict.icon, + width: 35, + height: (+image.height / +image.width) * 35, + // height: 30, + color: Cesium.Color.fromCssColorString(countryColor), scaleByDistance: new Cesium.NearFarScalar(7000000, 1.0, 18000000, 0.4), }, model: { @@ -157,19 +169,64 @@ function getMBEntityOpt({ } } +async function getImageByColor({ img: url, color: newColor }) { + // 步骤 1: 获取 SVG 内容 + const svg = await fetch(url) + const svgContent = await svg.text() + + // 步骤 2: 修改 SVG 的颜色 + const parser = new DOMParser() + const svgDoc = parser.parseFromString(svgContent, 'image/svg+xml') + + // 修改所有路径、圆形、矩形等元素的填充颜色 + const elements = svgDoc.querySelectorAll('path, circle, rect, polygon, line') + elements.forEach(element => { + // 修改 fill 属性 + element.setAttribute('fill', newColor) + // 也可以修改 stroke 颜色,防止可能的边框颜色问题 + element.setAttribute('stroke', newColor) + }) + + const svgElement = svgDoc.documentElement + // console.log(svgElement) + + // const transformValue = `rotate(${90}, 50, 50)` + // svgElement.setAttribute('transform', transformValue) + + // 获取 SVG 的宽度和高度 + const width = svgElement.getAttribute('width') + const height = svgElement.getAttribute('height') + + // 步骤 3: 转换为 Base64 编码 + const serializer = new XMLSerializer() + const modifiedSVG = serializer.serializeToString(svgDoc.documentElement) + + // 输出修改后的 SVG,确保颜色正确 + const base64SVG = 'data:image/svg+xml;base64,' + btoa(modifiedSVG) + + console.log(base64SVG) + return { img: base64SVG, width, height } +} + function createMBConicSensor({ entity, angle, show, + radius, + heading, + pitch, }: { entity: Cesium.Entity angle: number show: boolean + radius: number + heading: number + pitch: number }) { - console.log('entity', angle) + console.log('entity', angle, radius, heading, pitch) const conicSensor = new CesiumSensorVolumes.ConicSensorGraphics({ show, - radius: 2e7, + radius: radius * 1000, innerHalfAngle: 0, outerHalfAngle: Cesium.Math.toRadians(angle / 2), minimumClockAngle: 0, @@ -186,9 +243,11 @@ function createMBConicSensor({ Cesium.Transforms.headingPitchRollQuaternion( entity.position._value, new Cesium.HeadingPitchRoll( - Cesium.Math.toRadians(90), - 0, - Cesium.Math.toRadians(180) + // Cesium.Math.toRadians(heading), + Cesium.Math.toRadians(heading), + Cesium.Math.toRadians(pitch), + 0 + // Cesium.Math.toRadians(pitch) ) // 初始朝向 ), conicSensor: conicSensor, @@ -214,7 +273,7 @@ watch([mbPayloadShowMap, satellitePayloadShowMap], ([newMb, newSatellite]) => { show = newMb.get(key).detectingPayload.show } if (mubiaoMap.has(key)) { - // if(console.log(mubiaoMap.get(key).ellipsoid) + // console.log(mubiaoMap.get(key).ellipsoid) mubiaoMap.get(key).ellipsoid && (mubiaoMap.get(key).ellipsoid.show = show) mubiaoConicMap.get(key)?.conicSensor && @@ -237,6 +296,7 @@ function changeShowOrHideLoad() { // ;[...mubiaoMap.values()].forEach(entity => { // entity.ellipsoid.show = !entity.ellipsoid.show._value // }) + console.log(showOrHideLoad.value) for (const [key] of mbPayloadShowMap.entries()) { mbPayloadShowMap.get(key).detectingPayload.show = showOrHideLoad.value } diff --git a/src/js/Wave.js b/src/js/Wave.js new file mode 100644 index 000000000..efe16a8bf --- /dev/null +++ b/src/js/Wave.js @@ -0,0 +1,98 @@ +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 03fd81b39..2cda28756 100644 --- a/src/js/satelliteEntity.js +++ b/src/js/satelliteEntity.js @@ -22,6 +22,7 @@ class SatelliteEntity { this.entity = null this._underPoint = false this.underPointEntity = null + this._sensorRadius = 200 this._sensorAngle = 30 this._sensorType = 'conic' this._listener = null @@ -38,11 +39,13 @@ class SatelliteEntity { set sensor(showSensor) { // console.log(showSensor, 'showSensor') this._sensor = showSensor - if (showSensor && !this.sensorEntity) { - if (this._sensorType === 'conic') { - this.createConicSensor(this.entity) - } else if (this._sensorType === 'rectangle') { - this.createRectangleSensor(this.entity) + if (showSensor) { + if (!this.sensorEntity) { + if (this._sensorType === 'conic') { + this.createConicSensor(this.entity) + } else if (this._sensorType === 'rectangle') { + this.createRectangleSensor(this.entity) + } } } else { // if(this.sensorEntity) { @@ -61,6 +64,16 @@ class SatelliteEntity { } } + get sensorRadius() { + return this._sensorRadius + } + set sensorRadius(radius) { + this._sensorRadius = radius + if (this._sensorEntity) { + this._sensorEntity.radius = radius * 1000 + } + } + get underPoint() { return this._underPoint } @@ -353,7 +366,7 @@ class SatelliteEntity { ) const conicSensor = new CesiumSensorVolumes.ConicSensorGraphics({ show: true, - radius: 2e7, + radius: this._sensorRadius * 1000, innerHalfAngle: 0, outerHalfAngle: Cesium.Math.toRadians(this._sensorAngle / 2), minimumClockAngle: 0, diff --git a/src/main.ts b/src/main.ts index 38a7c8e7f..45593b1ee 100644 --- a/src/main.ts +++ b/src/main.ts @@ -11,6 +11,7 @@ import 'normalize.css' import 'virtual:windi.css' import './js/polylineTrail.js' +import './js/Wave.js' import Loading from '@/components/Loading/Loading' // import { Viewer } from "cesium"; diff --git a/src/utils/pos.js b/src/utils/pos.js index 5a4ab4666..72bb41bf3 100644 --- a/src/utils/pos.js +++ b/src/utils/pos.js @@ -1,3 +1,5 @@ +import { lineString, bezierSpline } from '@turf/turf' + export function cartesian32LonLat(cartesian3) { const cartographic = viewer.scene.globe.ellipsoid.cartesianToCartographic(cartesian3) @@ -8,3 +10,28 @@ export function cartesian32LonLat(cartesian3) { const height = cartographic.height return [lon, lat, height] } + +export function getPositionFromTime( + startTime, + pos, + totalAnimationTime, + interval = 100 +) { + const points = [] + + for (let i = 0; i <= totalAnimationTime / interval; i++) { + const time = Cesium.JulianDate.addSeconds( + startTime, + i, + new Cesium.JulianDate() + ) + const point = pos.getValue(time) + point && points.push(point) + } + + return points +} + +export function getBezierSpline(points) { + return bezierSpline(lineString(points)) +} diff --git a/src/views/Content/index.vue b/src/views/Content/index.vue index f1ccb216b..c46a600d2 100644 --- a/src/views/Content/index.vue +++ b/src/views/Content/index.vue @@ -60,7 +60,7 @@ const types = [ { name: 'XW', value: 'wzbXw' }, ] -const showPanelName = ref('wx') +const showPanelName = ref('zb') const panelList = [ // { diff --git a/src/views/Daodan/components/hooks/testHooks.jsx b/src/views/Daodan/components/hooks/testHooks.jsx index bdbf14e47..c8fe6edbd 100644 --- a/src/views/Daodan/components/hooks/testHooks.jsx +++ b/src/views/Daodan/components/hooks/testHooks.jsx @@ -1,9 +1,10 @@ import { ref, toRaw } from 'vue' import { useDaodan } from '../../ddHooks' -import { cartesian32LonLat } from '@/utils/pos' +import { cartesian32LonLat, getPositionFromTime } from '@/utils/pos' import ExplosionEffect from '@/js/Explosion' import { generateId } from '@/utils/id' import store from 'store2' +// import { getPositionFromTime } from '@/utils/pos' // import { useDaodan } from '../../ddHooks' const trajData = ref({ @@ -611,21 +612,21 @@ function createLine({ totalAnimationTime, startTime, positionProperty, type }) { }, }) } -function getPositionFromTime(startTime, pos, totalAnimationTime) { - const points = [] +// function getPositionFromTime(startTime, pos, totalAnimationTime) { +// const points = [] - for (let i = 0; i <= totalAnimationTime / 100; i++) { - const time = Cesium.JulianDate.addSeconds( - startTime, - i, - new Cesium.JulianDate() - ) - const point = pos.getValue(time) - point && points.push(point) - } +// for (let i = 0; i <= totalAnimationTime / 100; i++) { +// const time = Cesium.JulianDate.addSeconds( +// startTime, +// i, +// new Cesium.JulianDate() +// ) +// const point = pos.getValue(time) +// point && points.push(point) +// } - return points -} +// return points +// } function modelAnimationController(controller) { const { type, initVal, maxVal, fn, step, minVal, primitive } = controller diff --git a/src/views/Gantt/components/Gantt/hooks/gantt.ts b/src/views/Gantt/components/Gantt/hooks/gantt.ts index f90fd89b8..40dbbb723 100644 --- a/src/views/Gantt/components/Gantt/hooks/gantt.ts +++ b/src/views/Gantt/components/Gantt/hooks/gantt.ts @@ -52,8 +52,8 @@ const useGantt = ({ router, route }: GanttParams) => { }, // verticalSplitLineHighlight: { // lineColor: 'green', - // lineWidth: 3 - // } + // lineWidth: 3, + // }, }, grid: { // backgroundColor: bgColor, @@ -61,11 +61,11 @@ const useGantt = ({ router, route }: GanttParams) => { lineWidth: 1, lineColor: textColorWithOp, }, - verticalLine: { - lineWidth: 1, - lineColor: textColorWithOp, - lineDash: [4, 8], - }, + // verticalLine: { + // lineWidth: 1, + // lineColor: textColorWithOp, + // lineDash: [4, 8], + // }, }, taskList: { // backgroundColor: bgColor, @@ -83,21 +83,39 @@ const useGantt = ({ router, route }: GanttParams) => { timelineHeader: { backgroundColor: headerBgColor, colWidth: 140, - verticalLine: { - lineColor: textColorWithOp, - lineWidth: 1, - lineDash: [4, 2], - }, + // colWidth: 1040, + // verticalLine: { + // lineColor: textColorWithOp, + // lineWidth: 1, + // lineDash: [4, 2], + // }, horizontalLine: { lineColor: textColorWithOp, lineWidth: 1, lineDash: [4, 2], }, - scales: getTimeScales('day'), + scales: getTimeScales('month'), }, - minDate: '2024-11-14', + minDate: '2023-11-14', maxDate: '2024-12-30', - + markLine: [ + // { + // date: '2024-07-29', + // style: { + // lineWidth: 1, + // lineColor: 'blue', + // lineDash: [8, 4], + // }, + // }, + // { + // date: '2024-08-17', + // style: { + // lineWidth: 2, + // lineColor: 'red', + // lineDash: [8, 4], + // }, + // }, + ], scrollStyle: { scrollRailColor: 'RGBA(246,246,246,0)', visible: 'focus', @@ -343,10 +361,10 @@ const useGantt = ({ router, route }: GanttParams) => { }) const day = new Text({ - text: - scale === 'day' - ? startDate.toLocaleDateString() - : startDate.toLocaleTimeString(), + text: startDate.toLocaleDateString(), + // scale === 'day' + // ? startDate.toLocaleDateString() + // : startDate.toLocaleTimeString(), fontSize: 14, fontWeight: 'bold', fontFamily: 'sans-serif', diff --git a/src/views/Mubiao/components/HisTrajectory/hooks/mbTraj.ts b/src/views/Mubiao/components/HisTrajectory/hooks/mbTraj.ts index 3ee43ee87..dacac24b2 100644 --- a/src/views/Mubiao/components/HisTrajectory/hooks/mbTraj.ts +++ b/src/views/Mubiao/components/HisTrajectory/hooks/mbTraj.ts @@ -2,6 +2,7 @@ import { ref } from 'vue' import { point, bearing } from '@turf/turf' import { cartesian32LonLat } from '@/utils/pos' import { useEntity } from '@/hooks/entity' +import { getPositionFromTime } from '@/utils/pos' type TPoints = { time: number; position: Cesium.Cartesian3 }[] @@ -51,7 +52,7 @@ export const useMBTrajectory = () => { removeEntities() } - function createTarget(points: TPoints, posArray: number[]) { + async function createTarget(points: TPoints, posArray: number[]) { const totalAnimationTime = points[points.length - 1].time // console.log('totalAnimationTime', totalAnimationTime) @@ -59,8 +60,8 @@ export const useMBTrajectory = () => { const startTime = Cesium.JulianDate.now() // 添加路径点到位置属性 points.forEach(point => { - const pointEntity = createPoint(point.position) - entities.push(pointEntity) + // const pointEntity = createPoint(point.position) + // entities.push(pointEntity) const time = Cesium.JulianDate.addSeconds( Cesium.JulianDate.now(), point.time, @@ -68,13 +69,12 @@ export const useMBTrajectory = () => { ) positionProperty.addSample(time, point.position) }) - // positionProperty.setInterpolationOptions({ - // //二次多项式进行插值。二次多项式插值相较于线性插值会更光滑,但不如高阶多项式平滑 - // interpolationDegree: 2, - // //赫尔米特多项式插值算法。使得插值曲线能够平滑过渡,并且可以更好地控制运动的速度和方向变化 - // interpolationAlgorithm: Cesium.HermitePolynomialApproximation, - // }) - // positionProperty._time.map(time => { + positionProperty.setInterpolationOptions({ + interpolationDegree: 5, + interpolationAlgorithm: Cesium.LagrangePolynomialApproximation, + }) + console.log(positionProperty, 'getValue') + // positionProperty._time.map(time => { // console.log(positionProperty.getValue(time), 'getValue') // }) // 获取 line 插值后的值 @@ -91,9 +91,16 @@ export const useMBTrajectory = () => { // now = Cesium.JulianDate.addSeconds(now, 30, new Cesium.JulianDate()) // } // console.log(linePositions) - - const mbEntityOpt = getMBEntityOpt({ + const positionList = getPositionFromTime( + startTime, + positionProperty, + totalAnimationTime, + 1 + ) + console.log(positionList, '====') + const mbEntityOpt = await getMBEntityOpt({ id: mbData.value.id, + country: mbData.value.country, targetType: mbData.value.targetType, }) // 创建实体 @@ -107,8 +114,8 @@ export const useMBTrajectory = () => { }, false), // point: { pixelSize: 10, color: Cesium.Color.RED }, polyline: { - positions: Cesium.Cartesian3.fromDegreesArrayHeights(posArray), - // positions: linePositions, + // positions: Cesium.Cartesian3.fromDegreesArrayHeights(posArray), + positions: positionList, width: 5, // material: new Cesium.PolylineTrailLinkMaterialProperty({ // color: Cesium.Color.YELLOW, diff --git a/src/views/Mubiao/components/MultiHisTrajectory/hooks/multiMbTraj.ts b/src/views/Mubiao/components/MultiHisTrajectory/hooks/multiMbTraj.ts index 58ade1a4f..49a19c3d6 100644 --- a/src/views/Mubiao/components/MultiHisTrajectory/hooks/multiMbTraj.ts +++ b/src/views/Mubiao/components/MultiHisTrajectory/hooks/multiMbTraj.ts @@ -1,11 +1,16 @@ import { ref } from 'vue' +import { getPositionFromTime } from '@/utils/pos' import { useEntity } from '@/hooks/entity' +import { useMubiao } from '../../../hooks/mubiao' +import { useTree } from '@/utils/tree' type TPoints = { time: number; position: Cesium.Cartesian3 }[] const { mubiaoMap, showEntity, getHisTraj, getMBEntityOpt } = useEntity() const showMultiHisTrajCom = ref(false) +const { filterTreeNodeByField, getLeafNode } = useTree() + export const useMultiMBTrajectory = () => { let pointsEntities: Cesium.Entity[] = [] @@ -25,11 +30,17 @@ export const useMultiMBTrajectory = () => { async function loadMultiHisTraj(timeRange: string[]) { removeEntities() + const { data: mbTree } = useMubiao() const mbIds = [...mubiaoMap.keys()] showEntity(false) if (mbIds.length === 0) { return } + const nodes = filterTreeNodeByField({ + treeData: mbTree.value, + params: mbIds, + paramName: 'dataId', + }) for (const mbId of mbIds) { const { points, posArray, timeArray } = await getHisTraj({ id: mbId, @@ -41,8 +52,10 @@ export const useMultiMBTrajectory = () => { continue } + const mbData = nodes.find(node => node.dataId === mbId).data + const color = Cesium.Color.fromRandom({ alpha: 1 }) - createTarget(mbId, points, posArray as number[], color, timeArray) + createTarget(mbId, mbData, points, posArray as number[], color, timeArray) } const allTime = [...timesMap.value.values()].flat() @@ -62,8 +75,9 @@ export const useMultiMBTrajectory = () => { } } - function createTarget( + async function createTarget( mbId: string, + mbData: Record, points: TPoints, posArray: number[], color: Cesium.Color, @@ -73,19 +87,38 @@ export const useMultiMBTrajectory = () => { // console.log('totalAnimationTime', totalAnimationTime) const positionProperty = new Cesium.SampledPositionProperty() // const startTime = Cesium.JulianDate.now() + + const startTime = Cesium.JulianDate.fromDate(new Date(timeArray[0])) + const totalAnimationTime = timeArray[timeArray.length - 1] - timeArray[0] + + // const bezierPoints = getBezierSpline(chunk(posArray, 3)) + // console.log(bezierPoints) // 添加路径点到位置属性 points.forEach((point, index) => { - const pointEntity = createPoint(point.position, color) - pointsEntities.push(pointEntity) + // const pointEntity = createPoint(point.position, color) + // pointsEntities.push(pointEntity) const time = Cesium.JulianDate.fromDate(new Date(timeArray[index])) // console.log(new Date(timeArray[index]).toLocaleString()) positionProperty.addSample(time, point.position) }) - - const mbEntityOpt = getMBEntityOpt({ - id: mbId, - targetType: '甲', + positionProperty.setInterpolationOptions({ + interpolationDegree: 5, + interpolationAlgorithm: Cesium.LagrangePolynomialApproximation, }) + + console.log(mbData, 'mbData') + const mbEntityOpt = await getMBEntityOpt({ + id: mbId, + targetType: mbData.targetType, + country: mbData.country, + }) + const positionList = getPositionFromTime( + startTime, + positionProperty, + totalAnimationTime, + 1000 + ) + // console.log(positionList) // console.log(mbEntityOpt) // 创建实体 const mbTarget = viewer.entities.add({ @@ -93,7 +126,8 @@ export const useMultiMBTrajectory = () => { position: positionProperty, // point: { pixelSize: 10, color: Cesium.Color.RED }, polyline: { - positions: Cesium.Cartesian3.fromDegreesArrayHeights(posArray), + // positions: Cesium.Cartesian3.fromDegreesArrayHeights(posArray), + positions: positionList, width: 5, material: new Cesium.PolylineGlowMaterialProperty({ glowPower: 0.1, diff --git a/src/views/Mubiao/hooks/mubiao.ts b/src/views/Mubiao/hooks/mubiao.ts index 66c05d15a..97675b5a3 100644 --- a/src/views/Mubiao/hooks/mubiao.ts +++ b/src/views/Mubiao/hooks/mubiao.ts @@ -76,15 +76,16 @@ export const useMubiao = () => { // console.log('mbPos', mbPos) - nodes.forEach(({ data, dataId: id }: IMubiao) => { + nodes.forEach(async ({ data, dataId: id }: IMubiao) => { const { target_time, target_geom } = mbPos.find(item => item.target_id === id) ?? {} const pos = parseWKT(target_geom).coordinates - const mbEntity = addMubiaoEntity({ + const mbEntity = await addMubiaoEntity({ id, position: pos, target_time, + country: data.country, targetType: data.targetType, extendInfo: data.extendInfo, }) @@ -101,16 +102,22 @@ export const useMubiao = () => { const res = await sendCheckedTargetIds(ids) } - const addMubiaoEntity = ({ + const addMubiaoEntity = async ({ id, position, + country, target_time, targetType, extendInfo, }: Record) => { // 添加目标实体 // console.log(window.settings, targetType, '-----') - const mbEntityOpt = getMBEntityOpt({ id, targetType, extendInfo }) + const mbEntityOpt = await getMBEntityOpt({ + id, + country, + targetType, + extendInfo, + }) const mubiaoEntity = viewer.entities.add({ name: id, @@ -124,7 +131,11 @@ export const useMubiao = () => { if (extendInfo?.detectingPayload?.angle) { const conic = createMBConicSensor({ entity: mubiaoEntity, + radius: extendInfo?.detectingPayload?.radius, + angle: extendInfo?.detectingPayload?.angle, + heading: extendInfo?.detectingPayload?.heading, + pitch: extendInfo?.detectingPayload?.pitch, show: mbPayloadShowMap.get(id).detectingPayload.show, }) mubiaoConicMap.set(id, conic) diff --git a/src/views/Mubiao/hooks/mubiaoDetail.jsx b/src/views/Mubiao/hooks/mubiaoDetail.jsx index dd17965b5..51e59caab 100644 --- a/src/views/Mubiao/hooks/mubiaoDetail.jsx +++ b/src/views/Mubiao/hooks/mubiaoDetail.jsx @@ -6,6 +6,7 @@ import Communication from '@/views/Payload/Communication.jsx' import { updateMbPayload } from '@/api/Mubiao' import { useEntity } from '@/hooks/entity' import { useMubiao } from './mubiao' +import { isNull, isUndefined } from 'es-toolkit' const { openDetailsModal } = useModal() export const useMubiaoDetail = () => { @@ -27,16 +28,23 @@ export const useMubiaoDetail = () => { show: false, }, ] - } else if (payLoadType === 'conic') { + } else if (payLoadType === 'airplaneConic') { payloadData.value = [ { id, - angle: null, + angle: 30, + radius: 10, + heading: 90, + pitch: 180, show: false, }, ] } } + + function removeCommunicationPayload() { + payloadData.value = [] + } const { mbPayloadShowMap } = useEntity() function renderMubiaoDetailsContent(mbData) { @@ -72,13 +80,21 @@ export const useMubiaoDetail = () => { */}
探测载荷
- {payloadData.value.length === 0 && ( + {payloadData.value.length === 0 ? ( addCommunicationPayload(mbData)} > - 添加 + 添加载荷 + + ) : ( + removeCommunicationPayload()} + > + 删除载荷 )}
@@ -113,6 +129,15 @@ export const useMubiaoDetail = () => { function updateMbLoad({ mbData, detection }) { const { getMubiaoData } = useMubiao() const { id, show, ...detectionData } = detection[0] + + if ( + Object.values(detectionData).some( + item => isNull(item) || isUndefined(item) + ) + ) { + window.$message.error('探测载荷信息不完整') + return + } const payloadData = { id: mbData.id, extendInfo: { diff --git a/src/views/Payload/Detection.jsx b/src/views/Payload/Detection.jsx index aa9a4f8a5..70adc15a8 100644 --- a/src/views/Payload/Detection.jsx +++ b/src/views/Payload/Detection.jsx @@ -83,6 +83,7 @@ export default defineComponent({ ) }, @@ -102,22 +103,6 @@ export default defineComponent({ }, ], conic: [ - // { - // title: '载荷类型', - // key: 'type', - // render(row) { - // return ( - // - // ) - // }, - // }, { title: '开合角', key: 'angle', @@ -127,41 +112,83 @@ export default defineComponent({ v-model:value={row.angle} max={120} min={0} - // disabled={['光学', '雷达'].includes(row.type)} > ) }, }, - // { - // title: '水平半角', - // key: 'xHalfAngle', - // width: 120, - // render(row) { - // return ( - // - // ) - // }, - // }, - // { - // title: '垂直半角', - // key: 'yHalfAngle', - // width: 120, - // render(row) { - // return ( - // - // ) - // }, - // }, + { + title: '辐射距离(km)', + key: 'radius', + render(row) { + return ( + + ) + }, + }, + { + title: '是否开启', + key: 'show', + width: 120, + render(row) { + return ( + changePayloadStatus(row)} + > + ) + }, + }, + ], + airplaneConic: [ + { + title: '开合角', + key: 'angle', + render(row) { + return ( + + ) + }, + }, + { + title: '偏航角', + key: 'heading', + render(row) { + return ( + + ) + }, + }, + { + title: '俯仰角', + key: 'pitch', + render(row) { + return ( + + ) + }, + }, + + { + title: '辐射距离(km)', + key: 'radius', + render(row) { + return ( + + ) + }, + }, { title: '是否开启', key: 'show', diff --git a/src/views/Satellite/components/SatDetail.jsx b/src/views/Satellite/components/SatDetail.jsx index d725a13aa..10a6e89ce 100644 --- a/src/views/Satellite/components/SatDetail.jsx +++ b/src/views/Satellite/components/SatDetail.jsx @@ -6,6 +6,8 @@ import Communication from '@/views/Payload/Communication.jsx' import { useEntity } from '@/hooks/entity' import { updateSatellitePayload } from '@/api/Satellite' import { useSatellite } from '../hooks/satellite' +import { isNull, isUndefined } from 'es-toolkit' + const { openDetailsModal } = useModal() export function showDetailsSatellite(option) { @@ -16,9 +18,13 @@ export function showDetailsSatellite(option) { detectingPayload.value.push({ id, angle: null, + radius: null, show: false, }) } + function removeDetectingPayload() { + detectingPayload.value = [] + } const communicationPayload = ref([]) function addCommunicationPayload() { communicationPayload.value.push({ @@ -27,12 +33,16 @@ export function showDetailsSatellite(option) { show: false, }) } + function removeCommunicationPayload() { + detectingPayload.value = [] + } const { satellitePayloadShowMap } = useEntity() if (extendInfo?.detectingPayload) { detectingPayload.value.push({ id, angle: extendInfo.detectingPayload.angle, + radius: extendInfo.detectingPayload.radius, show: satellitePayloadShowMap.get(id).detectingPayload.show, }) } @@ -63,9 +73,13 @@ export function showDetailsSatellite(option) { {/*
探测载荷
*/}
探测载荷
- {detectingPayload.value.length === 0 && ( + {detectingPayload.value.length === 0 ? ( - 添加 + 添加载荷 + + ) : ( + + 删除载荷 )}
@@ -78,13 +92,21 @@ export function showDetailsSatellite(option) { )}
通信载荷
- {communicationPayload.value.length === 0 && ( + {communicationPayload.value.length === 0 ? ( - 添加 + 添加载荷 + + ) : ( + + 删除载荷 )}
@@ -115,6 +137,18 @@ function updateSatelliteLoad({ sat: sateData, detection, communication }) { if (!detection[0] && !communication[0]) { return } + + if ( + detection[0] && + Object.values(detection[0]).some(item => isNull(item) || isUndefined(item)) + ) { + window.$message.error('探测载荷信息不完整') + return + } + if (communication[0] && communication[0].target.length > 0) { + window.$message.error('通信载荷信息不完整') + return + } const { getSatelliteList } = useSatellite() const payloadData = { id: sateData.id, diff --git a/src/views/Satellite/hooks/satellite.ts b/src/views/Satellite/hooks/satellite.ts index d9f0e6dc4..84aed587e 100644 --- a/src/views/Satellite/hooks/satellite.ts +++ b/src/views/Satellite/hooks/satellite.ts @@ -66,6 +66,8 @@ export function useSatellite() { // satellite.sensorType = Math.random() > 0.5 ? 'conic' : 'rectangle' const satPayload = satellitePayloadShowMap.get(id) if (satPayload && satPayload.detectingPayload) { + satPayload.detectingPayload.radius && + (satellite.sensorRadius = satPayload.detectingPayload.radius) satPayload.detectingPayload.angle && (satellite.sensorAngle = satPayload.detectingPayload.angle) satPayload.detectingPayload.show && (satellite.sensor = true)