This commit is contained in:
John Doe 2021-04-29 00:05:01 -04:00
commit 8f98aa225e
7 changed files with 669 additions and 0 deletions

138
geolocation/index.html Normal file
View file

@ -0,0 +1,138 @@
<html>
<head>
<title>Map Demo</title>
<link rel="stylesheet" href="https://unpkg.com/leaflet@1.7.1/dist/leaflet.css" integrity="sha512-xodZBNTC5n17Xt2atTPuE1HxjVMSvLVW9ocqUKLsCC5CXdbqCmblAshOMAS6/keqq/sMZMZ19scR4PsZChSR7A==" crossorigin=""/>
<script src="https://unpkg.com/leaflet@1.7.1/dist/leaflet.js" integrity="sha512-XQoYMqMTK8LvdxXYG3nZ448hOEQiglfqkJs1NOQV44cWnUrBc8PkAOcXy20w0vlaXaVUearIOBhiXZ5V3ynxwA==" crossorigin=""></script>
<style>
*{
font-family: Arial, Helvetica, sans-serif;
}
body{
margin: 0px;
}
.header{
font-weight: bold;
font-size: 2.0em;
}
#mapid {
width: 600px;
float: left;
height: 600px;
}
#controls {
padding-left: 10px;
display: flex;
align-items: center;
height: 600px;
width: 600px;
}
</style>
</head>
<body>
<div id="visualize_geolocation">
<div id="mapid"></div>
<div id="controls">
<div>
<span class="header">Visualizing Geolocation</span><br>
<p>
Most people are at least somewhat familiar with the notion of geolocation of users by communications networks.
However, this can be hard to visualize, and the differences between the geolocation capabilities of various types of network
(which are often quite substantial) are often ignored.
</p>
<p>
This tool allows you to visualize the accuracy with which a user's location can be determined (shown as a red circle), using
a map of real-world cities for scale. We hope this makes clear why we believe FemtoStar's geolocation-resistance to be so important.
</p>
<b>Pick a city</b><br>
<input type="radio" id="button_nyc" name="city" onclick="setCity('nyc');" checked>
<label for="button_nyc">New York City, USA</label><br>
<input type="radio" id="button_rio" name="city" onclick="setCity('rio');">
<label for="button_rio">Rio de Janeiro, Brazil</label><br>
<input type="radio" id="button_berlin" name="city" onclick="setCity('berlin');">
<label for="button_berlin">Berlin, Germany</label><br>
<input type="radio" id="button_capetown" name="city" onclick="setCity('capetown');">
<label for="button_capetown">Cape Town, South Africa</label><br>
<input type="radio" id="button_tokyo" name="city" onclick="setCity('tokyo');">
<label for="button_tokyo">Tokyo, Japan</label><br>
<input type="radio" id="button_sydney" name="city" onclick="setCity('sydney');">
<label for="button_sydney">Sydney, Australia</label>
<br><br>
<b>Pick a network type</b><br>
<input type="radio" id="button_gps" name="network" onclick="setNetwork('gps');">
<label for="button_gps">Network with GPS reporting (incl. most geostationary satellite networks)</label><br>
<input type="radio" id="button_cellular_urban" name="network" onclick="setNetwork('cellular_urban');" checked>
<label for="button_cellular_urban">Cellular network (urban area, no GPS reporting)</label><br>
<input type="radio" id="button_cellular_rural" name="network" onclick="setNetwork('cellular_rural');">
<label for="button_cellular_rural">Cellular network (rural area, no GPS reporting)</label><br>
<input type="radio" id="button_satellite" name="network" onclick="setNetwork('satellite');">
<label for="button_satellite">Traditional satellite network (non-geostationary orbit, no GPS reporting)</label><br>
<input type="radio" id="button_femtostar" name="network" onclick="setNetwork('femtostar');">
<label for="button_femtostar">FemtoStar</label>
</div>
</div>
</div>
<script>
/* Tileservers that work well:
https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png
http://server.arcgisonline.com/ArcGIS/rest/services/World_Imagery/MapServer/tile/{z}/{y}/{x}
*/
var tileserver = "https://server.arcgisonline.com/ArcGIS/rest/services/World_Imagery/MapServer/tile/{z}/{y}/{x}";
var set_city = "nyc";
var set_network = "cellular_urban";
let cities = {
"nyc": [40.758896, -73.985130],
"rio": [-22.91141, -43.16921],
"berlin": [52.51938, 13.40884],
"capetown": [-33.91496, 18.42453],
"tokyo": [35.67671, 139.75294],
"sydney": [-33.85907, 151.20810]
}
let networks = {
"gps": {"accuracy": 5, "zoom": 18},
"cellular_urban": {"accuracy": 60, "zoom": 17},
"cellular_rural": {"accuracy": 400, "zoom": 14},
"satellite": {"accuracy": 750, "zoom": 13},
"femtostar": {"accuracy": 300000, "zoom": 4}
}
function setNetwork(new_network){
set_network = new_network;
circle.setRadius(networks[set_network].accuracy);
mymap.flyTo(cities[set_city], networks[set_network].zoom);
}
function setCity(new_city){
set_city = new_city;
circle.setRadius(networks[set_network].accuracy);
circle.setLatLng(cities[set_city]);
mymap.flyTo(cities[set_city], networks[set_network].zoom, {
animate: false,
duration: 6
});
}
document.getElementById("button_cellular_urban").checked = true;
document.getElementById("button_nyc").checked = true;
var mymap = L.map('mapid').setView([40.758896, -73.985130], 17);
L.tileLayer(tileserver, {
maxZoom: 18,
attribution: 'Map data &copy; Esri &mdash; Source: Esri, i-cubed, USDA, USGS, AEX, GeoEye, Getmapping, Aerogrid, IGN, IGP, UPR-EGP, and the GIS User Community',
id: 'mapbox/streets-v11'
}).addTo(mymap);
var circle = L.circle([40.758896, -73.985130], {
color: 'red',
fillColor: '#f03',
fillOpacity: 0.5,
radius: 60
}).addTo(mymap);
</script>
</body>
</html>

