Commit f15d862e by licheng

chore: 修改模拟轨道数据方法

parent 275e6bfd
<template> <template>
<div class="cesium-container" ref="cesiumContainer"></div> <div class="cesium-container" ref="cesiumContainer"></div>
<div class="controls absolute top-5 right-5 z-10 space-x-2"> <div class="controls absolute top-5 right-5 z-10 space-x-2">
<el-button @click="toggleSatellite('ISS')">显示/隐藏 ISS</el-button> <el-select v-model="activeSatellite" class="w-[120px]!">
<el-button @click="toggleSatellite('HAIYANG 2D')">显示/隐藏 HAIYANG 2D</el-button> <el-option v-for="i in satelliteNum" :key="i" :label="'satellite' + i" :value="i" />
<el-button @click="toggleSatellite('LANDSAT 8')">显示/隐藏 LANDSAT 8</el-button> </el-select>
<el-button @click="toggleSatellite(`satellite${activeSatellite}`)">显示/隐藏轨道</el-button>
</div> </div>
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { onMounted, ref } from 'vue' import { onMounted, ref } from 'vue'
import * as Cesium from 'cesium' import * as Cesium from 'cesium'
import * as satellite from 'satellite.js' import { computeRandomOrbit } from './satellite-data'
// ---------------- Cesium Token ---------------- // ---------------- Cesium Token ----------------
Cesium.Ion.defaultAccessToken = Cesium.Ion.defaultAccessToken =
...@@ -23,6 +24,8 @@ const cesiumContainer = ref<HTMLDivElement | null>(null) ...@@ -23,6 +24,8 @@ const cesiumContainer = ref<HTMLDivElement | null>(null)
let viewer: Cesium.Viewer let viewer: Cesium.Viewer
const infoOffset = 2000000 // 信息框相对卫星的高度偏移(米) const infoOffset = 2000000 // 信息框相对卫星的高度偏移(米)
const imageUrl = '/src/assets/imgs/satellite.png' // 卫星图标路径 const imageUrl = '/src/assets/imgs/satellite.png' // 卫星图标路径
const satelliteNum = 13 // 添加卫星数量
const activeSatellite = ref(1)
// ---------- 所有卫星实体集合(用于全局点击事件) ---------- // ---------- 所有卫星实体集合(用于全局点击事件) ----------
const satellites: { const satellites: {
...@@ -49,7 +52,7 @@ const satellites: { ...@@ -49,7 +52,7 @@ const satellites: {
function computeOrbitFromTLE( function computeOrbitFromTLE(
tle1: string, tle1: string,
tle2: string, tle2: string,
numPoints = 360, numPoints = 720,
timeStep = 6 timeStep = 6
): { ): {
positionProperty: Cesium.SampledPositionProperty positionProperty: Cesium.SampledPositionProperty
...@@ -116,9 +119,9 @@ function computeOrbitFromTLE( ...@@ -116,9 +119,9 @@ function computeOrbitFromTLE(
* @param tle1 TLE 第一行 * @param tle1 TLE 第一行
* @param tle2 TLE 第二行 * @param tle2 TLE 第二行
*/ */
function addSatelliteEntity(name: string, tle1: string, tle2: string) { function addSatelliteEntity(name: string, _tle1: string = '', _tle2: string = '') {
// 计算轨道数据 // 计算轨道数据
const { positionProperty, orbitPositions } = computeOrbitFromTLE(tle1, tle2) const { positionProperty, orbitPositions } = computeRandomOrbit()
// ---------- 卫星本体(图标) ---------- // ---------- 卫星本体(图标) ----------
const satelliteEntity = viewer.entities.add({ const satelliteEntity = viewer.entities.add({
...@@ -163,7 +166,7 @@ function addSatelliteEntity(name: string, tle1: string, tle2: string) { ...@@ -163,7 +166,7 @@ function addSatelliteEntity(name: string, tle1: string, tle2: string) {
return labelPos return labelPos
}, false), }, false),
label: { label: {
text: `卫星: ${name}\nTLE: ${tle1.slice(0, 10)}...`, // 显示部分 TLE text: `卫星: ${name}\nTLE: ${name}`, // 显示部分 TLE
font: '14px sans-serif', font: '14px sans-serif',
fillColor: Cesium.Color.WHITE, fillColor: Cesium.Color.WHITE,
style: Cesium.LabelStyle.FILL_AND_OUTLINE, style: Cesium.LabelStyle.FILL_AND_OUTLINE,
...@@ -189,19 +192,25 @@ function addSatelliteEntity(name: string, tle1: string, tle2: string) { ...@@ -189,19 +192,25 @@ function addSatelliteEntity(name: string, tle1: string, tle2: string) {
width: 1.5, width: 1.5,
material: Cesium.Color.WHITE.withAlpha(0.6), material: Cesium.Color.WHITE.withAlpha(0.6),
show: false, // 初始隐藏 show: false, // 初始隐藏
arcType: Cesium.ArcType.NONE arcType: Cesium.ArcType.NONE // 直线
} }
}) })
// ---------- 保存到全局数组,统一管理点击事件 ---------- // ---------- 保存到全局数组,统一管理点击事件 ----------
satellites.push({ entity: satelliteEntity, path: pathEntity, info: infoEntity, line: lineEntity, visible: false }) satellites.push({
entity: satelliteEntity,
path: pathEntity,
info: infoEntity,
line: lineEntity,
visible: false
})
return { satelliteEntity, pathEntity, infoEntity } return { satelliteEntity, pathEntity, infoEntity }
} }
// ---------- 切换指定卫星显示 ---------- // ---------- 切换指定卫星显示 ----------
function toggleSatellite(name: string) { function toggleSatellite(name: string) {
const sat = satellites.find(s => s.entity.name === name) const sat = satellites.find((s) => s.entity.name === name)
if (!sat) return if (!sat) return
sat.visible = !sat.visible sat.visible = !sat.visible
...@@ -246,28 +255,16 @@ onMounted(() => { ...@@ -246,28 +255,16 @@ onMounted(() => {
viewer.clock.shouldAnimate = true viewer.clock.shouldAnimate = true
// ---------- 添加卫星 ---------- // ---------- 添加卫星 ----------
addSatelliteEntity( for (let i = 0;i < satelliteNum; i++) {
'ISS', addSatelliteEntity(`satellite${i + 1}`)
'1 49008U 21062A 25110.53320445 .00000056 00000-0 47020-4 0 9995', }
'2 49008 98.7432 113.8688 0001070 179.9589 180.1588 14.19859554196601'
)
addSatelliteEntity(
'HAIYANG 2D',
'1 48621U 21043A 25110.51258281 .00000013 00000-0 85647-4 0 9990',
'2 48621 65.9966 277.0130 0008040 261.0819 98.9340 13.83372903198126'
)
addSatelliteEntity(
'LANDSAT 8',
'1 39084U 13008A 25110.50130981 .00000736 00000-0 17327-3 0 9991',
'2 39084 98.1890 181.7768 0001114 99.4629 260.6696 14.57133819648167'
)
// ---------- 全局点击事件 ---------- // ---------- 全局点击事件 ----------
viewer.screenSpaceEventHandler.setInputAction((click) => { viewer.screenSpaceEventHandler.setInputAction((click) => {
const picked = viewer.scene.pick(click.position) const picked = viewer.scene.pick(click.position)
if (!picked) return if (!picked) return
const sat = satellites.find(s => s.entity === picked.id) const sat = satellites.find((s) => s.entity === picked.id)
if (!sat) return if (!sat) return
sat.visible = !sat.visible sat.visible = !sat.visible
......
...@@ -44,7 +44,7 @@ export const lineOptions: EChartsOption = { ...@@ -44,7 +44,7 @@ export const lineOptions: EChartsOption = {
}, },
toolbox: { toolbox: {
feature: { feature: {
dataZoom: { dataZoom: { // 缩放工具,框选缩放
// yAxisIndex: 'none' // yAxisIndex: 'none'
show: true show: true
}, },
...@@ -55,11 +55,11 @@ export const lineOptions: EChartsOption = { ...@@ -55,11 +55,11 @@ export const lineOptions: EChartsOption = {
// 缩放图例(需导入 dataZoom) // 缩放图例(需导入 dataZoom)
dataZoom: [ dataZoom: [
{ {
type: 'inside', // 内部缩放 type: 'inside', // 内部使用鼠标滚轮缩放
start: 0, start: 0,
end: 100 end: 100
}, },
{ { // 下面的缩放图例
start: 0, start: 0,
end: 100 end: 100
} }
......
import * as Cesium from 'cesium'
// import * as satellite from 'satellite.js'
/**
* 随机生成卫星轨道数据(不依赖 TLE)
* @param numPoints 采样点数量(轨道上取多少个点)
* @param timeStep 每两个采样点之间的时间间隔(秒)
*/
export function computeRandomOrbit(
numPoints = 720,
timeStep = 6
): {
positionProperty: Cesium.SampledPositionProperty
orbitPositions: Cesium.Cartesian3[]
startTime: Cesium.JulianDate
stopTime: Cesium.JulianDate
} {
// 起始时间:以当前时间为起点
const startTime = Cesium.JulianDate.now()
const stopTime = Cesium.JulianDate.addSeconds(
startTime,
numPoints * timeStep,
new Cesium.JulianDate()
)
const positionProperty = new Cesium.SampledPositionProperty()
const orbitPositions: Cesium.Cartesian3[] = []
// ========== 随机轨道参数 ==========
const earthRadius = 6371e3 // 地球半径 m
const altitude = 500e3 + Math.random() * 1500e3 // 500~2000 km 高度
const orbitRadius = earthRadius + altitude
const inclination = Math.random() * 180 // 倾角 (0~180度)
const raan = Math.random() * 360 // 升交点赤经 (0~360度)
for (let i = 0; i < numPoints; i++) {
const currentTime = Cesium.JulianDate.addSeconds(
startTime,
i * timeStep,
new Cesium.JulianDate()
)
// 沿轨道运动的角度(相位)
const angle = (i / numPoints) * 2 * Math.PI
// 初始轨道在赤道平面上的位置 (X, Y)
const x = orbitRadius * Math.cos(angle)
const y = orbitRadius * Math.sin(angle)
const z = 0
let pos = new Cesium.Cartesian3(x, y, z)
// ========== 旋转到随机倾角和 RAAN ==========
const rotInc = Cesium.Matrix3.fromRotationX(Cesium.Math.toRadians(inclination))
const rotRaan = Cesium.Matrix3.fromRotationZ(Cesium.Math.toRadians(raan))
const rot = Cesium.Matrix3.multiply(rotRaan, rotInc, new Cesium.Matrix3())
pos = Cesium.Matrix3.multiplyByVector(rot, pos, new Cesium.Cartesian3())
// 保存轨道点
orbitPositions.push(pos)
positionProperty.addSample(currentTime, pos)
}
return { positionProperty, orbitPositions, startTime, stopTime }
}
export const satelliteList = [
{
name: 'FENGYUN 3E',
tle1: '1 49008U 21062A 25110.53320445 .00000056 00000-0 47020-4 0 9995',
tle2: '2 49008 98.7432 113.8688 0001070 179.9589 180.1588 14.19859554196601'
},
{
name: 'HAIYANG 2D',
tle1: '1 48621U 21043A 25110.51258281 .00000013 00000-0 85647-4 0 9990',
tle2: '2 48621 65.9966 277.0130 0008040 261.0819 98.9340 13.83372903198126'
},
{
name: 'LANDSAT 8',
tle1: '1 39084U 13008A 25110.50130981 .00000736 00000-0 17327-3 0 9991',
tle2: '2 39084 98.1890 181.7768 0001114 99.4629 260.6696 14.57133819648167'
},
{
name: 'NPP',
tle1: '1 37849U 11061A 25110.49703421 .00000187 00000-0 10942-3 0 9994',
tle2: '2 37849 98.7546 50.3268 0002538 92.2298 267.9169 14.19521446698466'
},
{
name: 'AQUA',
tle1: '1 27424U 02022A 25110.49190655 .00001925 00000-0 40090-3 0 9996',
tle2: '2 27424 98.3731 68.1378 0001092 108.6371 1.6953 14.61156736221563'
},
{
name: 'METOP-B',
tle1: '1 38771U 12049A 25110.49181281 .00000226 00000-0 12288-3 0 9999',
tle2: '2 38771 98.5819 166.1057 0001889 116.2950 243.8422 14.21481267653201'
},
{
name: 'FENGYUN 3D',
tle1: '1 43010U 17072A 25110.49054369 .00000220 00000-0 12607-3 0 9997',
tle2: '2 43010 98.9580 73.7176 0001801 140.6894 219.4412 14.19611249385010'
},
{
name: 'TERRA',
tle1: '1 25994U 99068A 25110.48571943 .00000910 00000-0 19615-3 0 9996',
tle2: '2 25994 98.0028 170.3979 0003633 112.5667 305.9700 14.60635640348012'
},
{
name: 'HAIYANG 2B',
tle1: '1 43655U 18081A 25110.47966778 .00000017 00000-0 59327-4 0 9992',
tle2: '2 43655 99.3354 120.5116 0000942 17.4675 342.6509 13.79304456326652'
},
{
name: 'HAIYANG 1D',
tle1: '1 45721U 20036A 25110.46824375 .00000386 00000-0 15392-3 0 9998',
tle2: '2 45721 98.6261 55.5181 0000373 328.6016 31.5146 14.34080572254383'
},
{
name: 'FENGYUN 3F',
tle1: '1 57490U 23111A 25110.46159014 .00000157 00000-0 94462-4 0 9994',
tle2: '2 57490 98.7292 182.1999 0000353 80.1805 279.9412 14.20029968 88872'
},
{
name: 'HAIYANG 2C',
tle1: '1 46469U 20066A 25110.45826591 .00000025 00000-0 96784-4 0 9997',
tle2: '2 46469 65.9963 187.7873 0009304 301.6522 58.3638 13.83374632231318'
},
{
name: 'HAIYANG 1C',
tle1: '1 43609U 18068A 25110.45163331 .00000304 00000-0 12415-3 0 9993',
tle2: '2 43609 98.5643 182.7302 0009066 267.3309 92.6838 14.34142709346490'
}
]
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment