feat: 添加 Cesium 配置文件和离线地图支持,优化初始化选项
This commit is contained in:
@ -0,0 +1,31 @@
|
|||||||
|
import type { Viewer } from 'cesium';
|
||||||
|
|
||||||
|
import * as Cesium from 'cesium';
|
||||||
|
|
||||||
|
export const VIEWER_OPTIONS: Viewer.ConstructorOptions = {
|
||||||
|
animation: true, // .cesium-viewer-animationContainer https://cesium.com/learn/ion-sdk/ref-doc/Animation.html
|
||||||
|
baseLayer: Cesium.ImageryLayer.fromProviderAsync(
|
||||||
|
Cesium.TileMapServiceImageryProvider.fromUrl(Cesium.buildModuleUrl('Assets/Textures/NaturalEarthII')),
|
||||||
|
),
|
||||||
|
baseLayerPicker: !true,
|
||||||
|
fullscreenButton: !true, // 全屏按钮
|
||||||
|
geocoder: !true, // = IonGeocodeProviderType.DEFAULT] - 在使用Geocoder小部件进行搜索时使用的地理编码服务或服务。如果设置为false,则不会创建Geocoder小部件。
|
||||||
|
|
||||||
|
// globe: false, // 地球
|
||||||
|
homeButton: true, // Home按钮
|
||||||
|
infoBox: false, // InfoBox小部件。
|
||||||
|
navigationHelpButton: false, // 是否显示导航帮助按钮
|
||||||
|
orderIndependentTranslucency: false, // 顺序无关透明度
|
||||||
|
projectionPicker: !true, // 投影选择器
|
||||||
|
requestRenderMode: !true, // 如果为真,渲染帧将仅在场景内部发生变化时需要时发生。启用此功能可以减少应用程序的CPU/GPU使用率,并在移动设备上节省更多电量,但在此模式下需要使用{@link Scene#requestRender}显式渲染新帧。在API的其他部分对场景进行更改后,在许多情况下都需要这样做。请参阅{@link https://cesium.com/blog/2018/01/24/cesium-scene-rendering-performance/|使用显式渲染提高性能}。
|
||||||
|
sceneModePicker: true, // 是否显示场景模式选择器(2D/3D切换)
|
||||||
|
selectionIndicator: true,
|
||||||
|
shadows: true, // Determines if shadows are cast by light sources.
|
||||||
|
|
||||||
|
/* animationContainer: !true, */
|
||||||
|
/* timelineContainer: true, */
|
||||||
|
/* bottomContainer: document.createElement('p'), // The DOM element or ID that will contain the bottomContainer. If not specified, the bottomContainer is added to the widget itself. */
|
||||||
|
shouldAnimate: !true,
|
||||||
|
showRenderLoopErrors: true, // 如果为真,当发生渲染循环错误时,此小部件将自动向用户显示包含错误的HTML面板。
|
||||||
|
timeline: true,
|
||||||
|
};
|
37
src/pages/cesium/cesium-helper/00.cesium-init.globe.ts
Normal file
37
src/pages/cesium/cesium-helper/00.cesium-init.globe.ts
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
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);
|
||||||
|
}
|
||||||
|
}
|
@ -1,7 +1,7 @@
|
|||||||
// TODO: 干掉 api.cesium.com
|
|
||||||
// XXX: ion-sdk ???
|
|
||||||
|
|
||||||
import * as Cesium from 'cesium';
|
import * as Cesium from 'cesium';
|
||||||
|
|
||||||
|
import { VIEWER_OPTIONS } from './00.cesium-init.VIEWER_OPTIONS';
|
||||||
|
|
||||||
import 'cesium/Build/Cesium/Widgets/widgets.css';
|
import 'cesium/Build/Cesium/Widgets/widgets.css';
|
||||||
|
|
||||||
Object.assign(window, { Cesium });
|
Object.assign(window, { Cesium });
|
||||||
@ -9,42 +9,28 @@ Object.assign(window, { Cesium });
|
|||||||
_configureCesium();
|
_configureCesium();
|
||||||
|
|
||||||
export function cesium_init(container: Element) {
|
export function cesium_init(container: Element) {
|
||||||
const viewer = new Cesium.Viewer(container, {
|
const viewer = new Cesium.Viewer(container, VIEWER_OPTIONS);
|
||||||
animation: true, // .cesium-viewer-animationContainer https://cesium.com/learn/ion-sdk/ref-doc/Animation.html
|
|
||||||
...{
|
|
||||||
baseLayer: Cesium.ImageryLayer.fromProviderAsync(
|
|
||||||
Cesium.TileMapServiceImageryProvider.fromUrl(Cesium.buildModuleUrl('Assets/Textures/NaturalEarthII')),
|
|
||||||
),
|
|
||||||
baseLayerPicker: !true,
|
|
||||||
geocoder: !true, // = IonGeocodeProviderType.DEFAULT] - 在使用Geocoder小部件进行搜索时使用的地理编码服务或服务。如果设置为false,则不会创建Geocoder小部件。
|
|
||||||
},
|
|
||||||
fullscreenButton: !true, // 全屏按钮
|
|
||||||
// globe: false, // 地球
|
|
||||||
homeButton: true, // Home按钮
|
|
||||||
infoBox: false, // InfoBox小部件。
|
|
||||||
navigationHelpButton: false, // 是否显示导航帮助按钮
|
|
||||||
orderIndependentTranslucency: false, // 顺序无关透明度
|
|
||||||
projectionPicker: !true, // 投影选择器
|
|
||||||
requestRenderMode: !true, // 如果为真,渲染帧将仅在场景内部发生变化时需要时发生。启用此功能可以减少应用程序的CPU/GPU使用率,并在移动设备上节省更多电量,但在此模式下需要使用{@link Scene#requestRender}显式渲染新帧。在API的其他部分对场景进行更改后,在许多情况下都需要这样做。请参阅{@link https://cesium.com/blog/2018/01/24/cesium-scene-rendering-performance/|使用显式渲染提高性能}。
|
|
||||||
sceneModePicker: true, // 是否显示场景模式选择器(2D/3D切换)
|
|
||||||
selectionIndicator: true,
|
|
||||||
shadows: true, // Determines if shadows are cast by light sources.
|
|
||||||
/* animationContainer: !true, */
|
|
||||||
/* timelineContainer: true, */
|
|
||||||
/* bottomContainer: document.createElement('p'), // The DOM element or ID that will contain the bottomContainer. If not specified, the bottomContainer is added to the widget itself. */
|
|
||||||
shouldAnimate: !true,
|
|
||||||
showRenderLoopErrors: true, // 如果为真,当发生渲染循环错误时,此小部件将自动向用户显示包含错误的HTML面板。
|
|
||||||
timeline: true, // If set to false, the Timeline widget will not be created.
|
|
||||||
});
|
|
||||||
|
|
||||||
viewer.scene.debugShowFramesPerSecond = true;
|
viewer.scene.debugShowFramesPerSecond = true;
|
||||||
|
|
||||||
// _configureMapTile(viewer);
|
|
||||||
|
|
||||||
return viewer;
|
return viewer;
|
||||||
}
|
}
|
||||||
|
|
||||||
function _configureCesium() {
|
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);
|
const minutes = 0 - new Date().getTimezoneOffset(); // 0 - (-480);
|
||||||
|
|
||||||
@ -74,49 +60,3 @@ function _configureCesium() {
|
|||||||
60, // 北纬
|
60, // 北纬
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
function _configureMapTile(viewer: Cesium.Viewer) {
|
|
||||||
const provider = new Cesium.UrlTemplateImageryProvider({
|
|
||||||
maximumLevel: 18,
|
|
||||||
minimumLevel: 3,
|
|
||||||
url: 'https://webst02.is.autonavi.com/appmaptile?style=6&x={x}&y={y}&z={z}',
|
|
||||||
});
|
|
||||||
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function _flyToDemo(viewer: Cesium.Viewer) {
|
|
||||||
// 将三维球定位到中国
|
|
||||||
viewer.camera.flyTo({
|
|
||||||
complete: function complete() {},
|
|
||||||
destination: Cesium.Cartesian3.fromDegrees(103.84, 31.15, 17_850_000),
|
|
||||||
orientation: {
|
|
||||||
heading: Cesium.Math.toRadians(348.420_294_285_197_8),
|
|
||||||
pitch: Cesium.Math.toRadians(-89.740_266_879_720_41),
|
|
||||||
roll: Cesium.Math.toRadians(0),
|
|
||||||
},
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
@ -9,7 +9,7 @@ export async function demo_01_OrbitGeneration(viewer: Viewer) {
|
|||||||
2 62879 42.9977 257.3937 0001725 269.2925 90.7748 15.77864921 5143`;
|
2 62879 42.9977 257.3937 0001725 269.2925 90.7748 15.77864921 5143`;
|
||||||
|
|
||||||
// 解析TLE数据
|
// 解析TLE数据
|
||||||
const lines = tle.split('\n');
|
const lines = tle.split('\n') as [string, string, string];
|
||||||
const satelliteName = lines[0].trim();
|
const satelliteName = lines[0].trim();
|
||||||
const tleLine1 = lines[1];
|
const tleLine1 = lines[1];
|
||||||
const tleLine2 = lines[2];
|
const tleLine2 = lines[2];
|
||||||
@ -30,7 +30,7 @@ export async function demo_01_OrbitGeneration(viewer: Viewer) {
|
|||||||
// 计算一条完整的轨道
|
// 计算一条完整的轨道
|
||||||
for (let i = 0; i < totalMinutes; i += timeStepInMinutes) {
|
for (let i = 0; i < totalMinutes; i += timeStepInMinutes) {
|
||||||
// 创建时间点
|
// 创建时间点
|
||||||
const time = new Date(now.getTime() + i * 60000);
|
const time = new Date(now.getTime() + i * 60_000);
|
||||||
|
|
||||||
// 获取卫星位置
|
// 获取卫星位置
|
||||||
const positionAndVelocity = propagate(satrec, time);
|
const positionAndVelocity = propagate(satrec, time);
|
||||||
@ -49,8 +49,8 @@ export async function demo_01_OrbitGeneration(viewer: Viewer) {
|
|||||||
pointsArray.push(
|
pointsArray.push(
|
||||||
Cesium.Cartesian3.fromDegrees(
|
Cesium.Cartesian3.fromDegrees(
|
||||||
Cesium.Math.toDegrees(Math.atan2(p.y, p.x)),
|
Cesium.Math.toDegrees(Math.atan2(p.y, p.x)),
|
||||||
Cesium.Math.toDegrees(Math.atan2(p.z, Math.sqrt(p.x * p.x + p.y * p.y))),
|
Cesium.Math.toDegrees(Math.atan2(p.z, Math.hypot(p.x, p.y))),
|
||||||
Math.sqrt(p.x * p.x + p.y * p.y + p.z * p.z) * 1000, // 转换为米
|
Math.hypot(p.x, p.y, p.z) * 1000, // 转换为米
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -68,11 +68,10 @@ export async function demo_01_OrbitGeneration(viewer: Viewer) {
|
|||||||
|
|
||||||
const currentPosition = Cesium.Cartesian3.fromDegrees(
|
const currentPosition = Cesium.Cartesian3.fromDegrees(
|
||||||
Cesium.Math.toDegrees(Math.atan2(p.y, p.x)),
|
Cesium.Math.toDegrees(Math.atan2(p.y, p.x)),
|
||||||
Cesium.Math.toDegrees(Math.atan2(p.z, Math.sqrt(p.x * p.x + p.y * p.y))),
|
Cesium.Math.toDegrees(Math.atan2(p.z, Math.hypot(p.x, p.y))),
|
||||||
Math.sqrt(p.x * p.x + p.y * p.y + p.z * p.z) * 1000, // 转换为米
|
Math.hypot(p.x, p.y, p.z) * 1000, // 转换为米
|
||||||
);
|
);
|
||||||
|
|
||||||
await PromiseConfirmationService({ message: '创建轨道线' });
|
|
||||||
viewer.entities.add({
|
viewer.entities.add({
|
||||||
name: `${satelliteName} Orbit`,
|
name: `${satelliteName} Orbit`,
|
||||||
polyline: {
|
polyline: {
|
||||||
@ -85,7 +84,6 @@ export async function demo_01_OrbitGeneration(viewer: Viewer) {
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
await PromiseConfirmationService({ message: '添加卫星实体' });
|
|
||||||
// 添加卫星实体
|
// 添加卫星实体
|
||||||
const satellite = viewer.entities.add({
|
const satellite = viewer.entities.add({
|
||||||
label: {
|
label: {
|
||||||
@ -113,6 +111,5 @@ export async function demo_01_OrbitGeneration(viewer: Viewer) {
|
|||||||
});
|
});
|
||||||
|
|
||||||
// 将相机定位到卫星
|
// 将相机定位到卫星
|
||||||
await PromiseConfirmationService({ message: '飞向卫星' });
|
|
||||||
viewer.flyTo(satellite, { duration: 3 });
|
viewer.flyTo(satellite, { duration: 3 });
|
||||||
}
|
}
|
||||||
|
@ -11,8 +11,8 @@ export async function demo_02_Track(viewer: Viewer) {
|
|||||||
2 62879 42.9977 257.3937 0001725 269.2925 90.7748 15.77864921 5143`;
|
2 62879 42.9977 257.3937 0001725 269.2925 90.7748 15.77864921 5143`;
|
||||||
|
|
||||||
// 解析TLE数据
|
// 解析TLE数据
|
||||||
const lines = tle.split('\n');
|
const lines = tle.split('\n') as [string, string, string];
|
||||||
const satelliteName = lines[0].trim();
|
const satelliteName = lines[0]?.trim();
|
||||||
const satrec = twoline2satrec(lines[1], lines[2]);
|
const satrec = twoline2satrec(lines[1], lines[2]);
|
||||||
|
|
||||||
// 创建卫星实体
|
// 创建卫星实体
|
||||||
@ -51,7 +51,11 @@ export async function demo_02_Track(viewer: Viewer) {
|
|||||||
const totalSeconds = 60 * 60 * 2; // 2小时的轨迹
|
const totalSeconds = 60 * 60 * 2; // 2小时的轨迹
|
||||||
const timeStepInSeconds = 30; // 每30秒一个点
|
const timeStepInSeconds = 30; // 每30秒一个点
|
||||||
const startTime = Cesium.JulianDate.fromDate(new Date());
|
const startTime = Cesium.JulianDate.fromDate(new Date());
|
||||||
const endTime = Cesium.JulianDate.addSeconds(startTime, totalSeconds, new Cesium.JulianDate());
|
const endTime = Cesium.JulianDate.addSeconds(
|
||||||
|
startTime,
|
||||||
|
totalSeconds,
|
||||||
|
new Cesium.JulianDate(),
|
||||||
|
);
|
||||||
|
|
||||||
// 设置时钟范围
|
// 设置时钟范围
|
||||||
viewer.clock.startTime = startTime.clone();
|
viewer.clock.startTime = startTime.clone();
|
||||||
@ -69,34 +73,35 @@ export async function demo_02_Track(viewer: Viewer) {
|
|||||||
// 用于存储轨道点的数组(用于显示完整轨道)
|
// 用于存储轨道点的数组(用于显示完整轨道)
|
||||||
const orbitPositions: Cesium.Cartesian3[] = [];
|
const orbitPositions: Cesium.Cartesian3[] = [];
|
||||||
|
|
||||||
// 保存卫星高度数据,用于覆盖范围计算
|
|
||||||
let satelliteAltitude = 550000; // 默认高度为550公里
|
|
||||||
|
|
||||||
// 计算轨道上的点
|
// 计算轨道上的点
|
||||||
for (let i = 0; i <= totalSeconds; i += timeStepInSeconds) {
|
for (let i = 0; i <= totalSeconds; i += timeStepInSeconds) {
|
||||||
const time = Cesium.JulianDate.addSeconds(startTime, i, new Cesium.JulianDate());
|
const time = Cesium.JulianDate.addSeconds(
|
||||||
|
startTime,
|
||||||
|
i,
|
||||||
|
new Cesium.JulianDate(),
|
||||||
|
);
|
||||||
const jsDate = Cesium.JulianDate.toDate(time);
|
const jsDate = Cesium.JulianDate.toDate(time);
|
||||||
|
|
||||||
// 计算卫星位置
|
// 计算卫星位置
|
||||||
const positionAndVelocity = propagate(satrec, jsDate);
|
const positionAndVelocity = propagate(satrec, jsDate);
|
||||||
if (typeof positionAndVelocity.position !== 'boolean') {
|
if (typeof positionAndVelocity.position === 'boolean') {
|
||||||
|
console.error('Error calculating satellite position');
|
||||||
|
} else {
|
||||||
const gmst = gstime(jsDate);
|
const gmst = gstime(jsDate);
|
||||||
const position = eciToEcf(positionAndVelocity.position, gmst);
|
const position = eciToEcf(positionAndVelocity.position, gmst);
|
||||||
|
|
||||||
// 转换为Cesium坐标(单位:米)
|
// 转换为Cesium坐标(单位:米)
|
||||||
const cesiumPosition = new Cesium.Cartesian3(position.x * 1000, position.y * 1000, position.z * 1000);
|
const cesiumPosition = new Cesium.Cartesian3(
|
||||||
|
position.x * 1000,
|
||||||
// 计算卫星高度
|
position.y * 1000,
|
||||||
const cartographic = Cesium.Cartographic.fromCartesian(cesiumPosition);
|
position.z * 1000,
|
||||||
satelliteAltitude = cartographic.height;
|
);
|
||||||
|
|
||||||
// 保存位置用于绘制完整轨道
|
// 保存位置用于绘制完整轨道
|
||||||
orbitPositions.push(cesiumPosition);
|
orbitPositions.push(cesiumPosition);
|
||||||
|
|
||||||
// 添加位置样本
|
// 添加位置样本
|
||||||
positionProperty.addSample(time, cesiumPosition);
|
positionProperty.addSample(time, cesiumPosition);
|
||||||
} else {
|
|
||||||
console.error('Error calculating satellite position');
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -108,7 +113,7 @@ export async function demo_02_Track(viewer: Viewer) {
|
|||||||
clampToGround: false,
|
clampToGround: false,
|
||||||
material: new Cesium.PolylineDashMaterialProperty({
|
material: new Cesium.PolylineDashMaterialProperty({
|
||||||
color: Cesium.Color.CYAN,
|
color: Cesium.Color.CYAN,
|
||||||
dashLength: 8.0,
|
dashLength: 8,
|
||||||
}),
|
}),
|
||||||
positions: orbitPositions,
|
positions: orbitPositions,
|
||||||
width: 1,
|
width: 1,
|
||||||
@ -117,100 +122,74 @@ export async function demo_02_Track(viewer: Viewer) {
|
|||||||
|
|
||||||
// 设置卫星的位置
|
// 设置卫星的位置
|
||||||
satelliteEntity.position = positionProperty;
|
satelliteEntity.position = positionProperty;
|
||||||
satelliteEntity.orientation = new Cesium.VelocityOrientationProperty(positionProperty);
|
satelliteEntity.orientation = new Cesium.VelocityOrientationProperty(
|
||||||
|
positionProperty,
|
||||||
|
);
|
||||||
|
|
||||||
// 添加卫星覆盖范围
|
// 添加卫星覆盖范围
|
||||||
// Starlink 卫星通常覆盖范围以锥形方式向地面投射
|
// Starlink 卫星通常覆盖范围以锥形方式向地面投射
|
||||||
// 创建一个椭球体来表示卫星的覆盖范围
|
// 创建一个椭球体来表示卫星的覆盖范围
|
||||||
const coverageAngle = 45; // 覆盖角度(度)
|
const coverageAngle = 45; // 覆盖角度(度)
|
||||||
const _coverageRadius = satelliteAltitude * Math.tan(Cesium.Math.toRadians(coverageAngle));
|
|
||||||
|
|
||||||
// 创建覆盖范围实体
|
// 创建覆盖范围实体
|
||||||
const _coverageEntity = viewer.entities.add({
|
|
||||||
ellipsoid: {
|
|
||||||
material: Cesium.Color.BLUE.withAlpha(0.2),
|
|
||||||
outline: true,
|
|
||||||
outlineColor: Cesium.Color.BLUE.withAlpha(0.8),
|
|
||||||
radii: new Cesium.CallbackProperty(() => {
|
|
||||||
const position = satelliteEntity.position?.getValue(viewer.clock.currentTime);
|
|
||||||
if (!position) return new Cesium.Cartesian3(10000, 10000, 10000);
|
|
||||||
|
|
||||||
// 获取当前卫星高度
|
|
||||||
const cartographic = Cesium.Cartographic.fromCartesian(position);
|
|
||||||
const height = cartographic.height;
|
|
||||||
|
|
||||||
// 计算覆盖范围半径 (基于锥角)
|
|
||||||
const coverageRadius = height * Math.tan(Cesium.Math.toRadians(coverageAngle));
|
|
||||||
|
|
||||||
// 椭球体形状: xy平面为圆形基底,z轴方向为高度
|
|
||||||
return new Cesium.Cartesian3(coverageRadius, coverageRadius, height / 2);
|
|
||||||
}, false),
|
|
||||||
slicePartitions: 24,
|
|
||||||
stackPartitions: 16,
|
|
||||||
},
|
|
||||||
id: 'STARLINK-11371-coverage',
|
|
||||||
name: 'STARLINK-11371 Coverage',
|
|
||||||
orientation: new Cesium.CallbackProperty(() => {
|
|
||||||
// 确保椭球体始终指向地球中心
|
|
||||||
const position = satelliteEntity.position?.getValue(viewer.clock.currentTime);
|
|
||||||
if (!position) return Cesium.Transforms.eastNorthUpToFixedFrame(new Cesium.Cartesian3());
|
|
||||||
|
|
||||||
// 计算从卫星到地球中心的方向
|
|
||||||
const _direction = Cesium.Cartesian3.normalize(
|
|
||||||
Cesium.Cartesian3.negate(position, new Cesium.Cartesian3()),
|
|
||||||
new Cesium.Cartesian3(),
|
|
||||||
);
|
|
||||||
|
|
||||||
return Cesium.Transforms.headingPitchRollQuaternion(position, new Cesium.HeadingPitchRoll(0, Math.PI, 0));
|
|
||||||
}, false),
|
|
||||||
position: positionProperty,
|
|
||||||
});
|
|
||||||
|
|
||||||
// 添加地面覆盖范围投影
|
// 添加地面覆盖范围投影
|
||||||
viewer.entities.add({
|
viewer.entities.add({
|
||||||
ellipse: {
|
ellipse: {
|
||||||
granularity: Cesium.Math.toRadians(1.0),
|
granularity: Cesium.Math.toRadians(1),
|
||||||
height: 0,
|
height: 0,
|
||||||
material: Cesium.Color.BLUE.withAlpha(0.2),
|
material: Cesium.Color.BLUE.withAlpha(0.2),
|
||||||
outline: true,
|
outline: true,
|
||||||
outlineColor: Cesium.Color.BLUE.withAlpha(0.8),
|
outlineColor: Cesium.Color.BLUE.withAlpha(0.8),
|
||||||
outlineWidth: 2,
|
outlineWidth: 2,
|
||||||
semiMajorAxis: new Cesium.CallbackProperty(() => {
|
semiMajorAxis: new Cesium.CallbackProperty(() => {
|
||||||
const satPosition = satelliteEntity.position?.getValue(viewer.clock.currentTime);
|
const satPosition = satelliteEntity.position?.getValue(
|
||||||
if (!satPosition) return 10000;
|
viewer.clock.currentTime,
|
||||||
|
);
|
||||||
|
if (!satPosition) return 10_000;
|
||||||
|
|
||||||
// 计算卫星高度
|
// 计算卫星高度
|
||||||
const cartographic = Cesium.Cartographic.fromCartesian(satPosition);
|
const cartographic = Cesium.Cartographic.fromCartesian(satPosition);
|
||||||
// 根据高度和覆盖角度计算地面覆盖半径
|
// 根据高度和覆盖角度计算地面覆盖半径
|
||||||
return cartographic.height * Math.tan(Cesium.Math.toRadians(coverageAngle));
|
return (
|
||||||
|
cartographic.height * Math.tan(Cesium.Math.toRadians(coverageAngle))
|
||||||
|
);
|
||||||
}, false),
|
}, false),
|
||||||
semiMinorAxis: new Cesium.CallbackProperty(() => {
|
semiMinorAxis: new Cesium.CallbackProperty(() => {
|
||||||
const satPosition = satelliteEntity.position?.getValue(viewer.clock.currentTime);
|
const satPosition = satelliteEntity.position?.getValue(
|
||||||
if (!satPosition) return 10000;
|
viewer.clock.currentTime,
|
||||||
|
);
|
||||||
|
if (!satPosition) return 10_000;
|
||||||
|
|
||||||
// 计算卫星高度
|
// 计算卫星高度
|
||||||
const cartographic = Cesium.Cartographic.fromCartesian(satPosition);
|
const cartographic = Cesium.Cartographic.fromCartesian(satPosition);
|
||||||
// 根据高度和覆盖角度计算地面覆盖半径
|
// 根据高度和覆盖角度计算地面覆盖半径
|
||||||
return cartographic.height * Math.tan(Cesium.Math.toRadians(coverageAngle));
|
return (
|
||||||
|
cartographic.height * Math.tan(Cesium.Math.toRadians(coverageAngle))
|
||||||
|
);
|
||||||
}, false),
|
}, false),
|
||||||
},
|
},
|
||||||
id: 'STARLINK-11371-ground-coverage',
|
id: 'STARLINK-11371-ground-coverage',
|
||||||
name: 'STARLINK-11371 Ground Coverage',
|
name: 'STARLINK-11371 Ground Coverage',
|
||||||
position: new Cesium.CallbackPositionProperty(() => {
|
position: new Cesium.CallbackPositionProperty(() => {
|
||||||
const satPosition = satelliteEntity.position?.getValue(viewer.clock.currentTime);
|
const satPosition = satelliteEntity.position?.getValue(
|
||||||
|
viewer.clock.currentTime,
|
||||||
|
);
|
||||||
if (!satPosition) return new Cesium.Cartesian3();
|
if (!satPosition) return new Cesium.Cartesian3();
|
||||||
|
|
||||||
// 计算卫星在地表的投影点
|
// 计算卫星在地表的投影点
|
||||||
const cartographic = Cesium.Cartographic.fromCartesian(satPosition);
|
const cartographic = Cesium.Cartographic.fromCartesian(satPosition);
|
||||||
return Cesium.Cartesian3.fromRadians(cartographic.longitude, cartographic.latitude, 0);
|
return Cesium.Cartesian3.fromRadians(
|
||||||
|
cartographic.longitude,
|
||||||
|
cartographic.latitude,
|
||||||
|
0,
|
||||||
|
);
|
||||||
}, false),
|
}, false),
|
||||||
});
|
});
|
||||||
|
|
||||||
{
|
|
||||||
// https://github.com/CesiumGS/cesium/issues/8350
|
// https://github.com/CesiumGS/cesium/issues/8350
|
||||||
// 设置相机自动跟踪卫星
|
// 设置相机自动跟踪卫星
|
||||||
viewer.trackedEntity = satelliteEntity;
|
viewer.trackedEntity = satelliteEntity;
|
||||||
}
|
|
||||||
|
|
||||||
// 开始动画
|
// 开始动画
|
||||||
viewer.clock.shouldAnimate = true;
|
viewer.clock.shouldAnimate = true;
|
||||||
|
Reference in New Issue
Block a user