Created
May 9, 2017 16:18
-
-
Save jonyrock/6d5f2339100af6b24cc049832d4bffd4 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
Terminator.js -- Overlay day/night region on a Leaflet map | |
based on https://github.com/joergdietrich/Leaflet.Terminator | |
*/ | |
/* | |
Calculate the present UTC Julian Date. Function is valid after | |
the beginning of the UNIX epoch 1970-01-01 and ignores leap | |
seconds. | |
*/ | |
Date.prototype.getJulian = function() { | |
return (this / 86400000) + 2440587.5; | |
} | |
/* | |
Calculate Greenwich Mean Sidereal Time according to | |
http://aa.usno.navy.mil/faq/docs/GAST.php | |
*/ | |
Date.prototype.getGMST = function() { | |
var julianDay = this.getJulian(); | |
var d = julianDay - 2451545.0; | |
// Low precision equation is good enough for our purposes. | |
return (18.697374558 + 24.06570982441908 * d) % 24; | |
} | |
export const Terminator = L.Polygon.extend({ | |
options: { | |
color: '#00', | |
opacity: 0.5, | |
fillColor: '#00', | |
fillOpacity: 0.5, | |
resolution: 2 | |
}, | |
initialize: function(options) { | |
this.version = '0.1.0'; | |
this._R2D = 180 / Math.PI; | |
this._D2R = Math.PI / 180; | |
L.Util.setOptions(this, options); | |
var latLng = this._compute(this.options.time || null) | |
this.setLatLngs(latLng); | |
}, | |
setTime: function(date) { | |
console.log('set time'); | |
this.options.time = date; | |
var latLng = this._compute(date || null) | |
this.setLatLngs(latLng); | |
}, | |
/* | |
Compute the position of the Sun in ecliptic coordinates at julianDay. | |
Following http://en.wikipedia.org/wiki/Position_of_the_Sun | |
*/ | |
_sunEclipticPosition: function(julianDay) { | |
// Days since start of J2000.0 | |
var n = julianDay - 2451545.0; | |
// mean longitude of the Sun | |
var L = 280.460 + 0.9856474 * n; | |
L %= 360; | |
// mean anomaly of the Sun | |
var g = 357.528 + 0.9856003 * n; | |
g %= 360; | |
// ecliptic longitude of Sun | |
var lambda = L + 1.915 * Math.sin(g * this._D2R) + | |
0.02 * Math.sin(2 * g * this._D2R); | |
// distance from Sun in AU | |
var R = 1.00014 - 0.01671 * Math.cos(g * this._D2R) - | |
0.0014 * Math.cos(2 * g * this._D2R); | |
return { | |
"lambda": lambda, | |
"R": R | |
}; | |
}, | |
/* | |
Following the short term expression in | |
http://en.wikipedia.org/wiki/Axial_tilt#Obliquity_of_the_ecliptic_.28Earth.27s_axial_tilt.29 | |
*/ | |
_eclipticObliquity: function(julianDay) { | |
var n = julianDay - 2451545.0; | |
// Julian centuries since J2000.0 | |
var T = n / 36525; | |
var epsilon = 23.43929111 - | |
T * (46.836769 / 3600 - | |
T * (0.0001831 / 3600 + | |
T * (0.00200340 / 3600 - | |
T * (0.576e-6 / 3600 - | |
T * 4.34e-8 / 3600)))); | |
return epsilon; | |
}, | |
/* | |
Compute the Sun's equatorial position from its ecliptic position. | |
Inputs are expected in degrees. Outputs are in degrees as well. | |
*/ | |
_sunEquatorialPosition: function(sunEclLng, eclObliq) { | |
var alpha = Math.atan(Math.cos(eclObliq * this._D2R) * | |
Math.tan(sunEclLng * this._D2R)) * this._R2D; | |
var delta = Math.asin(Math.sin(eclObliq * this._D2R) * | |
Math.sin(sunEclLng * this._D2R)) * this._R2D; | |
var lQuadrant = Math.floor(sunEclLng / 90) * 90; | |
var raQuadrant = Math.floor(alpha / 90) * 90; | |
alpha = alpha + (lQuadrant - raQuadrant); | |
return { | |
"alpha": alpha, | |
"delta": delta | |
}; | |
}, | |
/* | |
Compute the hour angle of the sun for a longitude on Earth. | |
Return the hour angle in degrees. | |
*/ | |
_hourAngle: function(lng, sunPos, gst) { | |
var lst = gst + lng / 15; | |
return lst * 15 - sunPos.alpha; | |
}, | |
/* | |
For a given hour angle and sun position, compute the | |
latitude of the terminator in degrees. | |
*/ | |
_latitude: function(ha, sunPos) { | |
var lat = Math.atan(-Math.cos(ha * this._D2R) / | |
Math.tan(sunPos.delta * this._D2R)) * this._R2D; | |
return lat; | |
}, | |
_compute: function(time) { | |
if (time == null) { | |
var today = new Date(); | |
} else { | |
var today = new Date(time); | |
} | |
var julianDay = today.getJulian(); | |
var gst = today.getGMST(); | |
var latLng = []; | |
var ha, lat; | |
var sunEclPos = this._sunEclipticPosition(julianDay); | |
var eclObliq = this._eclipticObliquity(julianDay); | |
var sunEqPos = this._sunEquatorialPosition(sunEclPos.lambda, eclObliq); | |
for (var i = 0; i <= 720 * this.options.resolution; i++) { | |
var lng = -360 + i / this.options.resolution; | |
ha = this._hourAngle(lng, sunEqPos, gst); | |
var lat = this._latitude(ha, sunEqPos); | |
latLng[i + 1] = [lat, lng]; | |
} | |
if (sunEqPos.delta < 0) { | |
latLng[0] = [90, -360]; | |
latLng[latLng.length] = [90, 360]; | |
} else { | |
latLng[0] = [-90, -360]; | |
latLng[latLng.length] = [-90, 360]; | |
} | |
return latLng; | |
} | |
}); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment