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.
- data/lib/suntrack/Point3D.rb +191 -0
- data/lib/suntrack/RAstro.rb +99 -0
- metadata +4 -2
|
@@ -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.
|
|
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-
|
|
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
|
|