Public
Edited
Nov 1, 2023
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Facts and calculations:
We got the data from Wayfinder.

The dataset are from 4 sources. It has `${wayfinder_data7.length}` objects overall.<br/>
A total of `${active_satellite.length}` active satellites.
A total of `${active_LEO_satellite.length}` active satellites move through low Earth orbit.<br/>
Russia junk pieces count: `${Russia_junk.length}`, count as ${(Russia_junk.length/All_junk_in_LEO.length*100).toFixed(1)} % <br/>
US junk pieces count: `${US_junk.length}`, count as `${(US_junk.length/All_junk_in_LEO.length*100).toFixed(1)}` % <br/>
China junk pieces count: `${China_junk.length}`, count as `${(China_junk.length/All_junk_in_LEO.length*100).toFixed(1)}` % <br/>
All junk in total: `${All_junk_in_LEO.length}`<br/>
Junk from other countries in LEO, `${(100-31.4-25.1-23.4).toFixed(1)}`%

Insert cell
Insert cell
Insert cell
Insert cell
All_junk_in_LEO = data2Parsed.filter(t=> t.status!='Active' ) // US: 25.1% (4148); PRC: 23.4% (3861); CIS: 31.4% (5191)
Insert cell
Russia_junk = data2Parsed.filter(t=> t.status!='Active' && t.country=='CIS' ) // US: 25.1% (4148); PRC: 23.4% (3861); CIS: 31.4% (5191)
Insert cell
US_junk = data2Parsed.filter(t=> t.status!='Active' && t.country=='US' ) // US: 25.1% (4148); PRC: 23.4% (3861); CIS: 31.4% (5191)
Insert cell
China_junk = data2Parsed.filter(t=> t.status!='Active' && t.country=='PRC' ) // US: 25.1% (4148); PRC: 23.4% (3861); CIS: 31.4% (5191)
Insert cell
renderer = {
const renderer = new THREE.WebGLRenderer({antialias: true});
renderer.setPixelRatio(window.devicePixelRatio);
renderer.setSize(width, height);
const controls = new THREE.OrbitControls(camera, renderer.domElement);
controls.minDistance = 15000;
controls.maxDistance = 100000;
controls.enablePan = false;
while (true) {
const ts = particleSystem.geometry.attributes.t.array;
for (var i = 0; i < ts.length; i++) {
ts[i] = ts[i] > 0 && ts[i] < 1 ? ts[i] + 0.01 :
ts[i] >= 1 ? 1 :
0;
}
particleSystem.geometry.attributes.t.needsUpdate = true;
renderer.render(scene, camera);
renderer.domElement.id = 'sceneCanvas'
yield renderer.domElement
}
}
Insert cell
// reset t attribute to 0
function updateArray() {
const a = particleSystem.geometry.attributes.t;
a.array.forEach((el, idx) => {
a.array[idx] = 0;
});
a.needsUpdate = true;
}
Insert cell

