|
1
|
|
|
/**************************************************************************** |
|
2
|
|
|
Leaflet.Terminator.js, |
|
3
|
|
|
|
|
4
|
|
|
(c) 2016, FCOO |
|
5
|
|
|
|
|
6
|
|
|
https://github.com/FCOO/Leaflet.Terminator |
|
7
|
|
|
https://github.com/FCOO |
|
8
|
|
|
|
|
9
|
|
|
****************************************************************************/ |
|
10
|
|
|
(function (L/*, window, document, undefined*/) { |
|
11
|
|
|
"use strict"; |
|
12
|
|
|
|
|
13
|
|
|
/* Terminator.js -- Overlay day/night region on a Leaflet map */ |
|
14
|
|
|
|
|
15
|
|
|
/* Extending prototype of native object - don't do it |
|
16
|
|
|
Date.prototype.getJulian = function() { |
|
17
|
|
|
// Calculate the present UTC Julian Date. Function is valid after the beginning of the UNIX epoch 1970-01-01 and ignores leap seconds. |
|
18
|
|
|
return (this / 86400000) + 2440587.5; |
|
19
|
|
|
}; |
|
20
|
|
|
*/ |
|
21
|
|
|
function getJulian( date ){ |
|
22
|
|
|
// Calculate the present UTC Julian Date. Function is valid after the beginning of the UNIX epoch 1970-01-01 and ignores leap seconds. |
|
23
|
|
|
return (date / 86400000) + 2440587.5; |
|
24
|
|
|
} |
|
25
|
|
|
|
|
26
|
|
|
/* Extending prototype of native object - don't do it |
|
27
|
|
|
Date.prototype.getGMST = function() { |
|
28
|
|
|
// Calculate Greenwich Mean Sidereal Time according to http://aa.usno.navy.mil/faq/docs/GAST.php / |
|
29
|
|
|
var julianDay = this.getJulian(); |
|
30
|
|
|
var d = julianDay - 2451545.0; |
|
31
|
|
|
// Low precision equation is good enough for our purposes. |
|
32
|
|
|
return (18.697374558 + 24.06570982441908 * d) % 24; |
|
33
|
|
|
}; |
|
34
|
|
|
*/ |
|
35
|
|
|
function getGMST( date ){ |
|
36
|
|
|
// Calculate Greenwich Mean Sidereal Time according to http://aa.usno.navy.mil/faq/docs/GAST.php / |
|
37
|
|
|
var julianDay = getJulian( date ); |
|
38
|
|
|
var d = julianDay - 2451545.0; |
|
39
|
|
|
// Low precision equation is good enough for our purposes. |
|
40
|
|
|
return (18.697374558 + 24.06570982441908 * d) % 24; |
|
41
|
|
|
} |
|
42
|
|
|
|
|
43
|
|
|
|
|
44
|
|
|
L.Terminator = L.Polygon.extend({ |
|
45
|
|
|
options: { |
|
46
|
|
|
color: '#00', |
|
47
|
|
|
opacity: 0.5, |
|
48
|
|
|
fillColor: '#00', |
|
49
|
|
|
fillOpacity: 0.5, |
|
50
|
|
|
resolution: 2 |
|
51
|
|
|
}, |
|
52
|
|
|
|
|
53
|
|
|
initialize: function(options) { |
|
54
|
|
|
this.VERSION = "1.0.1"; |
|
55
|
|
|
this._R2D = 180 / Math.PI; |
|
56
|
|
|
this._D2R = Math.PI / 180; |
|
57
|
|
|
L.Util.setOptions(this, options); |
|
58
|
|
|
var latLng = this._compute(this.options.time || null); |
|
59
|
|
|
this.setLatLngs(latLng); |
|
60
|
|
|
}, |
|
61
|
|
|
|
|
62
|
|
|
onAdd: function(map) { |
|
63
|
|
|
L.Polygon.prototype.onAdd.call(this, map); |
|
64
|
|
|
var that = this; |
|
65
|
|
|
// Subscribe to datetime updates |
|
66
|
|
|
map.on('datetimechange', function(evt) { |
|
67
|
|
|
var datetime = evt.datetime.split('T'); |
|
68
|
|
|
var date = datetime[0].split('-'); |
|
69
|
|
|
var time = datetime[1].split(':'); |
|
70
|
|
|
datetime = new Date(Date.UTC(parseInt(date[0]), parseInt(date[1])-1, parseInt(date[2]), parseInt(time[0]), parseInt(time[1]), parseInt(time[2].replace('Z','')))); |
|
71
|
|
|
that.setTime(datetime); |
|
72
|
|
|
}); |
|
73
|
|
|
}, |
|
74
|
|
|
|
|
75
|
|
|
setTime: function(date) { |
|
76
|
|
|
this.options.time = date; |
|
77
|
|
|
var latLng = this._compute(date || null); |
|
78
|
|
|
this.setLatLngs(latLng); |
|
79
|
|
|
}, |
|
80
|
|
|
|
|
81
|
|
|
_sunEclipticPosition: function(julianDay) { |
|
82
|
|
|
/* Compute the position of the Sun in ecliptic coordinates at |
|
83
|
|
|
julianDay. Following |
|
84
|
|
|
http://en.wikipedia.org/wiki/Position_of_the_Sun */ |
|
85
|
|
|
// Days since start of J2000.0 |
|
86
|
|
|
var n = julianDay - 2451545.0; |
|
87
|
|
|
// mean longitude of the Sun |
|
88
|
|
|
var L = 280.460 + 0.9856474 * n; |
|
89
|
|
|
L %= 360; |
|
90
|
|
|
// mean anomaly of the Sun |
|
91
|
|
|
var g = 357.528 + 0.9856003 * n; |
|
92
|
|
|
g %= 360; |
|
93
|
|
|
// ecliptic longitude of Sun |
|
94
|
|
|
var lambda = L + 1.915 * Math.sin(g * this._D2R) + 0.02 * Math.sin(2 * g * this._D2R); |
|
95
|
|
|
// distance from Sun in AU |
|
96
|
|
|
var R = 1.00014 - 0.01671 * Math.cos(g * this._D2R) - 0.0014 * Math.cos(2 * g * this._D2R); |
|
97
|
|
|
return {"lambda": lambda, "R": R}; |
|
98
|
|
|
}, |
|
99
|
|
|
|
|
100
|
|
|
_eclipticObliquity: function(julianDay) { |
|
101
|
|
|
// Following the short term expression in |
|
102
|
|
|
// http://en.wikipedia.org/wiki/Axial_tilt#Obliquity_of_the_ecliptic_.28Earth.27s_axial_tilt.29 |
|
103
|
|
|
var n = julianDay - 2451545.0; |
|
104
|
|
|
// Julian centuries since J2000.0 |
|
105
|
|
|
var T = n / 36525; |
|
106
|
|
|
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)))); |
|
107
|
|
|
return epsilon; |
|
108
|
|
|
}, |
|
109
|
|
|
|
|
110
|
|
|
_sunEquatorialPosition: function(sunEclLng, eclObliq) { |
|
111
|
|
|
/* Compute the Sun's equatorial position from its ecliptic |
|
112
|
|
|
* position. Inputs are expected in degrees. Outputs are in |
|
113
|
|
|
* degrees as well. */ |
|
114
|
|
|
var alpha = Math.atan(Math.cos(eclObliq * this._D2R) * Math.tan(sunEclLng * this._D2R)) * this._R2D; |
|
115
|
|
|
var delta = Math.asin(Math.sin(eclObliq * this._D2R) * Math.sin(sunEclLng * this._D2R)) * this._R2D; |
|
116
|
|
|
|
|
117
|
|
|
var lQuadrant = Math.floor(sunEclLng / 90) * 90; |
|
118
|
|
|
var raQuadrant = Math.floor(alpha / 90) * 90; |
|
119
|
|
|
alpha = alpha + (lQuadrant - raQuadrant); |
|
120
|
|
|
|
|
121
|
|
|
return {"alpha": alpha, "delta": delta}; |
|
122
|
|
|
}, |
|
123
|
|
|
|
|
124
|
|
|
_hourAngle: function(lng, sunPos, gst) { |
|
125
|
|
|
/* Compute the hour angle of the sun for a longitude on |
|
126
|
|
|
* Earth. Return the hour angle in degrees. */ |
|
127
|
|
|
var lst = gst + lng / 15; |
|
128
|
|
|
return lst * 15 - sunPos.alpha; |
|
129
|
|
|
}, |
|
130
|
|
|
|
|
131
|
|
|
_latitude: function(ha, sunPos) { |
|
132
|
|
|
/* For a given hour angle and sun position, compute the |
|
133
|
|
|
* latitude of the terminator in degrees. */ |
|
134
|
|
|
var lat = Math.atan(-Math.cos(ha * this._D2R) / |
|
135
|
|
|
Math.tan(sunPos.delta * this._D2R)) * this._R2D; |
|
136
|
|
|
return lat; |
|
137
|
|
|
}, |
|
138
|
|
|
|
|
139
|
|
|
_compute: function(time) { |
|
140
|
|
|
var today = time === null ? new Date() : new Date(time), |
|
141
|
|
|
julianDay = getJulian(today), //today.getJulian(), |
|
142
|
|
|
gst = getGMST( today ), //today.getGMST(), |
|
143
|
|
|
latLng = [], |
|
144
|
|
|
ha, lat, lng, |
|
145
|
|
|
sunEclPos = this._sunEclipticPosition(julianDay), |
|
146
|
|
|
eclObliq = this._eclipticObliquity(julianDay), |
|
147
|
|
|
sunEqPos = this._sunEquatorialPosition(sunEclPos.lambda, eclObliq); |
|
148
|
|
|
|
|
149
|
|
|
for (var i = 0; i <= 720 * this.options.resolution; i++) { |
|
150
|
|
|
lng = -360 + i / this.options.resolution; |
|
151
|
|
|
ha = this._hourAngle(lng, sunEqPos, gst); |
|
152
|
|
|
lat = this._latitude(ha, sunEqPos); |
|
153
|
|
|
latLng[i+1] = [lat, lng]; |
|
154
|
|
|
} |
|
155
|
|
|
if (sunEqPos.delta < 0) { |
|
156
|
|
|
latLng[0] = [90, -360]; |
|
157
|
|
|
latLng[latLng.length] = [90, 360]; |
|
158
|
|
|
} else { |
|
159
|
|
|
latLng[0] = [-90, -360]; |
|
160
|
|
|
latLng[latLng.length] = [-90, 360]; |
|
161
|
|
|
} |
|
162
|
|
|
return latLng; |
|
163
|
|
|
} |
|
164
|
|
|
|
|
165
|
|
|
}); |
|
166
|
|
|
|
|
167
|
|
|
L.terminator = function(options) { |
|
168
|
|
|
return new L.Terminator(options); |
|
169
|
|
|
}; |
|
170
|
|
|
|
|
171
|
|
|
}(L, this, document)); |
|
|
|
|
|
|
172
|
|
|
|
|
173
|
|
|
|
|
174
|
|
|
|
|
175
|
|
|
|
|
176
|
|
|
|
This checks looks for references to variables that have not been declared. This is most likey a typographical error or a variable has been renamed.
To learn more about declaring variables in Javascript, see the MDN.