使用TLE计算轨道并使用Cesium绘制
依赖库
- satellite.js
npm install satellite.js
实现思路
- 利用satellite.js获取一个轨道周期内的全部轨迹点坐标
- 使用Cesium的primitive绘制轨迹线
完整代码
import { twoline2satrec, propagate, gstime, eciToEcf } from "satellite.js";const tle1 = `1 00005U 58002B 24282.07474862 .00001783 00000-0 22061-2 0 9998 `
const tle2 = `2 00005 34.2560 58.9866 1843712 236.2153 104.9193 10.85699439376194 `const satrec = twoline2satrec(item.tleLine1, item.tleLine2); /*** 计算卫星每圈所需的时间* * @param {Object} satrec - 卫星轨道数据* @param {number} satrec.no - 卫星每分钟的平均角速度,单位为弧度/分钟* @returns {number} 卫星运行一圈所需的时间,单位为分钟*/
function calCircleBySatrec(satrec) {return (2 * Math.PI) / satrec.no;
}/*** 根据卫星的 TLE 数据和指定时间计算卫星在地心惯性坐标系中的位置。** @param {Object} satrec - 卫星轨道数据对象,包含轨道信息。* @param {number} [time=Date.now()] - 可选参数,计算位置的时间(时间戳,默认为当前时间)。* @param {string} type - 坐标系类型,支持 "ECI"(地心惯性坐标系)和 "ECF"(地心固定坐标系)。* @returns {Cesium.Cartesian3|undefined} - 卫星在指定坐标系中的位置/undefined。*/
function getPositionFromTle(satrec, time = Date.now(), type = "ECI") {const curTimeDate = new Date(time);const { position } = propagate(satrec, curTimeDate) || {};if (!position) return;const conversionFactor = 1000; // 米转换因子if (type === "ECI") {return new Cesium.Cartesian3(position.x * conversionFactor,position.y * conversionFactor,position.z * conversionFactor);}if (type === "ECF") {const gmst = gstime(curTimeDate);const positionEcf = eciToEcf(position, gmst);if (!positionEcf) return;return new Cesium.Cartesian3(positionEcf.x * conversionFactor,positionEcf.y * conversionFactor,positionEcf.z * conversionFactor);}return;
}const timeStamp = Date.now();
const minsPerInterval = calCircleBySatrec(satrec); //轨道周期
const positionsArr = []; // 轨迹点数组for (let i = 0; i <= minsPerInterval; i++) {const curPosition = getPositionFromTle(satrec, timeStamp + i * 60 * 1000);if (curPosition) {positionsArr.push(curPosition);}
}const viewer = new Cesium.Viewer('cesiumContainer', {})const satPolylineCollection = viewer.scene.primitives.add(new Cesium.PolylineCollection());const trackPrimitive = satPolylineCollection.add({id: 1,positions: positionsArr,width: 2,material: Cesium.Material.fromType("Color", {glowPower: 0.1,color: new Cesium.Color(0, 0.9, 0.8, 0.3),// color: new Cesium.Color(...getRandomColor()),}),});