// trigger t update based on launch date
function particleAnimation(year) {
document.getElementById('chart-title').innerHTML = `Launches in ${year} by country` //update title
data.forEach((k, idx) => {
if (parseInt(k.launch) <= year && particleSystem.geometry.attributes.t.array[idx] == 0) {
particleSystem.geometry.attributes.t.array[idx] = 0.001;
}
});
particleSystem.geometry.attributes.t.needsUpdate = true;
}
Insert cell
particleSystem = {

const geometry = new THREE.BufferGeometry();
const vertices = [];
const targetVertices = [];
const colors = [];
const sizes = [];
const t = []; // create array for animation values
let color = new THREE.Color(0xffffff);

data2Parsed.forEach((el, idx) => {
vertices.push(0, 0, 0); // all satellites start from 0, 0, 0 for simplicity
targetVertices.push(el.tX, el.tY, el.tZ); // final position as calculated with satellite.js
color = color.setStyle(colorScale(el.type));
colors.push(color.r, color.g, color.b);
sizes.push( el.type==='Satellite'? 3 + Math.random(): 2+2*Math.random());
t.push(1.0); // start with 1.0 so we can see the satellites when the page is loaded, reset to 0 with animate button
});

geometry.addAttribute('position', new THREE.Float32BufferAttribute(vertices, 3));
geometry.addAttribute('targetPosition', new THREE.Float32BufferAttribute(targetVertices, 3));
geometry.addAttribute('color', new THREE.Float32BufferAttribute(colors, 3));
geometry.addAttribute('size', new THREE.Float32BufferAttribute(sizes, 1).setDynamic(true));
geometry.addAttribute('t', new THREE.Float32BufferAttribute(t, 1).setDynamic(true));

const material = new THREE.ShaderMaterial({
vertexShader: vertexShader,
fragmentShader: fragmentShader,
transparent: true,
blending: THREE.NormalBlending,
vertexColors: true
});

const particleSystem = new THREE.Points(geometry, material);
return particleSystem;
}
Insert cell
vertexShader = `
attribute vec3 targetPosition;
attribute float size;
attribute float t;
varying vec3 vColor;

float exponentialInOut(float k) {
if (k <= 0.0) {
return 0.0;
}
else if (k >= 1.0) {
return 1.0;
}
else if ((k *= 2.0) < 1.0) {
return 0.5 * pow(1024.0, k - 1.0);
}
return 0.5 * (-pow(2.0, - 10.0 * (k - 1.0)) + 2.0);
}


void main() {
vColor = color;
vec4 mvPosition = modelViewMatrix * vec4(position, 1.0);
gl_PointSize = size;

float progress = exponentialInOut(t);
vec3 delta = targetPosition - position;
vec3 newPosition = position + delta * progress;

gl_Position = projectionMatrix * modelViewMatrix * vec4(newPosition, 1.0);
}
`;
Insert cell
Insert cell
function createPlanet (r, img) {
const geometry = new THREE.SphereGeometry(r, 70, 70);
const material = new THREE.MeshStandardMaterial({
map: new THREE.TextureLoader().load(img),
roughness: 1,
metalness: 0
});
const mesh = new THREE.Mesh(geometry, material);
return mesh
}
Insert cell
camera = {
const fov = 45;
const aspect = width/height;
const near = 1000;
const far = 200000;
const camera = new THREE.PerspectiveCamera(fov, aspect, near, far);
camera.position.set(0, 50000, 0)
return camera;
}
Insert cell
scene = {
const scene = new THREE.Scene();
scene.background = new THREE.Color('#020202');
const ambientLight = new THREE.AmbientLight('white', 0.25);
const spotLight = new THREE.SpotLight('white');
spotLight.position.set(75000, 75000, 75000);
const earth = createPlanet(6357, "https://i.ibb.co/R7bpCNz/earth-dark.jpg");
earth.position.set(0, 0, 0);
scene.add(earth);
scene.add(ambientLight);
scene.add(spotLight);
scene.add(particleSystem);
return scene
}
Insert cell
colorScale = d3.scaleOrdinal().range(colorList).domain(allTypes);
Insert cell
Insert cell
colorList = ['#91c078', '#d5d5d5', '#b623a1', '#da89ca', '#881b79'];
Insert cell
Insert cell
Insert cell
Insert cell
allTypes = [... new Set( data2Parsed.map(t=> t.type)) ]
Insert cell
countryMap=({})
Insert cell
data2Parsed.map(t=> t.country).forEach( d=> {
if(d!= 'N/A' && d!='' && countryMap[d] ){
countryMap[d]++
} else {
if(d=='N/A' || d=='') return;
countryMap[d]=1
}
})
Insert cell
getAllCountry()
Insert cell
data2Parsed.length
Insert cell
function getAllCountry(){
const countryMap={}
data2Parsed.map(t=> t.country).forEach( d=> {
if(d!= 'N/A' && d!='' && countryMap[d] ){
countryMap[d]++
} else {
if(d=='N/A' || d=='') return;
countryMap[d]=1
}
})
return countryMap
}
Insert cell
allCountries = [... new Set( data2Parsed.map(t=> t.country)) ]
Insert cell
data2Parsed.filter(t=> t.status!='Active' && t.country=='PRC' ) // US: 25.1% (4148); PRC: 23.4% (3861); CIS: 31.4% (5191)
Insert cell
data2Parsed.filter(t=> t.status!='Active' ) // 16511/25323 space junk: 16511
Insert cell
data2Parsed.filter(t=> t.country=='CIS' ) //25323 CIS: 5335; US, PRC:
Insert cell
all_object_by_date = data2Parsed.filter(t=> t.date!='N/A'&& t.date!=''&& t.status!='Active')
Insert cell
all_object_by_date.filter(a=> a.date.indexOf('1959')>-1) // 2018: 319; 2019: 275, 2020: 1026, 2021: 1634
Insert cell
data = d3.csv('https://gist.githubusercontent.com/yarynam/fced8b86b800b2ee1de3352bafbf9458/raw/e07803b2fdf81b7befb82ec1c8d2f2e3a20f71cd/precleaned-sats.csv')
Insert cell
data2Parsed = wayfinder_data7.filter(a=> a.orbit==='LEO')
Insert cell
wayfinder_data7.filter(t=> t.orbit==='LEO')
Insert cell
wayfinder_data7.filter(t=> t.status=='Active')
Insert cell
wayfinder_data7.filter(a=>a.status==='Active'&& a.orbit==='LEO' && a.type=='Satellite') // 8360/9158
Insert cell
wayfinder_data_parsed@2.csv
Type Table, then Shift-Enter. Ctrl-space for more options.

Insert cell
wayfinder_data_parsed3.csv
Type Table, then Shift-Enter. Ctrl-space for more options.

Insert cell
function getCountry(str){
if(str==='CN'){
return
}
}
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