新增载荷的删除、和俯仰角辐射距离等参数、修改轨迹曲线、jb分类和颜色等

This commit is contained in:
严争鸣 2025-02-25 10:43:57 +08:00
parent 2cf73646a7
commit de9d1a4db5
30 changed files with 521 additions and 140 deletions

11
package-lock.json generated
View File

@ -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",

View File

@ -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",

View File

@ -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',

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.3 KiB

View File

@ -0,0 +1 @@
<svg width="756" height="352" version="1.1" xmlns="http://www.w3.org/2000/svg" desc="Created with imagetracer.js version 1.2.5"><path fill="rgb(255, 102, 102)" stroke="#f66" stroke-width="0" opacity="1" d="M 278 40 L 280 52 L 728 52 L 728 308 L 282 308 L 280 314 L 274 312 L 28 178 L 278 40 Z M 280 84 L 280 162 L 282 164 L 696 164 L 696 86 L 694 84 L 280 84 Z M 242 96 L 96 178 L 248 260 L 248 98 L 242 96 Z M 280 196 L 280 274 L 282 276 L 696 276 L 696 198 L 694 196 L 280 196 Z "></path></svg>

After

Width:  |  Height:  |  Size: 496 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.3 KiB

View File

@ -0,0 +1 @@
<svg width="756" height="352" version="1.1" xmlns="http://www.w3.org/2000/svg" desc="Created with imagetracer.js version 1.2.5"><path fill="rgb(255, 102, 102)" stroke="#f66" stroke-width="0" opacity="1" d="M 278 44 L 280 56 L 728 56 L 728 312 L 282 312 L 280 318 L 274 316 L 28 182 L 278 44 Z M 280 88 L 280 278 L 282 280 L 304 280 L 304 90 L 302 88 L 280 88 Z M 336 88 L 336 280 L 696 280 L 696 88 L 336 88 Z M 242 100 L 96 182 L 248 264 L 248 102 L 242 100 Z "></path></svg>

After

Width:  |  Height:  |  Size: 476 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.3 KiB

View File

@ -0,0 +1 @@
<svg width="756" height="364" version="1.1" xmlns="http://www.w3.org/2000/svg" desc="Created with imagetracer.js version 1.2.5"><path fill="rgb(255, 102, 102)" stroke="#f66" stroke-width="0" opacity="1" d="M 278 48 L 280 60 L 728 60 L 728 316 L 282 316 L 280 322 L 274 320 L 28 186 L 278 48 Z M 280 92 L 280 284 L 696 284 L 696 92 L 280 92 Z M 242 104 L 96 186 L 248 268 L 248 106 L 242 104 Z "></path></svg>

After

Width:  |  Height:  |  Size: 408 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.6 KiB

View File

@ -0,0 +1 @@
<svg width="408" height="564" version="1.1" xmlns="http://www.w3.org/2000/svg" desc="Created with imagetracer.js version 1.2.5"><path fill="rgb(255, 102, 102)" stroke="#f66" stroke-width="0" opacity="1" d="M 184 28 L 214 28 L 216 30 L 216 170 L 372 326 L 350 348 L 216 218 L 216 470 L 260 518 L 238 536 L 202 500 L 166 536 L 144 518 L 184 474 L 184 222 L 54 348 L 32 326 L 184 174 L 184 28 Z "></path></svg>

After

Width:  |  Height:  |  Size: 407 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.5 KiB

View File

@ -0,0 +1 @@
<svg width="408" height="520" version="1.1" xmlns="http://www.w3.org/2000/svg" desc="Created with imagetracer.js version 1.2.5"><path fill="rgb(255, 102, 102)" stroke="#f66" stroke-width="0" opacity="1" d="M 184 28 L 214 28 L 216 30 L 216 170 L 372 326 L 350 348 L 216 218 L 216 458 L 232 460 L 232 492 L 172 492 L 172 460 L 184 458 L 184 222 L 54 348 L 32 326 L 184 174 L 184 28 Z "></path></svg>

After

Width:  |  Height:  |  Size: 397 B

View File

@ -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<string, number> }
}) {
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
}

98
src/js/Wave.js Normal file
View File

@ -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
},
})

View File

@ -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,12 +39,14 @@ class SatelliteEntity {
set sensor(showSensor) {
// console.log(showSensor, 'showSensor')
this._sensor = showSensor
if (showSensor && !this.sensorEntity) {
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) {
this.removeSensor()
@ -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,

View File

@ -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";

View File

@ -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))
}

View File

