h-cesium-viewer
This commit is contained in:
@ -1,4 +0,0 @@
|
||||
- 卫星覆盖范围: 当前实现是基于卫星高度的一个简化估算(altitude * 0.8),代码注释也指明了这一点。这种方法不够精确,仅能提供一个大致的视觉参考。精确的覆盖范围计算需要考虑卫星的视场角 (FOV) 或波束宽度等具体参数。
|
||||
- TLE 数据 → 轨道 → 位置 & 速度
|
||||
- 大小 → 需要外部规格数据
|
||||
- 精确姿态 → 需要专门的 ADCS 数据 (TLE 不提供)
|
4
src/components/h-cesium-viewer/_资料/README copy.md
Normal file
4
src/components/h-cesium-viewer/_资料/README copy.md
Normal file
@ -0,0 +1,4 @@
|
||||
- 卫星覆盖范围: 当前实现是基于卫星高度的一个简化估算(altitude \* 0.8),代码注释也指明了这一点。这种方法不够精确,仅能提供一个大致的视觉参考。精确的覆盖范围计算需要考虑卫星的视场角 (FOV) 或波束宽度等具体参数。
|
||||
- TLE 数据 → 轨道 → 位置 & 速度
|
||||
- 大小 → 需要外部规格数据
|
||||
- 精确姿态 → 需要专门的 ADCS 数据 (TLE 不提供)
|
39
src/components/h-cesium-viewer/_资料/README.md
Normal file
39
src/components/h-cesium-viewer/_资料/README.md
Normal file
@ -0,0 +1,39 @@
|
||||
## 配置项目
|
||||
|
||||
- https://github.dev/CesiumGS/cesium-vite-example
|
||||
|
||||
### 其他
|
||||
|
||||
- https://cesium.com/blog/2024/02/13/configuring-vite-or-webpack-for-cesiumjs/
|
||||
- https://cesium.com/learn/cesiumjs-learn/cesiumjs-quickstart/
|
||||
- vite-plugin-cesium
|
||||
|
||||
## 参考
|
||||
|
||||
- [vue-cesium](https://zouyaoji.top/vue-cesium/#/zh-CN/component/controls/vc-navigation)
|
||||
- https://cesium.pages.dev/
|
||||
|
||||
## 离线地图
|
||||
|
||||
- https://github.com/CesiumGS/cesium/tree/main/Documentation/OfflineGuide
|
||||
- https://blog.csdn.net/lhllhllhl_/article/details/145857779
|
||||
- https://blog.csdn.net/m0_54849806/article/details/126070809
|
||||
- https://juejin.cn/post/6969838266182795278
|
||||
- https://blog.csdn.net/CSDNqinzhike/article/details/139587028
|
||||
|
||||
## TLE
|
||||
|
||||
### 格式
|
||||
|
||||
- https://celestrak.org/NORAD/documentation/tle-fmt.php
|
||||
- https://en.wikipedia.org/wiki/Two-line_element_set#Format
|
||||
|
||||
### 轨道数据
|
||||
|
||||
- https://celestrak.org/NORAD/elements/
|
||||
- https://www.n2yo.com/satellites/?c=PRC&t=country
|
||||
- https://www.space-track.org/#catalog
|
||||
|
||||
### 相关
|
||||
|
||||
- https://www.satview.org/?sat_id=63158U
|
@ -1,31 +1,24 @@
|
||||
import * as Cesium from 'cesium';
|
||||
import { eciToEcf, gstime, propagate, type SatRec, twoline2satrec } from 'satellite.js';
|
||||
|
||||
import { VIEWER_OPTIONS_FN } from './VIEWER_OPTIONS';
|
||||
import type { GroundStationOptions, SatelliteOptions } from './h-cesium-viewer-class.types'; // 2小时
|
||||
|
||||
export interface GroundStationOptions {
|
||||
height?: number; // 可选高度,默认为0
|
||||
id: string; // 站点的唯一标识符
|
||||
latitude: number;
|
||||
longitude: number;
|
||||
name: string;
|
||||
pixelSize?: number; // 点的可选像素大小
|
||||
}
|
||||
import { VIEWER_OPTIONS_FN } from './helper/_VIEWER_OPTIONS';
|
||||
import { configureCesium } from './helper/configureCesium';
|
||||
import { configureTimeLine } from './helper/configureTimeLine';
|
||||
|
||||
// 卫星选项接口
|
||||
export interface SatelliteOptions {
|
||||
id: string; // 卫星的唯一标识符
|
||||
orbitDurationHours?: number; // 轨道显示时长(小时),默认为 2
|
||||
showOrbit?: boolean; // 是否显示完整轨道线,默认为 true
|
||||
timeStepSeconds?: number; // 轨道计算步长(秒),默认为 30
|
||||
tle: string; // 包含卫星名称和两行 TLE 数据的字符串,格式如下:
|
||||
// NAME
|
||||
// TLE1
|
||||
// TLE2
|
||||
}
|
||||
const 默认轨道时长秒 = 2 * 60 * 60;
|
||||
|
||||
export { type GroundStationOptions, type SatelliteOptions } from './h-cesium-viewer-class.types';
|
||||
|
||||
Cesium.Ion.defaultAccessToken = import.meta.env.VITE_CESIUM_ION_TOKEN; // 用了离线地图的情况是不需要的。
|
||||
|
||||
Object.assign(globalThis, { Cesium });
|
||||
|
||||
configureCesium();
|
||||
|
||||
export class HCesiumViewerCls {
|
||||
private viewer: Cesium.Viewer | null = null;
|
||||
viewer: Cesium.Viewer | null = null;
|
||||
// 用于存储当前地面站实体的 Map
|
||||
currentStationEntities: Map<string, Cesium.Entity> = new Map();
|
||||
// 用于存储当前卫星实体的 Map (包括轨道实体)
|
||||
@ -45,6 +38,10 @@ export class HCesiumViewerCls {
|
||||
initCesiumViewer(container: ConstructorParameters<typeof Cesium.Viewer>[0]) {
|
||||
this.viewer = new Cesium.Viewer(container, VIEWER_OPTIONS_FN());
|
||||
|
||||
configureTimeLine(this.viewer);
|
||||
|
||||
this.viewer.scene.debugShowFramesPerSecond = true;
|
||||
|
||||
// 初始化时清空可能存在的旧实体引用
|
||||
this.currentStationEntities.clear();
|
||||
this.currentSatelliteEntities.clear();
|
||||
@ -158,7 +155,7 @@ export class HCesiumViewerCls {
|
||||
const {
|
||||
id,
|
||||
tle,
|
||||
orbitDurationHours = 2, // 默认轨道时长 2 小时
|
||||
orbitDurationSeconds = 默认轨道时长秒,
|
||||
timeStepSeconds = 30, // 默认步长 30 秒
|
||||
showOrbit = true, // 默认显示轨道
|
||||
} = options;
|
||||
@ -215,18 +212,17 @@ export class HCesiumViewerCls {
|
||||
color: randomBaseColor, // 使用随机基色
|
||||
}),
|
||||
width: 2,
|
||||
leadTime: (orbitDurationHours * 3600) / 2, // 显示未来一半时间的轨迹
|
||||
trailTime: (orbitDurationHours * 3600) / 2, // 显示过去一半时间的轨迹
|
||||
leadTime: orbitDurationSeconds / 2, // 显示未来一半时间的轨迹
|
||||
trailTime: orbitDurationSeconds / 2, // 显示过去一半时间的轨迹
|
||||
},
|
||||
});
|
||||
|
||||
// --- 计算轨道 ---
|
||||
const totalSeconds = orbitDurationHours * 60 * 60;
|
||||
const startTime = this.viewer.clock.currentTime; // 使用当前 viewer 的时间作为起点
|
||||
const positionProperty = new Cesium.SampledPositionProperty();
|
||||
const orbitPositions: Cesium.Cartesian3[] = []; // 用于存储完整轨道点
|
||||
|
||||
for (let i = 0; i <= totalSeconds; i += timeStepSeconds) {
|
||||
for (let i = 0; i <= orbitDurationSeconds; i += timeStepSeconds) {
|
||||
const time = Cesium.JulianDate.addSeconds(startTime, i, new Cesium.JulianDate());
|
||||
const jsDate = Cesium.JulianDate.toDate(time);
|
||||
|
||||
@ -311,7 +307,7 @@ export class HCesiumViewerCls {
|
||||
ellipse: {
|
||||
semiMajorAxis: coverageRadius,
|
||||
semiMinorAxis: coverageRadius, // 假设圆形覆盖
|
||||
material: randomBaseColor.withAlpha(0.2), // 基于随机基色的半透明填充
|
||||
material: randomBaseColor.withAlpha(0.2 + 0.3), // 基于随机基色的半透明填充
|
||||
heightReference: Cesium.HeightReference.CLAMP_TO_GROUND, // 贴合地形
|
||||
outline: true,
|
||||
outlineColor: randomBaseColor.withAlpha(0.8), // 基于随机基色的较深半透明轮廓
|
||||
|
@ -0,0 +1,20 @@
|
||||
export interface GroundStationOptions {
|
||||
height?: number; // 可选高度,默认为0
|
||||
id: string; // 站点的唯一标识符
|
||||
latitude: number;
|
||||
longitude: number;
|
||||
name: string;
|
||||
pixelSize?: number; // 点的可选像素大小
|
||||
}
|
||||
|
||||
// 卫星选项接口
|
||||
export interface SatelliteOptions {
|
||||
id: string; // 卫星的唯一标识符
|
||||
orbitDurationSeconds?: number; // 轨道显示时长
|
||||
showOrbit?: boolean; // 是否显示完整轨道线,默认为 true
|
||||
timeStepSeconds?: number; // 轨道计算步长(秒),默认为 30
|
||||
tle: string; // 包含卫星名称和两行 TLE 数据的字符串,格式如下:
|
||||
// NAME
|
||||
// TLE1
|
||||
// TLE2
|
||||
}
|
20
src/components/h-cesium-viewer/helper/_TOOLTIP_MAP.ts
Normal file
20
src/components/h-cesium-viewer/helper/_TOOLTIP_MAP.ts
Normal file
@ -0,0 +1,20 @@
|
||||
/* prettier-ignore */
|
||||
export const TOOLTIP_MAP = {
|
||||
NORAD_CAT_ID_卫星编号: "5位数字,如'63158',表示NORAD卫星唯一目录编号",
|
||||
CLASSIFICATION_TYPE_卫星分类: "1个字母,如'U',表示数据分类",
|
||||
OBJECT_ID_国际标识符: "8个字符,如'25045B'(年份+发射编号+部件),不足时右侧补空格",
|
||||
EPOCH_历元时间: "14位数字,如'25071.65907894',表示轨道数据的参考时间(年份+年积日.一天中的小数部分)",
|
||||
MEAN_MOTION_DOT_平均运动一阶导数: "10位数字,如'.00072212',表示平均运动变化率的一半,单位圈/天²,左侧补空格",
|
||||
MEAN_MOTION_DDOT_平均运动二阶导数: "8位科学计数法,如'-50502-6'表示-5.0502×10⁻⁶圈/天³,最后一位是指数",
|
||||
BSTAR_BSTAR拖曳项: "BSTAR参数。8位科学计数法,如'39937-3'表示0.39937×10⁻³/地球半径,表示大气拖曳影响",
|
||||
EPHEMERIS_TYPE_星历类型: "通常为'0',表示使用SGP4星历模型",
|
||||
ELEMENT_SET_NO_元素集编号: "4位数字,如'9999',表示TLE版本号",
|
||||
// CHECKSUM_校验和: "1位数字,用于验证数据完整性,可选项",
|
||||
INCLINATION_轨道倾角: "8位数字,如'19.0363',表示轨道与赤道平面的夹角(度),范围0°-180°",
|
||||
RA_OF_ASC_NODE_升交点赤经: "8位数字,如'63.0294',表示轨道升交点的赤经(度),范围0°-360°",
|
||||
ECCENTRICITY_离心率: "7位数字,无小数点,如'7375486'表示0.7375486,小数点隐含在最前面",
|
||||
ARG_OF_PERICENTER_近地点幅角: "8位数字,如'181.9338',表示近地点相对升交点的角度(度),范围0°-360°",
|
||||
MEAN_ANOMALY_平近点角: "8位数字,如'171.6150',表示历元时的平近点角(度),范围0°-360°",
|
||||
MEAN_MOTION_平均运动: "11位数字,如'2.21786616',表示卫星每天绕地球的圈数(圈/天)",
|
||||
REV_AT_EPOCH_历元时的圈数: "5位数字,如'13',表示卫星在历元时完成的轨道圈数,最后以为是校验和,共6位",
|
||||
};
|
46
src/components/h-cesium-viewer/helper/configureCesium.ts
Normal file
46
src/components/h-cesium-viewer/helper/configureCesium.ts
Normal file
@ -0,0 +1,46 @@
|
||||
import * as Cesium from 'cesium';
|
||||
|
||||
export function configureCesium() {
|
||||
if (document.querySelector('#hide-cesium-viewer-bottom') === null) {
|
||||
document.head.append(
|
||||
Object.assign(document.createElement('style'), {
|
||||
id: 'hide-cesium-viewer-bottom',
|
||||
innerHTML: `
|
||||
.cesium-viewer-bottom {
|
||||
display: none !important;
|
||||
}
|
||||
`.trim(),
|
||||
type: 'text/css',
|
||||
}),
|
||||
);
|
||||
}
|
||||
|
||||
/* 时间日期格式化 */ {
|
||||
const minutes = 0 - new Date().getTimezoneOffset(); // 0 - (-480);
|
||||
|
||||
// Animation 的时间日期格式化
|
||||
Cesium.AnimationViewModel.defaultDateFormatter = function (date) {
|
||||
const dataZone8 = Cesium.JulianDate.addMinutes(date, minutes, new Cesium.JulianDate());
|
||||
return Cesium.JulianDate.toIso8601(dataZone8).slice(0, 10);
|
||||
};
|
||||
Cesium.AnimationViewModel.defaultTimeFormatter = function (time) {
|
||||
const dataZone8 = Cesium.JulianDate.addMinutes(time, minutes, new Cesium.JulianDate());
|
||||
return Cesium.JulianDate.toIso8601(dataZone8).slice(11, 19);
|
||||
};
|
||||
|
||||
// Timeline 的时间日期格式化
|
||||
// @ts-expect-error node_modules/@cesium/widgets/Source/Timeline/Timeline.js
|
||||
Cesium.Timeline.prototype.makeLabel = function (time) {
|
||||
const dataZone8 = Cesium.JulianDate.addMinutes(time, minutes, new Cesium.JulianDate());
|
||||
return Cesium.JulianDate.toIso8601(dataZone8).slice(0, 19);
|
||||
};
|
||||
}
|
||||
|
||||
// 默认视图区域
|
||||
Cesium.Camera.DEFAULT_VIEW_RECTANGLE = Cesium.Rectangle.fromDegrees(
|
||||
75, // 西经
|
||||
10, // 南纬
|
||||
140, // 东经
|
||||
60, // 北纬
|
||||
);
|
||||
}
|
34
src/components/h-cesium-viewer/helper/configureMapTile.ts
Normal file
34
src/components/h-cesium-viewer/helper/configureMapTile.ts
Normal file
@ -0,0 +1,34 @@
|
||||
import * as Cesium from 'cesium';
|
||||
|
||||
const provider = new Cesium.UrlTemplateImageryProvider({
|
||||
maximumLevel: 18,
|
||||
minimumLevel: 3,
|
||||
url: 'https://webst02.is.autonavi.com/appmaptile?style=6&x={x}&y={y}&z={z}',
|
||||
});
|
||||
|
||||
export function configureMapTile(viewer: Cesium.Viewer) {
|
||||
if (viewer.baseLayerPicker) {
|
||||
// 如果有底图选择器
|
||||
const customLayerViewModel = new Cesium.ProviderViewModel({
|
||||
category: 'Cesium ion', // 或 'Other 、Cesium ion'、'Bing Maps' 等
|
||||
creationFunction() {
|
||||
return provider;
|
||||
},
|
||||
iconUrl: 'gaodeImage.png',
|
||||
name: '高德地图',
|
||||
tooltip: '高德地图',
|
||||
});
|
||||
// 设置高德地图为默认图层
|
||||
viewer.baseLayerPicker.viewModel.imageryProviderViewModels.unshift(customLayerViewModel);
|
||||
const selectedViewModel = viewer.baseLayerPicker.viewModel.imageryProviderViewModels[0];
|
||||
if (!selectedViewModel) {
|
||||
console.error('未找到默认底图');
|
||||
return;
|
||||
}
|
||||
viewer.baseLayerPicker.viewModel.selectedImagery = selectedViewModel;
|
||||
} else {
|
||||
// 如果没有底图选择器
|
||||
viewer.imageryLayers.removeAll();
|
||||
viewer.imageryLayers.addImageryProvider(provider);
|
||||
}
|
||||
}
|
20
src/components/h-cesium-viewer/helper/configureTimeLine.ts
Normal file
20
src/components/h-cesium-viewer/helper/configureTimeLine.ts
Normal file
@ -0,0 +1,20 @@
|
||||
import * as Cesium from 'cesium';
|
||||
|
||||
const 默认场景的时间跨度 = 2 * 60 * 60; // 2小时
|
||||
|
||||
export function configureTimeLine(viewer: Cesium.Viewer, totalSeconds = 默认场景的时间跨度) {
|
||||
const start = Cesium.JulianDate.fromIso8601(new Date().toISOString());
|
||||
const stop = Cesium.JulianDate.addSeconds(start, totalSeconds, new Cesium.JulianDate());
|
||||
|
||||
// 设置时钟范围
|
||||
viewer.clock.startTime = start.clone();
|
||||
viewer.clock.stopTime = stop.clone();
|
||||
viewer.clock.currentTime = start.clone();
|
||||
viewer.clock.clockRange = Cesium.ClockRange.LOOP_STOP;
|
||||
viewer.clock.multiplier = 30; // 30倍速播放
|
||||
|
||||
// 设置时间轴范围
|
||||
viewer.timeline.zoomTo(start, stop);
|
||||
|
||||
viewer.clock.shouldAnimate = true;
|
||||
}
|
Reference in New Issue
Block a user