Update with new in Eclipse stuff.
parent
7ef34855cf
commit
340d7b032c
|
@ -3,4 +3,4 @@
|
|||
Uses Satnogs data to generate a map of all stations on Production and all sats currently observed.
|
||||
|
||||
|
||||
Currently hosted at iit.minecraft16.ml:5000/map_view
|
||||
Currently hosted at satnogs.minecraft16.ml
|
11
satnogs.py
11
satnogs.py
|
@ -131,11 +131,8 @@ def updateTLE():
|
|||
|
||||
|
||||
|
||||
@app.route('/')
|
||||
def index():
|
||||
return 'Satnogs Network Info<br>Updated every 5 min<br><a href="/occuringobservations">IDs of all occuring observations with links to the obs</a><br><a href="/api/activestations">IDs of all stations actively in an observation</a><br><a href="/api/onlinestations">All online stations</a><br><a href="/api/occuringobservations">IDs of all occuring observations</a>'
|
||||
|
||||
@app.route("/map_view")
|
||||
|
||||
@app.route("/")
|
||||
def map_view():
|
||||
stations = []
|
||||
for x in Stations:
|
||||
|
@ -184,7 +181,7 @@ def api_occuring_sats():
|
|||
satellite.compute(now)
|
||||
lat = satellite.sublat*57.295779514
|
||||
long = satellite.sublong*57.295779514
|
||||
obs[x.satellite['norad_cat_id']] = {"name":x.satellite["name"],"transmitter_name":x.transmitter["description"],"transmitter_downlink":x.transmitter["downlink_low"],"transmitter_mode":modes[x.transmitter["mode_id"]],"lat_lng":[lat,long]}
|
||||
obs[x.satellite['norad_cat_id']] = {"name":x.satellite["name"],"lat_lng":[lat,long],"eclipsed":satellite.eclipsed}
|
||||
return json.dumps(obs)
|
||||
|
||||
@app.route('/api/satstationpairs')
|
||||
|
@ -201,7 +198,7 @@ def get_sat_loc(norad):
|
|||
satellite.compute(now)
|
||||
lat = satellite.sublat*57.295779514
|
||||
long = satellite.sublong*57.295779514
|
||||
return json.dumps([lat,long])
|
||||
return json.dumps([lat,long,satellite.eclipsed])
|
||||
|
||||
updatePasses()
|
||||
updateStations()
|
||||
|
|
|
@ -1,26 +1,3 @@
|
|||
"""The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2014 Sean Herron, 2018 Fabian P. Schmidt
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
"""
|
||||
|
||||
import requests
|
||||
import re
|
||||
|
||||
|
|
|
@ -0,0 +1,495 @@
|
|||
"use strict";
|
||||
|
||||
// This file is part of Leaflet.Geodesic.
|
||||
// Copyright (C) 2017 Henry Thasler
|
||||
// based on code by Chris Veness Copyright (C) 2014 https://github.com/chrisveness/geodesy
|
||||
//
|
||||
// Leaflet.Geodesic is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Leaflet.Geodesic is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Leaflet.Geodesic. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
|
||||
/** Extend Number object with method to convert numeric degrees to radians */
|
||||
if (typeof Number.prototype.toRadians === "undefined") {
|
||||
Number.prototype.toRadians = function() {
|
||||
return this * Math.PI / 180;
|
||||
};
|
||||
}
|
||||
|
||||
/** Extend Number object with method to convert radians to numeric (signed) degrees */
|
||||
if (typeof Number.prototype.toDegrees === "undefined") {
|
||||
Number.prototype.toDegrees = function() {
|
||||
return this * 180 / Math.PI;
|
||||
};
|
||||
}
|
||||
|
||||
var INTERSECT_LNG = 179.999; // Lng used for intersection and wrap around on map edges
|
||||
|
||||
L.Geodesic = L.Polyline.extend({
|
||||
options: {
|
||||
color: "blue",
|
||||
steps: 10,
|
||||
dash: 1,
|
||||
wrap: true
|
||||
},
|
||||
|
||||
initialize: function(latlngs, options) {
|
||||
this.options = this._merge_options(this.options, options);
|
||||
this.options.dash = Math.max(1e-3, Math.min(1, parseFloat(this.options.dash) || 1));
|
||||
this.datum = {};
|
||||
this.datum.ellipsoid = {
|
||||
a: 6378137,
|
||||
b: 6356752.3142,
|
||||
f: 1 / 298.257223563
|
||||
}; // WGS-84
|
||||
this._latlngs = this._generate_Geodesic(latlngs);
|
||||
L.Polyline.prototype.initialize.call(this, this._latlngs, this.options);
|
||||
},
|
||||
|
||||
setLatLngs: function(latlngs) {
|
||||
this._latlngs = this._generate_Geodesic(latlngs);
|
||||
L.Polyline.prototype.setLatLngs.call(this, this._latlngs);
|
||||
},
|
||||
|
||||
/**
|
||||
* Calculates some statistic values of current geodesic multipolyline
|
||||
* @returns (Object} Object with several properties (e.g. overall distance)
|
||||
*/
|
||||
getStats: function() {
|
||||
let obj = {
|
||||
distance: 0,
|
||||
points: 0,
|
||||
polygons: this._latlngs.length
|
||||
}, poly, points;
|
||||
|
||||
for (poly = 0; poly < this._latlngs.length; poly++) {
|
||||
obj.points += this._latlngs[poly].length;
|
||||
for (points = 0; points < (this._latlngs[poly].length - 1); points++) {
|
||||
obj.distance += this._vincenty_inverse(this._latlngs[poly][points],
|
||||
this._latlngs[poly][points + 1]).distance;
|
||||
}
|
||||
}
|
||||
return obj;
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* Creates geodesic lines from geoJson. Replaces all current features of this instance.
|
||||
* Supports LineString, MultiLineString and Polygon
|
||||
* @param {Object} geojson - geosjon as object.
|
||||
*/
|
||||
geoJson: function(geojson) {
|
||||
|
||||
let normalized = L.GeoJSON.asFeature(geojson);
|
||||
let features = normalized.type === "FeatureCollection" ? normalized.features : [
|
||||
normalized
|
||||
];
|
||||
this._latlngs = [];
|
||||
for (let feature of features) {
|
||||
let geometry = feature.type === "Feature" ? feature.geometry :
|
||||
feature,
|
||||
coords = geometry.coordinates;
|
||||
|
||||
switch (geometry.type) {
|
||||
case "LineString":
|
||||
this._latlngs.push(this._generate_Geodesic([L.GeoJSON.coordsToLatLngs(
|
||||
coords, 0)]));
|
||||
break;
|
||||
case "MultiLineString":
|
||||
case "Polygon":
|
||||
this._latlngs.push(this._generate_Geodesic(L.GeoJSON.coordsToLatLngs(
|
||||
coords, 1)));
|
||||
break;
|
||||
case "Point":
|
||||
case "MultiPoint":
|
||||
console.log("Dude, points can't be drawn as geodesic lines...");
|
||||
break;
|
||||
default:
|
||||
console.log("Drawing " + geometry.type +
|
||||
" as a geodesic is not supported. Skipping...");
|
||||
}
|
||||
}
|
||||
L.Polyline.prototype.setLatLngs.call(this, this._latlngs);
|
||||
},
|
||||
|
||||
/**
|
||||
* Creates a great circle. Replaces all current lines.
|
||||
* @param {Object} center - geographic position
|
||||
* @param {number} radius - radius of the circle in metres
|
||||
*/
|
||||
createCircle: function(center, radius) {
|
||||
let polylineIndex = 0;
|
||||
let prev = {
|
||||
lat: 0,
|
||||
lng: 0,
|
||||
brg: 0
|
||||
};
|
||||
let step;
|
||||
|
||||
this._latlngs = [];
|
||||
this._latlngs[polylineIndex] = [];
|
||||
|
||||
let direct = this._vincenty_direct(L.latLng(center), 0, radius, this.options
|
||||
.wrap);
|
||||
prev = L.latLng(direct.lat, direct.lng);
|
||||
this._latlngs[polylineIndex].push(prev);
|
||||
for (step = 1; step <= this.options.steps;) {
|
||||
direct = this._vincenty_direct(L.latLng(center), 360 / this.options
|
||||
.steps * step, radius, this.options.wrap);
|
||||
let gp = L.latLng(direct.lat, direct.lng);
|
||||
if (Math.abs(gp.lng - prev.lng) > 180) {
|
||||
let inverse = this._vincenty_inverse(prev, gp);
|
||||
let sec = this._intersection(prev, inverse.initialBearing, {
|
||||
lat: -89,
|
||||
lng: ((gp.lng - prev.lng) > 0) ? -INTERSECT_LNG : INTERSECT_LNG
|
||||
}, 0);
|
||||
if (sec) {
|
||||
this._latlngs[polylineIndex].push(L.latLng(sec.lat, sec.lng));
|
||||
polylineIndex++;
|
||||
this._latlngs[polylineIndex] = [];
|
||||
prev = L.latLng(sec.lat, -sec.lng);
|
||||
this._latlngs[polylineIndex].push(prev);
|
||||
} else {
|
||||
polylineIndex++;
|
||||
this._latlngs[polylineIndex] = [];
|
||||
this._latlngs[polylineIndex].push(gp);
|
||||
prev = gp;
|
||||
step++;
|
||||
}
|
||||
} else {
|
||||
this._latlngs[polylineIndex].push(gp);
|
||||
prev = gp;
|
||||
step++;
|
||||
}
|
||||
}
|
||||
|
||||
L.Polyline.prototype.setLatLngs.call(this, this._latlngs);
|
||||
},
|
||||
|
||||
/**
|
||||
* Creates a geodesic Polyline from given coordinates
|
||||
* Note: dashed lines are under work
|
||||
* @param {Object} latlngs - One or more polylines as an array. See Leaflet doc about Polyline
|
||||
* @returns (Object} An array of arrays of geographical points.
|
||||
*/
|
||||
_generate_Geodesic: function(latlngs) {
|
||||
let _geo = [], _geocnt = 0;
|
||||
|
||||
for (let poly = 0; poly < latlngs.length; poly++) {
|
||||
_geo[_geocnt] = [];
|
||||
let prev = L.latLng(latlngs[poly][0]);
|
||||
for (let points = 0; points < (latlngs[poly].length - 1); points++) {
|
||||
// use prev, so that wrapping behaves correctly
|
||||
let pointA = prev;
|
||||
let pointB = L.latLng(latlngs[poly][points + 1]);
|
||||
if (pointA.equals(pointB)) {
|
||||
continue;
|
||||
}
|
||||
let inverse = this._vincenty_inverse(pointA, pointB);
|
||||
_geo[_geocnt].push(prev);
|
||||
for (let s = 1; s <= this.options.steps;) {
|
||||
let distance = inverse.distance / this.options.steps;
|
||||
// dashed lines don't go the full distance between the points
|
||||
let dist_mult = s - 1 + this.options.dash;
|
||||
let direct = this._vincenty_direct(pointA, inverse.initialBearing, distance*dist_mult, this.options.wrap);
|
||||
let gp = L.latLng(direct.lat, direct.lng);
|
||||
if (Math.abs(gp.lng - prev.lng) > 180) {
|
||||
let sec = this._intersection(pointA, inverse.initialBearing, {
|
||||
lat: -89,
|
||||
lng: ((gp.lng - prev.lng) > 0) ? -INTERSECT_LNG : INTERSECT_LNG
|
||||
}, 0);
|
||||
if (sec) {
|
||||
_geo[_geocnt].push(L.latLng(sec.lat, sec.lng));
|
||||
_geocnt++;
|
||||
_geo[_geocnt] = [];
|
||||
prev = L.latLng(sec.lat, -sec.lng);
|
||||
_geo[_geocnt].push(prev);
|
||||
} else {
|
||||
_geocnt++;
|
||||
_geo[_geocnt] = [];
|
||||
_geo[_geocnt].push(gp);
|
||||
prev = gp;
|
||||
s++;
|
||||
}
|
||||
} else {
|
||||
_geo[_geocnt].push(gp);
|
||||
// Dashed lines start a new line
|
||||
if (this.options.dash < 1){
|
||||
_geocnt++;
|
||||
// go full distance this time, to get starting point for next line
|
||||
let direct_full = this._vincenty_direct(pointA, inverse.initialBearing, distance*s, this.options.wrap);
|
||||
_geo[_geocnt] = [];
|
||||
prev = L.latLng(direct_full.lat, direct_full.lng);
|
||||
_geo[_geocnt].push(prev);
|
||||
}
|
||||
else prev = gp;
|
||||
s++;
|
||||
}
|
||||
}
|
||||
}
|
||||
_geocnt++;
|
||||
}
|
||||
return _geo;
|
||||
},
|
||||
|
||||
/**
|
||||
* Vincenty direct calculation.
|
||||
* based on the work of Chris Veness (https://github.com/chrisveness/geodesy)
|
||||
*
|
||||
* @private
|
||||
* @param {number} initialBearing - Initial bearing in degrees from north.
|
||||
* @param {number} distance - Distance along bearing in metres.
|
||||
* @returns (Object} Object including point (destination point), finalBearing.
|
||||
*/
|
||||
|
||||
_vincenty_direct: function(p1, initialBearing, distance, wrap) {
|
||||
var φ1 = p1.lat.toRadians(),
|
||||
λ1 = p1.lng.toRadians();
|
||||
var α1 = initialBearing.toRadians();
|
||||
var s = distance;
|
||||
|
||||
var a = this.datum.ellipsoid.a,
|
||||
b = this.datum.ellipsoid.b,
|
||||
f = this.datum.ellipsoid.f;
|
||||
|
||||
var sinα1 = Math.sin(α1);
|
||||
var cosα1 = Math.cos(α1);
|
||||
|
||||
var tanU1 = (1 - f) * Math.tan(φ1),
|
||||
cosU1 = 1 / Math.sqrt((1 + tanU1 * tanU1)),
|
||||
sinU1 = tanU1 * cosU1;
|
||||
var σ1 = Math.atan2(tanU1, cosα1);
|
||||
var sinα = cosU1 * sinα1;
|
||||
var cosSqα = 1 - sinα * sinα;
|
||||
var uSq = cosSqα * (a * a - b * b) / (b * b);
|
||||
var A = 1 + uSq / 16384 * (4096 + uSq * (-768 + uSq * (320 - 175 *
|
||||
uSq)));
|
||||
var B = uSq / 1024 * (256 + uSq * (-128 + uSq * (74 - 47 * uSq)));
|
||||
|
||||
var σ = s / (b * A),
|
||||
σʹ, iterations = 0;
|
||||
var sinσ, cosσ;
|
||||
var cos2σM;
|
||||
do {
|
||||
cos2σM = Math.cos(2 * σ1 + σ);
|
||||
sinσ = Math.sin(σ);
|
||||
cosσ = Math.cos(σ);
|
||||
var Δσ = B * sinσ * (cos2σM + B / 4 * (cosσ * (-1 + 2 * cos2σM *
|
||||
cos2σM) -
|
||||
B / 6 * cos2σM * (-3 + 4 * sinσ * sinσ) * (-3 + 4 * cos2σM *
|
||||
cos2σM)));
|
||||
σʹ = σ;
|
||||
σ = s / (b * A) + Δσ;
|
||||
} while (Math.abs(σ - σʹ) > 1e-12 && ++iterations);
|
||||
|
||||
var x = sinU1 * sinσ - cosU1 * cosσ * cosα1;
|
||||
var φ2 = Math.atan2(sinU1 * cosσ + cosU1 * sinσ * cosα1, (1 - f) *
|
||||
Math.sqrt(sinα * sinα + x * x));
|
||||
var λ = Math.atan2(sinσ * sinα1, cosU1 * cosσ - sinU1 * sinσ * cosα1);
|
||||
var C = f / 16 * cosSqα * (4 + f * (4 - 3 * cosSqα));
|
||||
var L = λ - (1 - C) * f * sinα *
|
||||
(σ + C * sinσ * (cos2σM + C * cosσ * (-1 + 2 * cos2σM * cos2σM)));
|
||||
|
||||
var λ2;
|
||||
if (wrap) {
|
||||
λ2 = (λ1 + L + 3 * Math.PI) % (2 * Math.PI) - Math.PI; // normalise to -180...+180
|
||||
} else {
|
||||
λ2 = (λ1 + L); // do not normalize
|
||||
}
|
||||
|
||||
var revAz = Math.atan2(sinα, -x);
|
||||
|
||||
return {
|
||||
lat: φ2.toDegrees(),
|
||||
lng: λ2.toDegrees(),
|
||||
finalBearing: revAz.toDegrees()
|
||||
};
|
||||
},
|
||||
|
||||
/**
|
||||
* Vincenty inverse calculation.
|
||||
* based on the work of Chris Veness (https://github.com/chrisveness/geodesy)
|
||||
*
|
||||
* @private
|
||||
* @param {LatLng} p1 - Latitude/longitude of start point.
|
||||
* @param {LatLng} p2 - Latitude/longitude of destination point.
|
||||
* @returns {Object} Object including distance, initialBearing, finalBearing.
|
||||
* @throws {Error} If formula failed to converge.
|
||||
*/
|
||||
_vincenty_inverse: function(p1, p2) {
|
||||
var φ1 = p1.lat.toRadians(),
|
||||
λ1 = p1.lng.toRadians();
|
||||
var φ2 = p2.lat.toRadians(),
|
||||
λ2 = p2.lng.toRadians();
|
||||
|
||||
var a = this.datum.ellipsoid.a,
|
||||
b = this.datum.ellipsoid.b,
|
||||
f = this.datum.ellipsoid.f;
|
||||
|
||||
var L = λ2 - λ1;
|
||||
var tanU1 = (1 - f) * Math.tan(φ1),
|
||||
cosU1 = 1 / Math.sqrt((1 + tanU1 * tanU1)),
|
||||
sinU1 = tanU1 * cosU1;
|
||||
var tanU2 = (1 - f) * Math.tan(φ2),
|
||||
cosU2 = 1 / Math.sqrt((1 + tanU2 * tanU2)),
|
||||
sinU2 = tanU2 * cosU2;
|
||||
|
||||
var λ = L,
|
||||
λʹ, iterations = 0;
|
||||
var cosSqα, sinσ, cos2σM, cosσ, σ, sinλ, cosλ;
|
||||
do {
|
||||
sinλ = Math.sin(λ);
|
||||
cosλ = Math.cos(λ);
|
||||
var sinSqσ = (cosU2 * sinλ) * (cosU2 * sinλ) + (cosU1 * sinU2 -
|
||||
sinU1 * cosU2 * cosλ) * (cosU1 * sinU2 - sinU1 * cosU2 * cosλ);
|
||||
sinσ = Math.sqrt(sinSqσ);
|
||||
if (sinσ == 0) return 0; // co-incident points
|
||||
cosσ = sinU1 * sinU2 + cosU1 * cosU2 * cosλ;
|
||||
σ = Math.atan2(sinσ, cosσ);
|
||||
var sinα = cosU1 * cosU2 * sinλ / sinσ;
|
||||
cosSqα = 1 - sinα * sinα;
|
||||
cos2σM = cosσ - 2 * sinU1 * sinU2 / cosSqα;
|
||||
if (isNaN(cos2σM)) cos2σM = 0; // equatorial line: cosSqα=0 (§6)
|
||||
var C = f / 16 * cosSqα * (4 + f * (4 - 3 * cosSqα));
|
||||
λʹ = λ;
|
||||
λ = L + (1 - C) * f * sinα * (σ + C * sinσ * (cos2σM + C * cosσ * (-
|
||||
1 + 2 * cos2σM * cos2σM)));
|
||||
} while (Math.abs(λ - λʹ) > 1e-12 && ++iterations < 100);
|
||||
if (iterations >= 100) {
|
||||
console.log("Formula failed to converge. Altering target position.");
|
||||
return this._vincenty_inverse(p1, {
|
||||
lat: p2.lat,
|
||||
lng: p2.lng - 0.01
|
||||
});
|
||||
// throw new Error('Formula failed to converge');
|
||||
}
|
||||
|
||||
var uSq = cosSqα * (a * a - b * b) / (b * b);
|
||||
var A = 1 + uSq / 16384 * (4096 + uSq * (-768 + uSq * (320 - 175 *
|
||||
uSq)));
|
||||
var B = uSq / 1024 * (256 + uSq * (-128 + uSq * (74 - 47 * uSq)));
|
||||
var Δσ = B * sinσ * (cos2σM + B / 4 * (cosσ * (-1 + 2 * cos2σM *
|
||||
cos2σM) -
|
||||
B / 6 * cos2σM * (-3 + 4 * sinσ * sinσ) * (-3 + 4 * cos2σM *
|
||||
cos2σM)));
|
||||
|
||||
var s = b * A * (σ - Δσ);
|
||||
|
||||
var fwdAz = Math.atan2(cosU2 * sinλ, cosU1 * sinU2 - sinU1 * cosU2 *
|
||||
cosλ);
|
||||
var revAz = Math.atan2(cosU1 * sinλ, -sinU1 * cosU2 + cosU1 * sinU2 *
|
||||
cosλ);
|
||||
|
||||
s = Number(s.toFixed(3)); // round to 1mm precision
|
||||
return {
|
||||
distance: s,
|
||||
initialBearing: fwdAz.toDegrees(),
|
||||
finalBearing: revAz.toDegrees()
|
||||
};
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* Returns the point of intersection of two paths defined by point and bearing.
|
||||
* based on the work of Chris Veness (https://github.com/chrisveness/geodesy)
|
||||
*
|
||||
* @param {LatLon} p1 - First point.
|
||||
* @param {number} brng1 - Initial bearing from first point.
|
||||
* @param {LatLon} p2 - Second point.
|
||||
* @param {number} brng2 - Initial bearing from second point.
|
||||
* @returns {Object} containing lat/lng information of intersection.
|
||||
*
|
||||
* @example
|
||||
* var p1 = LatLon(51.8853, 0.2545), brng1 = 108.55;
|
||||
* var p2 = LatLon(49.0034, 2.5735), brng2 = 32.44;
|
||||
* var pInt = LatLon.intersection(p1, brng1, p2, brng2); // pInt.toString(): 50.9078°N, 4.5084°E
|
||||
*/
|
||||
_intersection: function(p1, brng1, p2, brng2) {
|
||||
// see http://williams.best.vwh.net/avform.htm#Intersection
|
||||
|
||||
var φ1 = p1.lat.toRadians(),
|
||||
λ1 = p1.lng.toRadians();
|
||||
var φ2 = p2.lat.toRadians(),
|
||||
λ2 = p2.lng.toRadians();
|
||||
var θ13 = Number(brng1).toRadians(),
|
||||
θ23 = Number(brng2).toRadians();
|
||||
var Δφ = φ2 - φ1,
|
||||
Δλ = λ2 - λ1;
|
||||
|
||||
var δ12 = 2 * Math.asin(Math.sqrt(Math.sin(Δφ / 2) * Math.sin(Δφ / 2) +
|
||||
Math.cos(φ1) * Math.cos(φ2) * Math.sin(Δλ / 2) * Math.sin(Δλ /
|
||||
2)));
|
||||
if (δ12 == 0) return null;
|
||||
|
||||
// initial/final bearings between points
|
||||
var θ1 = Math.acos((Math.sin(φ2) - Math.sin(φ1) * Math.cos(δ12)) /
|
||||
(Math.sin(δ12) * Math.cos(φ1)));
|
||||
if (isNaN(θ1)) θ1 = 0; // protect against rounding
|
||||
var θ2 = Math.acos((Math.sin(φ1) - Math.sin(φ2) * Math.cos(δ12)) /
|
||||
(Math.sin(δ12) * Math.cos(φ2)));
|
||||
var θ12, θ21;
|
||||
if (Math.sin(λ2 - λ1) > 0) {
|
||||
θ12 = θ1;
|
||||
θ21 = 2 * Math.PI - θ2;
|
||||
} else {
|
||||
θ12 = 2 * Math.PI - θ1;
|
||||
θ21 = θ2;
|
||||
}
|
||||
|
||||
var α1 = (θ13 - θ12 + Math.PI) % (2 * Math.PI) - Math.PI; // angle 2-1-3
|
||||
var α2 = (θ21 - θ23 + Math.PI) % (2 * Math.PI) - Math.PI; // angle 1-2-3
|
||||
|
||||
if (Math.sin(α1) == 0 && Math.sin(α2) == 0) return null; // infinite intersections
|
||||
if (Math.sin(α1) * Math.sin(α2) < 0) return null; // ambiguous intersection
|
||||
|
||||
//α1 = Math.abs(α1);
|
||||
//α2 = Math.abs(α2);
|
||||
// ... Ed Williams takes abs of α1/α2, but seems to break calculation?
|
||||
|
||||
var α3 = Math.acos(-Math.cos(α1) * Math.cos(α2) +
|
||||
Math.sin(α1) * Math.sin(α2) * Math.cos(δ12));
|
||||
var δ13 = Math.atan2(Math.sin(δ12) * Math.sin(α1) * Math.sin(α2),
|
||||
Math.cos(α2) + Math.cos(α1) * Math.cos(α3));
|
||||
var φ3 = Math.asin(Math.sin(φ1) * Math.cos(δ13) +
|
||||
Math.cos(φ1) * Math.sin(δ13) * Math.cos(θ13));
|
||||
var Δλ13 = Math.atan2(Math.sin(θ13) * Math.sin(δ13) * Math.cos(φ1),
|
||||
Math.cos(δ13) - Math.sin(φ1) * Math.sin(φ3));
|
||||
var λ3 = λ1 + Δλ13;
|
||||
λ3 = (λ3 + 3 * Math.PI) % (2 * Math.PI) - Math.PI; // normalise to -180..+180º
|
||||
|
||||
return {
|
||||
lat: φ3.toDegrees(),
|
||||
lng: λ3.toDegrees()
|
||||
};
|
||||
},
|
||||
|
||||
/**
|
||||
* Overwrites obj1's values with obj2's and adds obj2's if non existent in obj1
|
||||
* @param obj1
|
||||
* @param obj2
|
||||
* @returns obj3 a new object based on obj1 and obj2
|
||||
*/
|
||||
_merge_options: function(obj1, obj2) {
|
||||
let obj3 = {};
|
||||
for (let attrname in obj1) {
|
||||
obj3[attrname] = obj1[attrname];
|
||||
}
|
||||
for (let attrname in obj2) {
|
||||
obj3[attrname] = obj2[attrname];
|
||||
}
|
||||
return obj3;
|
||||
}
|
||||
});
|
||||
|
||||
L.geodesic = function(latlngs, options) {
|
||||
return new L.Geodesic(latlngs, options);
|
||||
};
|
Binary file not shown.
After Width: | Height: | Size: 2.5 KiB |
|
@ -6,27 +6,48 @@
|
|||
integrity="sha512-nMMmRyTVoLYqjP9hrbed9S+FzjZHW5gY1TWCHA5ckwXZBadntCNs8kEqAWdrb9O7rxbCaA4lKTIWjDXZxflOcA=="
|
||||
crossorigin=""></script>
|
||||
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
|
||||
<script src=" https://unpkg.com/@joergdietrich/leaflet.terminator@1.0.0/L.Terminator.js"></script>
|
||||
<script async src="//pagead2.googlesyndication.com/pagead/js/adsbygoogle.js"></script>
|
||||
<script src="/static/Leaflet.Geodesic.js"></script>
|
||||
</head>
|
||||
|
||||
<style>
|
||||
#mapid { height: 500px; }
|
||||
#mapid { height: 700px; }
|
||||
</style>
|
||||
|
||||
<div class="container">
|
||||
<div class="row"> .
|
||||
<div class="col-md-12">
|
||||
<center>
|
||||
<img src="/static/satnogs-net-logo.png">
|
||||
<img src="/static/satnogs-net-logo.png">
|
||||
<br>
|
||||
<br>
|
||||
<div id="mapid" ></div>
|
||||
|
||||
</center>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- Satnogs -->
|
||||
<ins class="adsbygoogle"
|
||||
style="display:inline-block;width:468px;height:60px"
|
||||
data-ad-client="ca-pub-3327739403768095"
|
||||
data-ad-slot="5333748891"></ins>
|
||||
<script>
|
||||
(adsbygoogle = window.adsbygoogle || []).push({});
|
||||
</script>
|
||||
|
||||
<script>
|
||||
|
||||
var sat = L.icon({
|
||||
var light_sat = L.icon({
|
||||
iconUrl: 'static/light-satellite-marker.png',
|
||||
iconSize: [40, 40],
|
||||
iconAnchor: [20, 20],
|
||||
popupAnchor: [0, 0],
|
||||
|
||||
});
|
||||
|
||||
var dark_sat = L.icon({
|
||||
iconUrl: 'static/satellite-marker.png',
|
||||
iconSize: [40, 40],
|
||||
iconAnchor: [20, 20],
|
||||
|
@ -50,7 +71,7 @@ var active_station = L.icon({
|
|||
|
||||
});
|
||||
|
||||
var mymap = L.map('mapid').setView([0,0], 2);
|
||||
var mymap = L.map('mapid',{worldCopyJump:true}).setView([0,0], 2);
|
||||
L.tileLayer('https://api.tiles.mapbox.com/v4/{id}/{z}/{x}/{y}.png?access_token={accessToken}', {
|
||||
attribution: 'Map data © <a href="https://www.openstreetmap.org/">OpenStreetMap</a> contributors, <a href="https://creativecommons.org/licenses/by-sa/2.0/">CC-BY-SA</a>, Imagery © <a href="https://www.mapbox.com/">Mapbox</a>',
|
||||
maxZoom: 18,
|
||||
|
@ -78,8 +99,12 @@ var links = {}
|
|||
$.get("/api/occuringsats", function(data, status){
|
||||
data = JSON.parse(data)
|
||||
Object.keys(data).forEach(function(key){
|
||||
sat = light_sat
|
||||
if(data[key]["eclipsed"]){
|
||||
sat = dark_sat
|
||||
}
|
||||
marker = L.marker(data[key]["lat_lng"],{icon: sat,zIndexOffset:1000}).addTo(mymap);
|
||||
marker.bindPopup("<b>Name: "+data[key]["name"]+"</b>");
|
||||
marker.bindPopup("<b>Name: "+data[key]["name"]+"</b><br><b>Norad: "+key+"</b><br><b>Eclipsed?: "+data[key]["eclipsed"]);
|
||||
sats[key] = marker;
|
||||
});
|
||||
});
|
||||
|
@ -88,8 +113,9 @@ $.get("/api/satstationpairs", function(data, status){
|
|||
data = JSON.parse(data)
|
||||
data.forEach(function(entry){
|
||||
firstpolyline = new L.Polyline([[stationList[entry[0]]._latlng.lat,stationList[entry[0]]._latlng.lng],[sats[entry[1]]._latlng.lat,sats[entry[1]]._latlng.lng]], {color: '#'+entry[1].toString(16).repeat(2).substr(0,6),weight: 3,opacity: 1,smoothFactor: 1});
|
||||
firstpolyline.addTo(mymap)
|
||||
firstpolyline.bringToFront()
|
||||
|
||||
firstpolyline.addTo(mymap)
|
||||
|
||||
links[entry[0]] = firstpolyline
|
||||
stationList[entry[0]].setIcon(active_station)
|
||||
stationList[entry[0]].setZIndexOffset(500)
|
||||
|
@ -118,8 +144,12 @@ setInterval(function(){
|
|||
})
|
||||
|
||||
Object.keys(data).forEach(function(key){
|
||||
sat = light_sat
|
||||
if(data[key]["eclipsed"]){
|
||||
sat = dark_sat
|
||||
}
|
||||
marker = L.marker(data[key]["lat_lng"],{icon: sat,zIndexOffset:1000}).addTo(mymap);
|
||||
marker.bindPopup("<b>Name: "+data[key]["name"]+"</b><br><b>Norad: "+key+"</b>");
|
||||
marker.bindPopup("<b>Name: "+data[key]["name"]+"</b><br><b>Norad: "+key+"</b><br><b>Eclipsed?: "+data[key]["eclipsed"]);
|
||||
sats[key] = marker;
|
||||
});
|
||||
|
||||
|
@ -136,6 +166,7 @@ setInterval(function(){
|
|||
})
|
||||
data.forEach(function(entry){
|
||||
firstpolyline = new L.Polyline([[stationList[entry[0]]._latlng.lat,stationList[entry[0]]._latlng.lng],[sats[entry[1]]._latlng.lat,sats[entry[1]]._latlng.lng]], {color: '#'+entry[1].toString(16).repeat(2).substr(0,6),weight:3,opacity:1,smoothFactor: 1});
|
||||
|
||||
firstpolyline.addTo(mymap)
|
||||
links[entry[0]] = firstpolyline
|
||||
stationList[entry[0]].setIcon(active_station)
|
||||
|
@ -146,5 +177,17 @@ setInterval(function(){
|
|||
console.log(links)
|
||||
|
||||
}, 20000);
|
||||
|
||||
var t = L.terminator();
|
||||
t.addTo(mymap);
|
||||
setInterval(function(){updateTerminator(t)}, 500);
|
||||
function updateTerminator(t) {
|
||||
var t2 = L.terminator();
|
||||
t.setLatLngs(t2.getLatLngs());
|
||||
t.redraw();
|
||||
}
|
||||
|
||||
</script>
|
||||
</script>
|
||||
|
||||
|
||||
<a rel="license" href="http://creativecommons.org/licenses/by-sa/4.0/"><img alt="Creative Commons License" style="border-width:0" src="https://i.creativecommons.org/l/by-sa/4.0/88x31.png" /></a><br />This work is licensed under a <a rel="license" href="http://creativecommons.org/licenses/by-sa/4.0/">Creative Commons Attribution-ShareAlike 4.0 International License</a>
|
||||
|
|
Loading…
Reference in New Issue