Public
Edited
Jul 14, 2023
Insert cell
md`# 人造卫星可视化效果`
Insert cell
// Project info:
// Original dataset: https://www.ucsusa.org/resources/satellite-database
// Dataset used: https://github.com/abhijeetamle/Satellite-Trajectory-Visualization/blob/main/UCS-Satellite-Database-4-1-2020.xls
// Project repo: https://github.com/abhijeetamle/Satellite-Trajectory-Visualization
// Project website: https://abhijeetamle.github.io/Satellite-Trajectory-Visualization/
Insert cell
html`<select id="orbit_selected_id">
<option value="ALL" selected>Select orbit - All</option>
<option value="LEO">Leo</option>
<option value="GEO">Geo</option>
<option value="MEO">Meo</option>
<option value="Elliptical">Elliptical</option>
</select>`
Insert cell
globe = {

let orbit_selected = document.getElementById("orbit_selected_id").value

let orbit_array_leo = orbit("LEO");
let orbit_array_meo = orbit("MEO");
let orbit_array_geo = orbit("GEO");
let orbit_array_elliptical = orbit("Elliptical");

let canvas = this;
if (!canvas) {
canvas = DOM.context2d(width, width/2).canvas;
}

const context = canvas.getContext("2d");

const path = d3.geoPath()
.context(context);
context.drawImage(naturalEarth, 0, 0, width, width/2);

let earth = this;

if (!earth) {
earth = new THREE.Mesh();
earth.geometry = new THREE.SphereBufferGeometry(1, 40, 40);
earth.rotation.y = Math.PI;
}

let texture = this;

if (!texture) {
const texture = new THREE.CanvasTexture(canvas);
earth.material = new THREE.MeshLambertMaterial({ map: texture });
} else {
texture.needsUpdate = true;
}

const camera = new THREE.PerspectiveCamera(30, 2, 0.1, 60);
camera.position.set(15, 2, 2);

let scene = this;
console.log(scene)
if (!scene) {
scene = new THREE.Scene();
scene.background = new THREE.Color('#000000');
scene.add(earth, light());
}

for (let obt of orbit_array_geo) {
scene.add(obt);
}

for (let obt of orbit_array_leo) {
scene.add(obt);
}

for (let obt of orbit_array_meo) {
scene.add(obt);
}

for (let obt of orbit_array_elliptical) {
scene.add(obt);
}

// -- start of renderer
const renderer = new THREE.WebGLRenderer({antialias: true})

renderer.setSize(width, width / 2);
renderer.setPixelRatio(devicePixelRatio);

invalidation.then(() => renderer.dispose());
// -- end of renderer

// controls
const controls = new THREE.OrbitControls(camera, renderer.domElement);
controls.minDistance = 3;
controls.maxDistance = 40;

const redraw = () => renderer.render(scene(), camera);

controls.addEventListener("change", redraw);

invalidation.then(() => {
controls.removeEventListener("change", redraw);
controls.dispose();
});
// end of controls

// function to change the orbits
d3.select("#orbit_selected_id").on("change", function(d) {
while(scene.children.length > 0){
scene.remove(scene.children[0])
}

const context = canvas.getContext("2d");
const path = d3.geoPath()
.context(context);
context.drawImage(naturalEarth, 0, 0, width, width/2);

scene.add(earth, light());

orbit_selected = document.getElementById("orbit_selected_id").value

if (orbit_selected == "GEO") {
for (let obt of orbit_array_geo) {
scene.add(obt);
}
}
else if (orbit_selected == "LEO") {
for (let obt of orbit_array_leo) {
scene.add(obt);
}
}
else if (orbit_selected == "MEO") {
for (let obt of orbit_array_meo) {
scene.add(obt);
}
}
else if (orbit_selected == "Elliptical") {
for (let obt of orbit_array_elliptical) {
scene.add(obt);
}
}
else {
for (let obt of orbit_array_geo) {
scene.add(obt);
}
for (let obt of orbit_array_leo) {
scene.add(obt);
}
for (let obt of orbit_array_meo) {
scene.add(obt);
}
for (let obt of orbit_array_elliptical) {
scene.add(obt);
}
}

})

let lastUpdated = performance.now();
let count = 3;

while (true) {

let timeScale = 250; // set the speed of Earth rotation
if (count > 0){
console.log("in globe start - 6 time scale 999..")
timeScale = 99999999;
count = count - 1;
}

await Promises.tick(1000 / 60);
const currentTime = performance.now();

const simulatedTimeDelta = (currentTime - lastUpdated) * timeScale / 1000;

// simulate rotation of the Earth
earth.rotation.y += earthAngularVelocity * simulatedTimeDelta;

// rotate satellite
for (let obt of orbit_array_leo) {
obt.rotation.y += obt.satelliteAngularVelocity * simulatedTimeDelta;
}
for (let obt of orbit_array_meo) {
obt.rotation.y += obt.satelliteAngularVelocity * simulatedTimeDelta;
}
for (let obt of orbit_array_geo) {
obt.rotation.y += obt.satelliteAngularVelocity * simulatedTimeDelta;
}
for (let obt of orbit_array_elliptical) {
obt.rotation.y += obt.satelliteAngularVelocity * simulatedTimeDelta;
}

lastUpdated = currentTime;

renderer.render(scene, camera);
yield renderer.domElement;
}
}
Insert cell
function orbit(selected_orbit) {
let orbit_array = [];
for (let row of dataset) {
let orbit_type = row["Class of Orbit"];
if (selected_orbit != 'ALL' && orbit_type != selected_orbit){
continue;
}

let orbit = this;
orbit = new THREE.Group();
// ----- Set variables ---------------------

let satelliteInclination = +row["Inclination (degrees)"];
orbit.satelliteInclination = satelliteInclination;
let satelliteAltitude = +row["Apogee (km)"] * 1000;
orbit.satelliteAltitude = satelliteAltitude;
let satelliteVelocity = Math.sqrt(G * earthMass / (earthRadius + satelliteAltitude)); // meters per second
let satelliteAngularVelocity = satelliteVelocity / (earthRadius + satelliteAltitude); // radians per second
orbit.satelliteAngularVelocity = satelliteAngularVelocity;
let orbitRadiusInEarthRadii = (earthRadius + satelliteAltitude) / earthRadius;
orbit.orbitRadiusInEarthRadii = orbitRadiusInEarthRadii;

// ----- Track -------------------------------------

let track = this;
track = new THREE.Line();

track.geometry = new THREE.CircleGeometry(1, 80);
track.geometry.vertices.shift();
track.geometry.vertices.push(track.geometry.vertices[0]);
track.geometry.rotateX(Math.PI / 2); // rotate geometry so default is equatorial orbit
if (orbit_type == "GEO") {
track.material = new THREE.LineBasicMaterial({ color: 0xf2d96b }); // yellow ffd000
}
else if (orbit_type == "LEO") {
track.material = new THREE.LineBasicMaterial({ color: 0x7ee695 }); // green 05612a
}
else if (orbit_type == "MEO") {
track.material = new THREE.LineBasicMaterial({ color: 0x8490e8 }); // blue 72afed
//track.material = new THREE.LineBasicMaterial({ color: 0xf2d96b }); // yellow ffd000
//track.material = new THREE.LineBasicMaterial({ color: 0xe86868 }); // red ff0000
}
else {
track.material = new THREE.LineBasicMaterial({ color: 0xed7be0 }); // pink ff00e1
}
// Geo - Yellow
// Leo - Green
// Meo - Blue
// Elliptical - Pink

track.scale.setScalar(orbitRadiusInEarthRadii);

// ------ Satellite ---------------------------------------

var dotGeometry = new THREE.Geometry();
dotGeometry.vertices.push(new THREE.Vector3( 0, 0, 0));
if (orbit_type == "GEO") {
//var dotMaterial = new THREE.PointsMaterial( { size: 4, sizeAttenuation: false, color: 0xff0000 } ); // Red
var dotMaterial = new THREE.PointsMaterial( { size: 4, sizeAttenuation: false, color: 0xffd000 } ); // Yellow
}
else if (orbit_type == "LEO") {
var dotMaterial = new THREE.PointsMaterial( { size: 4, sizeAttenuation: false, color: 0x05612a } ); // Green
}
else if (orbit_type == "MEO") {
var dotMaterial = new THREE.PointsMaterial( { size: 4, sizeAttenuation: false, color: 0x72afed } ); // Blue
//var dotMaterial = new THREE.PointsMaterial( { size: 4, sizeAttenuation: false, color: 0xffd000 } ); // Yellow
//var dotMaterial = new THREE.PointsMaterial( { size: 4, sizeAttenuation: false, color: 0xff0000 } ); // Red
}
else {
var dotMaterial = new THREE.PointsMaterial( { size: 4, sizeAttenuation: false, color: 0xff00e1 } ); // Pink
}
var satellite = new THREE.Points( dotGeometry, dotMaterial );

// satellite.scale.setScalar(1.20);
satellite.position.x = orbitRadiusInEarthRadii;

// --------Add track and satellite to orbit -------------------------------------

orbit.add(track, satellite);
orbit.rotation.x = satelliteInclination * Math.PI / 180;

orbit_array.push(orbit);
}
return orbit_array;
}
Insert cell
function light() {
const light = new THREE.Group();
const ambient = new THREE.AmbientLight("#888")
const directional = new THREE.DirectionalLight("#aaa")
directional.position.x = 10;
light.add(ambient, directional)
return light;
}
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
naturalEarth = d3.image(
"https://gist.githubusercontent.com/jake-low/d519e00853b15e9cec391c3dab58e77f/raw/6e796038e4f34524059997f8e1f1c42ea289d805/ne1-small.png",
{crossOrigin: "anonymous"})
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell

Purpose-built for displays of data

Observable is your go-to platform for exploring data and creating expressive data visualizations. Use reactive JavaScript notebooks for prototyping and a collaborative canvas for visual data exploration and dashboard creation.
Learn more