/*
* kollavarsham
* http://kollavarsham.org
*
* Copyright (c) 2014-2023 The Kollavarsham Team
* Licensed under the MIT license.
*/
/**
* @module celestial
*/
import { MathHelper } from '../mathHelper';
import { PlanetarySystem } from './planetarySystem/index';
/**
*
* **INTERNAL/PRIVATE**
*
* @class Celestial
*/
export class Celestial {
constructor(system = 'SuryaSiddhanta') {
const planetarySystem = new PlanetarySystem(system);
this.planets = planetarySystem.planets;
this.yuga = planetarySystem.yuga;
this.backLastConjunctionAhargana = -1;
this.backNextConjunctionAhargana = -1;
this.backLastConjunctionLongitude = -1;
this.backNextConjunctionLongitude = -1;
}
static threeRelation(left, center, right) {
if (left < center && center < right) {
return 1;
}
else if (right < center && center < left) {
return -1;
}
return 0;
}
static declination(longitude) {
// https://en.wikipedia.org/wiki/Declination
return Math.asin(Math.sin(longitude / MathHelper.radianInDegrees) * Math.sin(24 / MathHelper.radianInDegrees)) *
MathHelper.radianInDegrees;
}
static getSunriseTime(time, equationOfTime) {
// TODO: Add Tests if/when feasible
const sunriseTime = (time - equationOfTime) * 24;
const sunriseHour = MathHelper.truncate(sunriseTime);
const sunriseMinute = MathHelper.truncate(60 * MathHelper.fractional(sunriseTime));
return { sunriseHour, sunriseMinute };
}
static getTithi(trueSolarLongitude, trueLunarLongitude) {
let eclipticLongitude = trueLunarLongitude - trueSolarLongitude;
eclipticLongitude = MathHelper.zero360(eclipticLongitude);
return eclipticLongitude / 12;
}
setPlanetaryPositions(ahargana) {
const $planets = this.planets;
// Lunar apogee and node at sunrise
$planets.candrocca.MeanPosition = MathHelper.zero360(this.getMeanLongitude(ahargana, $planets.candrocca.YugaRotation) + 90);
$planets.rahu.MeanPosition = MathHelper.zero360(this.getMeanLongitude(ahargana, $planets.rahu.YugaRotation) + 180);
// mean and true sun at sunrise
const meanSolarLongitude = this.getMeanLongitude(ahargana, $planets.sun.YugaRotation);
$planets.sun.MeanPosition = meanSolarLongitude;
const trueSolarLongitude = MathHelper.zero360(meanSolarLongitude - this.getMandaEquation(meanSolarLongitude - $planets.sun.Apogee, 'sun'));
// mean and true moon at sunrise
const meanLunarLongitude = this.getMeanLongitude(ahargana, $planets.moon.YugaRotation);
$planets.moon.MeanPosition = meanLunarLongitude;
$planets.moon.Apogee = $planets.candrocca.MeanPosition;
const trueLunarLongitude = MathHelper.zero360(meanLunarLongitude - this.getMandaEquation(meanLunarLongitude - $planets.moon.Apogee, 'moon'));
// The below was a separate method named calculations.planetary (ported from planetary_calculations in perl)
const planetNames = ['mercury', 'venus', 'mars', 'jupiter', 'saturn'];
for (let i = 0; i < planetNames.length; i++) {
$planets[planetNames[i]].MeanPosition = this.getMeanLongitude(ahargana, $planets[planetNames[i]].Rotation);
}
return { trueSolarLongitude, trueLunarLongitude };
}
getMeanLongitude(ahargana, rotation) {
// https://en.wikipedia.org/wiki/Mean_longitude
// https://en.wikipedia.org/wiki/Ecliptic_coordinate_system#Spherical_coordinates
return 360 * MathHelper.fractional(rotation * ahargana / this.yuga.CivilDays);
}
getDaylightEquation(year, latitude, ahargana) {
// Good read - http://en.wikipedia.org/wiki/Equation_of_time#Calculating_the_equation_of_time
const meanSolarLongitude = this.getMeanLongitude(ahargana, this.planets.sun.YugaRotation);
// Sayana Solar Longitude and Declination
const sayanaMeanSolarLongitude = meanSolarLongitude + 54 / 3600 * (year - 499);
const sayanaDeclination = Celestial.declination(sayanaMeanSolarLongitude); // See Sewell, p.10
// Equation of day light by Analemma (https://en.wikipedia.org/wiki/Analemma)
const x = Math.tan(latitude / MathHelper.radianInDegrees) * Math.tan(sayanaDeclination / MathHelper.radianInDegrees);
return 0.5 * Math.asin(x) / Math.PI;
}
getMandaEquation(argument, planet) {
return Math.asin(this.planets[planet].MandaCircumference / 360 * Math.sin(argument / MathHelper.radianInDegrees)) * MathHelper.radianInDegrees;
}
getTrueLunarLongitude(ahargana) {
const meanLunarLongitude = this.getMeanLongitude(ahargana, this.planets.moon.YugaRotation);
const apogee = this.getMeanLongitude(ahargana, this.planets.candrocca.YugaRotation) + 90;
return MathHelper.zero360(meanLunarLongitude - this.getMandaEquation(meanLunarLongitude - apogee, 'moon'));
}
getTrueSolarLongitude(ahargana) {
const meanSolarLongitude = this.getMeanLongitude(ahargana, this.planets.sun.YugaRotation);
return MathHelper.zero360(meanSolarLongitude - this.getMandaEquation(meanSolarLongitude - this.planets.sun.Apogee, 'sun'));
}
getEclipticLongitude(ahargana) {
let eclipticLongitude = Math.abs(this.getTrueLunarLongitude(ahargana) - this.getTrueSolarLongitude(ahargana));
if (eclipticLongitude >= 180) {
eclipticLongitude = 360 - eclipticLongitude;
}
return eclipticLongitude;
}
findConjunction(leftX, leftY, rightX, rightY) {
const width = (rightX - leftX) / 2;
const centreX = (rightX + leftX) / 2;
if (width < MathHelper.epsilon) {
return this.getTrueSolarLongitude(centreX);
}
else {
const centreY = this.getEclipticLongitude(centreX);
const relation = Celestial.threeRelation(leftY, centreY, rightY);
if (relation < 0) {
rightX += width;
rightY = this.getEclipticLongitude(rightX);
return this.findConjunction(centreX, centreY, rightX, rightY);
}
else if (relation > 0) {
leftX -= width;
leftY = this.getEclipticLongitude(leftX);
return this.findConjunction(leftX, leftY, centreX, centreY);
}
else {
leftX += width / 2;
leftY = this.getEclipticLongitude(leftX);
rightX -= width / 2;
rightY = this.getEclipticLongitude(rightX);
return this.findConjunction(leftX, leftY, rightX, rightY);
}
}
}
getConjunction(ahargana) {
const leftX = ahargana - 2;
const leftY = this.getEclipticLongitude(leftX);
const rightX = ahargana + 2;
const rightY = this.getEclipticLongitude(rightX);
return this.findConjunction(leftX, leftY, rightX, rightY);
}
getLastConjunctionLongitude(ahargana, tithi) {
const newNew = this.yuga.CivilDays / (this.planets.moon.YugaRotation - this.planets.sun.YugaRotation);
ahargana -= tithi * (newNew / 30);
if (Math.abs(ahargana - this.backLastConjunctionAhargana) < 1) {
return this.backLastConjunctionLongitude;
}
else if (Math.abs(ahargana - this.backNextConjunctionAhargana) < 1) {
this.backLastConjunctionAhargana = this.backNextConjunctionAhargana;
this.backLastConjunctionLongitude = this.backNextConjunctionLongitude;
return this.backNextConjunctionLongitude;
}
else {
this.backLastConjunctionAhargana = ahargana;
this.backLastConjunctionLongitude = this.getConjunction(ahargana);
return this.backLastConjunctionLongitude;
}
}
getNextConjunctionLongitude(ahargana, tithi) {
const newNew = this.yuga.CivilDays / (this.planets.moon.YugaRotation - this.planets.sun.YugaRotation);
ahargana += (30 - tithi) * (newNew / 30);
if (Math.abs(ahargana - this.backNextConjunctionAhargana) < 1) {
return this.backNextConjunctionLongitude;
}
else {
this.backNextConjunctionAhargana = ahargana;
this.backNextConjunctionLongitude = this.getConjunction(ahargana);
return this.backNextConjunctionLongitude;
}
}
}