feat: 添加卫星覆盖范围计算功能

This commit is contained in:
严浩
2025-04-02 15:17:47 +08:00
parent 751b890a80
commit db9d394171
2 changed files with 85 additions and 3 deletions

View File

@ -0,0 +1,4 @@
- 卫星覆盖范围: 当前实现是基于卫星高度的一个简化估算altitude * 0.8),代码注释也指明了这一点。这种方法不够精确,仅能提供一个大致的视觉参考。精确的覆盖范围计算需要考虑卫星的视场角 (FOV) 或波束宽度等具体参数。
- TLE 数据 → 轨道 → 位置 & 速度
- 大小 → 需要外部规格数据
- 精确姿态 → 需要专门的 ADCS 数据 (TLE 不提供)

View File

@ -29,7 +29,14 @@ export class HCesiumViewerCls {
// 用于存储当前地面站实体的 Map
currentStationEntities: Map<string, Cesium.Entity> = new Map();
// 用于存储当前卫星实体的 Map (包括轨道实体)
currentSatelliteEntities: Map<string, { entity: Cesium.Entity; orbitEntity?: Cesium.Entity }> = new Map();
currentSatelliteEntities: Map<
string,
{
coverageEntity?: Cesium.Entity;
entity: Cesium.Entity;
orbitEntity?: Cesium.Entity;
}
> = new Map();
/**
* 初始化 Cesium Viewer
@ -250,6 +257,67 @@ export class HCesiumViewerCls {
satelliteEntity.position = positionProperty;
satelliteEntity.orientation = new Cesium.VelocityOrientationProperty(positionProperty);
// --- 添加卫星地面覆盖范围 ---
// 使用 CallbackProperty 动态计算星下点位置
const subsatellitePosition = new Cesium.CallbackPositionProperty(
(time, result) => {
// 从 satelliteEntity 获取当前时间的精确位置
const satelliteCartesian = positionProperty.getValue(time, result);
if (!satelliteCartesian) {
return; // 如果位置无效,则不返回任何内容
}
// 转换为地理坐标(包含高度)
const satelliteCartographic = Cesium.Cartographic.fromCartesian(satelliteCartesian);
if (!satelliteCartographic) {
return; // 如果转换失败,则不返回任何内容
}
// 创建星下点地理坐标高度设为0
const subsatelliteCartographic = new Cesium.Cartographic(
satelliteCartographic.longitude,
satelliteCartographic.latitude,
0,
);
// 转换回笛卡尔坐标
return Cesium.Cartographic.toCartesian(subsatelliteCartographic, Cesium.Ellipsoid.WGS84, result);
},
false,
Cesium.ReferenceFrame.FIXED,
); // isConstant: false, referenceFrame: FIXED
// 使用 CallbackProperty 动态计算覆盖半径 (基于高度的简单估算)
const coverageRadius = new Cesium.CallbackProperty((time) => {
const satelliteCartesian = positionProperty.getValue(time);
if (!satelliteCartesian) {
return 100_000; // 默认半径 100km
}
const satelliteCartographic = Cesium.Cartographic.fromCartesian(satelliteCartesian);
if (!satelliteCartographic) {
return 100_000;
}
const altitude = satelliteCartographic.height;
// 简化的估算:半径约为高度的 0.8 倍,最小 50km
// 实际应用中应基于卫星的视场角 (FOV) 或波束宽度计算
const calculatedRadius = altitude * 0.8;
return Math.max(calculatedRadius, 50_000); // 最小半径 50km
}, false); // isConstant 设置为 false
const coverageEntity = this.viewer.entities.add({
id: `${id}-coverage`,
name: `${name} 覆盖范围`,
position: subsatellitePosition,
ellipse: {
semiMajorAxis: coverageRadius,
semiMinorAxis: coverageRadius, // 假设圆形覆盖
material: Cesium.Color.RED.withAlpha(0.3), // 半透明红色
heightReference: Cesium.HeightReference.CLAMP_TO_GROUND, // 贴合地形
outline: true,
outlineColor: Cesium.Color.BLACK.withAlpha(0.5),
outlineWidth: 1,
// fill: true, // 默认填充
},
});
// --- 覆盖范围结束 ---
let orbitEntity: Cesium.Entity | undefined;
// 添加完整轨道线(如果需要)
if (showOrbit && orbitPositions.length > 1) {
@ -269,7 +337,7 @@ export class HCesiumViewerCls {
}
// 存储实体引用
this.currentSatelliteEntities.set(id, { entity: satelliteEntity, orbitEntity });
this.currentSatelliteEntities.set(id, { entity: satelliteEntity, orbitEntity, coverageEntity });
return satelliteEntity;
}
@ -288,6 +356,7 @@ export class HCesiumViewerCls {
if (satelliteData) {
let removedMain = true;
let removedOrbit = true;
let removedCoverage = true; // 新增:覆盖范围移除状态
// 移除卫星主体
if (satelliteData.entity) {
@ -305,8 +374,17 @@ export class HCesiumViewerCls {
}
}
// 移除覆盖范围
if (satelliteData.coverageEntity) {
removedCoverage = this.viewer.entities.remove(satelliteData.coverageEntity);
if (!removedCoverage) {
console.warn(`尝试从 Cesium 移除卫星覆盖范围 ID 为 "${satelliteData.coverageEntity.id}" 的实体失败。`);
}
}
// 如果主体和轨道(如果存在)都移除成功或不存在,则从 Map 中删除
if (removedMain && removedOrbit) {
// 如果主体、轨道(如果存在)和覆盖范围(如果存在)都移除成功或不存在,则从 Map 中删除
if (removedMain && removedOrbit && removedCoverage) {
this.currentSatelliteEntities.delete(entityId);
return true;
} else {