3
index.html Normal file
View file

@ -0,0 +1,3 @@
<h1>FemtoStar Visualization Tests</h1>
<a href="sats/satellites.html">Satellites</a><br>
<a href="geolocation/index.html">Geolocation</a>

398
sats/index.js Normal file
View file

@ -0,0 +1,398 @@
(function (L, d3, satelliteJs) {
var RADIANS = Math.PI / 180;
var DEGREES = 180 / Math.PI;
var R_EARTH = 6378.137; // equatorial radius (km)
/* =============================================== */
/* =============== CLOCK ========================= */
/* =============================================== */
/**
* Factory function for keeping track of elapsed time and rates.
*/
function Clock() {
this._rate = 60; // 1ms elapsed : 60sec simulated
this._date = d3.now();
this._elapsed = 0;
};
Clock.prototype.date = function (timeInMs) {
if (!arguments.length) return this._date + (this._elapsed * this._rate);
this._date = timeInMs;
return this;
};
Clock.prototype.elapsed = function (ms) {
if (!arguments.length) return this._date - d3.now(); // calculates elapsed
this._elapsed = ms;
return this;
};
Clock.prototype.rate = function (secondsPerMsElapsed) {
if (!arguments.length) return this._rate;
this._rate = secondsPerMsElapsed;
return this;
};
/* ==================================================== */
/* =============== CONVERSION ========================= */
/* ==================================================== */
function satrecToFeature(satrec, date, props) {
var properties = props || {};
var positionAndVelocity = satelliteJs.propagate(satrec, date);
var gmst = satelliteJs.gstime(date);
var positionGd = satelliteJs.eciToGeodetic(positionAndVelocity.position, gmst);
properties.height = positionGd.height;
return {
type: 'Feature',
properties: properties,
geometry: {
type: 'Point',
coordinates: [
positionGd.longitude * DEGREES,
positionGd.latitude * DEGREES
]
}
};
};
/* ==================================================== */
/* =============== TLE ================================ */
/* ==================================================== */
/**
* Factory function for working with TLE.
*/
function TLE() {
this._properties;
this._date;
};
TLE.prototype._lines = function (arry) {
return arry.slice(0, 2);
};
TLE.prototype.satrecs = function (tles) {
return tles.map(function (d) {
return satelliteJs.twoline2satrec.apply(null, this._lines(d));
});
};
TLE.prototype.features = function (tles) {
var date = this._date || d3.now();
return tles.map(function (d) {
var satrec = satelliteJs.twoline2satrec.apply(null, this._lines(d));
return satrecToFeature(satrec, date, this._properties(d));
});
};
TLE.prototype.lines = function (func) {
if (!arguments.length) return this._lines;
this._lines = func;
return this;
};
TLE.prototype.properties = function (func) {
if (!arguments.length) return this._properties;
this._properties = func;
return this;
};
TLE.prototype.date = function (ms) {
if (!arguments.length) return this._date;
this._date = ms;
return this;
};
/* ==================================================== */
/* =============== PARSE ============================== */
/* ==================================================== */
/**
* Parses text file string of tle into groups.
* @return {string[][]} Like [['tle line 1', 'tle line 2'], ...]
*/
function parseTle(tleString) {
// remove last newline so that we can properly split all the lines
var lines = tleString.replace(/\r?\n$/g, '').split(/\r?\n/);
return lines.reduce(function (acc, cur, index) {
if (index % 2 === 0) acc.push([]);
acc[acc.length - 1].push(cur);
return acc;
}, []);
};
/* ==================================================== */
/* =============== SATELLITE ========================== */
/* ==================================================== */
/**
* Satellite factory function that wraps satellitejs functionality
* and can compute footprints based on TLE and date
*
* @param {string[][]} tle two-line element
* @param {Date} date date to propagate with TLE
*/
function Satellite(tle, date) {
this._satrec = satelliteJs.twoline2satrec(tle[0], tle[1]);
this._satNum = this._satrec.satnum; // NORAD Catalog Number
this._altitude; // km
this._position = {
lat: null,
lng: null
};
this._halfAngle; // degrees
this._date;
this._gmst;
this.setDate(date);
this.update();
this._orbitType = this.orbitTypeFromAlt(this._altitude); // LEO, MEO, or GEO
};
/**
* Updates satellite position and altitude based on current TLE and date
*/
Satellite.prototype.update = function () {
var positionAndVelocity = satelliteJs.propagate(this._satrec, this._date);
var positionGd = satelliteJs.eciToGeodetic(positionAndVelocity.position, this._gmst);
this._position = {
lat: positionGd.latitude * DEGREES,
lng: positionGd.longitude * DEGREES
};
this._altitude = positionGd.height;
return this;
};
/**
* @returns {GeoJSON.Polygon} GeoJSON describing the satellite's current footprint on the Earth
*/
Satellite.prototype.getFootprint = function () {
var theta = this._halfAngle * RADIANS;
coreAngle = this._coreAngle(theta, this._altitude, R_EARTH) * DEGREES;
return d3.geoCircle()
.center([this._position.lng, this._position.lat])
.radius(coreAngle)();
};
/**
* A conical satellite with half angle casts a circle on the Earth. Find the angle
* from the center of the earth to the radius of this circle
* @param {number} theta: Satellite half angle in radians
* @param {number} altitude Satellite altitude
* @param {number} r Earth radius
* @returns {number} core angle in radians
*/
Satellite.prototype._coreAngle = function (theta, altitude, r) {
// if FOV is larger than Earth, assume it goes to the tangential point
if (Math.sin(theta) > r / (altitude + r)) {
return Math.acos(r / (r + altitude));
}
return Math.abs(Math.asin((r + altitude) * Math.sin(theta) / r)) - theta;
};
Satellite.prototype.halfAngle = function (halfAngle) {
if (!arguments.length) return this._halfAngle;
this._halfAngle = halfAngle;
return this;
};
Satellite.prototype.satNum = function (satNum) {
if (!arguments.length) return this._satNum;
this._satNum = satNum;
return this;
};
Satellite.prototype.altitude = function (altitude) {
if (!arguments.length) return this._altitude;
this._altitude = altitude;
return this;
};
Satellite.prototype.position = function (position) {
if (!arguments.length) return this._position;
this._position = position;
return this;
};
Satellite.prototype.getOrbitType = function () {
return this._orbitType;
};
/**
* sets both the date and the Greenwich Mean Sidereal Time
* @param {Date} date
*/
Satellite.prototype.setDate = function (date) {
this._date = date;
this._gmst = satelliteJs.gstime(date);
return this;
};
/**
* Maps an altitude to a type of satellite
* @param {number} altitude (in KM)
* @returns {'LEO' | 'MEO' | 'GEO'}
*/
Satellite.prototype.orbitTypeFromAlt = function (altitude) {
this._altitude = altitude || this._altitude;
return this._altitude < 1200 ? 'LEO' : this._altitude > 22000 ? 'GEO' : 'MEO';
};
/* =============================================== */
/* =================== GLOBE ===================== */
/* =============================================== */
// Approximate date the tle data was aquired from https://www.space-track.org/#recent
var TLE_DATA_DATE = new Date(2018, 0, 26).getTime();
var activeClock;
var sats;
var svg = d3.select('#globe');
var marginTop = 20;
var width = svg.attr('width');
var height = svg.attr('height') - marginTop;
var projection = d3.geoOrthographic()
.scale((height - 10) / 2)
.translate([width / 2, height / 2 + marginTop])
.precision(0.1);
var geoPath = d3.geoPath()
.projection(projection);
svg.append('path')
.datum({
type: 'Sphere'
})
.style('cursor', 'grab')
.attr('fill', '#2E86AB')
.attr('d', geoPath);
function initGlobe() {
d3.json('world-110m.json').then(function (worldData) {
svg.selectAll('.segment')
.data(topojson.feature(worldData, worldData.objects.countries).features)
.enter().append('path')
.style('cursor', 'grab')
.attr('class', 'segment')
.attr('d', geoPath)
.style('stroke', '#888')
.style('stroke-width', '1px')
.style('fill', '#e5e5e5')
.style('opacity', '.4');
});
}
function updateSats(date) {
sats.forEach(function (sat) {
return sat.setDate(date).update()
});
return sats
};
/**
* Create satellite objects for each record in the TLEs and begin animation
* @param {string[][]} parsedTles
*/
function initSats(parsedTles) {
activeClock = new Clock()
.rate(100)
.date(TLE_DATA_DATE);
sats = parsedTles.map(function (tle) {
var sat = new Satellite(tle, new Date(2018, 0, 26));
//61.73 degree half angle corresponds to 3 degree coverage angle, obviously
//this is far less than we intend to provide but it works well for this graphic.
sat.halfAngle(61.73);
return sat;
});
window.requestAnimationFrame(animateSats);
return sats;
};
function draw() {
redrawGlobe();
svg.selectAll('.footprint')
.data(sats, function (sat) {
return sat.satNum();
})
.join(
function (enter) {
return enter.append('path')
.attr('class', function (sat) {
return 'footprint footprint--' + sat.getOrbitType()
})
.style('cursor', 'grab');
}
).attr('d', function (sat) {
return geoPath(sat.getFootprint());
});
};
function redrawGlobe() {
svg.selectAll('.segment')
.attr('d', geoPath);
}
var m0;
var o0;
function mousedown() {
m0 = [d3.event.pageX, d3.event.pageY];
o0 = projection.rotate();
d3.event.preventDefault();
};
function mousemove() {
if (m0) {
var m1 = [d3.event.pageX, d3.event.pageY];
const o1 = [o0[0] + (m1[0] - m0[0]) / 6, o0[1] + (m0[1] - m1[1]) / 6];
projection.rotate(o1);
draw();
}
};
function mouseup() {
if (m0) {
mousemove();
m0 = null;
}
}
svg.on('mousedown', mousedown);
d3.select(window)
.on('mousemove', mousemove)
.on('mouseup', mouseup);
function animateSats(elapsed) {
var dateInMs = activeClock.elapsed(elapsed)
.date();
var date = new Date(dateInMs);
svg.select('.date-counter').text('' + date);
updateSats(date);
draw();
window.requestAnimationFrame(animateSats);
}
initGlobe();
// WARNING: THE TLES HERE ARE NOT REAL NORAD-PUBLISHED TLES - THE TLE FORMAT
// IS USED ONLY AS A WAY TO SPECIFY THE ORBITS IN THE CONSTELLATION.
d3.text('tles.txt')
.then(parseTle)
.then(initSats);
}(window.L, window.d3, window.satellite))

