162 → 174 SQL objects, 27 → 28 test suites, 3 new C source files. Features: - solar_elongation(body_id, ts): Sun-Earth-Planet angle [0,180] degrees - planet_phase(body_id, ts): illuminated disk fraction [0,1] - satellite_is_eclipsed/next_eclipse_entry/exit/eclipse_fraction: cylindrical shadow model (Vallado §5.3) for Earth shadow prediction - observing_night_quality(observer, ts): composite PL/pgSQL scoring based on astronomical darkness duration and Moon interference - moon_libration_longitude/latitude/position_angle/libration/subsolar_longitude: optical libration from Meeus (1998) Ch. 53 Refactored magnitude_funcs.c to extract shared compute_planet_geometry() used by magnitude, elongation, and phase — single VSOP87 evaluation per call. All 28 regression suites pass. Zero compiler warnings.
286 lines
11 KiB
Plaintext
286 lines
11 KiB
Plaintext
-- v017_features.sql -- Tests for v0.17.0: solar elongation, planet phase,
|
|
-- satellite eclipse, observing night quality, lunar libration
|
|
--
|
|
-- Verifies all 12 new functions added in v0.17.0.
|
|
CREATE EXTENSION IF NOT EXISTS pg_orrery;
|
|
NOTICE: extension "pg_orrery" already exists, skipping
|
|
-- ============================================================
|
|
-- Solar elongation: Mercury always < 28 deg
|
|
-- ============================================================
|
|
SELECT solar_elongation(1, '2024-01-15 00:00:00+00'::timestamptz) < 28.0
|
|
AS mercury_max_elongation;
|
|
mercury_max_elongation
|
|
------------------------
|
|
t
|
|
(1 row)
|
|
|
|
-- ============================================================
|
|
-- Solar elongation: Venus always < 47 deg
|
|
-- ============================================================
|
|
SELECT solar_elongation(2, '2024-01-15 00:00:00+00'::timestamptz) < 47.5
|
|
AS venus_max_elongation;
|
|
venus_max_elongation
|
|
----------------------
|
|
t
|
|
(1 row)
|
|
|
|
-- ============================================================
|
|
-- Solar elongation: Mars can exceed 90 deg (superior planet)
|
|
-- Use a date near opposition (2024-01-12 Mars at elongation ~180)
|
|
-- At least verify it can be large for outer planets
|
|
-- ============================================================
|
|
SELECT solar_elongation(4, '2024-12-08 00:00:00+00'::timestamptz) > 50.0
|
|
AS mars_large_elongation;
|
|
mars_large_elongation
|
|
-----------------------
|
|
t
|
|
(1 row)
|
|
|
|
-- ============================================================
|
|
-- Solar elongation: always [0, 180]
|
|
-- ============================================================
|
|
SELECT bool_and(
|
|
solar_elongation(body_id, '2024-06-15 00:00:00+00'::timestamptz) >= 0.0
|
|
AND solar_elongation(body_id, '2024-06-15 00:00:00+00'::timestamptz) <= 180.0
|
|
) AS elongation_in_range
|
|
FROM (VALUES (1),(2),(4),(5),(6),(7),(8)) AS t(body_id);
|
|
elongation_in_range
|
|
---------------------
|
|
t
|
|
(1 row)
|
|
|
|
-- ============================================================
|
|
-- Solar elongation: error on body_id 0, 3, 9
|
|
-- ============================================================
|
|
DO $$ BEGIN PERFORM solar_elongation(0, '2024-01-15 00:00:00+00'::timestamptz); EXCEPTION WHEN OTHERS THEN RAISE NOTICE 'elong body_id=0: %', SQLERRM; END $$;
|
|
NOTICE: elong body_id=0: solar_elongation: body_id 0 must be 1-8 (Mercury-Neptune)
|
|
DO $$ BEGIN PERFORM solar_elongation(3, '2024-01-15 00:00:00+00'::timestamptz); EXCEPTION WHEN OTHERS THEN RAISE NOTICE 'elong body_id=3: %', SQLERRM; END $$;
|
|
NOTICE: elong body_id=3: solar_elongation: cannot compute for Earth from Earth
|
|
DO $$ BEGIN PERFORM solar_elongation(9, '2024-01-15 00:00:00+00'::timestamptz); EXCEPTION WHEN OTHERS THEN RAISE NOTICE 'elong body_id=9: %', SQLERRM; END $$;
|
|
NOTICE: elong body_id=9: solar_elongation: body_id 9 must be 1-8 (Mercury-Neptune)
|
|
-- ============================================================
|
|
-- Planet phase: Jupiter always near 1.0 (outer planet)
|
|
-- ============================================================
|
|
SELECT planet_phase(5, '2024-01-15 00:00:00+00'::timestamptz) > 0.95
|
|
AS jupiter_nearly_full;
|
|
jupiter_nearly_full
|
|
---------------------
|
|
t
|
|
(1 row)
|
|
|
|
-- ============================================================
|
|
-- Planet phase: Neptune always near 1.0
|
|
-- ============================================================
|
|
SELECT planet_phase(8, '2024-06-15 00:00:00+00'::timestamptz) > 0.99
|
|
AS neptune_nearly_full;
|
|
neptune_nearly_full
|
|
---------------------
|
|
t
|
|
(1 row)
|
|
|
|
-- ============================================================
|
|
-- Planet phase: Venus varies significantly (inner planet)
|
|
-- Check it's in valid range
|
|
-- ============================================================
|
|
SELECT planet_phase(2, '2024-06-01 12:00:00+00'::timestamptz) BETWEEN 0.0 AND 1.0
|
|
AS venus_phase_valid;
|
|
venus_phase_valid
|
|
-------------------
|
|
t
|
|
(1 row)
|
|
|
|
-- ============================================================
|
|
-- Planet phase: always [0, 1] for all planets
|
|
-- ============================================================
|
|
SELECT bool_and(
|
|
planet_phase(body_id, '2024-01-15 00:00:00+00'::timestamptz) >= 0.0
|
|
AND planet_phase(body_id, '2024-01-15 00:00:00+00'::timestamptz) <= 1.0
|
|
) AS phase_in_range
|
|
FROM (VALUES (1),(2),(4),(5),(6),(7),(8)) AS t(body_id);
|
|
phase_in_range
|
|
----------------
|
|
t
|
|
(1 row)
|
|
|
|
-- ============================================================
|
|
-- Planet phase: error cases match elongation
|
|
-- ============================================================
|
|
DO $$ BEGIN PERFORM planet_phase(3, '2024-01-15 00:00:00+00'::timestamptz); EXCEPTION WHEN OTHERS THEN RAISE NOTICE 'phase body_id=3: %', SQLERRM; END $$;
|
|
NOTICE: phase body_id=3: planet_phase: cannot compute for Earth from Earth
|
|
-- ============================================================
|
|
-- Satellite eclipse: ISS point-in-time test
|
|
-- (At night the ISS can be eclipsed; just verify function returns bool)
|
|
-- ============================================================
|
|
SELECT satellite_is_eclipsed(
|
|
E'1 25544U 98067A 24001.50000000 .00016717 00000-0 10270-3 0 9025\n2 25544 51.6400 208.9163 0006703 30.1694 61.7520 15.50100486 00001'::tle,
|
|
'2024-01-01 12:00:00+00'::timestamptz
|
|
) IS NOT NULL
|
|
AS eclipse_returns_bool;
|
|
eclipse_returns_bool
|
|
----------------------
|
|
t
|
|
(1 row)
|
|
|
|
-- ============================================================
|
|
-- Satellite eclipse: next entry/exit return timestamps or NULL
|
|
-- ============================================================
|
|
SELECT satellite_next_eclipse_entry(
|
|
E'1 25544U 98067A 24001.50000000 .00016717 00000-0 10270-3 0 9025\n2 25544 51.6400 208.9163 0006703 30.1694 61.7520 15.50100486 00001'::tle,
|
|
'2024-01-01 12:00:00+00'::timestamptz
|
|
) > '2024-01-01 12:00:00+00'::timestamptz
|
|
AS entry_in_future;
|
|
entry_in_future
|
|
-----------------
|
|
t
|
|
(1 row)
|
|
|
|
SELECT satellite_next_eclipse_exit(
|
|
E'1 25544U 98067A 24001.50000000 .00016717 00000-0 10270-3 0 9025\n2 25544 51.6400 208.9163 0006703 30.1694 61.7520 15.50100486 00001'::tle,
|
|
'2024-01-01 12:00:00+00'::timestamptz
|
|
) > '2024-01-01 12:00:00+00'::timestamptz
|
|
AS exit_in_future;
|
|
exit_in_future
|
|
----------------
|
|
t
|
|
(1 row)
|
|
|
|
-- ============================================================
|
|
-- Satellite eclipse: fraction in [0, 1] for a 2-hour window
|
|
-- ============================================================
|
|
SELECT satellite_eclipse_fraction(
|
|
E'1 25544U 98067A 24001.50000000 .00016717 00000-0 10270-3 0 9025\n2 25544 51.6400 208.9163 0006703 30.1694 61.7520 15.50100486 00001'::tle,
|
|
'2024-01-01 12:00:00+00'::timestamptz,
|
|
'2024-01-01 14:00:00+00'::timestamptz
|
|
) BETWEEN 0.0 AND 1.0
|
|
AS eclipse_fraction_valid;
|
|
eclipse_fraction_valid
|
|
------------------------
|
|
t
|
|
(1 row)
|
|
|
|
-- ============================================================
|
|
-- Observing night quality: polar summer at 65N = 'poor'
|
|
-- (no astronomical darkness in June)
|
|
-- ============================================================
|
|
SELECT observing_night_quality('(65.0,25.0,0)'::observer, '2024-06-21 12:00:00+00'::timestamptz) = 'poor'
|
|
AS polar_summer_poor;
|
|
polar_summer_poor
|
|
-------------------
|
|
t
|
|
(1 row)
|
|
|
|
-- ============================================================
|
|
-- Observing night quality: winter mid-latitude returns valid rating
|
|
-- ============================================================
|
|
SELECT observing_night_quality('(43.7,-116.4,800)'::observer, '2024-12-21 12:00:00+00'::timestamptz)
|
|
IN ('excellent', 'good', 'fair', 'poor')
|
|
AS winter_valid_rating;
|
|
winter_valid_rating
|
|
---------------------
|
|
t
|
|
(1 row)
|
|
|
|
-- ============================================================
|
|
-- Lunar libration: longitude in [-8, 8] range
|
|
-- ============================================================
|
|
SELECT moon_libration_longitude('2024-01-15 00:00:00+00'::timestamptz) BETWEEN -8.5 AND 8.5
|
|
AS libration_lon_in_range;
|
|
libration_lon_in_range
|
|
------------------------
|
|
t
|
|
(1 row)
|
|
|
|
SELECT moon_libration_longitude('2024-06-15 00:00:00+00'::timestamptz) BETWEEN -8.5 AND 8.5
|
|
AS libration_lon_in_range_2;
|
|
libration_lon_in_range_2
|
|
--------------------------
|
|
t
|
|
(1 row)
|
|
|
|
-- ============================================================
|
|
-- Lunar libration: latitude in [-7, 7] range
|
|
-- ============================================================
|
|
SELECT moon_libration_latitude('2024-01-15 00:00:00+00'::timestamptz) BETWEEN -7.5 AND 7.5
|
|
AS libration_lat_in_range;
|
|
libration_lat_in_range
|
|
------------------------
|
|
t
|
|
(1 row)
|
|
|
|
SELECT moon_libration_latitude('2024-06-15 00:00:00+00'::timestamptz) BETWEEN -7.5 AND 7.5
|
|
AS libration_lat_in_range_2;
|
|
libration_lat_in_range_2
|
|
--------------------------
|
|
t
|
|
(1 row)
|
|
|
|
-- ============================================================
|
|
-- Lunar libration: position angle in [0, 360)
|
|
-- ============================================================
|
|
SELECT moon_libration_position_angle('2024-01-15 00:00:00+00'::timestamptz) BETWEEN -1.0 AND 361.0
|
|
AS libration_pa_in_range;
|
|
libration_pa_in_range
|
|
-----------------------
|
|
t
|
|
(1 row)
|
|
|
|
-- ============================================================
|
|
-- Lunar libration: composite returns same as individual functions
|
|
-- ============================================================
|
|
SELECT abs((moon_libration('2024-01-15 00:00:00+00'::timestamptz)).l
|
|
- moon_libration_longitude('2024-01-15 00:00:00+00'::timestamptz)) < 0.001
|
|
AS composite_matches_lon;
|
|
composite_matches_lon
|
|
-----------------------
|
|
t
|
|
(1 row)
|
|
|
|
SELECT abs((moon_libration('2024-01-15 00:00:00+00'::timestamptz)).b
|
|
- moon_libration_latitude('2024-01-15 00:00:00+00'::timestamptz)) < 0.001
|
|
AS composite_matches_lat;
|
|
composite_matches_lat
|
|
-----------------------
|
|
t
|
|
(1 row)
|
|
|
|
-- ============================================================
|
|
-- Lunar libration: changes over time (not constant)
|
|
-- ============================================================
|
|
SELECT moon_libration_longitude('2024-01-01 00:00:00+00'::timestamptz)
|
|
!= moon_libration_longitude('2024-01-15 00:00:00+00'::timestamptz)
|
|
AS libration_varies;
|
|
libration_varies
|
|
------------------
|
|
t
|
|
(1 row)
|
|
|
|
-- ============================================================
|
|
-- Subsolar longitude: in [0, 360) range
|
|
-- ============================================================
|
|
SELECT moon_subsolar_longitude('2024-01-15 00:00:00+00'::timestamptz) BETWEEN 0.0 AND 360.0
|
|
AS subsolar_in_range;
|
|
subsolar_in_range
|
|
-------------------
|
|
t
|
|
(1 row)
|
|
|
|
SELECT moon_subsolar_longitude('2024-06-15 00:00:00+00'::timestamptz) BETWEEN 0.0 AND 360.0
|
|
AS subsolar_in_range_2;
|
|
subsolar_in_range_2
|
|
---------------------
|
|
t
|
|
(1 row)
|
|
|
|
-- ============================================================
|
|
-- Subsolar longitude: changes significantly over synodic month
|
|
-- (full 360 degrees over ~29.5 days)
|
|
-- ============================================================
|
|
SELECT abs(moon_subsolar_longitude('2024-01-01 00:00:00+00'::timestamptz)
|
|
- moon_subsolar_longitude('2024-01-15 00:00:00+00'::timestamptz)) > 10.0
|
|
AS subsolar_moves;
|
|
subsolar_moves
|
|
----------------
|
|
t
|
|
(1 row)
|
|
|