-- v018_features.sql -- Tests for v0.18.0: Saturn ring tilt, penumbral eclipse, -- rise/set event windows, angular separation rate -- -- Verifies all 10 new functions added in v0.18.0. CREATE EXTENSION IF NOT EXISTS pg_orrery; NOTICE: extension "pg_orrery" already exists, skipping -- ============================================================ -- Saturn ring tilt: in [-27, +27] range -- ============================================================ SELECT saturn_ring_tilt('2024-01-15 00:00:00+00'::timestamptz) BETWEEN -27.0 AND 27.0 AS ring_tilt_in_range; ring_tilt_in_range -------------------- t (1 row) -- ============================================================ -- Saturn ring tilt: near zero around 2025 ring crossing -- (rings edge-on to Earth around March 2025) -- ============================================================ SELECT abs(saturn_ring_tilt('2025-03-23 00:00:00+00'::timestamptz)) < 5.0 AS ring_tilt_near_edge_on; ring_tilt_near_edge_on ------------------------ t (1 row) -- ============================================================ -- Saturn ring tilt: varies over time (not constant) -- ============================================================ SELECT saturn_ring_tilt('2024-01-01 00:00:00+00'::timestamptz) != saturn_ring_tilt('2024-07-01 00:00:00+00'::timestamptz) AS ring_tilt_varies; ring_tilt_varies ------------------ t (1 row) -- ============================================================ -- Saturn ring tilt: sign changes across ring plane crossing -- (2017 was fully open, 2025 is edge-on, tilt changes sign) -- ============================================================ SELECT abs(saturn_ring_tilt('2017-06-15 00:00:00+00'::timestamptz)) > 10.0 AS ring_tilt_open_2017; ring_tilt_open_2017 --------------------- t (1 row) -- ============================================================ -- Planet magnitude: Saturn now includes ring correction -- (ring-corrected magnitude should differ from globe-only) -- Saturn magnitude should be roughly between -0.5 and +1.5 -- ============================================================ SELECT planet_magnitude(6, '2024-01-15 00:00:00+00'::timestamptz) BETWEEN -1.0 AND 2.0 AS saturn_mag_valid_range; saturn_mag_valid_range ------------------------ t (1 row) -- ============================================================ -- Satellite shadow state: returns valid text values -- ============================================================ SELECT satellite_shadow_state( 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 ) IN ('sunlit', 'penumbra', 'umbra') AS shadow_state_valid; shadow_state_valid -------------------- t (1 row) -- ============================================================ -- Satellite in penumbra: returns bool -- ============================================================ SELECT satellite_in_penumbra( 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 penumbra_returns_bool; penumbra_returns_bool ----------------------- t (1 row) -- ============================================================ -- Backward compatibility: satellite_is_eclipsed still works -- (cone model upgrade is internal-only) -- ============================================================ 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_backward_compat; eclipse_backward_compat ------------------------- t (1 row) -- ============================================================ -- Penumbra entry precedes umbra entry (penumbra is outer zone) -- ============================================================ SELECT satellite_next_penumbra_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 ) <= 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 ) AS penumbra_precedes_umbra; penumbra_precedes_umbra ------------------------- t (1 row) -- ============================================================ -- Penumbra exit is after penumbra entry -- ============================================================ SELECT satellite_next_penumbra_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 penumbra_exit_in_future; penumbra_exit_in_future ------------------------- t (1 row) -- ============================================================ -- Eclipse fraction still valid after cone upgrade -- ============================================================ 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_still_valid; eclipse_fraction_still_valid ------------------------------ t (1 row) -- ============================================================ -- Sun rise/set events: mid-latitude 24h window returns events -- ============================================================ SELECT count(*) >= 1 AS sun_events_exist FROM sun_rise_set_events( '(43.7,-116.4,800)'::observer, '2024-06-21 00:00:00+00'::timestamptz, '2024-06-22 00:00:00+00'::timestamptz ); sun_events_exist ------------------ t (1 row) -- ============================================================ -- Sun rise/set events: events alternate rise/set -- ============================================================ SELECT bool_and(event_type IN ('rise', 'set')) AS sun_event_types_valid FROM sun_rise_set_events( '(43.7,-116.4,800)'::observer, '2024-06-21 00:00:00+00'::timestamptz, '2024-06-22 00:00:00+00'::timestamptz ); sun_event_types_valid ----------------------- t (1 row) -- ============================================================ -- Sun rise/set events: refracted vs geometric -- (refracted rise is earlier than geometric rise) -- ============================================================ SELECT (SELECT min(event_time) FROM sun_rise_set_events( '(43.7,-116.4,800)'::observer, '2024-06-21 00:00:00+00'::timestamptz, '2024-06-22 00:00:00+00'::timestamptz, true ) WHERE event_type = 'rise') <= (SELECT min(event_time) FROM sun_rise_set_events( '(43.7,-116.4,800)'::observer, '2024-06-21 00:00:00+00'::timestamptz, '2024-06-22 00:00:00+00'::timestamptz, false ) WHERE event_type = 'rise') AS refracted_rise_earlier; refracted_rise_earlier ------------------------ t (1 row) -- ============================================================ -- Moon rise/set events: returns valid event types -- ============================================================ SELECT bool_and(event_type IN ('rise', 'set')) AS moon_event_types_valid FROM moon_rise_set_events( '(43.7,-116.4,800)'::observer, '2024-01-15 00:00:00+00'::timestamptz, '2024-01-16 00:00:00+00'::timestamptz ); moon_event_types_valid ------------------------ t (1 row) -- ============================================================ -- Planet rise/set events: Jupiter over 24h -- ============================================================ SELECT count(*) >= 1 AS jupiter_events_exist FROM planet_rise_set_events( 5, '(43.7,-116.4,800)'::observer, '2024-01-15 00:00:00+00'::timestamptz, '2024-01-16 00:00:00+00'::timestamptz ); jupiter_events_exist ---------------------- t (1 row) -- ============================================================ -- Rise/set events: window > 366 days rejected -- ============================================================ DO $$ BEGIN PERFORM * FROM sun_rise_set_events( '(43.7,-116.4,800)'::observer, '2024-01-01 00:00:00+00'::timestamptz, '2025-03-01 00:00:00+00'::timestamptz ); EXCEPTION WHEN OTHERS THEN RAISE NOTICE 'window overflow: %', SQLERRM; END $$; NOTICE: window overflow: window exceeds 366-day maximum -- ============================================================ -- Rise/set events: stop before start rejected -- ============================================================ DO $$ BEGIN PERFORM * FROM sun_rise_set_events( '(43.7,-116.4,800)'::observer, '2024-06-22 00:00:00+00'::timestamptz, '2024-06-21 00:00:00+00'::timestamptz ); EXCEPTION WHEN OTHERS THEN RAISE NOTICE 'stop before start: %', SQLERRM; END $$; NOTICE: stop before start: stop time must be after start time -- ============================================================ -- eq_angular_rate: generic rate computation -- Two positions that are 10 deg apart, then 9 deg apart after 1 hour -- should give rate = -1.0 deg/hr (approaching) -- ============================================================ SELECT abs(eq_angular_rate( '(6.0, 45.0, 1.0)'::equatorial, '(6.667, 45.0, 1.0)'::equatorial, '(6.0, 45.0, 1.0)'::equatorial, '(6.6, 45.0, 1.0)'::equatorial, 3600.0 )) > 0.0 AS angular_rate_nonzero; angular_rate_nonzero ---------------------- t (1 row) -- ============================================================ -- eq_angular_rate: dt_seconds <= 0 rejected -- ============================================================ DO $$ BEGIN PERFORM eq_angular_rate( '(6.0, 45.0, 1.0)'::equatorial, '(7.0, 45.0, 1.0)'::equatorial, '(6.0, 45.0, 1.0)'::equatorial, '(7.0, 45.0, 1.0)'::equatorial, 0.0 ); EXCEPTION WHEN OTHERS THEN RAISE NOTICE 'dt_seconds=0: %', SQLERRM; END $$; NOTICE: dt_seconds=0: eq_angular_rate: dt_seconds must be positive -- ============================================================ -- planet_angular_rate: Moon rate ~0.5 deg/hr relative to Sun -- ============================================================ SELECT abs(planet_angular_rate(0, 10, '2024-01-15 00:00:00+00'::timestamptz)) > 0.1 AS moon_sun_rate_nonzero; moon_sun_rate_nonzero ----------------------- t (1 row) -- ============================================================ -- planet_angular_rate: same body rejected -- ============================================================ DO $$ BEGIN PERFORM planet_angular_rate(5, 5, '2024-01-15 00:00:00+00'::timestamptz); EXCEPTION WHEN OTHERS THEN RAISE NOTICE 'same body: %', SQLERRM; END $$; NOTICE: same body: planet_angular_rate: body IDs must be different -- ============================================================ -- planet_angular_rate: Jupiter-Saturn rate is small -- (outer planets move slowly) -- ============================================================ SELECT abs(planet_angular_rate(5, 6, '2024-01-15 00:00:00+00'::timestamptz)) < 1.0 AS outer_planet_rate_slow; outer_planet_rate_slow ------------------------ t (1 row)