suntrack 0.0.1 → 0.0.2

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.
@@ -0,0 +1,191 @@
1
+ # Suntrack::Point3D
2
+ # 3D vector with transformation functions, from "Astronomy on the Personal
3
+ # Computer", by Montenbruck and Pfleger (1991)
4
+
5
+ include Math
6
+ class Suntrack::Point3D
7
+
8
+ attr_accessor :x, :y, :z
9
+ def initialize(x, y, z)
10
+ @x = x
11
+ @y = y
12
+ @z = z
13
+ end
14
+
15
+ def to_s
16
+ "(" + @x.to_s + "," + @y.to_s + "," + @z.to_s + ")"
17
+ end
18
+
19
+ # Convert to Cartesian, from polar. No attempt is made to confirm that
20
+ # the original coordinates are polar (r, theta, phi). M&P, page 10.
21
+ def polar_to_cartesian!
22
+ # Note that this is 90-usual theta.
23
+ rcst = @x * cs(@y)
24
+ z = @x * sn(@y)
25
+ @x = rcst * cs(@z)
26
+ @y = rcst * sn(@z)
27
+ @z = z
28
+ end
29
+
30
+ # Precess an ecliptic Cartesian point between two epochs
31
+ # M&P, page 21
32
+ def precess_ecliptic_cartesian!(t1,t2)
33
+ a = pmat_ecliptic(t1,t2)
34
+ x = @x
35
+ y = @y
36
+ z = @z
37
+ @x = a[[0,0]] * x + a[[0,1]] * y + a[[0,2]] * z
38
+ @y = a[[1,0]] * x + a[[1,1]] * y + a[[1,2]] * z
39
+ @z = a[[2,0]] * x + a[[2,1]] * y + a[[2,2]] * z
40
+ end
41
+
42
+ # Precess an equatorial Cartesian point between two epochs
43
+ # M&P, page 21
44
+ def precess_equatorial_cartesian!(t1,t2)
45
+ a = pmat_equatorial(t1,t2)
46
+ x = @x
47
+ y = @y
48
+ z = @z
49
+ @x = a[[0,0]] * x + a[[0,1]] * y + a[[0,2]] * z
50
+ @y = a[[1,0]] * x + a[[1,1]] * y + a[[1,2]] * z
51
+ @z = a[[2,0]] * x + a[[2,1]] * y + a[[2,2]] * z
52
+ end
53
+
54
+ # Convert to polar, from Cartesian
55
+ # M&P, page 10
56
+ def cartesian_to_polar!
57
+ # Note that this is 90-usual theta
58
+ x = @x
59
+ y = @y
60
+ z = @z
61
+ rho = (x * x) + (y * y)
62
+ @x = sqrt(rho + (z * z))
63
+ @z = atn2(y, x)
64
+ @z += 360 if @z < 0
65
+ @y = atn2(z, sqrt(rho))
66
+ end
67
+
68
+ # Convert ecliptic coordinates to equatorial coordinates, given an epoch
69
+ # M&P, page 16
70
+ def ecliptic_to_equatorial!(t)
71
+ # Correction for ecliptic obliquity
72
+ # M&P, page 15
73
+ # Arises from slow alterations in the Earth's orbit as a result of
74
+ # perturbations from other planets.
75
+ eps = 23.43929111-(46.815+(0.00059-0.001813*t)*t)*t/3600
76
+ c = cs(eps)
77
+ s = sn(eps)
78
+ y = @y
79
+ z = @z
80
+ @y = (y * c) - (s * z)
81
+ @z = (y * s) + (c * z)
82
+ end
83
+
84
+ # Convert equatorial coordinates to ecliptic coordinates, given an epoch
85
+ def equatorial_to_ecliptic!(t)
86
+ # Correction for ecliptic obliquity
87
+ # M&P, page 15
88
+ # Arises from slow alterations in the Earth's orbit as a result of
89
+ # perturbations from other planets.
90
+ eps = 23.43929111-(46.815+(0.00059-0.001813*t)*t)*t/3600
91
+ y = @y
92
+ z = @z
93
+ c = cs(eps)
94
+ s = sn(eps)
95
+ @y = (y * c) + (s * z)
96
+ @z = (-1 * y * s) + (c * z)
97
+ end
98
+
99
+ # Convert equatorial coordinates to horizon coordinates
100
+ # M&P, pp. 34-35
101
+ def equatorial_to_horizon
102
+ cs_phi = cs(@z)
103
+ sn_phi = sn(@z)
104
+ cs_dec = cs(@x)
105
+ sn_dec = sn(@x)
106
+ cs_tau = cs(@y)
107
+ x = cs_dec * sn_phi * cs_tau - sn_dec * cs_phi
108
+ y = cs_dec * sn(@y)
109
+ z = cs_dec * cs_phi * cs_tau + sn_dec * sn_phi
110
+ pt = Suntrack::Point3D.new(x,y,z)
111
+ pt.cartesian_to_polar!
112
+ pt
113
+ end
114
+
115
+ private
116
+
117
+ # Precession matrix from one epoch to another, in ecliptic coordinates
118
+ # M&P, page 20
119
+ def pmat_ecliptic(t1,t2)
120
+ sec = 3600
121
+ dt = t2-t1
122
+ ppi = 174.876383889 +( ((3289.4789+0.60622*t1)*t1) + ((-869.8089-0.50491*t1) + 0.03536*dt)*dt )/sec;
123
+ pi = ( (47.0029-(0.06603-0.000598*t1)*t1)+ ((-0.03302+0.000598*t1)+0.000060*dt)*dt )*dt/sec;
124
+ pa = ( (5029.0966+(2.22226-0.000042*t1)*t1)+ ((1.11113-0.000042*t1)-0.000006*dt)*dt )*dt/sec;
125
+ c1 = cs(ppi+pa)
126
+ c2 = cs(pi)
127
+ c3 = cs(ppi);
128
+ s1 = sn(ppi+pa);
129
+ s2 = sn(pi)
130
+ s3 = sn(ppi);
131
+ a = Hash.new
132
+ a[[0,0]] = c1*c3+s1*c2*s3
133
+ a[[0,1]] = c1*s3-s1*c2*c3
134
+ a[[0,2]] = -s1*s2
135
+ a[[1,0]] = s1*c3-c1*c2*s3
136
+ a[[1,1]] = s1*s3+c1*c2*c3
137
+ a[[1,2]] = c1*s2
138
+ a[[2,0]] = s2*s3
139
+ a[[2,1]] = -s2*c3
140
+ a[[2,2]] = c2
141
+ a
142
+ end
143
+
144
+ # Precession matrix from one epoch to another, in equatorial coordinates
145
+ # M&P, page 20
146
+ def pmat_equatorial(t1,t2)
147
+ sec = 3600
148
+ dt = t2-t1
149
+ zeta = ( (2306.2181+(1.39656-0.000139*t1)*t1)+ ((0.30188-0.000345*t1)+0.017998*dt)*dt )*dt/sec
150
+ z = zeta + ( (0.79280+0.000411*t1)+0.000205*dt)*dt*dt/sec
151
+ theta = ( (2004.3109-(0.85330+0.000217*t1)*t1)- ((0.42665+0.000217*t1)+0.041833*dt)*dt )*dt/sec
152
+ c1 = cs(z);
153
+ c2 = cs(theta)
154
+ c3 = cs(zeta)
155
+ s1 = sn(z)
156
+ s2 = sn(theta)
157
+ s3 = sn(zeta)
158
+ a = Hash.new
159
+ a[[0,0]] = -s1*s3+c1*c2*c3
160
+ a[[0,1]] = -s1*c3-c1*c2*s3
161
+ a[[0,2]] = -c1*s2
162
+ a[[1,0]] = c1*s3+s1*c2*c3
163
+ a[[1,1]] = c1*c3-s1*c2*s3
164
+ a[[1,2]] = -s1*s2
165
+ a[[2,0]] = s2*c3
166
+ a[[2,1]] = -s2*s3
167
+ a[[2,2]] = c2
168
+ a
169
+ end
170
+
171
+ # Mathematical functions in degrees as needed
172
+ def cs(x)
173
+ cos(PI * x / 180)
174
+ end
175
+ def sn(x)
176
+ sin(PI * x / 180)
177
+ end
178
+ def atn2(y,x)
179
+ return 0 if x == 0 && y == 0
180
+ ax = x.abs
181
+ ay = y.abs
182
+ phi = atan(Float(y)/x) * 180 / PI
183
+ if (ay >= ax)
184
+ phi = 90 - (atan(Float(x)/y) * 180 / PI)
185
+ end
186
+ phi = 180 - phi if x < 0
187
+ phi = -phi if y < 0
188
+ phi
189
+ end
190
+
191
+ end
@@ -0,0 +1,99 @@
1
+ # Astronomical methods, designed to be used in tandem with Suntrack::Point3D,
2
+ # from "Astronomy on the Personal Computer", by Montenbruck and Pfleger (1991).
3
+
4
+ class Suntrack::RAstro
5
+
6
+
7
+ # Epoch constants for 1950 and 2000. Discussion on p. 15 of M&P.
8
+ B1950_EPOCH = -0.500002108
9
+ J2000_EPOCH = 0
10
+
11
+ # Declination and right ascension of Sirius, for testing purposes,
12
+ # measured in degrees.
13
+ SIRIUS_DECLINATION = -16.7306
14
+ SIRIUS_RA = 6.75242
15
+
16
+ # Sun position method.
17
+ def self.sun_position(t)
18
+ # Montebruck & Pfleger, page 36
19
+ # Low-precision Sun position as a function of t
20
+ # t is the number of T is the number of Julian centuries between the
21
+ # epoch and J2000
22
+ p2 = 6.283185307
23
+ coseps = 0.91748
24
+ sineps = 0.39778
25
+ m = p2*frac(0.993133+99.997361*t)
26
+ dl = 6893.0*sin(m)+72.0*sin(2*m)
27
+ l = p2*frac(0.7859453 + m/p2 + (6191.2*t+dl)/1296000);
28
+ sl = sin(l)
29
+ x = cos(l)
30
+ y = coseps*sl
31
+ z = sineps*sl
32
+ rho = sqrt(1.0-z*z)
33
+ declination = (360.0/p2)*atan(z/rho)
34
+ right_ascension = ( 48.0/p2)*atan(y/(x+rho))
35
+ right_ascension = right_ascension + 24.0 if right_ascension < 0
36
+ Suntrack::Point3D.new(0,declination,right_ascension)
37
+ end
38
+
39
+ # Local Mean Sidereal Time
40
+ # M&P, page 38.
41
+ def self.lmst(mjd,lambda)
42
+ mjd0 = mjd.to_i
43
+ ut = (mjd - mjd0) * 24
44
+ t = (mjd0 - 51544.5) / 36525.0
45
+ gmst = 6.697374558 + 1.0027379093*ut + (8640184.812866+(0.093104-6.2e-6*t)*t)*t/3600.0
46
+ lmst = 24 * frac((gmst-(Float(lambda)/15)) / 24)
47
+ lmst
48
+ end
49
+
50
+ # Utility method to get degrees/minutes/seconds from decimal degrees.
51
+ # M&P, page 11
52
+ def self.get_dms(ddd)
53
+ pt = Suntrack::Point3D.new(0,0,0)
54
+ pt.x = ddd.abs.to_i
55
+ d1 = (ddd.abs - pt.x) * 60
56
+ pt.y = d1.to_i
57
+ pt.z = (d1 - pt.y) * 60
58
+ pt.x = -pt.x if ddd < 0
59
+ pt
60
+ end
61
+
62
+ # Utility method to convert Ruby DateTime to modified Julian date
63
+ # M&P, page 12
64
+ def self.to_mjd(date_time)
65
+ a = (10000 * date_time.year) + (100 * date_time.month) + date_time.mday
66
+ m = date_time.month
67
+ y = date_time.year
68
+ if date_time.month <= 2
69
+ m = date_time.month + 12
70
+ y = date_time.year - 1
71
+ end
72
+ leapDays = (y/400).to_i - (y/100).to_i + (y/4).to_i
73
+ if a <= 15821004.1
74
+ leapDays = -2 + ((y+4716)/4).to_i - 1179
75
+ end
76
+ a = (365 * y) - 679004
77
+ a + leapDays + (30.6001 * (m + 1)).to_i + date_time.mday + (Float(date_time.hour)/24) + (Float(date_time.min)/1440) + (Float(date_time.sec)/86400)
78
+ end
79
+
80
+ # Utility method to convert modified Julian date to Julian dare
81
+ # M&P, page 12
82
+ def self.jd mjd
83
+ mjd + 2400000.5
84
+ end
85
+
86
+
87
+ # Utility method to convert Julian date to time needed by Sun position
88
+ # method
89
+ def self.get_time jd
90
+ (jd - 2451545)/36525
91
+ end
92
+
93
+ # Utility fraction method
94
+ def self.frac(x)
95
+ x = x - (x.to_i)
96
+ x = x + 1 if x < 0
97
+ x
98
+ end
99
+ end
metadata CHANGED
@@ -2,7 +2,7 @@
2
2
  name: suntrack
3
3
  version: !ruby/object:Gem::Version
4
4
  prerelease:
5
- version: 0.0.1
5
+ version: 0.0.2
6
6
  platform: ruby
7
7
  authors:
8
8
  - Joel M. Gottlieb
@@ -10,7 +10,7 @@ autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
12
 
13
- date: 2012-09-11 00:00:00 Z
13
+ date: 2012-09-12 00:00:00 Z
14
14
  dependencies: []
15
15
 
16
16
  description: Sun position as function of time
@@ -23,6 +23,8 @@ extra_rdoc_files: []
23
23
 
24
24
  files:
25
25
  - lib/suntrack.rb
26
+ - lib/suntrack/Point3D.rb
27
+ - lib/suntrack/RAstro.rb
26
28
  homepage:
27
29
  licenses: []
28
30