feat: 添加卫星实体类及相关功能,优化 Cesium 初始化和时间线设置
This commit is contained in:
@ -7,9 +7,9 @@ export const VIEWER_OPTIONS: Viewer.ConstructorOptions = {
|
||||
baseLayer: Cesium.ImageryLayer.fromProviderAsync(
|
||||
Cesium.TileMapServiceImageryProvider.fromUrl(Cesium.buildModuleUrl('Assets/Textures/NaturalEarthII')),
|
||||
),
|
||||
baseLayerPicker: !true,
|
||||
baseLayerPicker: false,
|
||||
fullscreenButton: !true, // 全屏按钮
|
||||
geocoder: !true, // = IonGeocodeProviderType.DEFAULT] - 在使用Geocoder小部件进行搜索时使用的地理编码服务或服务。如果设置为false,则不会创建Geocoder小部件。
|
||||
geocoder: false, // = IonGeocodeProviderType.DEFAULT] - 在使用Geocoder小部件进行搜索时使用的地理编码服务或服务。如果设置为false,则不会创建Geocoder小部件。
|
||||
|
||||
// globe: false, // 地球
|
||||
homeButton: true, // Home按钮
|
||||
|
@ -4,6 +4,8 @@ import { VIEWER_OPTIONS } from './00.cesium-init.VIEWER_OPTIONS';
|
||||
|
||||
import 'cesium/Build/Cesium/Widgets/widgets.css';
|
||||
|
||||
Cesium.Ion.defaultAccessToken = import.meta.env.VITE_CESIUM_ION_TOKEN; // 用了离线地图的情况是不需要的。
|
||||
|
||||
Object.assign(window, { Cesium });
|
||||
|
||||
_configureCesium();
|
||||
@ -13,6 +15,8 @@ export function cesium_init(container: Element) {
|
||||
|
||||
viewer.scene.debugShowFramesPerSecond = true;
|
||||
|
||||
initTimeLine(viewer);
|
||||
|
||||
return viewer;
|
||||
}
|
||||
|
||||
@ -60,3 +64,15 @@ function _configureCesium() {
|
||||
60, // 北纬
|
||||
);
|
||||
}
|
||||
|
||||
function initTimeLine(viewer: Cesium.Viewer, totalSeconds = /* 默认场景的时间跨度 */ 24 * 60 * 60) {
|
||||
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.timeline.zoomTo(start, stop);
|
||||
viewer.clock.multiplier = 1;
|
||||
viewer.clock.shouldAnimate = true;
|
||||
viewer.clock.clockRange = Cesium.ClockRange.LOOP_STOP;
|
||||
}
|
||||
|
108
src/pages/Satellite/Cesium/cesium-helper/SatelliteEntity.ts
Normal file
108
src/pages/Satellite/Cesium/cesium-helper/SatelliteEntity.ts
Normal file
@ -0,0 +1,108 @@
|
||||
import type { Cartesian3 } from 'cesium';
|
||||
|
||||
import * as Cesium from 'cesium';
|
||||
import { propagate, twoline2satrec } from 'satellite.js';
|
||||
|
||||
class SatelliteEntity {
|
||||
private leadTime!: number;
|
||||
private name!: string;
|
||||
private satrec: any;
|
||||
private stepSeconds!: number;
|
||||
private tleLine1!: string;
|
||||
private tleLine2!: string;
|
||||
private totalSeconds!: number;
|
||||
private trailTime!: number;
|
||||
|
||||
constructor(tle = '' /* , options = {} */) {
|
||||
const [name, tleLine1, tleLine2] = this._checkTle(tle);
|
||||
const circle = Number(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 = 86_400; // 24小时
|
||||
this.stepSeconds = 100;
|
||||
this.leadTime = Math.round((24 * 3600) / circle);
|
||||
this.trailTime = 0;
|
||||
}
|
||||
|
||||
_checkTle(tle: string) {
|
||||
const elements = tle.split('\n');
|
||||
if (elements.length !== 3) throw new Error('tle data error');
|
||||
return elements as [string, string, string];
|
||||
}
|
||||
|
||||
// 创建PositionProperty
|
||||
_getPositionProperty() {
|
||||
const start = Cesium.JulianDate.fromIso8601(new Date().toISOString());
|
||||
const positionProperty = new Cesium.SampledPositionProperty(Cesium.ReferenceFrame.INERTIAL);
|
||||
|
||||
const now = Date.now();
|
||||
for (let i = 0; i < this.totalSeconds / this.stepSeconds; i++) {
|
||||
const sateTime = new Date(now + i * this.stepSeconds * 1000);
|
||||
const 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,
|
||||
} as Cartesian3;
|
||||
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.fromRandom({ alpha: 1 });
|
||||
const satelliteEntity = {
|
||||
availability: new Cesium.TimeIntervalCollection([new Cesium.TimeInterval({ start, stop })]),
|
||||
description: this.name,
|
||||
label: {
|
||||
backgroundColor: new Cesium.Color(0.165, 0.165, 0.165, 0.5),
|
||||
backgroundPadding: new Cesium.Cartesian2(4, 4),
|
||||
fillColor: Cesium.Color.WHITE,
|
||||
font: '12px sans-serif',
|
||||
horizontalOrigin: Cesium.HorizontalOrigin.LEFT,
|
||||
outlineWidth: 1,
|
||||
pixelOffset: new Cesium.Cartesian2(0, 5),
|
||||
showBackground: true,
|
||||
text: this.name,
|
||||
verticalOrigin: Cesium.VerticalOrigin.TOP,
|
||||
// distanceDisplayCondition: new Cesium.DistanceDisplayCondition(10.0, 50000000),
|
||||
},
|
||||
name: this.name,
|
||||
path: new Cesium.PathGraphics({
|
||||
leadTime: this.leadTime,
|
||||
material: color,
|
||||
show: true,
|
||||
trailTime: this.trailTime,
|
||||
width: 0.5,
|
||||
}),
|
||||
point: {
|
||||
color,
|
||||
pixelSize: 8,
|
||||
// scaleByDistance: new Cesium.NearFarScalar(1.5e3, 1, 8.0e8, 0.5),
|
||||
},
|
||||
position: this._getPositionProperty(),
|
||||
};
|
||||
return satelliteEntity;
|
||||
}
|
||||
|
||||
// 获取地心惯性坐标系坐标
|
||||
getPositionEci(date: Date) {
|
||||
const result = propagate(this.satrec, date);
|
||||
// 检查position是否为对象且不是true
|
||||
if (typeof result.position !== 'object' || result.position === null) {
|
||||
return null;
|
||||
}
|
||||
return result.position;
|
||||
}
|
||||
}
|
||||
|
||||
export default SatelliteEntity;
|
8
src/pages/Satellite/Cesium/cesium-helper/_TLE_DATA.ts
Normal file
8
src/pages/Satellite/Cesium/cesium-helper/_TLE_DATA.ts
Normal file
@ -0,0 +1,8 @@
|
||||
export const TLE_LIST = [
|
||||
`2025-045A
|
||||
1 63157U 25045A 25069.35219743 .00000545 -65692-6 00000+0 0 9992
|
||||
2 63157 19.0062 64.6364 7327661 179.7218 141.4162 2.26206155 28`,
|
||||
`STARLINK-11371 [DTC]
|
||||
1 62879U 25024A 25062.93300820 .00003305 00000+0 21841-4 0 9995
|
||||
2 62879 42.9977 257.3937 0001725 269.2925 90.7748 15.77864921 5143`,
|
||||
];
|
@ -45,8 +45,6 @@ export async function demo_02_Track(viewer: Viewer) {
|
||||
outlineWidth: 2,
|
||||
pixelSize: 10,
|
||||
},
|
||||
// viewFrom: new Cartesian3(0, -1.5e7, 2.5e7),
|
||||
// https://www.google.com/search?q=cesium%C2%A0viewFrom%C2%A0+trackedEntity
|
||||
});
|
||||
|
||||
// 计算并绘制卫星轨迹
|
||||
|
@ -2,17 +2,28 @@
|
||||
import type { Viewer } from 'cesium';
|
||||
|
||||
import { cesium_init } from './cesium-helper/00.cesium-init';
|
||||
import { TLE_LIST } from './cesium-helper/_TLE_DATA';
|
||||
import { demo_01_OrbitGeneration } from './cesium-helper/demo_01_OrbitGeneration';
|
||||
import { demo_02_Track } from './cesium-helper/demo_02_Track';
|
||||
import SatelliteEntity from './cesium-helper/SatelliteEntity';
|
||||
|
||||
let viewer: Viewer;
|
||||
onMounted(async () => {
|
||||
viewer = cesium_init(document.getElementById('cesiumContainer')!);
|
||||
viewer = cesium_init(document.querySelector('#cesiumContainer')!);
|
||||
Object.assign(globalThis, { viewer });
|
||||
|
||||
(({ run }) => (run ? demo_01_OrbitGeneration(viewer) : null))({ run: false });
|
||||
|
||||
(({ run }) => (run ? demo_02_Track(viewer) : null))({ run: true });
|
||||
(({ run }) => (run ? demo_02_Track(viewer) : null))({ run: false });
|
||||
|
||||
// demo_01_OrbitGeneration(viewer);
|
||||
// demo_02_Track(viewer);
|
||||
|
||||
TLE_LIST.forEach((tle) => {
|
||||
const satellite = new SatelliteEntity(tle);
|
||||
const cesiumSateEntity = satellite.createSatelliteEntity();
|
||||
/* let result = */ viewer.entities.add(cesiumSateEntity);
|
||||
});
|
||||
});
|
||||
</script>
|
||||
|
||||
|
@ -34,4 +34,3 @@ async function handleConfirmAsync(e: MouseEvent) {
|
||||
</ACard>
|
||||
</ACard>
|
||||
</template>
|
||||
./HAPopconfirm.vue
|
||||
|
Reference in New Issue
Block a user