29
sats/satellites.html Normal file
View file

@ -0,0 +1,29 @@
<!DOCTYPE html>
<head>
<meta charset="utf-8">
<link rel="stylesheet" href="https://unpkg.com/leaflet@1.4.0/dist/leaflet.css" integrity="sha512-puBpdR0798OZvTTbP4A8Ix/l+A4dHDD0DGqYW6RQ+9jxkRFclaxxQb/SJAWZfWAkuyeQUytO7+7N4QKrDh+drA=="
crossorigin="" />
<script src="https://unpkg.com/leaflet@1.4.0/dist/leaflet.js" integrity="sha512-QVftwZFqvtRNi0ZyCtsznlKSWOStnDORoefr1enyq5mVL4tmKB3S/EnC3rRJcxCPavG10IcrVGSmPh6Qw5lwrg=="
crossorigin=""></script>
<script src="https://cdn.jsdelivr.net/npm/promise-polyfill@8.1/dist/polyfill.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/whatwg-fetch@3.0/dist/fetch.umd.min.js"></script>
<script src="https://d3js.org/d3.v5.min.js"></script>
<script src="https://d3js.org/d3-geo-projection.v2.min.js"></script>
<script src="https://d3js.org/d3-queue.v3.min.js"></script>
<script src="https://d3js.org/topojson.v2.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/satellite.js/3.0.0/satellite.min.js"></script>
<style>
.footprint--LEO {
fill: rgba(255, 177, 64, 0.08);
stroke: rgba(255, 177, 64, 0.5);
}
</style>
</head>
<body style="margin: 0px; background-color: #00111d;">
<svg id="globe" width="500" height="500"></svg>
<script src="index.js"></script>
</body>
</html>

