suntrack 0.0.1 → 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
@@ -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