Merge docs update for v0.12.0
This commit is contained in:
commit
c8e9d2d1fe
47
CLAUDE.md
47
CLAUDE.md
@ -1,9 +1,9 @@
|
|||||||
# pg_orrery — A Database Orrery for PostgreSQL
|
# pg_orrery — A Database Orrery for PostgreSQL
|
||||||
|
|
||||||
## What This Is
|
## What This Is
|
||||||
A database orrery — celestial mechanics types and functions for PostgreSQL. Native C extension using PGXS, 114 SQL functions, 9 custom types, covering satellites (SGP4/SDP4), planets (VSOP87 + optional JPL DE441), Moon (ELP2000-82B), 19 planetary moons (L1.2/TASS17/GUST86/MarsSat), stars (with proper motion and annual parallax), comets, asteroids (MPC catalog), Jupiter radio bursts, interplanetary Lambert transfers, equatorial RA/Dec coordinates with angular separation, atmospheric refraction, annual stellar aberration, and light-time correction.
|
A database orrery — celestial mechanics types and functions for PostgreSQL. Native C extension using PGXS, 132 SQL objects (124 user-visible functions + 8 GiST support), 9 custom types, covering satellites (SGP4/SDP4), planets (VSOP87 + optional JPL DE441), Moon (ELP2000-82B), 19 planetary moons (L1.2/TASS17/GUST86/MarsSat), stars (with proper motion and annual parallax), comets, asteroids (MPC catalog), Jupiter radio bursts, interplanetary Lambert transfers, equatorial RA/Dec coordinates with GiST-indexed angular separation, atmospheric refraction, annual stellar aberration, and light-time correction.
|
||||||
|
|
||||||
**Current version:** 0.10.0
|
**Current version:** 0.12.0
|
||||||
**Repository:** https://git.supported.systems/warehack.ing/pg_orrery
|
**Repository:** https://git.supported.systems/warehack.ing/pg_orrery
|
||||||
**Documentation:** https://pg-orrery.warehack.ing
|
**Documentation:** https://pg-orrery.warehack.ing
|
||||||
|
|
||||||
@ -11,7 +11,7 @@ A database orrery — celestial mechanics types and functions for PostgreSQL. Na
|
|||||||
```bash
|
```bash
|
||||||
make PG_CONFIG=/usr/bin/pg_config # Compile with PGXS
|
make PG_CONFIG=/usr/bin/pg_config # Compile with PGXS
|
||||||
sudo make install PG_CONFIG=/usr/bin/pg_config # Install extension
|
sudo make install PG_CONFIG=/usr/bin/pg_config # Install extension
|
||||||
make installcheck PG_CONFIG=/usr/bin/pg_config # Run 19 regression test suites
|
make installcheck PG_CONFIG=/usr/bin/pg_config # Run 22 regression test suites
|
||||||
```
|
```
|
||||||
|
|
||||||
Requires: PostgreSQL 17 development headers, GCC, Make.
|
Requires: PostgreSQL 17 development headers, GCC, Make.
|
||||||
@ -27,7 +27,7 @@ Image: `git.supported.systems/warehack.ing/pg_orrery:pg17`
|
|||||||
|
|
||||||
## Project Layout
|
## Project Layout
|
||||||
```
|
```
|
||||||
pg_orrery.control # Extension metadata (version 0.9.0)
|
pg_orrery.control # Extension metadata (version 0.12.0)
|
||||||
Makefile # PGXS build + Docker targets
|
Makefile # PGXS build + Docker targets
|
||||||
sql/
|
sql/
|
||||||
pg_orrery--0.1.0.sql # v0.1.0: satellite types/functions/operators
|
pg_orrery--0.1.0.sql # v0.1.0: satellite types/functions/operators
|
||||||
@ -39,6 +39,9 @@ sql/
|
|||||||
pg_orrery--0.7.0.sql # v0.7.0: GiST improvements
|
pg_orrery--0.7.0.sql # v0.7.0: GiST improvements
|
||||||
pg_orrery--0.8.0.sql # v0.8.0: orbital_elements type + MPC parser (82 functions)
|
pg_orrery--0.8.0.sql # v0.8.0: orbital_elements type + MPC parser (82 functions)
|
||||||
pg_orrery--0.9.0.sql # v0.9.0: equatorial type, refraction, proper motion, light-time (106 functions)
|
pg_orrery--0.9.0.sql # v0.9.0: equatorial type, refraction, proper motion, light-time (106 functions)
|
||||||
|
pg_orrery--0.10.0.sql # v0.10.0: angular separation, cone search, apparent functions (114 functions)
|
||||||
|
pg_orrery--0.11.0.sql # v0.11.0: orbital_elements constructors, moon equatorial (120 functions)
|
||||||
|
pg_orrery--0.12.0.sql # v0.12.0: equatorial GiST, DE moon equatorial (132 objects)
|
||||||
pg_orrery--0.1.0--0.2.0.sql # Migration: v0.1.0 → v0.2.0 (adds solar system)
|
pg_orrery--0.1.0--0.2.0.sql # Migration: v0.1.0 → v0.2.0 (adds solar system)
|
||||||
pg_orrery--0.2.0--0.3.0.sql # Migration: v0.2.0 → v0.3.0 (adds DE ephemeris)
|
pg_orrery--0.2.0--0.3.0.sql # Migration: v0.2.0 → v0.3.0 (adds DE ephemeris)
|
||||||
pg_orrery--0.3.0--0.4.0.sql # Migration: v0.3.0 → v0.4.0
|
pg_orrery--0.3.0--0.4.0.sql # Migration: v0.3.0 → v0.4.0
|
||||||
@ -47,6 +50,9 @@ sql/
|
|||||||
pg_orrery--0.6.0--0.7.0.sql # Migration: v0.6.0 → v0.7.0
|
pg_orrery--0.6.0--0.7.0.sql # Migration: v0.6.0 → v0.7.0
|
||||||
pg_orrery--0.7.0--0.8.0.sql # Migration: v0.7.0 → v0.8.0 (orbital_elements type)
|
pg_orrery--0.7.0--0.8.0.sql # Migration: v0.7.0 → v0.8.0 (orbital_elements type)
|
||||||
pg_orrery--0.8.0--0.9.0.sql # Migration: v0.8.0 → v0.9.0 (equatorial, refraction, proper motion, light-time)
|
pg_orrery--0.8.0--0.9.0.sql # Migration: v0.8.0 → v0.9.0 (equatorial, refraction, proper motion, light-time)
|
||||||
|
pg_orrery--0.9.0--0.10.0.sql # Migration: v0.9.0 → v0.10.0 (angular separation, cone search)
|
||||||
|
pg_orrery--0.10.0--0.11.0.sql # Migration: v0.10.0 → v0.11.0 (constructors, moon equatorial)
|
||||||
|
pg_orrery--0.11.0--0.12.0.sql # Migration: v0.11.0 → v0.12.0 (equatorial GiST, DE moon equatorial)
|
||||||
src/
|
src/
|
||||||
pg_orrery.c # PG_MODULE_MAGIC + _PG_init() (GUC registration)
|
pg_orrery.c # PG_MODULE_MAGIC + _PG_init() (GUC registration)
|
||||||
types.h # All struct definitions + constants + DE body ID mapping
|
types.h # All struct definitions + constants + DE body ID mapping
|
||||||
@ -58,7 +64,8 @@ src/
|
|||||||
sgp4_funcs.c # sgp4_propagate(), _safe(), _series(), tle_distance()
|
sgp4_funcs.c # sgp4_propagate(), _safe(), _series(), tle_distance()
|
||||||
coord_funcs.c # eci_to_geodetic(), eci_to_topocentric(), ground_track()
|
coord_funcs.c # eci_to_geodetic(), eci_to_topocentric(), ground_track()
|
||||||
pass_funcs.c # next_pass(), predict_passes(), predict_passes_refracted(), pass_visible()
|
pass_funcs.c # next_pass(), predict_passes(), predict_passes_refracted(), pass_visible()
|
||||||
gist_tle.c # GiST operator class (&&, <->)
|
gist_tle.c # GiST operator class for TLE (&&, <->)
|
||||||
|
gist_equatorial.c # GiST operator class for equatorial (KNN <->)
|
||||||
# --- Solar System (v0.2.0) ---
|
# --- Solar System (v0.2.0) ---
|
||||||
vsop87.c / vsop87.h # VSOP87 planetary ephemeris (Bretagnon 1988)
|
vsop87.c / vsop87.h # VSOP87 planetary ephemeris (Bretagnon 1988)
|
||||||
elp82b.c / elp82b.h # ELP2000-82B lunar ephemeris (Chapront 1988)
|
elp82b.c / elp82b.h # ELP2000-82B lunar ephemeris (Chapront 1988)
|
||||||
@ -83,7 +90,7 @@ src/
|
|||||||
# --- JPL DE Ephemeris (v0.3.0) ---
|
# --- JPL DE Ephemeris (v0.3.0) ---
|
||||||
de_reader.h / de_reader.c # Clean-room JPL DE binary reader (Chebyshev/Clenshaw)
|
de_reader.h / de_reader.c # Clean-room JPL DE binary reader (Chebyshev/Clenshaw)
|
||||||
eph_provider.h / eph_provider.c # Provider dispatch, GUC, lazy init, frame rotation
|
eph_provider.h / eph_provider.c # Provider dispatch, GUC, lazy init, frame rotation
|
||||||
de_funcs.c # All _de() SQL function implementations
|
de_funcs.c # All _de() SQL function implementations (incl. moon equatorial DE)
|
||||||
sgp4/ # Vendored SGP4/SDP4 (Bill Gray's sat_code, MIT license)
|
sgp4/ # Vendored SGP4/SDP4 (Bill Gray's sat_code, MIT license)
|
||||||
sgp4.c # Near-earth propagator (period < 225 min)
|
sgp4.c # Near-earth propagator (period < 225 min)
|
||||||
sdp4.c # Deep-space propagator (period >= 225 min)
|
sdp4.c # Deep-space propagator (period >= 225 min)
|
||||||
@ -96,7 +103,7 @@ src/
|
|||||||
PROVENANCE.md # Vendoring decision, modifications, verification
|
PROVENANCE.md # Vendoring decision, modifications, verification
|
||||||
LICENSE # MIT license (Bill Gray / Project Pluto)
|
LICENSE # MIT license (Bill Gray / Project Pluto)
|
||||||
test/
|
test/
|
||||||
sql/ # 16 regression test suites
|
sql/ # 22 regression test suites
|
||||||
expected/ # Expected output
|
expected/ # Expected output
|
||||||
data/vallado_518.json # 518 Vallado test vectors (AIAA 2006-6753-Rev1)
|
data/vallado_518.json # 518 Vallado test vectors (AIAA 2006-6753-Rev1)
|
||||||
docs/
|
docs/
|
||||||
@ -123,22 +130,23 @@ All types are fixed-size, `STORAGE = plain`, `ALIGNMENT = double`. No TOAST over
|
|||||||
| `orbital_elements` | 72 | Classical Keplerian elements for comets/asteroids (epoch, q, e, inc, omega, Omega, tp, H, G) |
|
| `orbital_elements` | 72 | Classical Keplerian elements for comets/asteroids (epoch, q, e, inc, omega, Omega, tp, H, G) |
|
||||||
| `equatorial` | 24 | Apparent RA (hours), Dec (degrees), distance (km) — of date |
|
| `equatorial` | 24 | Apparent RA (hours), Dec (degrees), distance (km) — of date |
|
||||||
|
|
||||||
## Function Domains (114 total)
|
## Function Domains (132 SQL objects)
|
||||||
|
|
||||||
| Domain | Theory | Key Functions | Count |
|
| Domain | Theory | Key Functions | Count |
|
||||||
|--------|--------|---------------|-------|
|
|--------|--------|---------------|-------|
|
||||||
| Satellite | SGP4/SDP4 (Brouwer 1959) | `observe()`, `predict_passes()`, `eci_to_equatorial()` | 25 |
|
| Satellite | SGP4/SDP4 (Brouwer 1959) | `observe()`, `predict_passes()`, `eci_to_equatorial()` | 25 |
|
||||||
| Planets | VSOP87 (Bretagnon 1988) | `planet_observe()`, `planet_equatorial()`, `planet_observe_apparent()` | 7 |
|
| Planets | VSOP87 (Bretagnon 1988) | `planet_observe()`, `planet_equatorial()`, `planet_observe_apparent()` | 7 |
|
||||||
| Sun/Moon | VSOP87 + ELP2000-82B | `sun_observe()`, `moon_observe()`, `sun/moon_equatorial()` | 6 |
|
| Sun/Moon | VSOP87 + ELP2000-82B | `sun_observe()`, `moon_observe()`, `sun/moon_equatorial()` | 6 |
|
||||||
| Planetary moons | L1.2, TASS17, GUST86, MarsSat | `galilean_observe()`, `saturn_moon_observe()` | 4 |
|
| Planetary moons | L1.2, TASS17, GUST86, MarsSat | `galilean_observe()`, `saturn_moon_observe()`, `*_equatorial()` | 12 |
|
||||||
| Stars | J2000 + IAU 1976 precession | `star_observe()`, `star_equatorial()`, `star_observe_pm()` | 5 |
|
| Stars | J2000 + IAU 1976 precession | `star_observe()`, `star_equatorial()`, `star_observe_pm()` | 5 |
|
||||||
| Comets/asteroids | Two-body Keplerian + MPC | `small_body_observe()`, `small_body_equatorial()`, `oe_from_mpc()` | 19 |
|
| Comets/asteroids | Two-body Keplerian + MPC | `small_body_observe()`, `small_body_equatorial()`, `oe_from_mpc()` | 19 |
|
||||||
| Refraction | Bennett (1982) | `atmospheric_refraction()`, `predict_passes_refracted()` | 4 |
|
| Refraction | Bennett (1982) | `atmospheric_refraction()`, `predict_passes_refracted()` | 4 |
|
||||||
| Equatorial spatial | Vincenty formula | `eq_angular_distance()`, `eq_within_cone()`, `<->` | 2 |
|
| Equatorial spatial | Vincenty formula | `eq_angular_distance()`, `eq_within_cone()`, `<->` | 2 |
|
||||||
| Jupiter radio | Carr et al. (1983) | `jupiter_burst_probability()` | 3 |
|
| Jupiter radio | Carr et al. (1983) | `jupiter_burst_probability()` | 3 |
|
||||||
| Transfers | Lambert (Izzo 2015) | `lambert_transfer()`, `lambert_c3()` | 2 |
|
| Transfers | Lambert (Izzo 2015) | `lambert_transfer()`, `lambert_c3()` | 2 |
|
||||||
| DE ephemeris | JPL DE440/441 (optional) | `planet_observe_de()`, `planet_equatorial_de()`, `*_apparent_de()` | 19 |
|
| DE ephemeris | JPL DE440/441 (optional) | `planet_observe_de()`, `*_equatorial_de()`, `*_apparent_de()` | 23 |
|
||||||
| GiST index | Altitude-band approximation | `&&` (overlap), `<->` (distance) | 8 |
|
| GiST index (TLE) | Altitude-band approximation | `&&` (overlap), `<->` (distance) | 8 |
|
||||||
|
| GiST index (equatorial) | Spherical bounding box | `<->` (KNN ordering) | 8 |
|
||||||
| Diagnostics | -- | `pg_orrery_ephemeris_info()` | 1 |
|
| Diagnostics | -- | `pg_orrery_ephemeris_info()` | 1 |
|
||||||
|
|
||||||
All functions are `PARALLEL SAFE`. VSOP87/ELP82B functions are `IMMUTABLE` (compiled-in coefficients). DE functions are `STABLE` (external file dependency).
|
All functions are `PARALLEL SAFE`. VSOP87/ELP82B functions are `IMMUTABLE` (compiled-in coefficients). DE functions are `STABLE` (external file dependency).
|
||||||
@ -241,6 +249,10 @@ Every `_de()` function mirrors an existing VSOP87 function:
|
|||||||
| `mars_moon_observe_de()` | `mars_moon_observe()` | STABLE |
|
| `mars_moon_observe_de()` | `mars_moon_observe()` | STABLE |
|
||||||
| `planet_equatorial_de()` | `planet_equatorial()` | STABLE |
|
| `planet_equatorial_de()` | `planet_equatorial()` | STABLE |
|
||||||
| `moon_equatorial_de()` | `moon_equatorial()` | STABLE |
|
| `moon_equatorial_de()` | `moon_equatorial()` | STABLE |
|
||||||
|
| `galilean_equatorial_de()` | `galilean_equatorial()` | STABLE |
|
||||||
|
| `saturn_moon_equatorial_de()` | `saturn_moon_equatorial()` | STABLE |
|
||||||
|
| `uranus_moon_equatorial_de()` | `uranus_moon_equatorial()` | STABLE |
|
||||||
|
| `mars_moon_equatorial_de()` | `mars_moon_equatorial()` | STABLE |
|
||||||
| `planet_observe_apparent_de()` | `planet_observe_apparent()` | STABLE |
|
| `planet_observe_apparent_de()` | `planet_observe_apparent()` | STABLE |
|
||||||
| `sun_observe_apparent_de()` | `sun_observe_apparent()` | STABLE |
|
| `sun_observe_apparent_de()` | `sun_observe_apparent()` | STABLE |
|
||||||
| `moon_observe_apparent_de()` | `moon_observe_apparent()` | STABLE |
|
| `moon_observe_apparent_de()` | `moon_observe_apparent()` | STABLE |
|
||||||
@ -268,7 +280,7 @@ All numerical logic is byte-identical to upstream. Verified against 518 Vallado
|
|||||||
|
|
||||||
## Testing
|
## Testing
|
||||||
|
|
||||||
19 regression test suites via `make installcheck`:
|
22 regression test suites via `make installcheck`:
|
||||||
|
|
||||||
| Suite | What it tests |
|
| Suite | What it tests |
|
||||||
|-------|--------------|
|
|-------|--------------|
|
||||||
@ -276,7 +288,7 @@ All numerical logic is byte-identical to upstream. Verified against 518 Vallado
|
|||||||
| sgp4_propagate | SGP4/SDP4, propagation series, tle_distance |
|
| sgp4_propagate | SGP4/SDP4, propagation series, tle_distance |
|
||||||
| coord_transforms | TEME-to-geodetic, TEME-to-topocentric, ground_track |
|
| coord_transforms | TEME-to-geodetic, TEME-to-topocentric, ground_track |
|
||||||
| pass_prediction | predict_passes, next_pass, pass_visible, min elevation filter |
|
| pass_prediction | predict_passes, next_pass, pass_visible, min elevation filter |
|
||||||
| gist_index | `&&` overlap, `<->` distance, GiST index scan, KNN ordering |
|
| gist_index | `&&` overlap, `<->` distance, GiST index scan, KNN ordering (TLE) |
|
||||||
| convenience | observe(), observe_safe(), tle_from_lines(), observer_from_geodetic() |
|
| convenience | observe(), observe_safe(), tle_from_lines(), observer_from_geodetic() |
|
||||||
| star_observe | Star observation, IAU 1976 precession, heliocentric type I/O |
|
| star_observe | Star observation, IAU 1976 precession, heliocentric type I/O |
|
||||||
| kepler_comet | Keplerian propagation (elliptic/parabolic/hyperbolic), comet_observe |
|
| kepler_comet | Keplerian propagation (elliptic/parabolic/hyperbolic), comet_observe |
|
||||||
@ -291,10 +303,13 @@ All numerical logic is byte-identical to upstream. Verified against 518 Vallado
|
|||||||
| refraction | Bennett refraction, P/T correction, apparent elevation, refracted pass prediction |
|
| refraction | Bennett refraction, P/T correction, apparent elevation, refracted pass prediction |
|
||||||
| aberration | Annual aberration magnitude, DE apparent fallback, angular distance, cone search, stellar parallax |
|
| aberration | Annual aberration magnitude, DE apparent fallback, angular distance, cone search, stellar parallax |
|
||||||
| vallado_518 | 518 Vallado test vectors (AIAA 2006-6753-Rev1), per-satellite breakdown |
|
| vallado_518 | 518 Vallado test vectors (AIAA 2006-6753-Rev1), per-satellite breakdown |
|
||||||
|
| v011_features | make_orbital_elements constructors, moon equatorial functions |
|
||||||
|
| gist_equatorial | Equatorial GiST KNN ordering, RA wrapping, cone search, EXPLAIN index scan |
|
||||||
|
| v012_features | DE moon equatorial fallback to VSOP87, invalid body_id rejection |
|
||||||
|
|
||||||
### PG Version Matrix
|
### PG Version Matrix
|
||||||
|
|
||||||
Test all 19 regression suites + DE reader unit test across PostgreSQL 14-18 using Docker:
|
Test all 22 regression suites + DE reader unit test across PostgreSQL 14-18 using Docker:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
make test-matrix # Full matrix (PG 14-18)
|
make test-matrix # Full matrix (PG 14-18)
|
||||||
@ -318,9 +333,9 @@ Logs saved to `test/matrix-logs/pg${ver}.log`. The script reuses the Dockerfile
|
|||||||
|
|
||||||
**Live:** https://pg-orrery.warehack.ing
|
**Live:** https://pg-orrery.warehack.ing
|
||||||
|
|
||||||
Starlight docs at `docs/` — 44 MDX pages covering all domains.
|
Starlight docs at `docs/` — 44+ MDX pages covering all domains.
|
||||||
|
|
||||||
Sections: Getting Started, Guides (9 domain walkthroughs incl. DE ephemeris), Workflow Translation (Skyfield/Horizons/GMAT/Radio Jupiter Pro comparisons), Reference (all 106 functions incl. DE variants, equatorial, refraction), Architecture (Hamilton's principles, constant custody, observation pipeline), Performance (benchmarks).
|
Sections: Getting Started, Guides (9 domain walkthroughs incl. DE ephemeris), Workflow Translation (Skyfield/Horizons/GMAT/Radio Jupiter Pro comparisons), Reference (all 132 SQL objects incl. DE variants, equatorial GiST, refraction), Architecture (Hamilton's principles, constant custody, observation pipeline), Performance (benchmarks).
|
||||||
|
|
||||||
### Local Development
|
### Local Development
|
||||||
```bash
|
```bash
|
||||||
|
|||||||
@ -368,6 +368,122 @@ FROM moon_equatorial_de(now()) AS e;
|
|||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
## galilean_equatorial_de
|
||||||
|
|
||||||
|
Computes the geocentric equatorial coordinates (RA/Dec) of a Galilean moon using JPL DE ephemeris for Jupiter's position. Falls back to VSOP87 for both Jupiter and Earth when DE is unavailable. Moon offsets always come from Lieske L1.2 theory.
|
||||||
|
|
||||||
|
### Signature
|
||||||
|
|
||||||
|
```sql
|
||||||
|
galilean_equatorial_de(moon_id int4, t timestamptz) → equatorial
|
||||||
|
```
|
||||||
|
|
||||||
|
### Parameters
|
||||||
|
|
||||||
|
| Parameter | Type | Description |
|
||||||
|
|-----------|------|-------------|
|
||||||
|
| `moon_id` | `int4` | 0=Io, 1=Europa, 2=Ganymede, 3=Callisto |
|
||||||
|
| `t` | `timestamptz` | Evaluation time |
|
||||||
|
|
||||||
|
### Returns
|
||||||
|
|
||||||
|
An `equatorial` with RA (hours), Dec (degrees), and distance (km) from Earth's center.
|
||||||
|
|
||||||
|
### Example
|
||||||
|
|
||||||
|
```sql
|
||||||
|
-- All 4 Galilean moons via DE
|
||||||
|
SELECT moon_id,
|
||||||
|
round(eq_ra(galilean_equatorial_de(moon_id, now()))::numeric, 4) AS ra,
|
||||||
|
round(eq_dec(galilean_equatorial_de(moon_id, now()))::numeric, 4) AS dec
|
||||||
|
FROM generate_series(0, 3) AS moon_id;
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## saturn_moon_equatorial_de
|
||||||
|
|
||||||
|
Computes the geocentric equatorial coordinates (RA/Dec) of a Saturn moon using JPL DE ephemeris for Saturn's position. Falls back to VSOP87 when DE is unavailable. Moon offsets come from TASS 1.7 theory.
|
||||||
|
|
||||||
|
### Signature
|
||||||
|
|
||||||
|
```sql
|
||||||
|
saturn_moon_equatorial_de(moon_id int4, t timestamptz) → equatorial
|
||||||
|
```
|
||||||
|
|
||||||
|
### Parameters
|
||||||
|
|
||||||
|
| Parameter | Type | Description |
|
||||||
|
|-----------|------|-------------|
|
||||||
|
| `moon_id` | `int4` | 0=Mimas, 1=Enceladus, 2=Tethys, 3=Dione, 4=Rhea, 5=Titan, 6=Iapetus, 7=Hyperion |
|
||||||
|
| `t` | `timestamptz` | Evaluation time |
|
||||||
|
|
||||||
|
### Example
|
||||||
|
|
||||||
|
```sql
|
||||||
|
-- Titan's position via DE
|
||||||
|
SELECT round(eq_ra(saturn_moon_equatorial_de(5, now()))::numeric, 4) AS ra,
|
||||||
|
round(eq_dec(saturn_moon_equatorial_de(5, now()))::numeric, 4) AS dec;
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## uranus_moon_equatorial_de
|
||||||
|
|
||||||
|
Computes the geocentric equatorial coordinates (RA/Dec) of a Uranus moon using JPL DE ephemeris for Uranus's position. Falls back to VSOP87 when DE is unavailable. Moon offsets come from GUST86 theory.
|
||||||
|
|
||||||
|
### Signature
|
||||||
|
|
||||||
|
```sql
|
||||||
|
uranus_moon_equatorial_de(moon_id int4, t timestamptz) → equatorial
|
||||||
|
```
|
||||||
|
|
||||||
|
### Parameters
|
||||||
|
|
||||||
|
| Parameter | Type | Description |
|
||||||
|
|-----------|------|-------------|
|
||||||
|
| `moon_id` | `int4` | 0=Miranda, 1=Ariel, 2=Umbriel, 3=Titania, 4=Oberon |
|
||||||
|
| `t` | `timestamptz` | Evaluation time |
|
||||||
|
|
||||||
|
### Example
|
||||||
|
|
||||||
|
```sql
|
||||||
|
-- Titania's position via DE
|
||||||
|
SELECT round(eq_ra(uranus_moon_equatorial_de(3, now()))::numeric, 4) AS ra,
|
||||||
|
round(eq_dec(uranus_moon_equatorial_de(3, now()))::numeric, 4) AS dec;
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## mars_moon_equatorial_de
|
||||||
|
|
||||||
|
Computes the geocentric equatorial coordinates (RA/Dec) of a Mars moon using JPL DE ephemeris for Mars's position. Falls back to VSOP87 when DE is unavailable. Moon offsets come from MarsSat analytical theory.
|
||||||
|
|
||||||
|
### Signature
|
||||||
|
|
||||||
|
```sql
|
||||||
|
mars_moon_equatorial_de(moon_id int4, t timestamptz) → equatorial
|
||||||
|
```
|
||||||
|
|
||||||
|
### Parameters
|
||||||
|
|
||||||
|
| Parameter | Type | Description |
|
||||||
|
|-----------|------|-------------|
|
||||||
|
| `moon_id` | `int4` | 0=Phobos, 1=Deimos |
|
||||||
|
| `t` | `timestamptz` | Evaluation time |
|
||||||
|
|
||||||
|
### Example
|
||||||
|
|
||||||
|
```sql
|
||||||
|
-- Both Mars moons via DE
|
||||||
|
SELECT moon_id,
|
||||||
|
round(eq_ra(mars_moon_equatorial_de(moon_id, now()))::numeric, 4) AS ra,
|
||||||
|
round(eq_dec(mars_moon_equatorial_de(moon_id, now()))::numeric, 4) AS dec
|
||||||
|
FROM generate_series(0, 1) AS moon_id;
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
## pg_orrery_ephemeris_info
|
## pg_orrery_ephemeris_info
|
||||||
|
|
||||||
Returns diagnostic information about the current ephemeris provider.
|
Returns diagnostic information about the current ephemeris provider.
|
||||||
|
|||||||
@ -6,7 +6,7 @@ sidebar:
|
|||||||
|
|
||||||
import { Aside, Tabs, TabItem } from "@astrojs/starlight/components";
|
import { Aside, Tabs, TabItem } from "@astrojs/starlight/components";
|
||||||
|
|
||||||
pg_orrery defines four operators on the `tle` type and two operator classes (GiST and SP-GiST) that enable indexed satellite queries over large catalogs. The GiST index accelerates conjunction screening (orbit-to-orbit overlap). The SP-GiST index accelerates pass prediction (observer-to-orbit visibility).
|
pg_orrery defines operators on the `tle` and `equatorial` types with three operator classes (two GiST + one SP-GiST) that enable indexed queries over large catalogs. The TLE GiST index accelerates conjunction screening (orbit-to-orbit overlap). The SP-GiST index accelerates pass prediction (observer-to-orbit visibility). The equatorial GiST index accelerates nearest-neighbor sky queries (angular distance KNN).
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
@ -205,6 +205,81 @@ REINDEX INDEX idx_tle_gist;
|
|||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
## GiST Operator Class: eq_gist_ops
|
||||||
|
|
||||||
|
The `eq_gist_ops` operator class enables GiST indexing on `equatorial` columns. With this index, the `<->` operator (angular distance in degrees via the Vincenty formula) supports index-ordered KNN queries — PostgreSQL traverses the tree by increasing angular distance without computing all distances upfront.
|
||||||
|
|
||||||
|
<Aside type="note">
|
||||||
|
`eq_gist_ops` is the **DEFAULT** operator class for the `equatorial` type using GiST. No explicit operator class is needed in `CREATE INDEX`.
|
||||||
|
</Aside>
|
||||||
|
|
||||||
|
### Creating the Index
|
||||||
|
|
||||||
|
```sql
|
||||||
|
CREATE INDEX idx_sky_eq ON sky_cache USING gist (eq);
|
||||||
|
```
|
||||||
|
|
||||||
|
### What Gets Indexed
|
||||||
|
|
||||||
|
The GiST index stores a 24-byte float-precision spherical bounding box for each entry:
|
||||||
|
- **RA range:** `[ra_low, ra_high]` in radians. When `ra_low > ra_high`, the box wraps across 0h (covers `[ra_low, 2pi) union [0, ra_high]`)
|
||||||
|
- **Dec range:** `[dec_low, dec_high]` in radians
|
||||||
|
|
||||||
|
Float precision (~0.12 arcsec bounding error at RA = 2pi) is more than sufficient for index pruning. Actual angular distance is computed in double precision via the Vincenty formula during recheck.
|
||||||
|
|
||||||
|
### Index-Accelerated Queries
|
||||||
|
|
||||||
|
<Tabs>
|
||||||
|
<TabItem label="KNN nearest-neighbor">
|
||||||
|
```sql
|
||||||
|
-- Find the 10 nearest sky objects to Jupiter
|
||||||
|
SELECT name,
|
||||||
|
round((eq <-> planet_equatorial_apparent(5, NOW()))::numeric, 4) AS dist_deg
|
||||||
|
FROM sky_cache
|
||||||
|
ORDER BY eq <-> planet_equatorial_apparent(5, NOW())
|
||||||
|
LIMIT 10;
|
||||||
|
```
|
||||||
|
</TabItem>
|
||||||
|
<TabItem label="Cone search">
|
||||||
|
```sql
|
||||||
|
-- Everything within 15 degrees of Vega, sorted by distance
|
||||||
|
SELECT name,
|
||||||
|
round((eq <-> star_equatorial(18.616, 38.784, NOW()))::numeric, 2) AS dist_deg
|
||||||
|
FROM sky_cache
|
||||||
|
WHERE eq_within_cone(eq, star_equatorial(18.616, 38.784, NOW()), 15.0)
|
||||||
|
ORDER BY eq <-> star_equatorial(18.616, 38.784, NOW());
|
||||||
|
```
|
||||||
|
</TabItem>
|
||||||
|
<TabItem label="EXPLAIN verification">
|
||||||
|
```sql
|
||||||
|
-- Confirm the planner uses the GiST index
|
||||||
|
SET enable_seqscan = off;
|
||||||
|
EXPLAIN (COSTS OFF)
|
||||||
|
SELECT name FROM sky_cache
|
||||||
|
ORDER BY eq <-> '(12.00000000,0.00000000,0.000)'::equatorial
|
||||||
|
LIMIT 3;
|
||||||
|
-- Should show: Index Scan using idx_sky_eq on sky_cache
|
||||||
|
RESET enable_seqscan;
|
||||||
|
```
|
||||||
|
</TabItem>
|
||||||
|
</Tabs>
|
||||||
|
|
||||||
|
### RA Wrapping
|
||||||
|
|
||||||
|
Objects near 0h (e.g., in Pisces/Aquarius) and objects near 24h are correctly identified as neighbors. The bounding box merge and distance functions handle the RA discontinuity at 0h/24h explicitly. An object at RA = 23.9h and another at RA = 0.1h are approximately 3 degrees apart (at moderate declination), and the KNN traversal finds them as neighbors.
|
||||||
|
|
||||||
|
### Polar Regions
|
||||||
|
|
||||||
|
Near the celestial poles (Dec approaching +/-90 degrees), RA becomes degenerate — a small patch of sky spans a wide RA range. Bounding boxes for polar objects may cover the full RA circle. This does not affect **correctness** (the Vincenty formula handles pole convergence naturally) but can degrade **index selectivity** for dense polar catalogs. For typical sky catalogs (<10,000 objects), the effect is negligible.
|
||||||
|
|
||||||
|
### Design Notes
|
||||||
|
|
||||||
|
- **KNN only** (strategy 15, `<->` ordering). No `&&` overlap operator — meaningless for point types.
|
||||||
|
- **Distance unit:** degrees, matching `eq_angular_distance()`.
|
||||||
|
- **Lower-bound contract hardened:** box boundaries widened by float epsilon before distance computation to guarantee KNN correctness under float-to-double promotion.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
### &? (Visibility Cone)
|
### &? (Visibility Cone)
|
||||||
|
|
||||||
Tests whether a satellite could possibly be visible from a ground observer during a time window. This is a geometric superset filter -- it may include satellites that do not produce an actual pass (false positives), but will never exclude one that does (no false negatives).
|
Tests whether a satellite could possibly be visible from a ground observer during a time window. This is a geometric superset filter -- it may include satellites that do not produce an actual pass (false positives), but will never exclude one that does (no false negatives).
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user