mirror of
https://github.com/jiangteng2019/satellite-track.git
synced 2025-06-16 14:58:19 +00:00
'增加卫星星座选择'
This commit is contained in:
parent
ed84dc1f95
commit
2d7b7d3cae
31
README.md
31
README.md
@ -1,9 +1,30 @@
|
||||
# satellite-track
|
||||
|
||||
satellite-track使用TLE数据追踪卫星,使用cesium、vue、satelliteJS开发。
|
||||
**README.en.md**
|
||||
|
||||
## [预览](https://jiangteng2019.github.io/satellite-track/)
|
||||
### satellite-track uses TLE data to track satellites and is developed using cesium, vue and satelliteJS.
|
||||
|
||||
###说明
|
||||
1、为了节约性能,卫星轨道数据选择显示,而不全量显示;
|
||||
2、数据来源于celestrak
|
||||
### [preview](https://jiangteng2019.github.io/satellite-track/)
|
||||
|
||||
|
||||
1. In order to save performance, the satellite orbit data is displayed by clicking.
|
||||
1. Data from celestrak.
|
||||
1. The access speed of github pages is slow, and the TLE data and cesium data are large. Please wait patiently for the resources to load.
|
||||
|
||||
-------------------------------------------
|
||||
|
||||
**README.md**
|
||||
|
||||
### satellite-track使用TLE数据追踪卫星,使用cesium、vue、satelliteJS开发。
|
||||
|
||||
### [预览](https://jiangteng2019.github.io/satellite-track/)
|
||||
|
||||
|
||||
1. 为了节约性能,卫星轨道数据点击显示,而非全量显示;
|
||||
1. 数据来源于celestrak;
|
||||
1. github pages 访问速度慢,TLE数据与cesium数据较大,请耐心等待资源加载;
|
||||
|
||||
|
||||
[](https://images.cnblogs.com/cnblogs_com/engeng/2270012/o_230203011203_1.jpg "satellite-track")
|
||||
|
||||
[](https://images.cnblogs.com/cnblogs_com/engeng/2270012/o_230203011139_2.jpg "satellite-track")
|
@ -1,21 +1,21 @@
|
||||
import axios from "axios";
|
||||
|
||||
const BASE_URL = "https://celestrak.org"
|
||||
const BASE_URL = "https://celestrak.org";
|
||||
|
||||
function getTleData(path = "") {
|
||||
let uri = BASE_URL + path;
|
||||
function getTleDataFromExternal(path = "") {
|
||||
let uri = `${BASE_URL}/NORAD/elements/gp.php?GROUP=${path}&FORMAT=tle`;
|
||||
return axios.get(uri).then(res => {
|
||||
res.status === 200 ? ElMessage.success('获取TLE成功') : ElMessage.error('获取TLE失败');
|
||||
return res.status === 200 ? Promise.resolve(res.data) : Promise.reject(res.statusText);
|
||||
if (res.status === 200) {
|
||||
ElMessage.success('获取TLE成功');
|
||||
localStorage.setItem(path, res.data); // 缓存TLE数据,减轻数据服务压力
|
||||
return Promise.resolve(res.data);
|
||||
} else {
|
||||
ElMessage.error('获取TLE失败');
|
||||
return Promise.reject(res.statusText);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* @description 获取最近30天的发射卫星的TLE数据
|
||||
* @returns Promise
|
||||
*/
|
||||
function getTleWithLastThirtyDays(path = "/NORAD/elements/gp.php?GROUP=last-30-days&FORMAT=tle") {
|
||||
return getTleData(path);
|
||||
}
|
||||
|
||||
export { getTleWithLastThirtyDays };
|
||||
|
||||
export { getTleDataFromExternal };
|
@ -12,7 +12,7 @@ class SatelliteEntity {
|
||||
this.tleLine2 = tleLine2.trim();
|
||||
this.satrec = twoline2satrec(this.tleLine1, this.tleLine2);
|
||||
|
||||
this.totalSeconds = 864000;// 864000
|
||||
this.totalSeconds = 86400;// 24小时
|
||||
this.stepSeconds = 100;
|
||||
this.leadTime = parseInt(24 * 3600 / circle);
|
||||
this.trailTime = 0;
|
||||
@ -56,7 +56,7 @@ class SatelliteEntity {
|
||||
description: this.name,
|
||||
availability: new Cesium.TimeIntervalCollection([new Cesium.TimeInterval({ start: start, stop: stop })]),
|
||||
position: this._getPositionProperty(),
|
||||
point: { pixelSize: 10, color: Cesium.Color.fromRandom({ alpha: 1.0 }) },
|
||||
point: { pixelSize: 8, color: Cesium.Color.fromRandom({ alpha: 1.0 }) },
|
||||
path: new Cesium.PathGraphics({
|
||||
width: 1,
|
||||
show: false,
|
||||
@ -67,7 +67,6 @@ class SatelliteEntity {
|
||||
label: {
|
||||
text: this.name,
|
||||
font: '12px sans-serif',
|
||||
scale: 0.8,
|
||||
showBackground: true,
|
||||
backgroundColor: new Cesium.Color(0.165, 0.165, 0.165, 0.5),
|
||||
backgroundPadding: new Cesium.Cartesian2(4, 4),
|
||||
|
@ -28,6 +28,7 @@
|
||||
fill: #edffff;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.menu_button:hover {
|
||||
color: #fff;
|
||||
fill: #fff;
|
||||
@ -40,11 +41,37 @@
|
||||
.el-drawer {
|
||||
background-color: rgba($color: #303336, $alpha: 0.9);
|
||||
color: #fff;
|
||||
|
||||
.satellite_type {
|
||||
color: #95D475;
|
||||
font-weight: bold;
|
||||
font-size: 14px;
|
||||
padding: 10px;
|
||||
padding-left: 0;
|
||||
}
|
||||
|
||||
.el-drawer__header {
|
||||
background-color: #303336;
|
||||
color: inherit;
|
||||
margin: 0
|
||||
}
|
||||
|
||||
.el-checkbox {
|
||||
color: inherit;
|
||||
}
|
||||
}
|
||||
|
||||
::-webkit-scrollbar {
|
||||
width: 6px;
|
||||
height: 6px;
|
||||
}
|
||||
|
||||
::-webkit-scrollbar-track {
|
||||
border-radius: 10px;
|
||||
}
|
||||
|
||||
::-webkit-scrollbar-thumb {
|
||||
background-color: #ccc;
|
||||
border-radius: 10px;
|
||||
transition: all .2s ease-in-out;
|
||||
}
|
@ -7,18 +7,11 @@
|
||||
</div>
|
||||
<!-- 抽屉 -->
|
||||
<el-drawer v-model="drawer" title="卫星选择" direction="ltr">
|
||||
<el-row>
|
||||
卫星
|
||||
</el-row>
|
||||
<el-checkbox-group v-model="checked" @change="handleSpacialInterestChange">
|
||||
<el-checkbox v-for="(item, index) in options" :label="item.value">{{ item.label }}</el-checkbox>
|
||||
</el-checkbox-group>
|
||||
|
||||
<el-row>
|
||||
气象和地球资源卫星
|
||||
</el-row>
|
||||
<el-checkbox-group v-model="checked" @change="handleWeatherSatelliteChange">
|
||||
<el-checkbox v-for="(item, index) in weatherSatellite" :label="item.value">{{ item.label }}</el-checkbox>
|
||||
<el-checkbox-group v-model="checked" @change="handleSatelliteChange" :max=5>
|
||||
<template v-for="(item, index) in allSatellite" :key="index">
|
||||
<el-row v-if="item.type === 'title'" class="satellite_type">{{ item.label }}</el-row>
|
||||
<el-checkbox v-if="!item.type" :label="item.value">{{ item.label }}</el-checkbox>
|
||||
</template>
|
||||
</el-checkbox-group>
|
||||
</el-drawer>
|
||||
</template>
|
||||
@ -29,97 +22,33 @@
|
||||
import * as Cesium from 'cesium';
|
||||
import "cesium/Build/Cesium/Widgets/widgets.css";
|
||||
|
||||
import { onMounted, onBeforeMount, ref } from 'vue';
|
||||
import { onMounted, ref, watch } from 'vue';
|
||||
|
||||
import "./SatelliteTrack.scss"
|
||||
|
||||
import { getTleWithLastThirtyDays } from '@/http/index'
|
||||
import { getTleDataFromExternal } from '@/http/index'
|
||||
|
||||
import SatelliteEntity from '@/js/SatelliteEntity';
|
||||
|
||||
import { specialSatellite, weatherSatellite, communicationSatellite, navigationSatellite, scientificSatellite, miscellaneousSatellite } from "./satelliteType"
|
||||
import { add } from 'lodash';
|
||||
|
||||
let allSatellite = [...specialSatellite, ...weatherSatellite, ...communicationSatellite, ...navigationSatellite, ...scientificSatellite, ...miscellaneousSatellite];
|
||||
|
||||
|
||||
window.CESIUM_BASE_URL = import.meta.env.MODE === 'development' ? '/cesium' : '/satellite-track/cesium';
|
||||
|
||||
let viewer;
|
||||
const totalSeconds = 864000;
|
||||
const totalSeconds = 86400;
|
||||
// 保存所有的卫星实例
|
||||
const satelliteMap = new Map();
|
||||
|
||||
// 响应式数据
|
||||
const drawer = ref(false);
|
||||
const checked = ref([]);
|
||||
const options = ref([
|
||||
{
|
||||
label: "Last 30 Days' Launches",
|
||||
value: 1
|
||||
},
|
||||
{
|
||||
label: 'Space Stations',
|
||||
value: 2
|
||||
},
|
||||
{
|
||||
label: '100 (or so) Brightest',
|
||||
value: 3
|
||||
},
|
||||
{
|
||||
label: 'Active Satellites',
|
||||
value: 4
|
||||
},
|
||||
{
|
||||
label: 'Analyst Satellites ',
|
||||
value: 5
|
||||
},
|
||||
{
|
||||
label: 'IRIDIUM 33 Debris',
|
||||
value: 6
|
||||
},
|
||||
{
|
||||
label: 'COSMOS 2251 Debris',
|
||||
value: 7
|
||||
}
|
||||
])
|
||||
|
||||
const weatherSatellite = ref([
|
||||
{
|
||||
label: 'Weather',
|
||||
value: 1
|
||||
},
|
||||
{
|
||||
label: 'NOAA',
|
||||
value: 2
|
||||
},
|
||||
{
|
||||
label: 'GOES',
|
||||
value: 3
|
||||
},
|
||||
{
|
||||
label: 'Earth Resources',
|
||||
value: 4
|
||||
},
|
||||
{
|
||||
label: 'Search & Rescue (SARSAT) ',
|
||||
value: 5
|
||||
},
|
||||
{
|
||||
label: 'Disaster Monitoring',
|
||||
value: 6
|
||||
},
|
||||
{
|
||||
label: 'TDRSS',
|
||||
value: 7
|
||||
},
|
||||
{
|
||||
label: 'ARGOS Data Collection System',
|
||||
value: 8
|
||||
},
|
||||
{
|
||||
label: 'Planet',
|
||||
value: 9
|
||||
},
|
||||
{
|
||||
label: 'Spire',
|
||||
value: 10
|
||||
}
|
||||
])
|
||||
const checked = ref([]);
|
||||
|
||||
const clickedSatelliteArray = [];
|
||||
|
||||
|
||||
Cesium.Ion.defaultAccessToken = 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJqdGkiOiJiYjZmMWM4Ny01YzQ4LTQ3MzUtYTI5Mi1hNTgyNjdhMmFiMmMiLCJpZCI6NjIwMjgsImlhdCI6MTYyNjY3MTMxNX0.5SelYUyzXWRoMyjjFvmFIAoPtWlJPQMjsVl2e_jQe-c';
|
||||
@ -194,48 +123,92 @@ function parseTle(data = "") {
|
||||
}
|
||||
|
||||
function addCesiumEventListener() {
|
||||
let callback = viewer.screenSpaceEventHandler.getInputAction(Cesium.ScreenSpaceEventType.LEFT_CLICK);// 还原点击聚焦方块的效果。
|
||||
let callback = viewer.screenSpaceEventHandler.getInputAction(Cesium.ScreenSpaceEventType.LEFT_CLICK);
|
||||
viewer.screenSpaceEventHandler.setInputAction(function onLeftClick(movement) {
|
||||
callback(movement);
|
||||
const pickedFeature = viewer.scene.pick(movement.position);
|
||||
console.log(pickedFeature);
|
||||
if (!Cesium.defined(pickedFeature)) {
|
||||
satelliteMap.forEach(item => {
|
||||
item.path.show = false;
|
||||
clickedSatelliteArray.forEach(item => {
|
||||
item.id.path.show = false;
|
||||
})
|
||||
return;
|
||||
}
|
||||
if (pickedFeature) {
|
||||
pickedFeature.id.path.show = new Cesium.ConstantProperty(true);
|
||||
pickedFeature.id.label.distanceDisplayCondition = undefined;
|
||||
clickedSatelliteArray.push(pickedFeature);
|
||||
}
|
||||
|
||||
}, Cesium.ScreenSpaceEventType.LEFT_CLICK);
|
||||
}
|
||||
|
||||
// 事件
|
||||
function handleSpacialInterestChange(e) {
|
||||
console.log(e);
|
||||
function handleSatelliteChange(e) {
|
||||
|
||||
}
|
||||
|
||||
function handleWeatherSatelliteChange(e) {
|
||||
console.log(e);
|
||||
|
||||
// 获取tle数据,从缓存中获取,若无请求数据
|
||||
|
||||
async function getTleData(path) {
|
||||
let data = localStorage.getItem(path);
|
||||
if (data) {
|
||||
console.log(`%c 命中缓存,key值为${path}`, 'color:#0f0;');
|
||||
return data;
|
||||
} else {
|
||||
console.warn("未命中缓存,开始下载TLE数据");
|
||||
return await getTleDataFromExternal(path);
|
||||
}
|
||||
}
|
||||
|
||||
// 创建satellite entity 实例
|
||||
async function addSatellite(path) {
|
||||
// 判断map中是否已经包含对应的路径实例
|
||||
if (satelliteMap.has(path)) {
|
||||
let satelliteList = satelliteMap.get(path);
|
||||
satelliteList.forEach(item => viewer.entities.add(item));
|
||||
} else {
|
||||
let result = await getTleData(path);
|
||||
let parsedResult = parseTle(result);
|
||||
let satelliteSet = new Set();
|
||||
|
||||
parsedResult.forEach(tle => {
|
||||
let satellite = new SatelliteEntity(tle);
|
||||
let cesiumSateEntity = satellite.createSatelliteEntity();
|
||||
let result = viewer.entities.add(cesiumSateEntity);
|
||||
satelliteSet.add(result);
|
||||
});
|
||||
satelliteMap.set(path, satelliteSet);
|
||||
}
|
||||
}
|
||||
|
||||
function removeSatellite(path) {
|
||||
if (satelliteMap.has(path)) {
|
||||
let satelliteList = satelliteMap.get(path);
|
||||
satelliteList.forEach(item => viewer.entities.remove(item));
|
||||
}
|
||||
}
|
||||
|
||||
// 侦听器
|
||||
watch(checked, (newValue, oldValue) => {
|
||||
let filterValue = newValue.concat(oldValue).filter((item, index, arr) => arr.indexOf(item) === arr.lastIndexOf(item));
|
||||
let satelliteClassify = allSatellite.find(item => item.value === filterValue[0]);
|
||||
// 勾选了卫星
|
||||
if (newValue.length > oldValue.length) {
|
||||
addSatellite(satelliteClassify.group);
|
||||
} else {
|
||||
//取消了勾选
|
||||
removeSatellite(satelliteClassify.group);
|
||||
}
|
||||
})
|
||||
|
||||
|
||||
// 生命周期
|
||||
onMounted(async () => {
|
||||
initCesium();
|
||||
initTimeLine();
|
||||
addCesiumEventListener();
|
||||
|
||||
let result = await getTleWithLastThirtyDays();
|
||||
let parsedResult = parseTle(result);
|
||||
|
||||
parsedResult.forEach(tle => {
|
||||
let satellite = new SatelliteEntity(tle);
|
||||
let cesiumSateEntity = satellite.createSatelliteEntity();
|
||||
let result = viewer.entities.add(cesiumSateEntity);
|
||||
satelliteMap.set(satellite.name, result);
|
||||
});
|
||||
})
|
||||
|
||||
|
||||
|
306
src/views/satellite-track/satelliteType.js
Normal file
306
src/views/satellite-track/satelliteType.js
Normal file
@ -0,0 +1,306 @@
|
||||
let specialSatellite = [
|
||||
{
|
||||
label: "特殊卫星",
|
||||
value: null,
|
||||
group: null,
|
||||
type: "title"
|
||||
},
|
||||
{
|
||||
label: "Last 30 Days' Launches",
|
||||
value: 1,
|
||||
group: 'last-30-days'
|
||||
},
|
||||
{
|
||||
label: 'Space Stations',
|
||||
value: 2,
|
||||
group: 'stations'
|
||||
},
|
||||
{
|
||||
label: '100 (or so) Brightest',
|
||||
value: 3,
|
||||
group: 'visual'
|
||||
},
|
||||
{
|
||||
label: 'Active Satellites',
|
||||
value: 4,
|
||||
group: 'active'
|
||||
},
|
||||
{
|
||||
label: 'Analyst Satellites ',
|
||||
value: 5,
|
||||
group: 'analyst'
|
||||
}
|
||||
];
|
||||
|
||||
let weatherSatellite = [
|
||||
{
|
||||
label: "气象和地球资源卫星",
|
||||
value: null,
|
||||
group: null,
|
||||
type: "title"
|
||||
},
|
||||
{
|
||||
label: 'Weather',
|
||||
value: 6,
|
||||
group: 'weather'
|
||||
},
|
||||
{
|
||||
label: 'NOAA',
|
||||
value: 7,
|
||||
group: 'noaa'
|
||||
},
|
||||
{
|
||||
label: 'GOES',
|
||||
value: 8,
|
||||
group: 'goes'
|
||||
},
|
||||
{
|
||||
label: 'Earth Resources',
|
||||
value: 9,
|
||||
group: 'resource'
|
||||
},
|
||||
{
|
||||
label: 'Search & Rescue (SARSAT) ',
|
||||
value: 10,
|
||||
group: 'sarsat'
|
||||
},
|
||||
{
|
||||
label: 'Disaster Monitoring',
|
||||
value: 11,
|
||||
group: 'dmc'
|
||||
},
|
||||
{
|
||||
label: 'TDRSS',
|
||||
value: 12,
|
||||
group: 'tdrss'
|
||||
},
|
||||
{
|
||||
label: 'ARGOS Data Collection System',
|
||||
value: 13,
|
||||
group: 'argos'
|
||||
},
|
||||
{
|
||||
label: 'Planet',
|
||||
value: 14,
|
||||
group: 'planet'
|
||||
},
|
||||
{
|
||||
label: 'Spire',
|
||||
value: 15,
|
||||
group: 'spire'
|
||||
}
|
||||
];
|
||||
|
||||
let communicationSatellite = [
|
||||
{
|
||||
label: "通讯卫星",
|
||||
value: null,
|
||||
group: null,
|
||||
type: "title"
|
||||
},
|
||||
{
|
||||
label: 'Active Geosynchronous',
|
||||
value: 16,
|
||||
group: 'geo'
|
||||
},
|
||||
{
|
||||
label: 'GEO Protected Zone',
|
||||
value: 17,
|
||||
group: 'gpz'
|
||||
},
|
||||
{
|
||||
label: 'GEO Protected Zone Plus',
|
||||
value: 18,
|
||||
group: 'gpz-plus'
|
||||
},
|
||||
{
|
||||
label: 'Intelsat',
|
||||
value: 19,
|
||||
group: 'intelsat'
|
||||
},
|
||||
{
|
||||
label: 'SES',
|
||||
value: 20,
|
||||
group: 'ses'
|
||||
},
|
||||
{
|
||||
label: 'Iridium',
|
||||
value: 21,
|
||||
group: 'iridium'
|
||||
},
|
||||
{
|
||||
label: 'Iridium NEXT',
|
||||
value: 22,
|
||||
group: 'iridium-NEXT'
|
||||
},
|
||||
{
|
||||
label: 'Starlink',
|
||||
value: 23,
|
||||
group: 'starlink'
|
||||
},
|
||||
{
|
||||
label: 'OneWeb',
|
||||
value: 24,
|
||||
group: 'oneweb'
|
||||
},
|
||||
{
|
||||
label: 'Orbcomm',
|
||||
value: 25,
|
||||
group: 'orbcomm'
|
||||
},
|
||||
{
|
||||
label: 'Globalstar',
|
||||
value: 26,
|
||||
group: 'globalstar'
|
||||
},
|
||||
{
|
||||
label: 'Swarm',
|
||||
value: 27,
|
||||
group: 'swarm'
|
||||
},
|
||||
{
|
||||
label: 'Amateur Radio',
|
||||
value: 28,
|
||||
group: 'amateur'
|
||||
},
|
||||
{
|
||||
label: 'Experimental Comm',
|
||||
value: 29,
|
||||
group: 'x-comm'
|
||||
},
|
||||
{
|
||||
label: 'Other Comm',
|
||||
value: 30,
|
||||
group: 'other-comm'
|
||||
},
|
||||
{
|
||||
label: 'SatNOGS',
|
||||
value: 31,
|
||||
group: 'satnogs'
|
||||
},
|
||||
{
|
||||
label: 'Gorizont',
|
||||
value: 32,
|
||||
group: 'gorizont'
|
||||
},
|
||||
{
|
||||
label: 'Raduga',
|
||||
value: 33,
|
||||
group: 'raduga'
|
||||
},
|
||||
{
|
||||
label: 'Molniya',
|
||||
value: 34,
|
||||
group: 'molniya'
|
||||
},
|
||||
];
|
||||
|
||||
let navigationSatellite = [
|
||||
{
|
||||
label: "导航卫星",
|
||||
value: null,
|
||||
group: null,
|
||||
type: "title"
|
||||
},
|
||||
{
|
||||
label: 'GNSS',
|
||||
value: 35,
|
||||
group: 'gnss'
|
||||
},
|
||||
{
|
||||
label: 'GPS Operational',
|
||||
value: 36,
|
||||
group: 'gps-ops'
|
||||
},
|
||||
{
|
||||
label: 'GLONASS Operational',
|
||||
value: 37,
|
||||
group: 'glo-ops'
|
||||
},
|
||||
{
|
||||
label: 'Galileo',
|
||||
value: 38,
|
||||
group: 'galileo'
|
||||
},
|
||||
{
|
||||
label: 'Beidou',
|
||||
value: 39,
|
||||
group: 'beidou'
|
||||
},
|
||||
{
|
||||
label: 'Satellite-Based Augmentation System',
|
||||
value: 40,
|
||||
group: 'sbas'
|
||||
},
|
||||
{
|
||||
label: 'Navy Navigation Satellite System (NNSS)',
|
||||
value: 41,
|
||||
group: 'nnss'
|
||||
},
|
||||
{
|
||||
label: 'Russian LEO Navigation',
|
||||
value: 42,
|
||||
group: 'musson'
|
||||
},
|
||||
];
|
||||
|
||||
let scientificSatellite = [
|
||||
{
|
||||
label: "科学卫星",
|
||||
value: null,
|
||||
group: null,
|
||||
type: "title"
|
||||
},
|
||||
{
|
||||
label: 'Space & Earth Science',
|
||||
value: 43,
|
||||
group: 'science'
|
||||
},
|
||||
{
|
||||
label: 'Geodetic',
|
||||
value: 44,
|
||||
group: 'geodetic'
|
||||
},
|
||||
{
|
||||
label: 'Engineering',
|
||||
value: 45,
|
||||
group: 'engineering'
|
||||
},
|
||||
{
|
||||
label: 'Education',
|
||||
value: 46,
|
||||
group: 'education'
|
||||
}
|
||||
];
|
||||
|
||||
let miscellaneousSatellite = [
|
||||
{
|
||||
label: "其他卫星",
|
||||
value: null,
|
||||
group: null,
|
||||
type: "title"
|
||||
},
|
||||
{
|
||||
label: 'Miscellaneous Military',
|
||||
value: 47,
|
||||
group: 'military'
|
||||
},
|
||||
{
|
||||
label: 'Radar Calibration',
|
||||
value: 48,
|
||||
group: 'radar'
|
||||
},
|
||||
{
|
||||
label: 'CubeSats',
|
||||
value: 49,
|
||||
group: 'cubesat'
|
||||
},
|
||||
{
|
||||
label: 'Other Satellites',
|
||||
value: 50,
|
||||
group: 'other'
|
||||
}
|
||||
]
|
||||
|
||||
export { specialSatellite, weatherSatellite, communicationSatellite, navigationSatellite, scientificSatellite, miscellaneousSatellite };
|
||||
|
Loading…
Reference in New Issue
Block a user