4
sats/tles-test.txt Normal file
View file

@ -0,0 +1,4 @@
1 00000U 00000A 00000.00000000 .00000000 00000-0 00000-0 0 0000
2 00000 53.0000 000.0000 0000000 000.0000 000.0000 14.12748000000000
1 00000U 00000A 00000.00000000 .00000000 00000-0 00000-0 0 0000
2 00000 53.0000 000.0000 0000000 000.0000 050.6230 14.12748000000000

96
sats/tles.txt Normal file
View file

@ -0,0 +1,96 @@
1 00000U 00000A 00000.00000000 .00000000 00000-0 00000-0 0 0000
2 00000 53.0000 000.0000 0000000 000.0000 000.0000 14.12748000000000
1 00000U 00000A 00000.00000000 .00000000 00000-0 00000-0 0 0000
2 00000 53.0000 000.0000 0000000 000.0000 090.0000 14.12748000000000
1 00000U 00000A 00000.00000000 .00000000 00000-0 00000-0 0 0000
2 00000 53.0000 000.0000 0000000 000.0000 180.0000 14.12748000000000
1 00000U 00000A 00000.00000000 .00000000 00000-0 00000-0 0 0000
2 00000 53.0000 000.0000 0000000 000.0000 270.0000 14.12748000000000
1 00000U 00000A 00000.00000000 .00000000 00000-0 00000-0 0 0000
2 00000 53.0000 030.0000 0000000 000.0000 307.5000 14.12748000000000
1 00000U 00000A 00000.00000000 .00000000 00000-0 00000-0 0 0000
2 00000 53.0000 030.0000 0000000 000.0000 037.5000 14.12748000000000
1 00000U 00000A 00000.00000000 .00000000 00000-0 00000-0 0 0000
2 00000 53.0000 030.0000 0000000 000.0000 127.5000 14.12748000000000
1 00000U 00000A 00000.00000000 .00000000 00000-0 00000-0 0 0000
2 00000 53.0000 030.0000 0000000 000.0000 217.5000 14.12748000000000
1 00000U 00000A 00000.00000000 .00000000 00000-0 00000-0 0 0000
2 00000 53.0000 060.0000 0000000 000.0000 255.0000 14.12748000000000
1 00000U 00000A 00000.00000000 .00000000 00000-0 00000-0 0 0000
2 00000 53.0000 060.0000 0000000 000.0000 345.0000 14.12748000000000
1 00000U 00000A 00000.00000000 .00000000 00000-0 00000-0 0 0000
2 00000 53.0000 060.0000 0000000 000.0000 075.0000 14.12748000000000
1 00000U 00000A 00000.00000000 .00000000 00000-0 00000-0 0 0000
2 00000 53.0000 060.0000 0000000 000.0000 165.0000 14.12748000000000
1 00000U 00000A 00000.00000000 .00000000 00000-0 00000-0 0 0000
2 00000 53.0000 090.0000 0000000 000.0000 202.5000 14.12748000000000
1 00000U 00000A 00000.00000000 .00000000 00000-0 00000-0 0 0000
2 00000 53.0000 090.0000 0000000 000.0000 292.5000 14.12748000000000
1 00000U 00000A 00000.00000000 .00000000 00000-0 00000-0 0 0000
2 00000 53.0000 090.0000 0000000 000.0000 022.5000 14.12748000000000
1 00000U 00000A 00000.00000000 .00000000 00000-0 00000-0 0 0000
2 00000 53.0000 090.0000 0000000 000.0000 112.5000 14.12748000000000
1 00000U 00000A 00000.00000000 .00000000 00000-0 00000-0 0 0000
2 00000 53.0000 120.0000 0000000 000.0000 150.0000 14.12748000000000
1 00000U 00000A 00000.00000000 .00000000 00000-0 00000-0 0 0000
2 00000 53.0000 120.0000 0000000 000.0000 240.0000 14.12748000000000
1 00000U 00000A 00000.00000000 .00000000 00000-0 00000-0 0 0000
2 00000 53.0000 120.0000 0000000 000.0000 330.0000 14.12748000000000
1 00000U 00000A 00000.00000000 .00000000 00000-0 00000-0 0 0000
2 00000 53.0000 120.0000 0000000 000.0000 060.0000 14.12748000000000
1 00000U 00000A 00000.00000000 .00000000 00000-0 00000-0 0 0000
2 00000 53.0000 150.0000 0000000 000.0000 097.5000 14.12748000000000
1 00000U 00000A 00000.00000000 .00000000 00000-0 00000-0 0 0000
2 00000 53.0000 150.0000 0000000 000.0000 187.5000 14.12748000000000
1 00000U 00000A 00000.00000000 .00000000 00000-0 00000-0 0 0000
2 00000 53.0000 150.0000 0000000 000.0000 277.5000 14.12748000000000
1 00000U 00000A 00000.00000000 .00000000 00000-0 00000-0 0 0000
2 00000 53.0000 150.0000 0000000 000.0000 007.5000 14.12748000000000
1 00000U 00000A 00000.00000000 .00000000 00000-0 00000-0 0 0000
2 00000 53.0000 180.0000 0000000 000.0000 045.0000 14.12748000000000
1 00000U 00000A 00000.00000000 .00000000 00000-0 00000-0 0 0000
2 00000 53.0000 180.0000 0000000 000.0000 135.0000 14.12748000000000
1 00000U 00000A 00000.00000000 .00000000 00000-0 00000-0 0 0000
2 00000 53.0000 180.0000 0000000 000.0000 225.0000 14.12748000000000
1 00000U 00000A 00000.00000000 .00000000 00000-0 00000-0 0 0000
2 00000 53.0000 180.0000 0000000 000.0000 315.0000 14.12748000000000
1 00000U 00000A 00000.00000000 .00000000 00000-0 00000-0 0 0000
2 00000 53.0000 210.0000 0000000 000.0000 352.5000 14.12748000000000
1 00000U 00000A 00000.00000000 .00000000 00000-0 00000-0 0 0000
2 00000 53.0000 210.0000 0000000 000.0000 082.5000 14.12748000000000
1 00000U 00000A 00000.00000000 .00000000 00000-0 00000-0 0 0000
2 00000 53.0000 210.0000 0000000 000.0000 172.5000 14.12748000000000
1 00000U 00000A 00000.00000000 .00000000 00000-0 00000-0 0 0000
2 00000 53.0000 210.0000 0000000 000.0000 262.5000 14.12748000000000
1 00000U 00000A 00000.00000000 .00000000 00000-0 00000-0 0 0000
2 00000 53.0000 240.0000 0000000 000.0000 300.0000 14.12748000000000
1 00000U 00000A 00000.00000000 .00000000 00000-0 00000-0 0 0000
2 00000 53.0000 240.0000 0000000 000.0000 030.0000 14.12748000000000
1 00000U 00000A 00000.00000000 .00000000 00000-0 00000-0 0 0000
2 00000 53.0000 240.0000 0000000 000.0000 120.0000 14.12748000000000
1 00000U 00000A 00000.00000000 .00000000 00000-0 00000-0 0 0000
2 00000 53.0000 240.0000 0000000 000.0000 210.0000 14.12748000000000
1 00000U 00000A 00000.00000000 .00000000 00000-0 00000-0 0 0000
2 00000 53.0000 270.0000 0000000 000.0000 247.5000 14.12748000000000
1 00000U 00000A 00000.00000000 .00000000 00000-0 00000-0 0 0000
2 00000 53.0000 270.0000 0000000 000.0000 337.5000 14.12748000000000
1 00000U 00000A 00000.00000000 .00000000 00000-0 00000-0 0 0000
2 00000 53.0000 270.0000 0000000 000.0000 067.5000 14.12748000000000
1 00000U 00000A 00000.00000000 .00000000 00000-0 00000-0 0 0000
2 00000 53.0000 270.0000 0000000 000.0000 157.5000 14.12748000000000
1 00000U 00000A 00000.00000000 .00000000 00000-0 00000-0 0 0000
2 00000 53.0000 300.0000 0000000 000.0000 195.0000 14.12748000000000
1 00000U 00000A 00000.00000000 .00000000 00000-0 00000-0 0 0000
2 00000 53.0000 300.0000 0000000 000.0000 285.0000 14.12748000000000
1 00000U 00000A 00000.00000000 .00000000 00000-0 00000-0 0 0000
2 00000 53.0000 300.0000 0000000 000.0000 015.0000 14.12748000000000
1 00000U 00000A 00000.00000000 .00000000 00000-0 00000-0 0 0000
2 00000 53.0000 300.0000 0000000 000.0000 105.0000 14.12748000000000
1 00000U 00000A 00000.00000000 .00000000 00000-0 00000-0 0 0000
2 00000 53.0000 330.0000 0000000 000.0000 142.5000 14.12748000000000
1 00000U 00000A 00000.00000000 .00000000 00000-0 00000-0 0 0000
2 00000 53.0000 330.0000 0000000 000.0000 232.5000 14.12748000000000
1 00000U 00000A 00000.00000000 .00000000 00000-0 00000-0 0 0000
2 00000 53.0000 330.0000 0000000 000.0000 322.5000 14.12748000000000
1 00000U 00000A 00000.00000000 .00000000 00000-0 00000-0 0 0000
2 00000 53.0000 330.0000 0000000 000.0000 052.5000 14.12748000000000

1
sats/world-110m.json Normal file

File diff suppressed because one or more lines are too long