solar 0.0.2 → 0.1.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/Gemfile +1 -1
- data/Gemfile.lock +30 -5
- data/README.rdoc +2 -2
- data/VERSION +1 -1
- data/lib/solar.rb +7 -462
- data/lib/solar/day_night.rb +65 -0
- data/lib/solar/lambert.rb +68 -0
- data/lib/solar/passages.rb +174 -0
- data/lib/solar/position.rb +51 -0
- data/lib/solar/radiation.rb +258 -0
- data/lib/solar/support.rb +228 -0
- data/solar.gemspec +15 -8
- data/test/test_solar.rb +11 -0
- metadata +29 -38
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: c8f9579b11f6e74d46611e8558786d36fd18a6f3
|
4
|
+
data.tar.gz: 73152c453267480d1d4b9db82fdf4fbad9b8e82b
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 40c66e8eca3c9457b31e6863d44057fcd758622133e6b11b2de734f5a06ec00812551ed09ff2a28fa51d574255366c41c2d9d439cffc0e8ebe98b5626554621c
|
7
|
+
data.tar.gz: d5d1537301f3f070966a250c874525dbb9be2f6e50c68a6f8d3e39e49617adf0a136d55b8a7c226798c3650f06e73efe2254758d60db8a30eb9b30a572177dd4
|
data/Gemfile
CHANGED
data/Gemfile.lock
CHANGED
@@ -4,16 +4,41 @@ GEM
|
|
4
4
|
activesupport (3.2.8)
|
5
5
|
i18n (~> 0.6)
|
6
6
|
multi_json (~> 1.0)
|
7
|
-
|
7
|
+
addressable (2.3.8)
|
8
|
+
builder (3.2.2)
|
9
|
+
faraday (0.7.6)
|
10
|
+
addressable (~> 2.2)
|
11
|
+
multipart-post (~> 1.1)
|
12
|
+
rack (~> 1.1)
|
13
|
+
git (1.2.9.1)
|
14
|
+
github_api (0.4.10)
|
15
|
+
faraday (~> 0.7.6)
|
16
|
+
hashie (~> 1.2.0)
|
17
|
+
multi_json (~> 1.0)
|
18
|
+
oauth2 (~> 0.5.2)
|
19
|
+
hashie (1.2.0)
|
20
|
+
highline (1.7.2)
|
8
21
|
i18n (0.6.1)
|
9
|
-
jeweler (
|
10
|
-
|
22
|
+
jeweler (2.0.1)
|
23
|
+
builder
|
24
|
+
bundler (>= 1.0)
|
11
25
|
git (>= 1.2.5)
|
26
|
+
github_api
|
27
|
+
highline (>= 1.6.15)
|
28
|
+
nokogiri (>= 1.5.10)
|
12
29
|
rake
|
13
30
|
rdoc
|
14
31
|
json (1.7.5)
|
32
|
+
mini_portile (0.6.2)
|
15
33
|
multi_json (1.3.6)
|
16
|
-
|
34
|
+
multipart-post (1.2.0)
|
35
|
+
nokogiri (1.6.6.2)
|
36
|
+
mini_portile (~> 0.6.0)
|
37
|
+
oauth2 (0.5.2)
|
38
|
+
faraday (~> 0.7)
|
39
|
+
multi_json (~> 1.0)
|
40
|
+
rack (1.6.4)
|
41
|
+
rake (10.4.2)
|
17
42
|
rdoc (3.12)
|
18
43
|
json (~> 1.4)
|
19
44
|
shoulda (3.1.1)
|
@@ -29,6 +54,6 @@ PLATFORMS
|
|
29
54
|
DEPENDENCIES
|
30
55
|
activesupport
|
31
56
|
bundler (~> 1)
|
32
|
-
jeweler (~>
|
57
|
+
jeweler (~> 2.0.1)
|
33
58
|
rdoc (~> 3.12)
|
34
59
|
shoulda
|
data/README.rdoc
CHANGED
@@ -1,6 +1,7 @@
|
|
1
1
|
= solar
|
2
2
|
|
3
3
|
Calculation of solar position, rise & set times for a given position & time.
|
4
|
+
Also calculation of solar radiation and radiation on a sloped surface.
|
4
5
|
|
5
6
|
== Contributing to solar
|
6
7
|
|
@@ -14,6 +15,5 @@ Calculation of solar position, rise & set times for a given position & time.
|
|
14
15
|
|
15
16
|
== Copyright
|
16
17
|
|
17
|
-
Copyright (c) 2012 Javier Goizueta. See LICENSE.txt for
|
18
|
+
Copyright (c) 2012-2015 Javier Goizueta. See LICENSE.txt for
|
18
19
|
further details.
|
19
|
-
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.
|
1
|
+
0.1.1
|
data/lib/solar.rb
CHANGED
@@ -5,466 +5,11 @@ require 'active_support/time'
|
|
5
5
|
# Algorithms are taken from Jean Meeus, Astronomical Algorithms
|
6
6
|
# Some code & ideas taken from John P. Power's astro-algo: http://astro-algo.rubyforge.org/astro-algo/
|
7
7
|
module Solar
|
8
|
-
|
9
|
-
ALTITUDES = {
|
10
|
-
:official => -50/60.0,
|
11
|
-
:civil => -6.0,
|
12
|
-
:nautical => -12.0,
|
13
|
-
:astronomical => -18.0
|
14
|
-
}
|
15
|
-
|
16
|
-
class <<self
|
17
|
-
|
18
|
-
# Day-night (or twilight) status at a given position and time
|
19
|
-
# returns :night, :day or :twilight
|
20
|
-
# options:
|
21
|
-
# * :twilight_zenith zenith for the sun at dawn (beginning of twilight)
|
22
|
-
# and at dusk (end of twilight). Default: :civil
|
23
|
-
# * :day_zenith zenith for the san at sunrise and sun set.
|
24
|
-
# Default: :official (sun aparently under the horizon, tangent to it)
|
25
|
-
# These parameters can be assigned zenith values in degrees of the symbols:
|
26
|
-
# :official, :civil, :nautical or :astronomical.
|
27
|
-
# Simple day night result (returning :day or :night) can be requested
|
28
|
-
# by setting :simple=>true (which usses the official day definition)
|
29
|
-
# or by setting a :zenith parameter to the fine the kind of day-night
|
30
|
-
# distinction.
|
31
|
-
# By passing :detailed=>true, the result will be one of:
|
32
|
-
# :night, :astronomical_twilight, :nautical_twilight, :civil_twilight, :day
|
33
|
-
def day_or_night(t, longitude, latitude, options={})
|
34
|
-
h, az = position(t, longitude, latitude)
|
35
|
-
options = {:zenith=>:official} if options[:simple]
|
36
|
-
if options[:detailed]
|
37
|
-
if h<Solar::ALTITUDES[:astronomical]
|
38
|
-
:night
|
39
|
-
elsif h<Solar::ALTITUDES[:nautical]
|
40
|
-
:astronomical_twilight
|
41
|
-
elsif h<Solar::ALTITUDES[:civil]
|
42
|
-
:nautical_twilight
|
43
|
-
elsif h<Solar::ALTITUDES[:official]
|
44
|
-
:civil_twilight
|
45
|
-
else
|
46
|
-
:day
|
47
|
-
end
|
48
|
-
else
|
49
|
-
# Determined :night / :twilight / :day state;
|
50
|
-
# twilight/day definition can be changed with options :zenith or :twilight_zenith, :day_zenith
|
51
|
-
if options[:zenith]
|
52
|
-
# only :day / :night distinction as defined by :zenith
|
53
|
-
twilight_altitude = day_altitude = altitude_from_options(options)
|
54
|
-
else
|
55
|
-
twilight_altitude = altitude_from_options(:zenith => options[:twilight_zenith] || :civil)
|
56
|
-
day_altitude = altitude_from_options(:zenith => options[:day_zenith] || :official)
|
57
|
-
end
|
58
|
-
(h > day_altitude) ? :day : (h <= twilight_altitude) ? :night : :twilight
|
59
|
-
end
|
60
|
-
end
|
61
|
-
|
62
|
-
# Sun horizontal coordinates (relative position) in degrees:
|
63
|
-
# * elevation (altitude over horizon) in degrees; positive upwards
|
64
|
-
# * azimuth in degrees measured clockwise (towards East) from North direction
|
65
|
-
def position(t, longitude, latitude)
|
66
|
-
|
67
|
-
delta_rad, alpha_rad = equatorial_position_rad(t)
|
68
|
-
alpha_deg = to_deg(alpha_rad)
|
69
|
-
# alpha_h += 360 if alpha_h < 0
|
70
|
-
|
71
|
-
|
72
|
-
# t as Julian centuries of 36525 ephemeris days form the epoch J2000.0
|
73
|
-
if false
|
74
|
-
# Float
|
75
|
-
jd = jd_f(t)
|
76
|
-
else
|
77
|
-
# Rational
|
78
|
-
jd = jd_r(t)
|
79
|
-
end
|
80
|
-
t = to_jc(jd)
|
81
|
-
|
82
|
-
# Sidereal time at Greenwich
|
83
|
-
theta = 280.46061837 + 360.98564736629*(jd-2451545) + (0.000387933 - t/38710000)*t*t
|
84
|
-
|
85
|
-
# Reduce magnitude to minimize errors
|
86
|
-
theta %= 360
|
87
|
-
|
88
|
-
# Local hour angle
|
89
|
-
h = theta + longitude - alpha_deg
|
90
|
-
h %= 360
|
91
|
-
|
92
|
-
latitude_rad = to_rad(latitude)
|
93
|
-
h_rad = to_rad(h)
|
94
|
-
|
95
|
-
# Local horizontal coordinates : Meeus pg 89
|
96
|
-
altitude_rad = Math.asin(Math.sin(latitude_rad)*Math.sin(delta_rad) + Math.cos(latitude_rad)*Math.cos(delta_rad)*Math.cos(h_rad))
|
97
|
-
azimuth_rad = Math.atan2((Math.sin(h_rad)),((Math.cos(h_rad) * Math.sin(latitude_rad)) - Math.tan(delta_rad) * Math.cos(latitude_rad)))
|
98
|
-
|
99
|
-
[to_deg(altitude_rad), (180+to_deg(azimuth_rad))%360 ]
|
100
|
-
|
101
|
-
end
|
102
|
-
|
103
|
-
# Sun rise time for a given date (UTC) and position.
|
104
|
-
# The :zenith or :altitude of the sun can be passed as an argument,
|
105
|
-
# which can be numeric (in degrees) or symbolic:
|
106
|
-
# :official, :civil, :nautical or :astronomical.
|
107
|
-
# nil is returned if the sun doesn't rise at the date and position.
|
108
|
-
def rise(date, longitude, latitude, options={})
|
109
|
-
rising, transit, setting = passages(date, longitude, latitude, options)
|
110
|
-
if rising==setting || (setting-rising)==1
|
111
|
-
nil # rising==setting => no rise; setting-rising == 1 => no set
|
112
|
-
else
|
113
|
-
rising
|
114
|
-
end
|
115
|
-
end
|
116
|
-
|
117
|
-
# Sun set time for a given date (UTC) and position.
|
118
|
-
# The :zenith or :altitude of the sun can be passed as an argument,
|
119
|
-
# which can be numeric (in degrees) or symbolic:
|
120
|
-
# :official, :civil, :nautical or :astronomical.
|
121
|
-
# nil is returned if the sun doesn't set at the date and position.
|
122
|
-
def set(date, longitude, latitude, options={})
|
123
|
-
rising, transit, setting = passages(date, longitude, latitude, options)
|
124
|
-
if rising==setting || (setting-rising)==1
|
125
|
-
nil # rising==setting => no rise; setting-rising == 1 => no set
|
126
|
-
else
|
127
|
-
setting
|
128
|
-
end
|
129
|
-
end
|
130
|
-
|
131
|
-
# Rise and set times as given by rise() and set()
|
132
|
-
def rise_and_set(date, longitude, latitude, options={})
|
133
|
-
rising, transit, setting = passages(date, longitude, latitude, options)
|
134
|
-
if rising==setting || (setting-rising)==1
|
135
|
-
nil # rising==setting => no rise; setting-rising == 1 => no set
|
136
|
-
else
|
137
|
-
[rising, setting]
|
138
|
-
end
|
139
|
-
end
|
140
|
-
|
141
|
-
# Solar passages [rising, transit, setting] for a given date (UTC) and position.
|
142
|
-
# The :zenith or :altitude of the sun can be passed as an argument,
|
143
|
-
# which can be numeric (in degrees) or symbolic:
|
144
|
-
# :official, :civil, :nautical or :astronomical.
|
145
|
-
# In circumpolar case:
|
146
|
-
# If Sun never rises, returns 00:00:00 on Date for all passages.
|
147
|
-
# If Sun never sets, returns 00:00:00 (rising), 12:00:00 (transit), 24:00:00 (setting)
|
148
|
-
# on Date for all passages.
|
149
|
-
def passages(date, longitude, latitude, options={})
|
150
|
-
|
151
|
-
ho = altitude_from_options(options)
|
152
|
-
t = to_jc(jd_r(date.to_datetime))
|
153
|
-
theta0 = (100.46061837 + (36000.770053608 + (0.000387933 - t/38710000)*t)*t) % 360
|
154
|
-
# Calculate apparent right ascention and declination for 0 hr Dynamical time for three days (degrees)
|
155
|
-
ra = []
|
156
|
-
decl = []
|
157
|
-
-1.upto(1) do |i|
|
158
|
-
declination, right_ascention = equatorial_position_rad((date+i).to_datetime)
|
159
|
-
ra << to_deg(right_ascention)
|
160
|
-
decl << to_deg(declination)
|
161
|
-
end
|
162
|
-
# tweak right ascention around 180 degrees (autumnal equinox)
|
163
|
-
if ra[0] > ra[1]
|
164
|
-
ra[0] -= 360
|
165
|
-
end
|
166
|
-
if ra[2] < ra[1]
|
167
|
-
ra[2] += 360
|
168
|
-
end
|
169
|
-
|
170
|
-
ho_rad, latitude_rad = [ho, latitude].map{|x| to_rad(x)}
|
171
|
-
decl_rad = decl.map{|x| to_rad(x)}
|
172
|
-
|
173
|
-
# approximate Hour Angle (degrees)
|
174
|
-
ha = Math.sin(ho_rad) / (Math.cos(latitude_rad) * Math.cos(decl_rad[1])) - Math.tan(latitude_rad) * Math.tan(decl_rad[1])
|
175
|
-
# handle circumpolar. see note 2 at end of chapter
|
176
|
-
if ha.abs <= 1
|
177
|
-
ha = to_deg(Math.acos(ha))
|
178
|
-
elsif ha > 1 # circumpolar - sun never rises
|
179
|
-
# format sunrise, sunset & solar noon as DateTime
|
180
|
-
sunrise = date.to_datetime
|
181
|
-
transit = date.to_datetime
|
182
|
-
sunset = date.to_datetime
|
183
|
-
return [sunrise, transit, sunset]
|
184
|
-
else # cirumpolar - sun never sets
|
185
|
-
# format sunrise, sunset & solar noon as DateTime
|
186
|
-
sunrise = date.to_datetime
|
187
|
-
transit = date.to_datetime + 0.5
|
188
|
-
sunset = date.to_datetime + 1
|
189
|
-
return [sunrise, transit, sunset]
|
190
|
-
end
|
191
|
-
# approximate m (fraction of 1 day)
|
192
|
-
# store days added or subtracted to add in later
|
193
|
-
m = []
|
194
|
-
days = [0]*3
|
195
|
-
for i in 0..2
|
196
|
-
case i
|
197
|
-
when 0
|
198
|
-
m[i] = (ra[1] - longitude - theta0) / 360 # transit
|
199
|
-
day_offset = +1
|
200
|
-
when 1
|
201
|
-
m[i] = m[0] - ha / 360 # rising
|
202
|
-
day_offset = -1
|
203
|
-
when 2
|
204
|
-
m[i] = m[0] + ha / 360 # setting
|
205
|
-
day_offset = -1
|
206
|
-
end
|
207
|
-
|
208
|
-
until m[i] >= 0 do
|
209
|
-
m[i] += 1
|
210
|
-
days[i] += day_offset
|
211
|
-
end
|
212
|
-
until m[i] <= 1 do
|
213
|
-
m[i] -= 1
|
214
|
-
days[i] -= day_offset
|
215
|
-
end
|
216
|
-
end
|
217
|
-
theta = [] # apparent sidereal time (degrees)
|
218
|
-
ra2 = [] # apparent right ascension (degrees)
|
219
|
-
decl2 = [] # apparent declination (degrees)
|
220
|
-
h = [] # local hour angle (degrees)
|
221
|
-
alt = [] # altitude (degrees)
|
222
|
-
delta_m = [1]*3
|
223
|
-
while ( delta_m[0] >= 0.01 || delta_m[1] >= 0.01 || delta_m[2] >= 0.01 ) do
|
224
|
-
0.upto(2) do |i|
|
225
|
-
theta[i] = theta0 + 360.985647 * m[i]
|
226
|
-
n = m[i] + delta_t(date.to_datetime).to_r / 86400
|
227
|
-
a = ra[1] - ra[0]
|
228
|
-
b = ra[2] - ra[1]
|
229
|
-
c = b - a
|
230
|
-
ra2[i] = ra[1] + n / 2 * ( a + b + n * c )
|
231
|
-
|
232
|
-
n = m[i] + delta_t(date.to_datetime).to_r / 86400
|
233
|
-
a = decl[1] - decl[0]
|
234
|
-
b = decl[2] - decl[1]
|
235
|
-
c = b - a
|
236
|
-
decl2[i] = decl[1] + n / 2 * ( a + b + n * c )
|
237
|
-
|
238
|
-
h[i] = theta[i] + longitude - ra2[i]
|
239
|
-
|
240
|
-
alt[i] = to_deg Math.asin(Math.sin(latitude_rad) * Math.sin(to_rad(decl2[i])) +
|
241
|
-
Math.cos(latitude_rad) * Math.cos(to_rad(decl2[i])) * Math.cos(to_rad(h[i])))
|
242
|
-
end
|
243
|
-
# adjust m
|
244
|
-
delta_m[0] = -h[0] / 360
|
245
|
-
1.upto(2) do |i|
|
246
|
-
delta_m[i] = (alt[i] - ho) / (360 * Math.cos(to_rad(decl2[i])) * Math.cos(latitude_rad) * Math.sin(to_rad(h[i])))
|
247
|
-
end
|
248
|
-
0.upto(2) do |i|
|
249
|
-
m[i] += delta_m[i]
|
250
|
-
end
|
251
|
-
end
|
252
|
-
# format sunrise, sunset & solar noon as DateTime
|
253
|
-
sunrise = date.to_datetime + m[1] + days[1]
|
254
|
-
transit = date.to_datetime + m[0] + days[0]
|
255
|
-
sunset = date.to_datetime + m[2] + days[2]
|
256
|
-
[sunrise, transit, sunset]
|
257
|
-
end
|
258
|
-
|
259
|
-
|
260
|
-
private
|
261
|
-
|
262
|
-
# Julian Day as Rational
|
263
|
-
def jd_r(t)
|
264
|
-
if false
|
265
|
-
# This computes JD with precision of seconds and yields smaller denominators
|
266
|
-
t = t.utc
|
267
|
-
t.to_date.ajd + Rational(t.hour,24) + Rational(t.min,1440) + Rational(t.sec,86400)
|
268
|
-
else
|
269
|
-
# This preserves the internal precision of t (which we probably don't need)
|
270
|
-
# and produces larger denominators in general
|
271
|
-
t.to_datetime.utc.ajd
|
272
|
-
end
|
273
|
-
end
|
274
|
-
|
275
|
-
# Julian Day as Float
|
276
|
-
def jd_f(t)
|
277
|
-
# t.to_date.ajd.to_f + t.hour/24.0 + t.min/1440.0 + t.sec/86400.0
|
278
|
-
t.to_datetime.utc.ajd.to_f
|
279
|
-
end
|
280
|
-
|
281
|
-
def to_rad(deg)
|
282
|
-
deg*Math::PI/180.0
|
283
|
-
end
|
284
|
-
|
285
|
-
def to_deg(rad)
|
286
|
-
rad*180.0/Math::PI
|
287
|
-
end
|
288
|
-
|
289
|
-
def to_h(deg)
|
290
|
-
deg/15.0
|
291
|
-
end
|
292
|
-
|
293
|
-
# Julian day to Julian Centuries since J2000.0
|
294
|
-
def to_jc(jd)
|
295
|
-
(jd - 2451545)/36525
|
296
|
-
end
|
297
|
-
|
298
|
-
def polynomial(coefficients, x)
|
299
|
-
coefficients.inject(0.0){|p, a| p*x + a}
|
300
|
-
end
|
301
|
-
|
302
|
-
# Conversion of Float to Rational preserving the exact value of the number
|
303
|
-
def to_r(x)
|
304
|
-
x = x.to_f
|
305
|
-
return Rational(x.to_i,1) if x.modulo(1)==0
|
306
|
-
if !x.finite?
|
307
|
-
return Rational(0,0) if x.nan?
|
308
|
-
return x<0 ? Rational(-1,0) : Rational(1,0)
|
309
|
-
end
|
310
|
-
|
311
|
-
f,e = Math.frexp(x)
|
312
|
-
|
313
|
-
if e < Float::MIN_EXP
|
314
|
-
bits = e+Float::MANT_DIG-Float::MIN_EXP
|
315
|
-
else
|
316
|
-
bits = [Float::MANT_DIG,e].max
|
317
|
-
#return Rational(x.to_i,1) if bits<e
|
318
|
-
end
|
319
|
-
p = Math.ldexp(f,bits)
|
320
|
-
e = bits - e
|
321
|
-
if e<Float::MAX_EXP
|
322
|
-
q = Math.ldexp(1,e)
|
323
|
-
else
|
324
|
-
q = Float::RADIX**e
|
325
|
-
end
|
326
|
-
return Rational(p.to_i,q.to_i)
|
327
|
-
end
|
328
|
-
|
329
|
-
# time to dynamical time
|
330
|
-
def to_td(t)
|
331
|
-
t = t.utc
|
332
|
-
t + to_r(delta_t(t))/86400
|
333
|
-
end
|
334
|
-
|
335
|
-
# dynamical_time to utc
|
336
|
-
def to_utc(td)
|
337
|
-
raise "Invalid dynamical time (should be utc)" unless td.utc?
|
338
|
-
td - to_r(delta_t(td))/86400
|
339
|
-
|
340
|
-
end
|
341
|
-
|
342
|
-
# Compute difference between dynamical time and UTC in seconds.
|
343
|
-
# See http://sunearth.gsfc.nasa.gov/eclipse/SEcat5/deltatpoly.html.
|
344
|
-
# Good from -1999 to +3000.
|
345
|
-
def delta_t(date)
|
346
|
-
|
347
|
-
year = date.year.to_f
|
348
|
-
y = year + (date.month.to_f - 0.5) / 12.0
|
349
|
-
|
350
|
-
case
|
351
|
-
when year < -500.0
|
352
|
-
u = (year - 1820.0) / 100.0
|
353
|
-
-20.0 + 32.0*u*u
|
354
|
-
when year < 500.0
|
355
|
-
u = y / 100.0
|
356
|
-
polynomial [0.0090316521, 0.022174192, -0.1798452, -5.952053, 33.78311, -1014.41, 10583.6], u
|
357
|
-
when year < 1600.0
|
358
|
-
u = (y - 1000.0) / 100.0
|
359
|
-
polynomial [0.0083572073, -0.005050998, -0.8503463, 0.319781, 71.23472, -556.01, 1574.2], u
|
360
|
-
when year < 1700.0
|
361
|
-
t = y - 1600.0
|
362
|
-
polynomial [1.0/7129.0, -0.01532, -0.9808, 120.0], t
|
363
|
-
when year < 1800.0
|
364
|
-
t = y - 1700.0
|
365
|
-
polynomial [-1.0/1174000.0, 0.00013336, -0.0059285, 0.1603, 8.83], t
|
366
|
-
when year < 1860.0
|
367
|
-
t = y - 1800.0
|
368
|
-
polynomial [0.000000000875, -0.0000001699, 0.0000121272, -0.00037436, 0.0041116, 0.0068612, -0.332447, 13.72], t
|
369
|
-
when year < 1900.0
|
370
|
-
t = y - 1860.0
|
371
|
-
polynomial [1.0/233174.0, -0.0004473624, 0.01680668, -0.251754, 0.5737, 7.62], t
|
372
|
-
when year < 1920.0
|
373
|
-
t = y - 1900.0
|
374
|
-
polynomial [-0.000197, 0.0061966, -0.0598939, 1.494119, -2.79], t
|
375
|
-
when year < 1941.0
|
376
|
-
t = y - 1920.0
|
377
|
-
polynomial [0.0020936, -0.076100, 0.84493, 21.20], t
|
378
|
-
when year < 1961.0
|
379
|
-
t = y - 1950.0
|
380
|
-
polynomial [1.0/2547.0, -1.0/233.0, 0.407, 29.07], t
|
381
|
-
when year < 1986.0
|
382
|
-
t = y - 1975.0
|
383
|
-
polynomial [-1.0/718.0, -1.0/260.0, 1.067, 45.45], t
|
384
|
-
when year < 2005.0
|
385
|
-
t = y - 2000.0
|
386
|
-
polynomial [0.00002373599, 0.000651814, 0.0017275, -0.060374, 0.3345, 63.86], t
|
387
|
-
when year < 2050.0
|
388
|
-
t = y - 2000.0
|
389
|
-
polynomial [0.005589, 0.32217, 62.92], t
|
390
|
-
when year < 2150.0
|
391
|
-
-20.0 + 32.0*((y - 1820.0)/100.0)**2 - 0.5628*(2150.0 - y)
|
392
|
-
else
|
393
|
-
u = (year - 1820.0) / 100.0
|
394
|
-
-20.0 + 32*u*u
|
395
|
-
end
|
396
|
-
end
|
397
|
-
|
398
|
-
# Solar equatorial coordinates / Low accuracy : Meeus pg 151
|
399
|
-
# returns [declination in radians, right ascension in radians]
|
400
|
-
def equatorial_position_rad(t)
|
401
|
-
# t as Julian centuries of 36525 ephemeris days form the epoch J2000.0
|
402
|
-
if false
|
403
|
-
# Float
|
404
|
-
jd = jd_f(to_td(t))
|
405
|
-
else
|
406
|
-
# Rational
|
407
|
-
jd = jd_r(to_td(t))
|
408
|
-
end
|
409
|
-
t = to_jc(jd)
|
410
|
-
|
411
|
-
# Geometric mean longitude of the Sun, referred to the mean equinox of the date
|
412
|
-
l = 280.46645 + (36000.76983 + 0.0003032*t)*t
|
413
|
-
|
414
|
-
# Mean anomaly of the Sun
|
415
|
-
m_deg = 357.52910 + (35999.05030 - (0.0001559 + 0.00000048*t)*t)*t
|
416
|
-
m_rad = to_rad(m_deg)
|
417
|
-
|
418
|
-
# Eccentricity of the Earth's orbit
|
419
|
-
e = 0.016708617 - (0.000042037 + 0.0000001236*t)*t
|
420
|
-
|
421
|
-
# Sun's Equation of the center
|
422
|
-
c = (1.914600 - (0.004817 + 0.000014*t)*t)*Math.sin(m_rad) + (0.019993 - 0.000101*t)*Math.sin(2*m_rad) + 0.000290*Math.sin(3*m_rad)
|
423
|
-
|
424
|
-
# Sun's true longitude
|
425
|
-
o = l + c
|
426
|
-
|
427
|
-
# Reduce magnitude to minimize errors
|
428
|
-
o %= 360
|
429
|
-
|
430
|
-
# Sun's apparent Longitude
|
431
|
-
omega_deg = 125.04 - 1934.136*t
|
432
|
-
omega_rad = to_rad(omega_deg)
|
433
|
-
lambda_deg = o - 0.00569 - 0.00478 * Math.sin(omega_rad)
|
434
|
-
|
435
|
-
# Reduce magnitude to minimize errors
|
436
|
-
lambda_deg %= 360
|
437
|
-
|
438
|
-
lambda_rad = to_rad(lambda_deg)
|
439
|
-
|
440
|
-
# Obliquity of the ecliptic
|
441
|
-
epsilon_deg = 23.4392966666667 - (0.012777777777777778 + (0.00059/60 - 0.00059/60*t)*t)*t + 0.00256*Math.cos(omega_rad)
|
442
|
-
epsilon_rad = to_rad(epsilon_deg)
|
443
|
-
|
444
|
-
# Sun's declination
|
445
|
-
delta_rad = Math.asin(Math.sin(epsilon_rad)*Math.sin(lambda_rad))
|
446
|
-
|
447
|
-
# Sun's right ascension
|
448
|
-
alpha_rad = Math.atan2(((Math.cos(epsilon_rad) * Math.sin(lambda_rad))),(Math.cos(lambda_rad)))
|
449
|
-
|
450
|
-
[delta_rad, alpha_rad]
|
451
|
-
end
|
452
|
-
|
453
|
-
def altitude_from_options(options)
|
454
|
-
if options.has_key?(:zenith)
|
455
|
-
zenith = options[:zenith]
|
456
|
-
if Symbol===zenith
|
457
|
-
altitude = ALTITUDES[zenith]
|
458
|
-
else
|
459
|
-
altitude = 90.0 - zenith
|
460
|
-
end
|
461
|
-
else
|
462
|
-
altitude = options[:altitude] || :official
|
463
|
-
altitude = ALTITUDES[altitude] if Symbol===altitude
|
464
|
-
end
|
465
|
-
altitude
|
466
|
-
end
|
467
|
-
|
468
|
-
end
|
469
|
-
|
470
8
|
end
|
9
|
+
|
10
|
+
require 'solar/support.rb'
|
11
|
+
require 'solar/passages.rb'
|
12
|
+
require 'solar/position.rb'
|
13
|
+
require 'solar/day_night.rb'
|
14
|
+
require 'solar/radiation.rb'
|
15
|
+
require 'solar/lambert.rb'
|