solar 0.0.2 → 0.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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'
|