Class: MoonPhases

Inherits:
Object
  • Object
show all
Defined in:
lib/astro_calc/moon_phases.rb

Overview

Credits tingletech

Constant Summary collapse

YEAR_IN_DAYS =
365.25
LIMIT_JULIAN_CALENDAR =
2299160
JULIAN_DAYS_IN_MONTH =
29.530588853

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(date = Date.today) ⇒ MoonPhases

Returns a new instance of MoonPhases.



16
17
18
19
# File 'lib/astro_calc/moon_phases.rb', line 16

def initialize(date = Date.today)
  @date = date
  perform_calculations
end

Instance Attribute Details

#ageObject (readonly)

Returns the value of attribute age.



10
11
12
# File 'lib/astro_calc/moon_phases.rb', line 10

def age
  @age
end

#constellationObject (readonly)

Returns the value of attribute constellation.



10
11
12
# File 'lib/astro_calc/moon_phases.rb', line 10

def constellation
  @constellation
end

#dateObject (readonly)

Returns the value of attribute date.



10
11
12
# File 'lib/astro_calc/moon_phases.rb', line 10

def date
  @date
end

#detailed_ageObject (readonly)

Returns the value of attribute detailed_age.



13
14
15
# File 'lib/astro_calc/moon_phases.rb', line 13

def detailed_age
  @detailed_age
end

#detailed_constellationObject (readonly)

Returns the value of attribute detailed_constellation.



13
14
15
# File 'lib/astro_calc/moon_phases.rb', line 13

def detailed_constellation
  @detailed_constellation
end

#detailed_distanceObject (readonly)

Returns the value of attribute detailed_distance.



13
14
15
# File 'lib/astro_calc/moon_phases.rb', line 13

def detailed_distance
  @detailed_distance
end

#detailed_positionObject (readonly)

Returns the value of attribute detailed_position.



13
14
15
# File 'lib/astro_calc/moon_phases.rb', line 13

def detailed_position
  @detailed_position
end

#distanceObject (readonly)

Returns the value of attribute distance.



10
11
12
# File 'lib/astro_calc/moon_phases.rb', line 10

def distance
  @distance
end

#latitudeObject (readonly)

Returns the value of attribute latitude.



10
11
12
# File 'lib/astro_calc/moon_phases.rb', line 10

def latitude
  @latitude
end

#longitudeObject (readonly)

Returns the value of attribute longitude.



10
11
12
# File 'lib/astro_calc/moon_phases.rb', line 10

def longitude
  @longitude
end

#magnitudeObject (readonly)

for svg



11
12
13
# File 'lib/astro_calc/moon_phases.rb', line 11

def magnitude
  @magnitude
end

#phaseObject (readonly)

Returns the value of attribute phase.



10
11
12
# File 'lib/astro_calc/moon_phases.rb', line 10

def phase
  @phase
end

#sweepObject (readonly)

for svg



11
12
13
# File 'lib/astro_calc/moon_phases.rb', line 11

def sweep
  @sweep
end

Instance Method Details

#normalize(value) ⇒ Float

Normalizes the value to be in the range 0..1

Parameters:

  • value (Float)

    the value to normalize

Returns:

  • (Float)

    the normalized value



110
111
112
113
114
# File 'lib/astro_calc/moon_phases.rb', line 110

def normalize(value)
  value -= value.floor 
  value += 1 if value < 0
  value
end

#perform_calculationsObject



21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
# File 'lib/astro_calc/moon_phases.rb', line 21

