ruby-ephemeris 1.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (3) hide show
  1. checksums.yaml +7 -0
  2. data/lib/ephemeris.rb +336 -0
  3. metadata +52 -0
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: dfc646687b8a3dbb654bd1d2f2e2b09e268fec7d9204fad4b63f7835b99d0157
4
+ data.tar.gz: 4a6b5b2bca82f971beeeb6ffff62141549054c3b13d59bf5ebe82fa564daab99
5
+ SHA512:
6
+ metadata.gz: 5d2f51a20fc76f4f2f75e16da7fd3dd6e65e17d53ea620d6925c7be24c2a501cd8a595aed5ed630d1f9d15f3c34cac635b340dc1479c8fcf34d371bc1d30ecae
7
+ data.tar.gz: fc43fc53d1a731e88d57d33e3a5d96eac5cec51e63757bc9b378134e1d21f9bfc07021221839846cc76efa9d9eb0ffa76049d0aabd57d74051c3fea40fb2a029
data/lib/ephemeris.rb ADDED
@@ -0,0 +1,336 @@
1
+ class Numeric
2
+ def deg
3
+ self * Math::PI / 180
4
+ end
5
+ def hms
6
+ hrs = self.to_i
7
+ m = ((self - hrs)*60).abs
8
+ min = m.to_i
9
+ sec = ((m - min)*60).to_i.abs
10
+ return hrs, min, sec
11
+ end
12
+ def to_hms
13
+ hrs, min, sec = self.hms
14
+ return "#{hrs.to_s.rjust(2, "0")}:#{min.to_s.rjust(2, "0")}:#{sec.to_s.rjust(2, "0")}"
15
+ end
16
+ end
17
+
18
+ class Ephemeris
19
+ attr_reader :sun, :moon, :mercury, :venus, :mars, :jupiter, :saturn, :uranus, :neptune
20
+
21
+ def body_data
22
+ @body = {
23
+ "sun" => {
24
+ "N" => 0.0,
25
+ "i" => 0.0,
26
+ "w" => 282.9404 + 4.70935e-5 * @d,
27
+ "a" => 1.000000,
28
+ "e" => 0.016709 - 1.151e-9 * @d,
29
+ "M" => 356.0470 + 0.98555 * @d},
30
+ #"M" => 356.0470 + 0.9856002585 * @d},
31
+ "moon" => {
32
+ "N" => 125.1228 - 0.0529538083 * @d,
33
+ "i" => 5.1454,
34
+ "w" => 318.0634 + 0.1643573223 * @d,
35
+ "a" => 60.2666,
36
+ "e" => 0.054900,
37
+ "M" => 115.3654 + 13.06478 * @d},
38
+ #"M" => 115.3654 + 13.0649929509 * @d},
39
+ "mercury" => {
40
+ "N" => 48.3313 + 3.24587e-5 * @d,
41
+ "i" => 7.0047 + 5.00e-8 * @d,
42
+ "w" => 29.1241 + 1.01444e-5 * @d,
43
+ "a" => 0.387098,
44
+ "e" => 0.205635 + 5.59e-10 * @d,
45
+ #"M" => 168.6562 + 4.09257 * @d},
46
+ "M" => 168.6562 + 4.0923344368 * @d},
47
+ "venus" => {
48
+ "N" => 76.6799 + 2.46590e-5 * @d,
49
+ "i" => 3.3946 + 2.75e-8 * @d,
50
+ "w" => 54.8910 + 1.38374e-5 * @d,
51
+ "a" => 0.723330,
52
+ "e" => 0.006773 - 1.302e-9 * @d,
53
+ #"M" => 48.0052 + 1.602206 * @d},
54
+ "M" => 48.0052 + 1.6021302244 * @d},
55
+ "mars" => {
56
+ "N" => 49.5574 + 2.11081e-5 * @d,
57
+ "i" => 1.8497 - 1.78e-8 * @d,
58
+ "w" => 286.5016 + 2.92961e-5 * @d,
59
+ "a" => 1.523688,
60
+ "e" => 0.093405 + 2.516e-9 * @d,
61
+ "M" => 18.6021 + 0.52398 * @d},
62
+ #"M" => 18.6021 + 0.5240207766 * @d},
63
+ "jupiter" => {
64
+ "N" => 100.4542 + 2.76854e-5 * @d,
65
+ "i" => 1.3030 - 1.557e-7 * @d,
66
+ "w" => 273.8777 + 1.64505e-5 * @d,
67
+ "a" => 5.20256,
68
+ "e" => 0.048498 + 4.469e-9 * @d,
69
+ "M" => 19.8950 + 0.083052 * @d},
70
+ #"M" => 19.8950 + 0.0830853001 * @d},
71
+ "saturn" => {
72
+ "N" => 113.6634 + 2.38980e-5 * @d,
73
+ "i" => 2.4886 - 1.081e-7 * @d,
74
+ "w" => 339.3939 + 2.97661e-5 * @d,
75
+ "a" => 9.55475,
76
+ "e" => 0.055546 - 9.499e-9 * @d,
77
+ "M" => 316.9670 + 0.03339 * @d},
78
+ #"M" => 316.9670 + 0.0334442282 * @d},
79
+ "uranus" => {
80
+ "N" => 74.0005 + 1.3978e-5 * @d,
81
+ "i" => 0.7733 + 1.9e-8 * @d,
82
+ "w" => 96.6612 + 3.0565e-5 * @d,
83
+ "a" => 19.18171 - 1.55e-8 * @d,
84
+ "e" => 0.047318 + 7.45e-9 * @d,
85
+ "M" => 142.5905 + 0.01168 * @d},
86
+ #"M" => 142.5905 + 0.011725806 * @d},
87
+ "neptune" => {
88
+ "N" => 131.7806 + 3.0173e-5 * @d,
89
+ "i" => 1.7700 - 2.55e-7 * @d,
90
+ "w" => 272.8461 - 6.027e-6 * @d,
91
+ "a" => 30.05826 + 3.313e-8 * @d,
92
+ "e" => 0.008606 + 2.15e-9 * @d,
93
+ "M" => 260.2471 + 0.005953 * @d}}
94
+ #"M" => 260.2471 + 0.005995147 * @d}}
95
+ end
96
+
97
+ def hms_dms(ra, dec) # Show HMS & DMS
98
+ h, m, s = (ra/15).hms
99
+ ra_hms = "#{h.to_s.rjust(2)}h #{m.to_s.rjust(2)}m #{s.to_s.rjust(2)}s"
100
+ d, m, s = dec.hms
101
+ dec_dms = "#{d.to_s.rjust(3)}° #{m.to_s.rjust(2)}´ #{s.to_s.rjust(2)}˝"
102
+ return ra_hms, dec_dms
103
+ end
104
+
105
+ def alt_az(ra, dec, time)
106
+ pi = Math::PI
107
+ ra_h = ra/15
108
+ #ha = (@sidtime - ra_h)*15
109
+ ha = (time - ra_h)*15
110
+ x = Math.cos(ha.deg) * Math.cos(dec.deg)
111
+ y = Math.sin(ha.deg) * Math.cos(dec.deg)
112
+ z = Math.sin(dec.deg)
113
+ xhor = x * Math.sin(@lat.deg) - z * Math.cos(@lat.deg)
114
+ yhor = y
115
+ zhor = x * Math.cos(@lat.deg) + z * Math.sin(@lat.deg)
116
+ az = Math.atan2(yhor, xhor)*180/pi + 180
117
+ alt = Math.asin(zhor)*180/pi
118
+ return alt, az
119
+ end
120
+
121
+ def body_alt_az(body, time)
122
+ self.alt_az(self.body_calc(body)[0], self.body_calc(body)[1], time)
123
+ end
124
+
125
+ def rts(ra, dec)
126
+ pi = Math::PI
127
+ transit = (ra - @ls - @lon)/15 + 12 + @tz
128
+ transit = (transit + 24) % 24
129
+ cos_lha = (-Math.sin(@lat.deg) * Math.sin(dec.deg)) / (Math.cos(@lat.deg) * Math.cos(dec.deg))
130
+ if cos_lha < -1
131
+ rise = "always"
132
+ set = "never"
133
+ elsif cos_lha > 1
134
+ rise = "never"
135
+ set = "always"
136
+ else
137
+ lha = Math.acos(cos_lha) * 180/pi
138
+ lha_h = lha/15
139
+ rise = ((transit - lha_h + 24) % 24).to_hms
140
+ set = ((transit + lha_h + 24) % 24).to_hms
141
+ end
142
+ trans = transit.to_hms
143
+ return rise, trans, set
144
+ end
145
+
146
+ def print
147
+
148
+ def distf(d)
149
+ int = d.to_i.to_s.rjust(2)
150
+ f = d % 1
151
+ frc = "%.4f" % f
152
+ return int + frc[1..5]
153
+ end
154
+
155
+ out = "Planet │ RA │ Dec │ Dist. │ Rise │ Trans │ Set \n"
156
+ out += "────────┼─────────────┼──────────────┼───────┼───────┼───────┼────── \n"
157
+
158
+ #["sun", "moon", "mercury", "venus", "mars", "jupiter", "saturn", "uranus", "neptune"].each do |p|
159
+ ["mercury", "venus", "mars", "jupiter", "saturn", "uranus", "neptune"].each do |p|
160
+ o = self.body_calc(p)
161
+ n_o = (p[0].upcase + p[1..]).ljust(7)
162
+ ra_o = o[3].ljust(11)
163
+ dec_o = o[4].ljust(12)
164
+ d_o = distf(o[2])[0..-3]
165
+ ris_o = o[5][0..-4].rjust(5)
166
+ tra_o = o[6][0..-4].rjust(5)
167
+ set_o = o[7][0..-4].rjust(5)
168
+
169
+ out += "#{n_o } │ #{ra_o } │ #{dec_o } │ #{d_o } │ #{ris_o} │ #{tra_o} │ #{set_o} \n"
170
+ end
171
+ return out
172
+ end
173
+
174
+ def initialize (date, lat, lon, tz)
175
+ pi = Math::PI
176
+
177
+ def get_vars(body) # GET VARIABLES FOR THE BODY
178
+ b = @body[body]
179
+ return b["N"], b["i"], b["w"], b["a"], b["e"], b["M"]
180
+ end
181
+
182
+ def body_calc(body) # CALCULATE FOR THE BODY
183
+ pi = Math::PI
184
+ n_b, i_b, w_b, a_b, e_b, m_b = self.get_vars(body)
185
+ w_b = (w_b + 360) % 360
186
+ m_b = m_b % 360
187
+ e1 = m_b + (180/pi) * e_b * Math.sin(m_b.deg) * (1 + e_b*Math.cos(m_b.deg))
188
+ e0 = 0
189
+ while (e1 - e0).abs > 0.0005
190
+ e0 = e1
191
+ e1 = e0 - (e0 - (180/pi) * e_b * Math.sin(e0.deg) - m_b) / (1 - e_b * Math.cos(e0.deg))
192
+ end
193
+ e = e1
194
+ x = a_b * (Math.cos(e.deg) - e_b)
195
+ y = a_b * Math.sqrt(1 - e_b*e_b) * Math.sin(e.deg)
196
+ r = Math.sqrt(x*x + y*y)
197
+ v = (Math.atan2(y, x)*180/pi + 360) % 360
198
+ xeclip = r * (Math.cos(n_b.deg) * Math.cos((v+w_b).deg) - Math.sin(n_b.deg) * Math.sin((v+w_b).deg) * Math.cos(i_b.deg))
199
+ yeclip = r * (Math.sin(n_b.deg) * Math.cos((v+w_b).deg) + Math.cos(n_b.deg) * Math.sin((v+w_b).deg) * Math.cos(i_b.deg))
200
+ zeclip = r * Math.sin((v+w_b).deg) * Math.sin(i_b.deg)
201
+ lon = (Math.atan2(yeclip, xeclip)*180/pi + 360) % 360
202
+ lat = Math.atan2(zeclip, Math.sqrt(xeclip*xeclip + yeclip*yeclip))*180/pi
203
+ r_b = Math.sqrt(xeclip*xeclip + yeclip*yeclip + zeclip*zeclip)
204
+ m_J = @body["jupiter"]["M"]
205
+ m_S = @body["saturn"]["M"]
206
+ m_U = @body["uranus"]["M"]
207
+ plon = 0
208
+ plat = 0
209
+ pdist = 0
210
+ case body
211
+ when "moon"
212
+ lb = (n_b + w_b + m_b) % 360
213
+ db = (lb - @ls + 360) % 360
214
+ fb = (lb - n_b + 360) % 360
215
+ plon += -1.274 * Math.sin((m_b - 2*db).deg)
216
+ plon += 0.658 * Math.sin((2*db).deg)
217
+ plon += -0.186 * Math.sin(@ms.deg)
218
+ plon += -0.059 * Math.sin((2*m_b - 2*db).deg)
219
+ plon += -0.057 * Math.sin((m_b - 2*db + @ms).deg)
220
+ plon += 0.053 * Math.sin((m_b + 2*db).deg)
221
+ plon += 0.046 * Math.sin((2*db - @ms).deg)
222
+ plon += 0.041 * Math.sin((m_b - @ms).deg)
223
+ plon += -0.035 * Math.sin(db.deg)
224
+ plon += -0.031 * Math.sin((m_b + @ms).deg)
225
+ plon += -0.015 * Math.sin((2*fb - 2*db).deg)
226
+ plon += 0.011 * Math.sin((m_b - 4*db).deg)
227
+ plat += -0.173 * Math.sin((fb - 2*db).deg)
228
+ plat += -0.055 * Math.sin((m_b - fb - 2*db).deg)
229
+ plat += -0.046 * Math.sin((m_b + fb - 2*db).deg)
230
+ plat += 0.033 * Math.sin((fb + 2*db).deg)
231
+ plat += 0.017 * Math.sin((2*m_b + fb).deg)
232
+ pdist += -0.58 * Math.cos((m_b - 2*db).deg)
233
+ pdist += -0.46 * Math.cos(2*db.deg)
234
+ when "jupiter"
235
+ plon += -0.332 * Math.sin((2*m_J - 5*m_S - 67.6).deg)
236
+ plon += -0.056 * Math.sin((2*m_J - 2*m_S + 21).deg)
237
+ plon += 0.042 * Math.sin((3*m_J - 5*m_S + 21).deg)
238
+ plon += -0.036 * Math.sin((m_J - 2*m_S).deg)
239
+ plon += 0.022 * Math.cos((m_J - m_S).deg)
240
+ plon += 0.023 * Math.sin((2*m_J - 3*m_S + 52).deg)
241
+ plon += -0.016 * Math.sin((m_J - 5*m_S - 69).deg)
242
+ when "saturn"
243
+ plon += 0.812 * Math.sin((2*m_J - 5*m_S - 67.6).deg)
244
+ plon += -0.229 * Math.cos((2*m_J - 4*m_S - 2).deg)
245
+ plon += 0.119 * Math.sin((m_J - 2*m_S - 3).deg)
246
+ plon += 0.046 * Math.sin((2*m_J - 6*m_S - 69).deg)
247
+ plon += 0.014 * Math.sin((m_J - 3*m_S + 32).deg)
248
+ plat += -0.020 * Math.cos((2*m_J - 4*m_S - 2).deg)
249
+ plat += 0.018 * Math.sin((2*m_J - 6*m_S - 49).deg)
250
+ when "uranus"
251
+ plon += 0.040 * Math.sin((m_S - 2*m_U + 6).deg)
252
+ plon += 0.035 * Math.sin((m_S - 3*m_U + 33).deg)
253
+ plon += -0.015 * Math.sin((m_J - m_U + 20).deg)
254
+ end
255
+ lon += plon
256
+ lat += plat
257
+ r_b += pdist
258
+ if body == "moon"
259
+ xeclip = Math.cos(lon.deg) * Math.cos(lat.deg)
260
+ yeclip = Math.sin(lon.deg) * Math.cos(lat.deg)
261
+ zeclip = Math.sin(lat.deg)
262
+ else
263
+ xeclip += @xs
264
+ yeclip += @ys
265
+ end
266
+ xequat = xeclip
267
+ yequat = yeclip * Math.cos(@ecl.deg) - zeclip * Math.sin(@ecl.deg)
268
+ zequat = yeclip * Math.sin(@ecl.deg) + zeclip * Math.cos(@ecl.deg)
269
+ ra = (Math.atan2(yequat, xequat)*180/pi + 360) % 360
270
+ dec = Math.atan2(zequat, Math.sqrt(xequat*xequat + yequat*yequat))*180/pi
271
+ body == "moon" ? par = Math.asin(1/r_b)*180/pi : par = (8.794/3600)/r_b
272
+ gclat = @lat - 0.1924 * Math.sin(2*@lat.deg)
273
+ rho = 0.99833 + 0.00167 * Math.cos(2*@lat.deg)
274
+ lst = @sidtime * 15
275
+ ha = (lst - ra + 360) % 360
276
+ g = Math.atan(Math.tan(gclat.deg) / Math.cos(ha.deg))*180/pi
277
+ topRA = ra - par * rho * Math.cos(gclat.deg) * Math.sin(ha.deg) / Math.cos(dec.deg)
278
+ topDecl = dec - par * rho * Math.sin(gclat.deg) * Math.sin((g - dec).deg) / Math.sin(g.deg)
279
+ ra = topRA.round(4)
280
+ dec = topDecl.round(4)
281
+ r = Math.sqrt(xequat*xequat + yequat*yequat + zequat*zequat).round(4)
282
+ ri, tr, se = self.rts(ra, dec)
283
+ object = [ra, dec, r, self.hms_dms(ra, dec), ri, tr, se].flatten
284
+ return object
285
+ end
286
+
287
+ # START OF INITIALIZE
288
+ @lat = lat
289
+ @lon = lon
290
+ @tz = tz
291
+ y = date[0..3].to_i
292
+ m = date[5..6].to_i
293
+ d = date[8..9].to_i
294
+ @d = 367*y - 7*(y + (m+9)/12) / 4 + 275*m/9 + d - 730530
295
+ @ecl = 23.4393 - 3.563E-7*@d
296
+
297
+ self.body_data
298
+
299
+ # SUN
300
+ n_s, i_s, w_s, a_s, e_s, m_s = self.get_vars("sun")
301
+ w_s = (w_s + 360) % 360
302
+ @ms = m_s % 360
303
+ es = @ms + (180/pi) * e_s * Math.sin(@ms.deg) * (1 + e_s*Math.cos(@ms.deg))
304
+ x = Math.cos(es.deg) - e_s
305
+ y = Math.sin(es.deg) * Math.sqrt(1 - e_s*e_s)
306
+ v = Math.atan2(y,x)*180/pi
307
+ r = Math.sqrt(x*x + y*y)
308
+ tlon = (v + w_s)%360
309
+ @xs = r * Math.cos(tlon.deg)
310
+ @ys = r * Math.sin(tlon.deg)
311
+ xe = @xs
312
+ ye = @ys * Math.cos(@ecl.deg)
313
+ ze = @ys * Math.sin(@ecl.deg)
314
+ r = Math.sqrt(xe*xe + ye*ye + ze*ze)
315
+ ra = Math.atan2(ye,xe)*180/pi
316
+ ra_s = ((ra + 360)%360).round(4)
317
+ dec_s = (Math.atan2(ze,Math.sqrt(xe*xe + ye*ye))*180/pi).round(4)
318
+
319
+ @ls = (w_s + @ms)%360
320
+ gmst0 = (@ls + 180)/15%24
321
+ @sidtime = gmst0 + @lon/15
322
+
323
+ @alt_s, @az_s = self.alt_az(ra_s, dec_s, @sidtime)
324
+
325
+ @sun = [ra_s, dec_s, 1.0, self.hms_dms(ra_s, dec_s)].flatten
326
+ @moon = self.body_calc("moon")
327
+ @mercury = self.body_calc("mercury")
328
+ @venus = self.body_calc("venus")
329
+ @mars = self.body_calc("mars")
330
+ @jupiter = self.body_calc("jupiter")
331
+ @saturn = self.body_calc("saturn")
332
+ @uranus = self.body_calc("uranus")
333
+ @neptune = self.body_calc("neptune")
334
+
335
+ end
336
+ end
metadata ADDED
@@ -0,0 +1,52 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: ruby-ephemeris
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Geir Isene
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2021-09-25 00:00:00.000000000 Z
12
+ dependencies: []
13
+ description: "Usage is simple and straightforward:\n\no = Ephemeris.new(date, lat,
14
+ lon, tz)\n...creates a new ephemeris object for the \"date\" (a string in ISO format
15
+ 2020-12-16) by supplying the observer latitude (lat), longitude (lon) and time zone
16
+ (tz).\n\nExample: today = Ephemeris.new(\"2020-12-16\", 59.568, 10.02, 1)\n\nYou
17
+ will then have access to the following data:\n\ntoday.sun\ntoday.moon \ntoday.mercury\ntoday.venus\ntoday.mars\ntoday.jupiter\ntoday.saturn\ntoday.uranus\ntoday.neptune\nBy
18
+ calling any of these, you will get back an array with the following data:\n\n[ra,
19
+ dec, distance, ra_string, dec_string, rise, transit, set]\n\nSee Github page for
20
+ more info: https://github.com/isene/ephemeris"
21
+ email: g@isene.com
22
+ executables: []
23
+ extensions: []
24
+ extra_rdoc_files: []
25
+ files:
26
+ - lib/ephemeris.rb
27
+ homepage: https://isene.com/
28
+ licenses:
29
+ - Unlicense
30
+ metadata:
31
+ source_code_uri: https://github.com/isene/ephemeris
32
+ post_install_message:
33
+ rdoc_options: []
34
+ require_paths:
35
+ - lib
36
+ required_ruby_version: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ required_rubygems_version: !ruby/object:Gem::Requirement
42
+ requirements:
43
+ - - ">="
44
+ - !ruby/object:Gem::Version
45
+ version: '0'
46
+ requirements: []
47
+ rubygems_version: 3.1.2
48
+ signing_key:
49
+ specification_version: 4
50
+ summary: Ephemeris class for Ruby. Sun, Moon and planet positions. Rise, tranist,
51
+ set times.
52
+ test_files: []