aboutsummaryrefslogtreecommitdiffstats
path: root/src/plugins/lunar.py
blob: f3415e07652dcd52bc7e749338681ad35af6f2c9 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
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
# -*- python -*-
'''
xpybar – xmobar replacement written in python
Copyright © 2014, 2015, 2016  Mattias Andrée (maandree@member.fsf.org)

This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU Affero General Public License for more details.

You should have received a copy of the GNU Affero General Public License
along with this program.  If not, see <http://www.gnu.org/licenses/>.
'''

import math
import time


class Lunar:
    '''
    Lunar observation
    
    @variable  fraction:float      The phase of the moon increasing linearly. 0 on new moon, 0,5 on
                                   full moon. ]0, 0,5[ when waxing and ]0m5, 1[ when waning.
    @variable  waxing:bool         `True` when moon is waxing (increasing illumination) and `False`
                                   when waning (decreasing). Not well defined on new moon (fraction = 0,
                                   illumination = 0) and full moon (fraction = 0,5, illumination = 1).
    @variable  terminator:float    The latitude, as seen from the northern hemisphere on Earth, of the
                                   terminator. The terminator is the line delimiting the sunlit area
                                   and the dark area.
    @variable  illumination:float  The illumnation of the moon, the fraction of the visible side's
                                   area that is sunlit
    '''
    
    REFERENCE_NEW_MOON = 934329600 # 11 August 1999 00:00:00 UTC
    '''
    :float  Time of last known new moon, in POSIX time
    '''
    
    SYNODIC_MONTH = 29.530588853
    '''
    :float  The length of a lunar month, in days
    '''
    
    def __init__(self):
        '''
        Constructor
        '''
        julian_day = lambda t   : t / 86400.0 + 2440587.5
        radians    = lambda deg : deg * math.pi / 180
        hacoversin = lambda deg : 0.5 - math.sin(radians(deg)) / 2
        
        ref = julian_day(Lunar.REFERENCE_NEW_MOON)
        now = julian_day(time.time())
        
        # TODO how to we calculate the Moon's apparent geocentric celestial longitude
        self.fraction = ((now - ref) / Lunar.SYNODIC_MONTH) % 1
        self.waxing = self.fraction <= 0.5 # we get an off by one without equality
        
        self.terminator = 90 - 360 * self.fraction # sunlit trailing
        if self.terminator < -90:
            self.terminator += 180 # visible side
        
        inverted = self.terminator < 0
        self.illumination = hacoversin(abs(self.terminator))
        if (not self.waxing) != inverted:
            self.illumination = 1 - self.illumination


# TODO add libration
# TODO add phase names
# TODO add solar and lunar eclipses
# TODO add position of sunlit area
# TODO add tides
# TODO add blue moon
# TODO add black moon
# TODO add moon colour
# TODO add altitude
# TODO add azimuth
# TODO add zodiac sign
# TODO add distances
# TODO add angular diameters