-- Test GiST index and operators (2-D: altitude + inclination) CREATE EXTENSION IF NOT EXISTS pg_orbit; -- Create test table with mixed orbit types CREATE TABLE test_orbits ( id serial, name text, tle tle ); -- ISS (LEO, ~400km, inclination 51.64 deg) INSERT INTO test_orbits (name, tle) VALUES ('ISS', '1 25544U 98067A 24001.50000000 .00016717 00000-0 10270-3 0 9025 2 25544 51.6400 208.9163 0006703 30.1694 61.7520 15.50100486 00001'); -- Hubble (LEO, ~540km, inclination 28.47 deg) INSERT INTO test_orbits (name, tle) VALUES ('Hubble', '1 20580U 90037B 24001.50000000 .00000790 00000+0 39573-4 0 9992 2 20580 28.4705 61.4398 0002797 317.3115 42.7577 15.09395228 00008'); -- GPS IIR-M (MEO, ~20200km, inclination 55.44 deg) INSERT INTO test_orbits (name, tle) VALUES ('GPS-IIR', '1 28874U 05038A 24001.50000000 .00000012 00000+0 00000+0 0 9993 2 28874 55.4408 300.3467 0117034 51.6543 309.5420 2.00557079 00006'); -- Equatorial-LEO: same altitude as ISS but near-equatorial inclination (5 deg). -- Same mean motion (15.501 rev/day) and eccentricity as ISS → same altitude band. -- Different inclination → should NOT overlap with ISS under 2-D key. INSERT INTO test_orbits (name, tle) VALUES ('Equatorial-LEO', '1 99901U 24999A 24001.50000000 .00016717 00000-0 10270-3 0 9990 2 99901 5.0000 208.9163 0006703 30.1694 61.7520 15.50100486 00001'); -- Create GiST index CREATE INDEX test_orbits_gist ON test_orbits USING gist (tle); -- 2-D overlap: ISS && Equatorial-LEO should be false (same altitude, different inclination) SELECT a.name AS sat_a, b.name AS sat_b, a.tle && b.tle AS overlaps FROM test_orbits a, test_orbits b WHERE a.id < b.id ORDER BY a.name, b.name; -- Altitude distance: ISS <-> Equatorial-LEO should be ~0 (same altitude shell) SELECT a.name AS sat_a, b.name AS sat_b, round((a.tle <-> b.tle)::numeric, 0) AS alt_dist_km FROM test_orbits a, test_orbits b WHERE a.id < b.id ORDER BY a.name, b.name; -- GiST index scan: find all sats overlapping ISS (altitude AND inclination) -- Should return only ISS itself (Equatorial-LEO is at same altitude but wrong inclination) SET enable_seqscan = off; SELECT name FROM test_orbits WHERE tle && (SELECT tle FROM test_orbits WHERE name = 'ISS') ORDER BY name; RESET enable_seqscan; -- Nearest-neighbor via GiST: order by altitude distance to ISS SET enable_seqscan = off; SELECT name, round((tle <-> (SELECT tle FROM test_orbits WHERE name = 'ISS'))::numeric, 0) AS dist FROM test_orbits WHERE name != 'ISS' ORDER BY tle <-> (SELECT tle FROM test_orbits WHERE name = 'ISS'); RESET enable_seqscan; -- Self-overlap is always true SELECT name, tle && tle AS self_overlap FROM test_orbits ORDER BY name; -- Cleanup DROP TABLE test_orbits;