@typescriptify/sweph 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +422 -0
- package/ephe/semo_18.se1 +0 -0
- package/ephe/sepl_18.se1 +0 -0
- package/originalCode/.eslintrc.json +124 -0
- package/originalCode/.gitattributes +2 -0
- package/originalCode/.github/FUNDING.yml +5 -0
- package/originalCode/.github/workflows/test.yml +35 -0
- package/originalCode/LICENSE +840 -0
- package/originalCode/README.md +91 -0
- package/originalCode/binding.gyp +41 -0
- package/originalCode/constants.js +366 -0
- package/originalCode/docs.gif +0 -0
- package/originalCode/index.d.ts +5115 -0
- package/originalCode/index.js +7 -0
- package/originalCode/index.mjs +109 -0
- package/originalCode/package.json +55 -0
- package/originalCode/src/functions/azalt.cpp +39 -0
- package/originalCode/src/functions/azalt_rev.cpp +35 -0
- package/originalCode/src/functions/calc.cpp +29 -0
- package/originalCode/src/functions/calc_pctr.cpp +31 -0
- package/originalCode/src/functions/calc_ut.cpp +29 -0
- package/originalCode/src/functions/close.cpp +6 -0
- package/originalCode/src/functions/cotrans.cpp +26 -0
- package/originalCode/src/functions/cotrans_sp.cpp +26 -0
- package/originalCode/src/functions/cs2degstr.cpp +19 -0
- package/originalCode/src/functions/cs2lonlatstr.cpp +23 -0
- package/originalCode/src/functions/cs2timestr.cpp +23 -0
- package/originalCode/src/functions/csnorm.cpp +15 -0
- package/originalCode/src/functions/csroundsec.cpp +15 -0
- package/originalCode/src/functions/d2l.cpp +15 -0
- package/originalCode/src/functions/date_conversion.cpp +30 -0
- package/originalCode/src/functions/day_of_week.cpp +15 -0
- package/originalCode/src/functions/degnorm.cpp +15 -0
- package/originalCode/src/functions/deltat.cpp +15 -0
- package/originalCode/src/functions/deltat_ex.cpp +24 -0
- package/originalCode/src/functions/difcs2n.cpp +19 -0
- package/originalCode/src/functions/difcsn.cpp +19 -0
- package/originalCode/src/functions/difdeg2n.cpp +19 -0
- package/originalCode/src/functions/difdegn.cpp +19 -0
- package/originalCode/src/functions/fixstar.cpp +32 -0
- package/originalCode/src/functions/fixstar2.cpp +32 -0
- package/originalCode/src/functions/fixstar2_mag.cpp +28 -0
- package/originalCode/src/functions/fixstar2_ut.cpp +32 -0
- package/originalCode/src/functions/fixstar_mag.cpp +28 -0
- package/originalCode/src/functions/fixstar_ut.cpp +32 -0
- package/originalCode/src/functions/gauquelin_sector.cpp +44 -0
- package/originalCode/src/functions/get_ayanamsa.cpp +15 -0
- package/originalCode/src/functions/get_ayanamsa_ex.cpp +27 -0
- package/originalCode/src/functions/get_ayanamsa_ex_ut.cpp +27 -0
- package/originalCode/src/functions/get_ayanamsa_name.cpp +19 -0
- package/originalCode/src/functions/get_ayanamsa_ut.cpp +15 -0
- package/originalCode/src/functions/get_current_file_data.cpp +28 -0
- package/originalCode/src/functions/get_library_path.cpp +8 -0
- package/originalCode/src/functions/get_orbital_elements.cpp +29 -0
- package/originalCode/src/functions/get_planet_name.cpp +19 -0
- package/originalCode/src/functions/get_tid_acc.cpp +7 -0
- package/originalCode/src/functions/heliacal_pheno_ut.cpp +52 -0
- package/originalCode/src/functions/heliacal_ut.cpp +52 -0
- package/originalCode/src/functions/helio_cross.cpp +33 -0
- package/originalCode/src/functions/helio_cross_ut.cpp +33 -0
- package/originalCode/src/functions/house_name.cpp +20 -0
- package/originalCode/src/functions/house_pos.cpp +36 -0
- package/originalCode/src/functions/houses.cpp +35 -0
- package/originalCode/src/functions/houses_armc.cpp +38 -0
- package/originalCode/src/functions/houses_armc_ex2.cpp +47 -0
- package/originalCode/src/functions/houses_ex.cpp +37 -0
- package/originalCode/src/functions/houses_ex2.cpp +46 -0
- package/originalCode/src/functions/jdet_to_utc.cpp +38 -0
- package/originalCode/src/functions/jdut1_to_utc.cpp +38 -0
- package/originalCode/src/functions/julday.cpp +25 -0
- package/originalCode/src/functions/lat_to_lmt.cpp +27 -0
- package/originalCode/src/functions/lmt_to_lat.cpp +27 -0
- package/originalCode/src/functions/lun_eclipse_how.cpp +34 -0
- package/originalCode/src/functions/lun_eclipse_when.cpp +31 -0
- package/originalCode/src/functions/lun_eclipse_when_loc.cpp +39 -0
- package/originalCode/src/functions/lun_occult_when_glob.cpp +35 -0
- package/originalCode/src/functions/lun_occult_when_loc.cpp +43 -0
- package/originalCode/src/functions/lun_occult_where.cpp +34 -0
- package/originalCode/src/functions/mooncross.cpp +26 -0
- package/originalCode/src/functions/mooncross_node.cpp +30 -0
- package/originalCode/src/functions/mooncross_node_ut.cpp +30 -0
- package/originalCode/src/functions/mooncross_ut.cpp +26 -0
- package/originalCode/src/functions/nod_aps.cpp +42 -0
- package/originalCode/src/functions/nod_aps_ut.cpp +42 -0
- package/originalCode/src/functions/orbit_max_min_true_distance.cpp +37 -0
- package/originalCode/src/functions/pheno.cpp +29 -0
- package/originalCode/src/functions/pheno_ut.cpp +29 -0
- package/originalCode/src/functions/radnorm.cpp +15 -0
- package/originalCode/src/functions/refrac.cpp +23 -0
- package/originalCode/src/functions/refrac_extended.cpp +32 -0
- package/originalCode/src/functions/revjul.cpp +33 -0
- package/originalCode/src/functions/rise_trans.cpp +44 -0
- package/originalCode/src/functions/rise_trans_true_hor.cpp +46 -0
- package/originalCode/src/functions/set_delta_t_userdef.cpp +14 -0
- package/originalCode/src/functions/set_ephe_path.cpp +14 -0
- package/originalCode/src/functions/set_jpl_file.cpp +14 -0
- package/originalCode/src/functions/set_sid_mode.cpp +20 -0
- package/originalCode/src/functions/set_tid_acc.cpp +14 -0
- package/originalCode/src/functions/set_topo.cpp +20 -0
- package/originalCode/src/functions/sidtime.cpp +15 -0
- package/originalCode/src/functions/sidtime0.cpp +21 -0
- package/originalCode/src/functions/sol_eclipse_how.cpp +34 -0
- package/originalCode/src/functions/sol_eclipse_when_glob.cpp +31 -0
- package/originalCode/src/functions/sol_eclipse_when_loc.cpp +39 -0
- package/originalCode/src/functions/sol_eclipse_where.cpp +30 -0
- package/originalCode/src/functions/solcross.cpp +26 -0
- package/originalCode/src/functions/solcross_ut.cpp +26 -0
- package/originalCode/src/functions/split_deg.cpp +35 -0
- package/originalCode/src/functions/time_equ.cpp +25 -0
- package/originalCode/src/functions/utc_time_zone.cpp +48 -0
- package/originalCode/src/functions/utc_to_jd.cpp +37 -0
- package/originalCode/src/functions/version.cpp +8 -0
- package/originalCode/src/functions/vis_limit_mag.cpp +50 -0
- package/originalCode/src/sweph.cpp +150 -0
- package/originalCode/src/sweph.h +119 -0
- package/originalCode/swisseph/swecl.c +6428 -0
- package/originalCode/swisseph/swedate.c +588 -0
- package/originalCode/swisseph/swedate.h +81 -0
- package/originalCode/swisseph/swehel.c +3511 -0
- package/originalCode/swisseph/swehouse.c +3143 -0
- package/originalCode/swisseph/swehouse.h +98 -0
- package/originalCode/swisseph/swejpl.c +958 -0
- package/originalCode/swisseph/swejpl.h +103 -0
- package/originalCode/swisseph/swemmoon.c +1930 -0
- package/originalCode/swisseph/swemplan.c +967 -0
- package/originalCode/swisseph/swemptab.h +10640 -0
- package/originalCode/swisseph/swenut2000a.h +2819 -0
- package/originalCode/swisseph/sweodef.h +326 -0
- package/originalCode/swisseph/sweph.c +8614 -0
- package/originalCode/swisseph/sweph.h +849 -0
- package/originalCode/swisseph/swephexp.h +1020 -0
- package/originalCode/swisseph/swephlib.c +4634 -0
- package/originalCode/swisseph/swephlib.h +189 -0
- package/package.json +28 -0
- package/scripts/gen-swemptab.js +177 -0
- package/scripts/gen-swenut2000a.js +106 -0
- package/src/SwissEph/README.md +268 -0
- package/src/SwissEph/UseCases/Ayanamsa.md +363 -0
- package/src/SwissEph/UseCases/AzimuthAltitude.md +408 -0
- package/src/SwissEph/UseCases/CoordinateSystems.md +337 -0
- package/src/SwissEph/UseCases/DateAndTime.md +368 -0
- package/src/SwissEph/UseCases/DeltaT.md +258 -0
- package/src/SwissEph/UseCases/EphemerisFiles.md +338 -0
- package/src/SwissEph/UseCases/FixedStars.md +300 -0
- package/src/SwissEph/UseCases/GauquelinSectors.md +304 -0
- package/src/SwissEph/UseCases/HeliacalEvents.md +396 -0
- package/src/SwissEph/UseCases/HelioCrossings.md +325 -0
- package/src/SwissEph/UseCases/HousePosition.md +254 -0
- package/src/SwissEph/UseCases/HouseSystems.md +279 -0
- package/src/SwissEph/UseCases/LunarEclipse.md +326 -0
- package/src/SwissEph/UseCases/MeridianTransit.md +279 -0
- package/src/SwissEph/UseCases/MoonCrossings.md +373 -0
- package/src/SwissEph/UseCases/NodesAndApsides.md +307 -0
- package/src/SwissEph/UseCases/Occultation.md +352 -0
- package/src/SwissEph/UseCases/OrbitalElements.md +469 -0
- package/src/SwissEph/UseCases/Phenomena.md +328 -0
- package/src/SwissEph/UseCases/PlanetPositions.md +366 -0
- package/src/SwissEph/UseCases/Planetocentric.md +278 -0
- package/src/SwissEph/UseCases/Refraction.md +314 -0
- package/src/SwissEph/UseCases/RiseAndSet.md +433 -0
- package/src/SwissEph/UseCases/SiderealTime.md +302 -0
- package/src/SwissEph/UseCases/SolarEclipse.md +379 -0
- package/src/SwissEph/UseCases/SunCrossings.md +275 -0
- package/src/SwissEph/UseCases/TopocentricCorrection.md +335 -0
- package/src/SwissEph/errors.ts +10 -0
- package/src/SwissEph/index.ts +823 -0
- package/src/SwissEph/types.ts +291 -0
- package/src/constants.ts +762 -0
- package/src/file-reader.ts +147 -0
- package/src/index.ts +10 -0
- package/src/swecl.ts +4526 -0
- package/src/swedate.ts +376 -0
- package/src/swehel.ts +1939 -0
- package/src/swehouse.ts +2167 -0
- package/src/swejpl.ts +470 -0
- package/src/swemmoon.ts +1318 -0
- package/src/swemplan.ts +585 -0
- package/src/swemptab.ts +4448 -0
- package/src/swenut2000a.ts +2763 -0
- package/src/sweph.ts +3993 -0
- package/src/swephlib.ts +2720 -0
- package/src/types.ts +490 -0
- package/tests/c-style/ayanamsa.test.ts +63 -0
- package/tests/c-style/config.test.ts +96 -0
- package/tests/c-style/crossings.test.ts +81 -0
- package/tests/c-style/date-time.test.ts +114 -0
- package/tests/c-style/eclipses.test.ts +84 -0
- package/tests/c-style/fixed-stars.test.ts +66 -0
- package/tests/c-style/heliacal.test.ts +34 -0
- package/tests/c-style/houses.test.ts +135 -0
- package/tests/c-style/math-utils.test.ts +160 -0
- package/tests/c-style/orbital.test.ts +78 -0
- package/tests/c-style/phenomena.test.ts +42 -0
- package/tests/c-style/planetocentric.test.ts +26 -0
- package/tests/c-style/planets.test.ts +117 -0
- package/tests/c-style/rise-set.test.ts +71 -0
- package/tests/helpers.ts +21 -0
- package/tests/modern/ayanamsa.test.ts +47 -0
- package/tests/modern/calc.test.ts +113 -0
- package/tests/modern/config.test.ts +46 -0
- package/tests/modern/crossings.test.ts +45 -0
- package/tests/modern/eclipses.test.ts +81 -0
- package/tests/modern/errors.test.ts +71 -0
- package/tests/modern/heliacal.test.ts +30 -0
- package/tests/modern/houses.test.ts +87 -0
- package/tests/modern/orbital.test.ts +79 -0
- package/tests/modern/phenomena.test.ts +41 -0
- package/tests/modern/rise-set.test.ts +60 -0
- package/tests/modern/statics.test.ts +99 -0
- package/tests/modern/utilities.test.ts +70 -0
- package/tsconfig.json +20 -0
|
@@ -0,0 +1,337 @@
|
|
|
1
|
+
# Coordinate Systems
|
|
2
|
+
|
|
3
|
+
Celestial objects can be located on the sky using different coordinate systems, each defined by a different reference plane. The three main systems are:
|
|
4
|
+
|
|
5
|
+
- **Ecliptic coordinates** (longitude and latitude): Based on the **ecliptic** -- the plane of Earth's orbit around the Sun, or equivalently, the Sun's apparent annual path across the sky. The Sun is always at latitude 0 by definition, and its longitude increases through the zodiac from 0 to 360 degrees. This is the native coordinate system for astrological work and solar system mechanics.
|
|
6
|
+
|
|
7
|
+
- **Equatorial coordinates** (Right Ascension and Declination): Based on the **celestial equator** -- Earth's equator projected onto the sky. This is the standard system for observational astronomy, telescope pointing, and star catalogs. Right Ascension (RA) is measured in hours (0h-24h) or degrees (0-360), and Declination (Dec) ranges from -90 to +90 degrees.
|
|
8
|
+
|
|
9
|
+
- **Horizontal coordinates** (Azimuth and Altitude): Based on the **observer's local horizon**. This is the most intuitive system -- it tells you where to look in the sky. Unlike the other two, it changes constantly as the Earth rotates and depends on your location.
|
|
10
|
+
|
|
11
|
+
The key angle connecting the ecliptic and equatorial systems is the **obliquity of the ecliptic** -- the 23.44 degree tilt of Earth's rotation axis relative to its orbital plane. Without this tilt, the ecliptic and equatorial planes would be the same, and there would be no seasons.
|
|
12
|
+
|
|
13
|
+
---
|
|
14
|
+
|
|
15
|
+
## Quick Example
|
|
16
|
+
|
|
17
|
+
```typescript
|
|
18
|
+
import { SwissEph } from '../index';
|
|
19
|
+
import { SE_MARS, SE_ECL_NUT, SEFLG_EQUATORIAL } from '../../constants';
|
|
20
|
+
|
|
21
|
+
const swe = new SwissEph();
|
|
22
|
+
const jd = SwissEph.julianDay(2024, 6, 21, 12);
|
|
23
|
+
|
|
24
|
+
// Get Mars in ecliptic coordinates (default)
|
|
25
|
+
const marsEcl = swe.calc(jd, SE_MARS);
|
|
26
|
+
console.log(`Mars ecliptic: lon=${marsEcl.longitude.toFixed(4)} deg, lat=${marsEcl.latitude.toFixed(4)} deg`);
|
|
27
|
+
|
|
28
|
+
// Get Mars in equatorial coordinates
|
|
29
|
+
const marsEqu = swe.calc(jd, SE_MARS, SEFLG_EQUATORIAL);
|
|
30
|
+
console.log(`Mars equatorial: RA=${marsEqu.longitude.toFixed(4)} deg, Dec=${marsEqu.latitude.toFixed(4)} deg`);
|
|
31
|
+
|
|
32
|
+
swe.close();
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
---
|
|
36
|
+
|
|
37
|
+
## Detailed Examples
|
|
38
|
+
|
|
39
|
+
### Converting ecliptic to equatorial with coordinateTransform
|
|
40
|
+
|
|
41
|
+
The static `coordinateTransform()` method converts between ecliptic and equatorial coordinates using the obliquity. Pass **positive** obliquity for ecliptic-to-equatorial, **negative** for equatorial-to-ecliptic.
|
|
42
|
+
|
|
43
|
+
```typescript
|
|
44
|
+
import { SwissEph } from '../index';
|
|
45
|
+
import { SE_SUN, SE_ECL_NUT } from '../../constants';
|
|
46
|
+
|
|
47
|
+
const swe = new SwissEph();
|
|
48
|
+
const jd = SwissEph.julianDay(2024, 6, 21, 12); // Summer solstice
|
|
49
|
+
|
|
50
|
+
// Get the obliquity of the ecliptic
|
|
51
|
+
// SE_ECL_NUT returns: [0] = true obliquity, [1] = mean obliquity, [2] = nutation lon, etc.
|
|
52
|
+
const eclNut = swe.calc(jd, SE_ECL_NUT);
|
|
53
|
+
const trueObliquity = eclNut.longitude;
|
|
54
|
+
console.log(`True obliquity: ${trueObliquity.toFixed(6)} deg`);
|
|
55
|
+
|
|
56
|
+
// Get the Sun's ecliptic position
|
|
57
|
+
const sun = swe.calc(jd, SE_SUN);
|
|
58
|
+
console.log(`\nSun ecliptic: lon=${sun.longitude.toFixed(4)} deg, lat=${sun.latitude.toFixed(4)} deg`);
|
|
59
|
+
|
|
60
|
+
// Convert to equatorial using coordinateTransform
|
|
61
|
+
// Positive obliquity = ecliptic -> equatorial
|
|
62
|
+
const equatorial = SwissEph.coordinateTransform(
|
|
63
|
+
[sun.longitude, sun.latitude, sun.distance],
|
|
64
|
+
trueObliquity
|
|
65
|
+
);
|
|
66
|
+
const ra = equatorial[0];
|
|
67
|
+
const dec = equatorial[1];
|
|
68
|
+
console.log(`Sun equatorial: RA=${ra.toFixed(4)} deg, Dec=${dec.toFixed(4)} deg`);
|
|
69
|
+
|
|
70
|
+
// Convert RA to hours
|
|
71
|
+
const raHours = ra / 15;
|
|
72
|
+
const h = Math.floor(raHours);
|
|
73
|
+
const m = Math.floor((raHours - h) * 60);
|
|
74
|
+
const s = ((raHours - h) * 60 - m) * 60;
|
|
75
|
+
console.log(`Sun RA: ${h}h ${m}m ${s.toFixed(1)}s`);
|
|
76
|
+
|
|
77
|
+
// At the summer solstice, the Sun's declination should be ~+23.44 degrees
|
|
78
|
+
// (equal to the obliquity, since the Sun is at the northernmost point of the ecliptic)
|
|
79
|
+
console.log(`\nSun declination at solstice: ${dec.toFixed(4)} deg (should be ~obliquity)`);
|
|
80
|
+
|
|
81
|
+
swe.close();
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
### Converting equatorial to ecliptic
|
|
85
|
+
|
|
86
|
+
Use **negative** obliquity to reverse the conversion:
|
|
87
|
+
|
|
88
|
+
```typescript
|
|
89
|
+
import { SwissEph } from '../index';
|
|
90
|
+
import { SE_SUN, SE_ECL_NUT, SEFLG_EQUATORIAL } from '../../constants';
|
|
91
|
+
|
|
92
|
+
const swe = new SwissEph();
|
|
93
|
+
const jd = SwissEph.julianDay(2024, 3, 20, 12);
|
|
94
|
+
|
|
95
|
+
// Get obliquity
|
|
96
|
+
const eclNut = swe.calc(jd, SE_ECL_NUT);
|
|
97
|
+
const eps = eclNut.longitude;
|
|
98
|
+
|
|
99
|
+
// Get Sun in equatorial coordinates
|
|
100
|
+
const sunEqu = swe.calc(jd, SE_SUN, SEFLG_EQUATORIAL);
|
|
101
|
+
console.log(`Sun equatorial: RA=${sunEqu.longitude.toFixed(4)} deg, Dec=${sunEqu.latitude.toFixed(4)} deg`);
|
|
102
|
+
|
|
103
|
+
// Convert back to ecliptic using NEGATIVE obliquity
|
|
104
|
+
const ecliptic = SwissEph.coordinateTransform(
|
|
105
|
+
[sunEqu.longitude, sunEqu.latitude, sunEqu.distance],
|
|
106
|
+
-eps // Negative = equatorial -> ecliptic
|
|
107
|
+
);
|
|
108
|
+
console.log(`Sun ecliptic: lon=${ecliptic[0].toFixed(4)} deg, lat=${ecliptic[1].toFixed(4)} deg`);
|
|
109
|
+
|
|
110
|
+
// Verify against the direct ecliptic calculation
|
|
111
|
+
const sunEcl = swe.calc(jd, SE_SUN);
|
|
112
|
+
console.log(`Sun ecliptic (direct): lon=${sunEcl.longitude.toFixed(4)} deg, lat=${sunEcl.latitude.toFixed(4)} deg`);
|
|
113
|
+
|
|
114
|
+
swe.close();
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
### Getting equatorial coordinates directly from calc()
|
|
118
|
+
|
|
119
|
+
Instead of converting manually, you can get equatorial coordinates directly by passing `SEFLG_EQUATORIAL`:
|
|
120
|
+
|
|
121
|
+
```typescript
|
|
122
|
+
import { SwissEph } from '../index';
|
|
123
|
+
import {
|
|
124
|
+
SE_SUN, SE_MOON, SE_MARS, SE_JUPITER, SE_SATURN,
|
|
125
|
+
SEFLG_EQUATORIAL,
|
|
126
|
+
} from '../../constants';
|
|
127
|
+
|
|
128
|
+
const swe = new SwissEph();
|
|
129
|
+
const jd = SwissEph.julianDay(2024, 8, 15, 0);
|
|
130
|
+
|
|
131
|
+
const bodies = [
|
|
132
|
+
{ id: SE_SUN, name: 'Sun' },
|
|
133
|
+
{ id: SE_MOON, name: 'Moon' },
|
|
134
|
+
{ id: SE_MARS, name: 'Mars' },
|
|
135
|
+
{ id: SE_JUPITER, name: 'Jupiter' },
|
|
136
|
+
{ id: SE_SATURN, name: 'Saturn' },
|
|
137
|
+
];
|
|
138
|
+
|
|
139
|
+
console.log('Body Ecl.Lon (deg) Ecl.Lat (deg) RA (deg) RA (h:m:s) Dec (deg)');
|
|
140
|
+
|
|
141
|
+
for (const b of bodies) {
|
|
142
|
+
const ecl = swe.calc(jd, b.id);
|
|
143
|
+
const equ = swe.calc(jd, b.id, SEFLG_EQUATORIAL);
|
|
144
|
+
|
|
145
|
+
const raH = equ.longitude / 15;
|
|
146
|
+
const h = Math.floor(raH);
|
|
147
|
+
const m = Math.floor((raH - h) * 60);
|
|
148
|
+
const s = ((raH - h) * 60 - m) * 60;
|
|
149
|
+
const raStr = `${String(h).padStart(2)}h${String(m).padStart(2,'0')}m${s.toFixed(0).padStart(2,'0')}s`;
|
|
150
|
+
|
|
151
|
+
console.log(
|
|
152
|
+
`${b.name.padEnd(10)}` +
|
|
153
|
+
`${ecl.longitude.toFixed(2).padStart(10)}` +
|
|
154
|
+
`${ecl.latitude.toFixed(2).padStart(13)}` +
|
|
155
|
+
`${equ.longitude.toFixed(2).padStart(12)} ` +
|
|
156
|
+
`${raStr.padStart(12)}` +
|
|
157
|
+
`${equ.latitude.toFixed(2).padStart(11)}`
|
|
158
|
+
);
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
swe.close();
|
|
162
|
+
```
|
|
163
|
+
|
|
164
|
+
### Ecliptic to horizontal coordinates (two-step conversion)
|
|
165
|
+
|
|
166
|
+
To go from ecliptic to horizontal (azimuth/altitude), you can use the `azalt()` method, which does the full conversion internally:
|
|
167
|
+
|
|
168
|
+
```typescript
|
|
169
|
+
import { SwissEph } from '../index';
|
|
170
|
+
import { SE_MARS } from '../../constants';
|
|
171
|
+
|
|
172
|
+
const swe = new SwissEph();
|
|
173
|
+
const jd = SwissEph.julianDay(2024, 8, 15, 22); // 10 PM UT
|
|
174
|
+
const geo = { longitude: -0.128, latitude: 51.507 }; // London
|
|
175
|
+
|
|
176
|
+
// Step 1: Get ecliptic position
|
|
177
|
+
const mars = swe.calc(jd, SE_MARS);
|
|
178
|
+
console.log(`Mars ecliptic: lon=${mars.longitude.toFixed(2)} deg, lat=${mars.latitude.toFixed(2)} deg`);
|
|
179
|
+
|
|
180
|
+
// Step 2: Convert to horizontal (azalt does this in one call)
|
|
181
|
+
const hor = swe.azalt(jd, geo, mars.longitude, mars.latitude, mars.distance);
|
|
182
|
+
console.log(`Mars horizontal: az=${hor.azimuth.toFixed(2)} deg (SE), alt=${hor.apparentAltitude.toFixed(2)} deg`);
|
|
183
|
+
|
|
184
|
+
// Convert to compass bearing
|
|
185
|
+
const compass = (hor.azimuth + 180) % 360;
|
|
186
|
+
console.log(`Mars compass bearing: ${compass.toFixed(2)} deg`);
|
|
187
|
+
|
|
188
|
+
swe.close();
|
|
189
|
+
```
|
|
190
|
+
|
|
191
|
+
### Getting obliquity values
|
|
192
|
+
|
|
193
|
+
The obliquity of the ecliptic is available through `SE_ECL_NUT`:
|
|
194
|
+
|
|
195
|
+
```typescript
|
|
196
|
+
import { SwissEph } from '../index';
|
|
197
|
+
import { SE_ECL_NUT } from '../../constants';
|
|
198
|
+
|
|
199
|
+
const swe = new SwissEph();
|
|
200
|
+
|
|
201
|
+
// Check obliquity at different epochs
|
|
202
|
+
const epochs = [
|
|
203
|
+
{ year: -3000, label: '3000 BCE' },
|
|
204
|
+
{ year: 0, label: '1 BCE' },
|
|
205
|
+
{ year: 1000, label: '1000 CE' },
|
|
206
|
+
{ year: 2000, label: '2000 CE (J2000)' },
|
|
207
|
+
{ year: 2024, label: '2024 CE' },
|
|
208
|
+
{ year: 3000, label: '3000 CE' },
|
|
209
|
+
];
|
|
210
|
+
|
|
211
|
+
console.log('Epoch True Obliquity Mean Obliquity');
|
|
212
|
+
console.log('----- -------------- --------------');
|
|
213
|
+
|
|
214
|
+
for (const e of epochs) {
|
|
215
|
+
const jd = SwissEph.julianDay(e.year, 1, 1, 12);
|
|
216
|
+
const nut = swe.calc(jd, SE_ECL_NUT);
|
|
217
|
+
|
|
218
|
+
// longitude = true obliquity, latitude = mean obliquity
|
|
219
|
+
console.log(
|
|
220
|
+
`${e.label.padEnd(20)}` +
|
|
221
|
+
`${nut.longitude.toFixed(6).padStart(12)} deg` +
|
|
222
|
+
`${nut.latitude.toFixed(6).padStart(14)} deg`
|
|
223
|
+
);
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
// The obliquity is currently decreasing at about 47" per century
|
|
227
|
+
// due to the gravitational influence of the other planets.
|
|
228
|
+
// It oscillates between about 22.1 and 24.5 degrees over a ~41,000 year cycle.
|
|
229
|
+
|
|
230
|
+
swe.close();
|
|
231
|
+
```
|
|
232
|
+
|
|
233
|
+
### Practical example: finding a planet's constellation
|
|
234
|
+
|
|
235
|
+
Constellation boundaries are defined in equatorial coordinates (RA/Dec). To determine which constellation a planet is in (astronomically, not astrologically), you need equatorial coordinates:
|
|
236
|
+
|
|
237
|
+
```typescript
|
|
238
|
+
import { SwissEph } from '../index';
|
|
239
|
+
import { SE_MARS, SEFLG_EQUATORIAL } from '../../constants';
|
|
240
|
+
|
|
241
|
+
const swe = new SwissEph();
|
|
242
|
+
const jd = SwissEph.julianDay(2024, 8, 15, 0);
|
|
243
|
+
|
|
244
|
+
const mars = swe.calc(jd, SE_MARS, SEFLG_EQUATORIAL);
|
|
245
|
+
const raDeg = mars.longitude;
|
|
246
|
+
const raHours = raDeg / 15;
|
|
247
|
+
const dec = mars.latitude;
|
|
248
|
+
|
|
249
|
+
console.log(`Mars RA: ${raHours.toFixed(4)} h = ${raDeg.toFixed(4)} deg`);
|
|
250
|
+
console.log(`Mars Dec: ${dec.toFixed(4)} deg`);
|
|
251
|
+
console.log();
|
|
252
|
+
console.log('To determine the constellation, compare these equatorial');
|
|
253
|
+
console.log('coordinates against the IAU constellation boundary data.');
|
|
254
|
+
console.log('(Constellation boundaries are defined in RA/Dec, epoch B1875.)');
|
|
255
|
+
|
|
256
|
+
swe.close();
|
|
257
|
+
```
|
|
258
|
+
|
|
259
|
+
---
|
|
260
|
+
|
|
261
|
+
## Deep Explanation
|
|
262
|
+
|
|
263
|
+
### The ecliptic plane
|
|
264
|
+
|
|
265
|
+
The **ecliptic** is the plane of Earth's orbit around the Sun. Equivalently, it is the apparent path the Sun traces across the sky over the course of a year. The planets all orbit roughly in this plane (within a few degrees), which is why ecliptic coordinates are natural for solar system work.
|
|
266
|
+
|
|
267
|
+
In the tropical zodiac (used in Western astrology), ecliptic longitude is measured from the **vernal equinox** -- the point where the Sun crosses the celestial equator heading north (around March 20). This point is defined as 0 degrees Aries. Longitude increases eastward through the zodiac signs: 0-30 Aries, 30-60 Taurus, and so on.
|
|
268
|
+
|
|
269
|
+
Ecliptic latitude measures angular distance above (+) or below (-) the ecliptic plane. The Sun's latitude is always essentially zero. The Moon's maximum latitude is about 5.1 degrees. Pluto can reach about 17 degrees.
|
|
270
|
+
|
|
271
|
+
### The celestial equator
|
|
272
|
+
|
|
273
|
+
The **celestial equator** is Earth's equator projected onto the sky. It is tilted relative to the ecliptic by the obliquity angle (~23.44 degrees). The two planes intersect at two points: the vernal equinox (0h RA = 0 degrees ecliptic longitude) and the autumnal equinox (12h RA = 180 degrees ecliptic longitude).
|
|
274
|
+
|
|
275
|
+
Right Ascension is measured eastward along the celestial equator from the vernal equinox. It is traditionally measured in hours (0h to 24h) because of its direct relationship to sidereal time: an object's RA equals the sidereal time when it crosses the meridian. However, the Swiss Ephemeris returns RA in degrees (0-360), and you can convert: `raHours = raDeg / 15`.
|
|
276
|
+
|
|
277
|
+
Declination measures angular distance above (+) or below (-) the celestial equator. The north celestial pole (near Polaris) is at Dec = +90 degrees.
|
|
278
|
+
|
|
279
|
+
### The obliquity of the ecliptic
|
|
280
|
+
|
|
281
|
+
The obliquity (symbol epsilon) is the angle between the ecliptic and the celestial equator -- it is the tilt of Earth's rotation axis relative to its orbit. Currently about 23.44 degrees, it:
|
|
282
|
+
|
|
283
|
+
- Changes slowly (currently decreasing at about 47 arcseconds per century)
|
|
284
|
+
- Oscillates between about 22.1 and 24.5 degrees over a ~41,000 year cycle (the obliquity cycle, one of the Milankovitch cycles)
|
|
285
|
+
- Is affected by nutation, which causes short-term oscillations of about 9 arcseconds with a period of ~18.6 years
|
|
286
|
+
|
|
287
|
+
The **mean obliquity** ignores nutation; the **true obliquity** includes it. For coordinate transformations, you generally want the true obliquity. You can get both from `SE_ECL_NUT`:
|
|
288
|
+
|
|
289
|
+
```typescript
|
|
290
|
+
const nut = swe.calc(jd, SE_ECL_NUT);
|
|
291
|
+
const trueObliquity = nut.longitude; // includes nutation
|
|
292
|
+
const meanObliquity = nut.latitude; // without nutation
|
|
293
|
+
```
|
|
294
|
+
|
|
295
|
+
### The coordinate transformation
|
|
296
|
+
|
|
297
|
+
The conversion between ecliptic and equatorial coordinates is a rotation around the X-axis (the vernal equinox direction) by the obliquity angle. The formulas are:
|
|
298
|
+
|
|
299
|
+
**Ecliptic to equatorial** (longitude/latitude to RA/Dec):
|
|
300
|
+
|
|
301
|
+
```
|
|
302
|
+
sin(Dec) = sin(lat) * cos(eps) + cos(lat) * sin(eps) * sin(lon)
|
|
303
|
+
cos(Dec) * cos(RA) = cos(lat) * cos(lon)
|
|
304
|
+
cos(Dec) * sin(RA) = -sin(lat) * sin(eps) + cos(lat) * cos(eps) * sin(lon)
|
|
305
|
+
```
|
|
306
|
+
|
|
307
|
+
**Equatorial to ecliptic** (the inverse):
|
|
308
|
+
|
|
309
|
+
Same formulas with the sign of eps negated, which is why `coordinateTransform` uses positive eps for ecliptic-to-equatorial and negative eps for the reverse.
|
|
310
|
+
|
|
311
|
+
### Precession and the J2000 reference frame
|
|
312
|
+
|
|
313
|
+
Due to gravitational torques from the Sun and Moon on Earth's equatorial bulge, the orientation of Earth's axis slowly rotates (precesses) with a period of about 25,770 years. This means:
|
|
314
|
+
|
|
315
|
+
- The vernal equinox drifts westward along the ecliptic at about 50 arcseconds per year (this is what causes the ayanamsa drift in sidereal astrology)
|
|
316
|
+
- Star catalogs are defined for a specific **epoch** (reference date), most commonly J2000.0 (January 1, 2000 at 12:00 TT)
|
|
317
|
+
- Coordinates "of date" use the equinox at the time of observation; coordinates in J2000 use the fixed J2000 equinox
|
|
318
|
+
|
|
319
|
+
By default, the Swiss Ephemeris returns positions referred to the equinox of date (the true equinox including precession and nutation). To get positions in the J2000 frame, use `SEFLG_J2000`. To get the equinox of date but without nutation (mean equinox), use `SEFLG_NONUT`.
|
|
320
|
+
|
|
321
|
+
### The FK5 reference frame
|
|
322
|
+
|
|
323
|
+
The Swiss Ephemeris uses the FK5 (Fifth Fundamental Catalogue) reference frame for the equatorial system and transforms to the ecliptic using the IAU standard obliquity. This is consistent with the JPL ephemerides. The FK5 frame is aligned to the International Celestial Reference Frame (ICRF), which is defined by distant quasars and is essentially inertial.
|
|
324
|
+
|
|
325
|
+
### When to use which coordinate system
|
|
326
|
+
|
|
327
|
+
| System | Best for |
|
|
328
|
+
|------------|-------------------------------------------------------------|
|
|
329
|
+
| Ecliptic | Astrology, planetary aspects, zodiac positions, solar system geometry |
|
|
330
|
+
| Equatorial | Telescope pointing, star catalogs, constellation identification, meridian transits |
|
|
331
|
+
| Horizontal | Visual observation, rise/set calculations, "where do I look in the sky?" |
|
|
332
|
+
|
|
333
|
+
### The distance component
|
|
334
|
+
|
|
335
|
+
All three systems include a third coordinate: **distance**. In ecliptic and equatorial systems, this is the distance from Earth (or the Sun, if heliocentric) in AU. In horizontal coordinates, it is typically not meaningful and the Swiss Ephemeris preserves whatever distance was in the input.
|
|
336
|
+
|
|
337
|
+
The `coordinateTransform()` function passes the distance through unchanged (it only rotates the angular coordinates). The distance is needed in the input array but is not modified by the transformation.
|