def perform_calculations
  year  = @date.year
  month = @date.month
  day   = @date.day

  #calculate the Julian date at 12h UT
  y = year - ((12 - month) / 10.0).floor
  m = month + 9 
  m = m - 12 if m >= 12
  
  k1 = (YEAR_IN_DAYS * (y + 4712)).floor
  k2 = (30.6 * m + 0.5 ).floor
  k3 = (((y / 100) + 49) * 0.75).floor - 38
  
  julian_day = k1 + k2 + day + 59                                    # for Julian calendar
  julian_day = julian_day - k3 if julian_day > LIMIT_JULIAN_CALENDAR # for Gregorian calendar
      
  #calculate moons age in Julian days
  i_phase  = normalize((julian_day - 2451550.1 ) / JULIAN_DAYS_IN_MONTH)
  @age = i_phase * JULIAN_DAYS_IN_MONTH
  
  @phase = case @age
    when 1.84566..5.53699 then "waxing crescent"
    when 5.53669..9.22831 then "first quarter"
    when 9.22831..12.91963 then "waxing gibbous"
    when 12.91963..16.61096 then "full moon"
    when 16.61096..20.30228 then "waning gibbous"
    when 20.30228..20.30228 then "last quarter"
    when 20.30228..27.68493 then "waning crescent"
    else "new moon"
  end
  
  #convert phase to radians
  i_phase_radians = i_phase * 2 * Math::PI  

  #calculate moon's distance
  distance_phase = 2 * Math::PI * normalize((julian_day - 2451562.2 ) / 27.55454988)
  @distance = 60.4 - 3.3 * Math.cos(distance_phase) - 0.6 * Math.cos(2 * i_phase_radians - distance_phase) - 0.5 * Math.cos(2 * i_phase_radians)

  #calculate moon's ecliptic latitude
  normal = 2 * Math::PI * normalize((julian_day - 2451565.2) / 27.212220817)
  @latitude = (5.1 * Math.sin(normal)).round(3)

  #calculate moon's ecliptic longitude
  real_phase = normalize((julian_day - 2451555.8) / 27.321582241)
  @longitude = (360 * real_phase + 6.3 * Math::sin(distance_phase) + 1.3 * Math.sin(2 * i_phase_radians - distance_phase) + 0.7 * Math.sin(2 * i_phase_radians)).round(3)

  @constellation = case @longitude
    when 33.18..51.16 then "Aries"
    when 51.16..93.44 then "Taurus"
    when 93.44..119.48 then "Gemini"
    when 119.48..135.30 then "Cancer"
    when 135.30..173.34 then "Leo"
    when 173.34..224.17 then "Virgo"
    when 224.17..242.57 then "Libra"
    when 242.57..271.26 then "Scorpio"
    when 271.26..302.49 then "Sagittarius"
    when 302.49..311.72 then "Capricorn"
    when 311.72..348.58 then "Aquarius"
    else "Pisces"
  end

  # the "sweep-flag" and the direction of movement change every quarter moon
  # zero and one are both new moon; 0.50 is full moon    
  case i_phase
  when 0.25..0.50 then
    @sweep     = [0, 0];
    @magnitude = 20 * (i_phase - 0.25) * 4
  when 0.50..0.75 then
    @sweep     = [1, 1];
    @magnitude = 20 - 20 * (i_phase - 0.50) * 4
  when 0.75..1.00 then
    @sweep     = [0, 1];
    @magnitude = 20 * (i_phase - 0.75) * 4
  else 
    @sweep     = [1, 0];
    @magnitude = 20 - 20 * i_phase   * 4
  end

  @detailed_position      = "Ecliptic position : λ #{@longitude} - β #{@latitude}"
  @detailed_age           = "Current cycle age #{(@age).round(2)} days"
  @detailed_distance      = "Distance is #{(@distance).round(2)} earth radii"
  @detailed_constellation = "The #{@phase} moon is in #{@constellation}"    
end

#svgString

Calculates the magnification for a given telescope and eyepiece

Returns:

  • (String)

    the SVG output



135
136
137
138
139
140
141
142
143
# File 'lib/astro_calc/moon_phases.rb', line 135

def svg
  output = ""
  output << "<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 100% 100%' version='1.1' id='moon_phase'>"
  output << "<path d='m100,0 a20,20 0 1,1 0,150 a20,20 0 1,1 0,-150' class='moon_back'></path>"
  output << "<image xlink:href='moon.jpg; x='0' y='0' height='200px' width='200px'/>"
  output << "<path d='m100,0 a#{@magnitude.round(2)},20 0 1,#{@sweep[0]} 0,150 a20,20 0 1,#{@sweep[1]} 0,-150' class='moon'></path>"
  output << "</svg>"
  output.html_safe
end

#unicodeString

Provides the unicode characters for the moon phase

Returns:

  • (String)

    the unicode string showing the moon phase



119
120
121
122
123
124
125
126
127
128
129
130
# File 'lib/astro_calc/moon_phases.rb', line 119

def unicode  
  case @phase 
    when 0.0625..0.1875 then "🌒"
    when 0.1875..0.3125 then "🌓"
    when 0.3125..0.4375 then "🌔"
    when 0.4375..0.5625 then "🌕"
    when 0.5625..0.6875 then "🌖"
    when 0.6875..0.8125 then "🌗"
    when 0.8125..0.9375 then "🌘"
    else "🌑"      
  end
end