@ -60,7 +60,7 @@ const types = [
{ name: 'XW', value: 'wzbXw' },
]
const showPanelName = ref('wx')
const showPanelName = ref('zb')
const panelList = [
// {

View File

@ -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

View File

@ -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',

View File

@ -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,12 +69,11 @@ export const useMBTrajectory = () => {
)
positionProperty.addSample(time, point.position)
})
// positionProperty.setInterpolationOptions({
// //二次多项式进行插值。二次多项式插值相较于线性插值会更光滑,但不如高阶多项式平滑
// interpolationDegree: 2,
// //赫尔米特多项式插值算法。使得插值曲线能够平滑过渡,并且可以更好地控制运动的速度和方向变化
// interpolationAlgorithm: Cesium.HermitePolynomialApproximation,
// })
positionProperty.setInterpolationOptions({
interpolationDegree: 5,
interpolationAlgorithm: Cesium.LagrangePolynomialApproximation,
})
console.log(positionProperty, 'getValue')
// positionProperty._time.map(time => {
// console.log(positionProperty.getValue(time), 'getValue')
// })
@ -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,

View File

@ -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<string, string | number>,
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,

View File

@ -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<string, string | number | number[]>) => {
// 添加目标实体
// 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)

View File

@ -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 = () => {
*/}
<div class="flex justify-between">
<div class="detail-item-title">探测载荷</div>
{payloadData.value.length === 0 && (
{payloadData.value.length === 0 ? (
<NButton
quaternary
type="primary"
onClick={() => addCommunicationPayload(mbData)}
>
添加
添加载荷
</NButton>
) : (
<NButton
quaternary
type="error"
onClick={() => removeCommunicationPayload()}
>
删除载荷
</NButton>
)}
</div>
@ -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: {

View File

@ -83,6 +83,7 @@ export default defineComponent({
<NInputNumber
v-model:value={row.radius}
// disabled={['', ''].includes(row.type)}
min={0}
></NInputNumber>
)
},
@ -102,22 +103,6 @@ export default defineComponent({
},
],
conic: [
// {
// title: '',
// key: 'type',
// render(row) {
// return (
// <NSelect
// v-model:value={row.type}
// options={[
// { label: '', value: '' },
// { label: '', value: '' },
// { label: '', value: '' },
// ]}
// ></NSelect>
// )
// },
// },
{
title: '开合角',
key: 'angle',
@ -127,41 +112,83 @@ export default defineComponent({
v-model:value={row.angle}
max={120}
min={0}
// disabled={['', ''].includes(row.type)}
></NInputNumber>
)
},
},
// {
// title: '',
// key: 'xHalfAngle',
// width: 120,
// render(row) {
// return (
// <NInputNumber
// v-model:value={row.angle}
// max={120}
// min={0}
// disabled={[''].includes(row.type)}
// ></NInputNumber>
// )
// },
// },
// {
// title: '',
// key: 'yHalfAngle',
// width: 120,
// render(row) {
// return (
// <NInputNumber
// v-model:value={row.angle}
// max={120}
// min={0}
// disabled={[''].includes(row.type)}
// ></NInputNumber>
// )
// },
// },
{
title: '辐射距离(km)',
key: 'radius',
render(row) {
return (
<NInputNumber v-model:value={row.radius} min={0}></NInputNumber>
)
},
},
{
title: '是否开启',
key: 'show',
width: 120,
render(row) {
return (
<NSwitch
v-model:value={row.show}
onUpdate:value={() => changePayloadStatus(row)}
></NSwitch>
)
},
},
],
airplaneConic: [
{
title: '开合角',
key: 'angle',
render(row) {
return (
<NInputNumber
v-model:value={row.angle}
max={120}
min={0}
></NInputNumber>
)
},
},
{
title: '偏航角',
key: 'heading',
render(row) {
return (
<NInputNumber
v-model:value={row.heading}
max={180}
min={-180}
></NInputNumber>
)
},
},
{
title: '俯仰角',
key: 'pitch',
render(row) {
return (
<NInputNumber
v-model:value={row.pitch}
max={180}
min={-180}
></NInputNumber>
)
},
},
{
title: '辐射距离(km)',
key: 'radius',
render(row) {
return (
<NInputNumber v-model:value={row.radius} min={0}></NInputNumber>
)
},
},
{
title: '是否开启',
key: 'show',

View File

@ -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) {
{/* <div class="detail-item-title">探测载荷</div> */}
<div class="flex justify-between">
<div class="detail-item-title">探测载荷</div>
{detectingPayload.value.length === 0 && (
{detectingPayload.value.length === 0 ? (
<NButton quaternary type="primary" onClick={addDetectingPayload}>
添加
添加载荷
</NButton>
) : (
<NButton quaternary type="error" onClick={removeDetectingPayload}>
删除载荷
</NButton>
)}
</div>
@ -78,13 +92,21 @@ export function showDetailsSatellite(option) {
)}
<div class="flex justify-between">
<div class="detail-item-title">通信载荷</div>
{communicationPayload.value.length === 0 && (
{communicationPayload.value.length === 0 ? (
<NButton
quaternary
type="primary"
onClick={addCommunicationPayload}
>
添加
添加载荷
</NButton>
) : (
<NButton
quaternary
type="error"
onClick={removeCommunicationPayload}
>
删除载荷
</NButton>
)}
</div>
@ -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,

View File

@ -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)