Skip to content

Commit 1fe2aa2

Browse files
committed
Merge branch 'dev'
2 parents 876ece6 + 0d30485 commit 1fe2aa2

File tree

12 files changed

+246
-95
lines changed

12 files changed

+246
-95
lines changed

.gitignore

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,7 @@
11
dist/app.js
22
node_modules
33
\.vscode/
4-
\.idea
4+
\.idea
5+
6+
# Ignore minimized output for now
7+
dist/app.min.js

CHANGELOG.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,13 @@
11
# Change Log
22
All notable changes to this project will be documented in this file.
33

4+
5+
## [0.4.0] - 2017-09-20
6+
7+
### Added
8+
9+
- **New! Lunar Phases** Now the calendar generate lunar phases for the principal satellite!
10+
411
## [0.3.0] - 2017-08-21
512

613
### Changed

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ I will address the problem with such exotic planets in the future.
3030

3131
## Feature Backlog
3232

33-
- [ ] Lunar Phases
33+
- [x] Lunar Phases
3434
- [x] Seasons
3535
- [ ] Astrological Features (zodiac-like)
3636
- [ ] Multi-Year Cycles (e.g., like in the Chinese Calendar)

dist/css/styles.css

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,3 +41,12 @@ div#generator > div {
4141
padding: 10px;
4242
}
4343

44+
/* Calendexample */
45+
table tbody tr td div.calenday {
46+
width: 40px;
47+
}
48+
49+
table div.calenday span {
50+
display: inline-block;
51+
width: 20px;
52+
}

