6 custom types (tle, eci_position, geodetic, topocentric, observer, pass_event), 67 SQL functions, 2 operators (&&, <->), and a GiST operator class for altitude-band indexing. Wraps Bill Gray's sat_code for SGP4/SDP4 propagation with WGS-72 constants for propagation and WGS-84 for coordinate output. All 5 regression tests pass on PG 18.
62 lines
2.0 KiB
SQL
62 lines
2.0 KiB
SQL
-- Test GiST index and operators
|
|
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)
|
|
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)
|
|
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)
|
|
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');
|
|
|
|
-- Create GiST index
|
|
CREATE INDEX test_orbits_gist ON test_orbits USING gist (tle);
|
|
|
|
-- Overlap: ISS && Hubble = false (different altitude bands: ~400km vs ~540km)
|
|
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 between different orbit regimes
|
|
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 LEO sats (overlap with ISS)
|
|
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;
|