UNPKG

astrology-insights

Version:

Comprehensive Vedic astrology engine for Node.js — Panchang, birth charts (Kundli), Vimshottari Dasha, divisional charts, dosha analysis, and planetary remedies. Swiss Ephemeris precision, validated against Drik Panchang.

161 lines (143 loc) 5.09 kB
/** * Planetary Position Calculator * Calculate sidereal positions for all 9 Vedic grahas. */ import { Ephemeris } from '../../calculations/ephemeris'; import { GrahaName, GrahaPosition, ALL_GRAHAS } from '../types'; import { SIGN_NAMES } from './constants'; import { determineDignity, getDignitySymbol, determineCombustion } from './states'; // Nakshatra data (inline to avoid circular deps) const NAKSHATRA_DATA: Array<{ name: string; lord: string }> = [ { name: 'Ashwini', lord: 'Ketu' }, { name: 'Bharani', lord: 'Venus' }, { name: 'Krittika', lord: 'Sun' }, { name: 'Rohini', lord: 'Moon' }, { name: 'Mrigashira', lord: 'Mars' }, { name: 'Ardra', lord: 'Rahu' }, { name: 'Punarvasu', lord: 'Jupiter' }, { name: 'Pushya', lord: 'Saturn' }, { name: 'Ashlesha', lord: 'Mercury' }, { name: 'Magha', lord: 'Ketu' }, { name: 'Purva Phalguni', lord: 'Venus' }, { name: 'Uttara Phalguni', lord: 'Sun' }, { name: 'Hasta', lord: 'Moon' }, { name: 'Chitra', lord: 'Mars' }, { name: 'Swati', lord: 'Rahu' }, { name: 'Vishakha', lord: 'Jupiter' }, { name: 'Anuradha', lord: 'Saturn' }, { name: 'Jyeshtha', lord: 'Mercury' }, { name: 'Mula', lord: 'Ketu' }, { name: 'Purva Ashadha', lord: 'Venus' }, { name: 'Uttara Ashadha', lord: 'Sun' }, { name: 'Shravana', lord: 'Moon' }, { name: 'Dhanishtha', lord: 'Mars' }, { name: 'Shatabhisha', lord: 'Rahu' }, { name: 'Purva Bhadrapada', lord: 'Jupiter' }, { name: 'Uttara Bhadrapada', lord: 'Saturn' }, { name: 'Revati', lord: 'Mercury' }, ]; function normalizeAngle(a: number): number { let n = a % 360; if (n < 0) n += 360; return n; } function computeNakshatra(lon: number): { name: string; number: number; pada: number; lord: string; } { const oneNak = 360 / 27; const onePada = oneNak / 4; const norm = normalizeAngle(lon); const idx = Math.floor(norm / oneNak); const posInNak = norm - idx * oneNak; const pada = Math.min(Math.floor(posInNak / onePada) + 1, 4); const nk = NAKSHATRA_DATA[idx] || { name: 'Unknown', lord: 'Unknown' }; return { name: nk.name, number: idx + 1, pada, lord: nk.lord }; } /** * Calculate sidereal positions for all 9 grahas. */ export function calculateAllPlanets( utcDate: Date, ayanamsa: number, ephemeris: Ephemeris, ): GrahaPosition[] { const positions: GrahaPosition[] = []; // First, calculate Sun position (needed for combustion checks) let sunSiderealLon = 0; for (const graha of ALL_GRAHAS) { const pos = ephemeris.calculatePosition(utcDate, graha); const siderealLon = normalizeAngle(pos.longitude - ayanamsa); // Get speed via the Ephemeris speed method const speed = getGrahaSpeed(utcDate, graha, ephemeris); // Rahu & Ketu are always retrograde let retrograde: boolean; if (graha === 'Rahu' || graha === 'Ketu') { retrograde = true; } else { retrograde = speed < 0; } const signNumber = Math.floor(siderealLon / 30) + 1; const degreeInSign = siderealLon - (signNumber - 1) * 30; const nak = computeNakshatra(siderealLon); const dignity = determineDignity(graha, signNumber, degreeInSign); const symbol = getDignitySymbol(dignity); if (graha === 'Sun') { sunSiderealLon = siderealLon; } positions.push({ name: graha, longitude: Math.round(siderealLon * 10000) / 10000, latitude: pos.latitude, speed: Math.round(speed * 10000) / 10000, retrograde, signName: SIGN_NAMES[signNumber] || 'Unknown', signNumber, degreeInSign: Math.round(degreeInSign * 100) / 100, nakshatra: nak.name, nakshatraNumber: nak.number, nakshatraPada: nak.pada, nakshatraLord: nak.lord, dignity, isCombust: false, // will be filled below combustOrb: 0, symbol, }); } // Now compute combustion for each planet (need Sun's position) for (const gp of positions) { if (gp.name === 'Sun') { sunSiderealLon = gp.longitude; break; } } for (const gp of positions) { const comb = determineCombustion(gp.name, gp.longitude, sunSiderealLon, gp.retrograde); gp.isCombust = comb.isCombust; gp.combustOrb = comb.orb; } return positions; } /** * Get the speed (degrees/day) for a graha. * Uses swe_calc_ut with SEFLG_SPEED. */ function getGrahaSpeed(utcDate: Date, graha: GrahaName, ephemeris: Ephemeris): number { try { const result = ephemeris.calculatePositionWithSpeed(utcDate, graha); return result.speed; } catch { // Fallback speeds (mean daily motion) const defaultSpeeds: Record<string, number> = { Sun: 0.9856, Moon: 13.176, Mars: 0.524, Mercury: 1.383, Jupiter: 0.083, Venus: 1.602, Saturn: 0.034, Rahu: -0.053, // always retrograde Ketu: -0.053, }; return defaultSpeeds[graha] || 0; } }