357 lines
12 KiB
JavaScript
357 lines
12 KiB
JavaScript
import { twoline2satrec, propagate } from 'satellite.js'
|
||
import CreateFrustum from './sensor.js'
|
||
// import './polylineTrail.js'
|
||
import chroma from 'chroma-js'
|
||
|
||
class SatelliteEntity {
|
||
constructor(tle = '', options = {}) {
|
||
const [name, tleLine1, tleLine2] = this._checkTle(tle)
|
||
let circle = tleLine2.slice(52, 64)
|
||
|
||
this.name = name.trim()
|
||
this.tleLine1 = tleLine1.trim()
|
||
this.tleLine2 = tleLine2.trim()
|
||
this.satrec = twoline2satrec(this.tleLine1, this.tleLine2)
|
||
|
||
this.totalSeconds = 7 * 86400 // 24小时
|
||
this.stepSeconds = 100
|
||
this.leadTime = parseInt((24 * 3600) / circle)
|
||
this.trailTime = 0
|
||
this.sensor = false
|
||
this.entity = null
|
||
this.sensorType = 'rectangle'
|
||
}
|
||
get sensor() {
|
||
return this.sensor
|
||
}
|
||
set sensor(showSensor) {
|
||
console.log(showSensor, 'showSensor')
|
||
if (showSensor) {
|
||
if (this.sensorType === 'conic') {
|
||
this.createConicSensor(this.entity)
|
||
} else {
|
||
this.createRectangleSensor(this.entity)
|
||
}
|
||
}
|
||
//showSensor &&
|
||
}
|
||
|
||
_checkTle(tle) {
|
||
let elements = tle.split('\n')
|
||
if (elements.length !== 3) {
|
||
throw new Error('tle data error')
|
||
}
|
||
return elements
|
||
}
|
||
|
||
// 获取地心惯性坐标系坐标
|
||
getPositionEci(time) {
|
||
return propagate(this.satrec, time).position
|
||
}
|
||
|
||
// 创建PositionProperty
|
||
_getPositionProperty() {
|
||
const start = Cesium.JulianDate.fromIso8601(new Date().toISOString())
|
||
const positionProperty = new Cesium.SampledPositionProperty(
|
||
Cesium.ReferenceFrame.INERTIAL
|
||
)
|
||
|
||
let now = Date.now()
|
||
for (let i = 0; i < this.totalSeconds / this.stepSeconds; i++) {
|
||
let sateTime = new Date(now + i * this.stepSeconds * 1000)
|
||
let sateCoord = this.getPositionEci(sateTime)
|
||
if (!sateCoord) {
|
||
continue
|
||
}
|
||
const cesiumTime = Cesium.JulianDate.addSeconds(
|
||
start,
|
||
i * this.stepSeconds,
|
||
new Cesium.JulianDate()
|
||
)
|
||
const cesiumPosition = {
|
||
x: sateCoord.x * 1000,
|
||
y: sateCoord.y * 1000,
|
||
z: sateCoord.z * 1000,
|
||
}
|
||
positionProperty.addSample(cesiumTime, cesiumPosition)
|
||
}
|
||
return positionProperty
|
||
}
|
||
|
||
// 创建卫星实例
|
||
createSatelliteEntity() {
|
||
const start = Cesium.JulianDate.fromIso8601(new Date().toISOString())
|
||
const stop = Cesium.JulianDate.addSeconds(
|
||
start,
|
||
this.totalSeconds,
|
||
new Cesium.JulianDate()
|
||
)
|
||
const color = Cesium.Color.fromCssColorString(
|
||
chroma.random().brighten().hex()
|
||
)
|
||
// const color = Cesium.Color.fromRandom({ alpha: 0.5 })
|
||
let satelliteEntity = {
|
||
name: this.name,
|
||
description: this.name,
|
||
show: true,
|
||
availability: new Cesium.TimeIntervalCollection([
|
||
new Cesium.TimeInterval({ start: start, stop: stop }),
|
||
]),
|
||
position: this._getPositionProperty(),
|
||
// point: {
|
||
// pixelSize: 8,
|
||
// color: color,
|
||
// // scaleByDistance: new Cesium.NearFarScalar(1.5e3, 1, 8.0e8, 0.5),
|
||
// },
|
||
path: new Cesium.PathGraphics({
|
||
width: 2,
|
||
show: true,
|
||
leadTime: this.leadTime,
|
||
trailTime: this.trailTime,
|
||
// material: color,
|
||
material: new Cesium.PolylineTrailLinkMaterialProperty({
|
||
color,
|
||
duration: 86400 * 1000,
|
||
}),
|
||
}),
|
||
label: {
|
||
show: true,
|
||
text: this.name,
|
||
font: '12px sans-serif',
|
||
showBackground: true,
|
||
backgroundColor: new Cesium.Color(0.165, 0.165, 0.165, 0.5),
|
||
backgroundPadding: new Cesium.Cartesian2(4, 4),
|
||
outlineWidth: 1,
|
||
verticalOrigin: Cesium.VerticalOrigin.TOP,
|
||
horizontalOrigin: Cesium.VerticalOrigin.LEFT,
|
||
pixelOffset: new Cesium.Cartesian2(0, 5),
|
||
fillColor: Cesium.Color.WHITE,
|
||
// distanceDisplayCondition: new Cesium.DistanceDisplayCondition(10.0, 50000000),
|
||
},
|
||
billboard: {
|
||
image: '/images/satellite.png',
|
||
width: 40,
|
||
height: 40,
|
||
show: true,
|
||
distanceDisplayCondition: new Cesium.DistanceDisplayCondition(
|
||
10.0,
|
||
50000000
|
||
),
|
||
},
|
||
// model: {
|
||
// uri: '/GV/resources/model/wx.glb',
|
||
// minimumPixelSize: 64,
|
||
// maximumScale: 20000,
|
||
// show: true,
|
||
// distanceDisplayCondition: new Cesium.DistanceDisplayCondition(
|
||
// 10.0,
|
||
// 50000000
|
||
// ),
|
||
// },
|
||
// cylinder: {
|
||
// HeightReference: Cesium.HeightReference.CLAMP_TO_GROUND,
|
||
// length: 1700000,
|
||
// topRadius: 0,
|
||
// bottomRadius: 700000 / 2,
|
||
// material: Cesium.Color.RED.withAlpha(0.4),
|
||
// outline: !0,
|
||
// numberOfVerticalLines: 0,
|
||
// outlineColor: Cesium.Color.RED.withAlpha(0.8),
|
||
// horizontalOrigin: Cesium.HorizontalOrigin.CENTER,
|
||
// },
|
||
orientation: new Cesium.VelocityOrientationProperty(
|
||
this._getPositionProperty()
|
||
),
|
||
}
|
||
// this.createSensor(satelliteEntity)
|
||
// return satelliteEntity
|
||
|
||
this.entity = viewer.entities.add(satelliteEntity)
|
||
return this.entity
|
||
}
|
||
|
||
createSensor(satellite) {
|
||
// const color = '#00ffff'
|
||
// let customSensor = new CesiumSensorVolumes.RectangularPyramidSensorVolume()
|
||
// // const sate = tasks.value.find((item) => item.satId === sate_id);
|
||
// // radius 是指波束的长度
|
||
// customSensor.radius = 40000000.0
|
||
// // customSensor.id = `${sate_id}_sensor`;
|
||
// customSensor.id = `test_sensor`
|
||
// customSensor.intersectionWidth = 1
|
||
// customSensor.xHalfAngle = Cesium.Math.toRadians(1)
|
||
// customSensor.yHalfAngle = Cesium.Math.toRadians(1)
|
||
// customSensor.lateralSurfaceMaterial = Cesium.Material.fromType('Color')
|
||
// customSensor.lateralSurfaceMaterial.uniforms.color =
|
||
// new Cesium.Color.fromCssColorString(color).withAlpha(0.3)
|
||
// // 默认矩阵
|
||
// customSensor.modelMatrix = new Cesium.Matrix4()
|
||
// // 使用preRender 监听卫星每帧运动
|
||
// viewer.scene.preRender.addEventListener((scene, time) => {
|
||
// customSensor.show = false
|
||
// // 判断数据源中所有实体是否准备就绪,viewer.dataSourceDisplay.dataSources = viewer.dataSources
|
||
// if (viewer.dataSourceDisplay.ready) {
|
||
// // const satellite = viewer.dataSources
|
||
// // .getByName("simDemon")[0]
|
||
// // .entities.getById(sate_id);
|
||
// // 根据时间获取卫星实时笛卡尔位置
|
||
// let position = Cesium.Property.getValueOrUndefined(
|
||
// satellite.position,
|
||
// time,
|
||
// new Cesium.Cartesian3()
|
||
// )
|
||
// // 根据卫星位置和朝向转换为矩阵信息,此处使用的是后台计算的四元数,实际一般情况应该使用Cesium.Transforms+position转换
|
||
// console.log(
|
||
// satellite.orientation.getValue(time),
|
||
// 'satellite.orientation.getValue(time)'
|
||
// )
|
||
// // let m = Cesium.Matrix4.fromRotationTranslation(
|
||
// // Cesium.Matrix3.fromQuaternion(
|
||
// // satellite.orientation.getValue(time),
|
||
// // new Cesium.Matrix3()
|
||
// // ),
|
||
// // position,
|
||
// // new Cesium.Matrix4()
|
||
// // )
|
||
// let m = this.getModelMatrix(position, satellite.orientation)
|
||
// console.log(m, 'm')
|
||
// // // let m = Cesium.Transforms.northUpEastToFixedFrame(position)
|
||
// customSensor.modelMatrix = m
|
||
// // customSensor.modelMatrix = this.getModelMatrix()
|
||
// customSensor.show = true
|
||
// }
|
||
// })
|
||
// viewer.scene.primitives.add(customSensor)
|
||
// let position = Cesium.Property.getValueOrUndefined(
|
||
// satellite.position,
|
||
// viewer.clock.currentTime,
|
||
// new Cesium.Cartesian3()
|
||
// )
|
||
}
|
||
|
||
createRectangleSensor(satellite) {
|
||
// viewer.scene.primitives.removeAll()
|
||
let position = Cesium.Property.getValueOrUndefined(
|
||
satellite.position,
|
||
viewer.clock.currentTime,
|
||
new Cesium.Cartesian3()
|
||
)
|
||
const rectangularPyramidSensor =
|
||
new CesiumSensorVolumes.RectangularPyramidSensorVolume()
|
||
rectangularPyramidSensor.modelMatrix = this.getModelMatrix(position)
|
||
rectangularPyramidSensor.radius = 20000000.0
|
||
rectangularPyramidSensor.xHalfAngle = Cesium.Math.toRadians(20.0)
|
||
rectangularPyramidSensor.yHalfAngle = Cesium.Math.toRadians(10.0)
|
||
rectangularPyramidSensor.lateralSurfaceMaterial =
|
||
Cesium.Material.fromType('Color')
|
||
rectangularPyramidSensor.lateralSurfaceMaterial.uniforms.color =
|
||
new Cesium.Color(0.0, 1.0, 1.0, 0.3)
|
||
|
||
viewer.scene.preRender.addEventListener((scene, time) => {
|
||
rectangularPyramidSensor.show = false
|
||
let position = Cesium.Property.getValueOrUndefined(
|
||
satellite.position,
|
||
time,
|
||
new Cesium.Cartesian3()
|
||
)
|
||
rectangularPyramidSensor.modelMatrix = this.getModelMatrix(position)
|
||
rectangularPyramidSensor.show = true
|
||
})
|
||
|
||
viewer.scene.primitives.add(rectangularPyramidSensor)
|
||
}
|
||
|
||
getModelMatrix(location) {
|
||
// let ellipsoid = viewer.scene.globe.ellipsoid
|
||
// console.log(position, '----')
|
||
// let location = ellipsoid.cartographicToCartesian(
|
||
// new Cesium.Cartographic(
|
||
// Cesium.Math.toRadians(120.0),
|
||
// Cesium.Math.toRadians(24.0),
|
||
// 1300000
|
||
// )
|
||
// )
|
||
let modelMatrix = Cesium.Transforms.northEastDownToFixedFrame(location)
|
||
let orientation = Cesium.Matrix3.multiply(
|
||
Cesium.Matrix3.multiply(
|
||
Cesium.Matrix3.fromRotationZ(0.0),
|
||
Cesium.Matrix3.fromRotationY(Cesium.Math.toRadians(0.0)),
|
||
new Cesium.Matrix3()
|
||
),
|
||
Cesium.Matrix3.fromRotationX(0.0),
|
||
new Cesium.Matrix3()
|
||
)
|
||
return Cesium.Matrix4.multiply(
|
||
modelMatrix,
|
||
Cesium.Matrix4.fromRotationTranslation(
|
||
orientation,
|
||
Cesium.Cartesian3.ZERO
|
||
),
|
||
new Cesium.Matrix4()
|
||
)
|
||
}
|
||
|
||
createConicSensor(satellite) {
|
||
let position = Cesium.Property.getValueOrUndefined(
|
||
satellite.position,
|
||
viewer.clock.currentTime,
|
||
new Cesium.Cartesian3()
|
||
)
|
||
// const conicSensor = new CesiumSensorVolumes.ConicSensorGraphics()
|
||
// conicSensor.radius = 20000000.0
|
||
// conicSensor.modelMatrix = this.getModelMatrix(position)
|
||
// conicSensor.intersectionColor = new Cesium.ConstantProperty(
|
||
// new Cesium.Color(0.1, 0.2, 0.3, 0.4)
|
||
// )
|
||
const customSensor = new CesiumSensorVolumes.CustomSensorVolume()
|
||
customSensor.modelMatrix = this.getModelMatrix(position)
|
||
customSensor.radius = 20000000.0
|
||
// customSensor.directions = directions;
|
||
viewer.scene.primitives.add(customSensor)
|
||
|
||
viewer.scene.preRender.addEventListener((scene, time) => {
|
||
customSensor.show = false
|
||
let position = Cesium.Property.getValueOrUndefined(
|
||
satellite.position,
|
||
time,
|
||
new Cesium.Cartesian3()
|
||
)
|
||
customSensor.modelMatrix = this.getModelMatrix(position)
|
||
customSensor.show = true
|
||
})
|
||
|
||
viewer.scene.primitives.add(customSensor)
|
||
}
|
||
|
||
// createSensor(satellite) {
|
||
// // let sensor = new Sensor({
|
||
// // position: satellite.position,
|
||
// // orientation: satellite.orientation,
|
||
// // aspectRatio: 1000,
|
||
// // })
|
||
// // viewer.scene.preRender.addEventListener((scene, time) => {
|
||
// let position = Cesium.Property.getValueOrUndefined(
|
||
// satellite.position,
|
||
// viewer.clock.currentTime,
|
||
// new Cesium.Cartesian3()
|
||
// )
|
||
// console.log(position, 'position')
|
||
|
||
// let heading = 0
|
||
// let pitch = 0
|
||
// let roll = 90
|
||
// let hpr = new Cesium.HeadingPitchRoll(heading, pitch, roll)
|
||
// let orientation = Cesium.Quaternion.fromHeadingPitchRoll(hpr)
|
||
// let sensor = new CreateFrustum({
|
||
// position: position,
|
||
// orientation: orientation,
|
||
// far: 1000000,
|
||
// aspectRatio: 600 / 1080,
|
||
// })
|
||
// console.log(sensor, 'sensor')
|
||
// // })
|
||
// }
|
||
}
|
||
|
||
export default SatelliteEntity
|