package.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
{
2-
"version": "0.3.0",
2+
"version": "0.4.0",
33
"author": {
44
"email": "thek3nger@gmail.com",
55
"name": "Davide Aversa"
@@ -29,7 +29,7 @@
2929
"react": "^15.6.1",
3030
"react-dom": "^15.6.1",
3131
"ts-node": "^3.0.4",
32-
"typescript": "^2.3.4"
32+
"typescript": "^2.5.2"
3333
},
3434
"devDependencies": {
3535
"ts-loader": "^2.3.2",

src/app.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import * as log from 'loglevel'
22

33
import * as GeneratorUI from "./interface"
44

5-
const VERSION = "v0.3.0";
5+
const VERSION = "v0.4.0";
66

77
export function init() {
88
log.setLevel("debug");

src/calendgen.ts

Lines changed: 78 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -1,47 +1,38 @@
1-
import * as Physic from "./physic"
21
import * as Newton from "./newton"
3-
4-
/**
5-
* `OrbitalBody` defines data representing information about an orbiting body of the solar system.
6-
*
7-
* This can be referred to a planet orbiting around a star, or a satellite orbiting a planet.
8-
*/
9-
interface OrbitalBody {
10-
mass: number /// The orbital body mass in Kg.
11-
rotation: number /// The rotation period in seconds.
12-
orbit: OrbitalParameters /// The orbital parameters.
13-
axial_tilt?: number /// Axial tilt for the body rotation wrt the orbital plane.
14-
}
2+
import { OrbitalBody, orbital_period, secondsToDays, eccentricity } from "./physic";
153

164
/**
175
* `SystemParameters` describes the parameters for a planet in star system.
186
*
197
* It includes the star mass, and the planet and satellites orbital information.
208
*/
219
interface SystemParameters {
22-
planet: OrbitalBody /// The planet.
23-
star_mass: number /// The orbiting star mass in Kg.
24-
satellites: Array<OrbitalBody> /// A list of satellites.
10+
readonly planet: OrbitalBody /// The planet.
11+
readonly satellites: ReadonlyArray<OrbitalBody> /// A list of satellites.
2512
}
2613

2714
/**
28-
* Define the orbital parameters for an orbital body.
15+
* The output data for the actual calendar.
2916
*/
30-
interface OrbitalParameters {
31-
periapsis: number /// The celestial body orbit periapsis in meters.
32-
apoapsis: number /// The celestial body orbit apopasis in meters.
33-
inclination?: number /// The inclination of the orbital plane respect to the system reference plane.
17+
interface CalendarParameters {
18+
readonly days_per_year: number /// Number of days in a year.
19+
readonly moon_day_period: number /// Number of days in a principal moon revolution.
20+
readonly months_per_year: number /// How many moon revolutions there are in a year.
21+
readonly base_days_per_month: number /// Number of days in a principal moon revolution (floored). // TODO: This is probably superfluous.
22+
readonly leap: LeapYearData /// Information about leap days.
3423
}
3524

3625
/**
37-
* The output data for the actual calendar.
26+
* Store information on the lunar phases of a single moon.
27+
*
28+
* All time correspond to the FIRST occurrence from time zero.
29+
* Values are expressed in seconds.
3830
*/
39-
interface CalendarParameters {
40-
days_per_year: number /// Number of days in a year.
41-
moon_day_period: number /// Number of days in a principal moon revolution.
42-
months_per_year: number /// How many moon revolutions there are in a year.
43-
base_days_per_month: number /// Number of days in a principal moon revolution (floored). // TODO: This is probably superfluous.
44-
leap: LeapYearData /// Information about leap days.
31+
export interface LunarPhases {
32+
readonly full_moon: number
33+
readonly new_moon: number
34+
readonly third_quart: number
35+
readonly first_quart: number
4536
}
4637

4738
/**
@@ -53,25 +44,26 @@ interface LeapYearData { leap_total_days: number, leap_period: number }
5344
* Output of the calendar generator. // TODO: Probably superfluous.
5445
*/
5546
export interface CalendarGeneratorOutput {
56-
calendar_parameters: CalendarParameters
47+
readonly calendar_parameters: CalendarParameters
5748
}
5849

5950
/**
6051
* Computed astronomical season-related events.
6152
*/
6253
export interface SeasonsParameters {
63-
spring_equinox: number, /// Time in seconds for the first equinox.
64-
summer_solstice: number,
65-
autumn_equinox: number,
66-
winter_solstice: number
54+
readonly spring_equinox: number, /// Time in seconds for the first equinox.
55+
readonly summer_solstice: number,
56+
readonly autumn_equinox: number,
57+
readonly winter_solstice: number
6758
}
6859

6960
/**
7061
* Encapsulate the global generator output.
7162
*/
7263
export interface GeneratorOutput {
73-
calendar: CalendarGeneratorOutput,
74-
seasons: SeasonsParameters
64+
readonly calendar: CalendarGeneratorOutput,
65+
readonly seasons: SeasonsParameters,
66+
readonly lunar_phases: LunarPhases
7567
}
7668

7769
/**
@@ -80,31 +72,25 @@ export interface GeneratorOutput {
8072
* @returns An instance of a generated calendar for the planet.
8173
*/
8274
export function generateCalendarFromOrbit(system_data: SystemParameters): GeneratorOutput {
83-
const planet_apoapsis = system_data.planet.orbit.apoapsis;
84-
const planet_periapsis = system_data.planet.orbit.periapsis;
85-
const planet_axis_major = (planet_apoapsis + planet_periapsis) / 2;
86-
const planet_mass = system_data.planet.mass;
8775
const planet_day_duration = system_data.planet.rotation;
88-
const eccentricity = (planet_apoapsis - planet_periapsis) / (planet_apoapsis + planet_periapsis);
8976

9077
// Compute planet orbital period.
91-
let planet_year = Physic.orbital_period(system_data.star_mass, planet_axis_major, planet_mass);
78+
let planet_year = orbital_period(system_data.planet);
9279

9380
let moon_periods: Array<number> = [];
9481
// Compute moon periods.
9582
for (let moon of system_data.satellites) {
96-
let moon_axis_major = (moon.orbit.periapsis + moon.orbit.apoapsis) / 2;
97-
moon_periods.push(Physic.orbital_period(planet_mass, moon_axis_major, moon.mass));
83+
moon_periods.push(orbital_period(moon));
9884
}
9985

100-
const seasons = computeSeasons(0, 6, 4, eccentricity, planet_year);
86+
const seasons = compute_seasons(system_data.planet, 6, 4);
10187
const calendar = generateCalendarFromPeriod(planet_year, moon_periods, planet_day_duration);
102-
//instantiateCalendar(calendar, 7, seasons);
103-
return { calendar, seasons };
88+
const lunar_phases = computeLunarPhases(system_data.planet, system_data.satellites[0], calendar);
89+
return { calendar, seasons, lunar_phases };
10490
}
10591

10692
function generateCalendarFromPeriod(planet_period: number, moon_periods: Array<number>, planet_day_duration: number = 86400): CalendarGeneratorOutput {
107-
let year_days_full = Physic.secondsToDays(planet_period, planet_day_duration);
93+
let year_days_full = secondsToDays(planet_period, planet_day_duration);
10894
let year_days = Math.floor(year_days_full);
10995

11096
// Compute Leap Years.
@@ -121,10 +107,10 @@ function generateCalendarFromPeriod(planet_period: number, moon_periods: Array<n
121107

122108
if (moon_periods.length > 0) {
123109
// TODO: For now, there is only one moon. In the future we may support multiple moons.
124-
let moon_day_period = Physic.secondsToDays(moon_periods[0], planet_day_duration);
125-
let month_days = Math.floor(Physic.secondsToDays(moon_periods[0], planet_day_duration));
110+
let moon_day_period = secondsToDays(moon_periods[0], planet_day_duration);
111+
let month_days = Math.floor(secondsToDays(moon_periods[0], planet_day_duration));
126112
let lunar_months = Math.floor(year_days / month_days);
127-
let days_remainder = year_days - lunar_months * month_days;
113+
// let days_remainder = year_days - lunar_months * month_days;
128114

129115
output_parameters = {
130116
days_per_year: year_days,
@@ -204,20 +190,54 @@ function thirdOrderConvergent(cf: Array<number>): [number, number] {
204190
}
205191

206192
// SEASONS
207-
208-
export function computeSeasons(axial_tilt: number, A: number, B: number, eccentricity: number, period: number): SeasonsParameters {
193+
export function compute_seasons(body: OrbitalBody, A: number, B: number) : SeasonsParameters {
194+
const e = eccentricity(body.orbit);
195+
const period = orbital_period(body);
209196
let E = Newton.NewtonRoot(
210-
(x) => (B * (Math.cos(x) - eccentricity) - A * (Math.sqrt(1 - eccentricity * eccentricity) * Math.sin(x))),
211-
(x) => -(B * Math.sin(x) + A * (Math.sqrt(1 - eccentricity * eccentricity)) * Math.cos(x)),
197+
(x) => (B * (Math.cos(x) - e) - A * (Math.sqrt(1 - e * e) * Math.sin(x))),
198+
(x) => -(B * Math.sin(x) + A * (Math.sqrt(1 - e * e)) * Math.cos(x)),
212199
1, 0.01);
213200
let E2 = E + Math.PI / 2;
214201
let E3 = E + Math.PI;
215202
let E4 = E + (3 / 2) * Math.PI;
216203
return {
217-
spring_equinox: (period / (2 * Math.PI)) * (E - eccentricity * Math.sin(E)),
218-
summer_solstice: (period / (2 * Math.PI)) * (E2 - eccentricity * Math.sin(E2)),
219-
autumn_equinox: (period / (2 * Math.PI)) * (E3 - eccentricity * Math.sin(E3)),
220-
winter_solstice: (period / (2 * Math.PI)) * (E4 - eccentricity * Math.sin(E4))
204+
spring_equinox: (period / (2 * Math.PI)) * (E - e * Math.sin(E)),
205+
summer_solstice: (period / (2 * Math.PI)) * (E2 - e * Math.sin(E2)),
206+
autumn_equinox: (period / (2 * Math.PI)) * (E3 - e * Math.sin(E3)),
207+
winter_solstice: (period / (2 * Math.PI)) * (E4 - e * Math.sin(E4))
221208
};
222209

210+
}
211+
212+
// LUNAR PHASES
213+
export function computeLunarPhases(planet: OrbitalBody, moon: OrbitalBody, calendar: CalendarGeneratorOutput): LunarPhases {
214+
const moon_period = calendar.calendar_parameters.moon_day_period;
215+
// Compute first full moon.
216+
// Full moons occurs when the moon is aligned with the SUN-PLANET axis.
217+
// This is equivalent of saying that the full moon occurs when the true anomaly of the moon orbit is 0.
218+
// FM = kP (where P is the orbital period and k is an integer)
219+
const full_moon_time = 0;
220+
// Compute first new moon.
221+
// This occurs when the moon is in opposition to the SUN-PLANET axis.
222+
// This is equivalent of saying that the new moon occurs when the true anomaly of the moon orbit is PI.
223+
// NM = P/2 + kP
224+
// (Note that Mean Anomaly, Eccentric Anomaly and True Anomaly are equivalent on 0 and PI)
225+
const new_moon_time = Math.floor(moon_period / 2);
226+
// Compute the third quart.
227+
// this occur when MOON-PLANET axis is perpendicular to the SUN-PLANET orbit.
228+
// This is equivalent of saying that the third quarter occurs when the true anomaly of the moon orbit is PI/2.
229+
// In this case MA, EA, and TA **do not match**. The formula is more complex.
230+
const moon_apoapsis = moon.orbit.apoapsis;
231+
const moon_periapsis = moon.orbit.periapsis;
232+
const e = (moon_apoapsis - moon_periapsis) / (moon_apoapsis + moon_periapsis);
233+
const gamma = Math.sqrt((1 + e) / (1 - e));
234+
const third_quart_time = Math.floor(moon_period * (1 / Math.PI) * Math.atan(1 / gamma) - e * ((2 * gamma) / (gamma * gamma) + 1));
235+
// Compute the first quart.
236+
// this occur when MOON-PLANET axis is anti-perpendicular to the SUN-PLANET orbit.
237+
// This is equivalent of saying that the third quarter occurs when the true anomaly of the moon orbit is -PI/2.
238+
// In this case MA, EA, and TA **do not match**. The formula is more complex.
239+
const first_quart_time = Math.floor(-third_quart_time + moon_period); // TODO: Check this.
240+
241+
return { full_moon: full_moon_time, new_moon: new_moon_time, first_quart: first_quart_time, third_quart: third_quart_time };
242+
223243
}

0 commit comments

Comments
 (0)