/* * 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; } } }