Module: Astro::Moon
- Defined in:
- lib/astro/moon.rb
Overview
Provides functions for lunar phases and lunar month dates (eg. new/full moon)
This file is a thoughtless manual compilation of Astro::MoonPhase perl module (which, in turn, is influenced by moontool.c). I don’t know how it all works.
Defined Under Namespace
Constant Summary collapse
- EPOCH =
Astronomical constants. 1980 January 0.0
2444238.5- ELONGE =
Constants defining the Sun’s apparent orbit.
ecliptic longitude of the Sun at epoch 1980.0
278.833540- ELONGP =
ecliptic longitude of the Sun at perigee
282.596403- ECCENT =
eccentricity of Earth’s orbit
0.016718- SUNSMAX =
semi-major axis of Earth’s orbit, km
1.495985e8- SUNANGSIZ =
sun’s angular size, degrees, at semi-major axis distance
0.533128- MMLONG =
moon’s mean longitude at the epoch
64.975464- MMLONGP =
mean longitude of the perigee at the epoch
349.383063- MLNODE =
mean longitude of the node at the epoch
151.950429- MINC =
inclination of the Moon’s orbit
5.145396- MECC =
eccentricity of the Moon’s orbit
0.054900- MANGSIZ =
moon’s angular size at distance a from Earth
0.5181- MSMAX =
semi-major axis of Moon’s orbit in km
384401.0- MPARALLAX =
parallax at distance a from Earth
0.9507- SYNMONTH =
synodic month (new Moon to new Moon)
29.53058868
Class Method Summary collapse
-
.phase(dt = nil) ⇒ Object
Finds the lunar phase for the specified date.
-
.phasehunt(date = nil) ⇒ Object
Finds the key dates of the specified lunar month.
Class Method Details
.phase(dt = nil) ⇒ Object
Finds the lunar phase for the specified date. Takes a DateTime object (or creates one using now() function). Returns a Phase struct instance. (see Constants section)
# find the current moon illumination, in percents
Astro::Moon.phase.illumination * 100 # => 63.1104513958699
# find the current moon phase (new moon is 0 or 100,
# full moon is 50, etc)
Astro::Moon.phase.phase * 100 # => 70.7802812241989
124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 |
# File 'lib/astro/moon.rb', line 124 def phase(dt = nil) dt = DateTime.now if !dt pdate = dt.ajd # Calculation of the Sun's position. day = pdate - EPOCH # date within epoch n = ((360 / 365.2422) * day) % 360.0 m = (n + ELONGE - ELONGP) % 360.0 # convert from perigee # co-ordinates to epoch 1980.0 ec = kepler(m, ECCENT) # solve equation of Kepler ec = Math.sqrt((1 + ECCENT) / (1 - ECCENT)) * Math.tan(ec / 2) ec = 2 * todeg(Math.atan(ec)) # true anomaly lambdasun = (ec + ELONGP) % 360.0 # Sun's geocentric ecliptic # longitude # Orbital distance factor. f = ((1 + ECCENT * Math.cos(torad(ec))) / (1 - ECCENT * ECCENT)) sundist = SUNSMAX / f # distance to Sun in km sunang = f * SUNANGSIZ # Sun's angular size in degrees # Calculation of the Moon's position. # Moon's mean longitude. ml = (13.1763966 * day + MMLONG) % 360.0 # Moon's mean anomaly. mm = (ml - 0.1114041 * day - MMLONGP) % 360.0 # Moon's ascending node mean longitude. mn = (MLNODE - 0.0529539 * day) % 360.0 # Evection. ev = 1.2739 * Math.sin(torad(2 * (ml - lambdasun) - mm)) # Annual equation. ae = 0.1858 * Math.sin(torad(m)) # Correction term. a3 = 0.37 * Math.sin(torad(m)) # Corrected anomaly. mmp = mm + ev - ae - a3 # Correction for the equation of the centre. mec = 6.2886 * Math.sin(torad(mmp)) # Another correction term. a4 = 0.214 * Math.sin(torad(2 * mmp)) # Corrected longitude. lp = ml + ev + mec - ae + a4 # Variation. v = 0.6583 * Math.sin(torad(2 * (lp - lambdasun))) # True longitude. lpp = lp + v # Corrected longitude of the node. np = mn - 0.16 * Math.sin(torad(m)) # Y inclination coordinate. y = Math.sin(torad(lpp - np)) * Math.cos(torad(MINC)) # X inclination coordinate. x = Math.cos(torad(lpp - np)) # Ecliptic longitude. lambdamoon = todeg(Math.atan2(y, x)) lambdamoon += np # Ecliptic latitude. betam = todeg(Math.asin(Math.sin(torad(lpp - np)) * Math.sin(torad(MINC)))) # Calculation of the phase of the Moon. # Age of the Moon in degrees. moonage = lpp - lambdasun # Phase of the Moon. moonphase = (1 - Math.cos(torad(moonage))) / 2 # Calculate distance of moon from the centre of the Earth. moondist = (MSMAX * (1 - MECC * MECC)) / (1 + MECC * Math.cos(torad(mmp + mec))) # Calculate Moon's angular diameter. moondfrac = moondist / MSMAX moonang = MANGSIZ / moondfrac # Calculate Moon's parallax. moonpar = MPARALLAX / moondfrac pphase = moonphase mpfrac = (moonage % 360) / 360.0 mage = SYNMONTH * mpfrac dist = moondist angdia = moonang sudist = sundist suangdia = sunang Phase.new(mpfrac, pphase, mage, dist, angdia, sudist, suangdia) end |
.phasehunt(date = nil) ⇒ Object
Finds the key dates of the specified lunar month. Takes a DateTime object (or creates one using now() function). Returns a PhaseHunt struct instance. (see Constants section)
# find the date/time of the full moon in this lunar month
Astro::Moon.phasehunt.moon_full.strftime("%D %T %Z") \
# => "03/04/07 02:17:40 +0300"
81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 |
# File 'lib/astro/moon.rb', line 81 def phasehunt(date = nil) date = DateTime.now if !date sdate = date.ajd adate = sdate - 45 ad1 = DateTime.jd(adate) k1 = ((ad1.year + ((ad1.month - 1) * (1.0 / 12.0)) - 1900) * 12.3685).floor adate = nt1 = meanphase(adate, k1) while true adate += SYNMONTH k2 = k1 + 1 nt2 = meanphase(adate, k2) break if nt1 <= sdate && nt2 > sdate nt1 = nt2 k1 = k2 end return PhaseHunt.new(*[ truephase(k1, 0.0), truephase(k1, 0.25), truephase(k1, 0.5), truephase(k1, 0.75), truephase(k2, 0.0) ].map { |_| _.new_offset(date.offset) }) end |