140 lines
6.1 KiB
PL/PgSQL
140 lines
6.1 KiB
PL/PgSQL
-- pg_orrery 0.16.0 -> 0.17.0: solar elongation, planet phase, satellite eclipse,
|
|
-- observing night quality, lunar libration
|
|
|
|
-- ============================================================
|
|
-- Solar elongation (1)
|
|
-- ============================================================
|
|
|
|
CREATE FUNCTION solar_elongation(int4, timestamptz) RETURNS float8
|
|
AS 'MODULE_PATHNAME', 'solar_elongation'
|
|
LANGUAGE C IMMUTABLE STRICT PARALLEL SAFE;
|
|
COMMENT ON FUNCTION solar_elongation(int4, timestamptz) IS
|
|
'Sun-Earth-Planet angle in degrees [0, 180]. How far a planet appears from the Sun. Body IDs 1-8.';
|
|
|
|
-- ============================================================
|
|
-- Planet phase fraction (1)
|
|
-- ============================================================
|
|
|
|
CREATE FUNCTION planet_phase(int4, timestamptz) RETURNS float8
|
|
AS 'MODULE_PATHNAME', 'planet_phase'
|
|
LANGUAGE C IMMUTABLE STRICT PARALLEL SAFE;
|
|
COMMENT ON FUNCTION planet_phase(int4, timestamptz) IS
|
|
'Illuminated fraction of a planet disk as seen from Earth [0.0, 1.0]. Body IDs 1-8.';
|
|
|
|
-- ============================================================
|
|
-- Satellite eclipse prediction (4)
|
|
-- ============================================================
|
|
|
|
CREATE FUNCTION satellite_is_eclipsed(tle, timestamptz) RETURNS bool
|
|
AS 'MODULE_PATHNAME', 'satellite_is_eclipsed'
|
|
LANGUAGE C IMMUTABLE STRICT PARALLEL SAFE;
|
|
COMMENT ON FUNCTION satellite_is_eclipsed(tle, timestamptz) IS
|
|
'True if the satellite is in Earth cylindrical shadow at the given time.';
|
|
|
|
CREATE FUNCTION satellite_next_eclipse_entry(tle, timestamptz) RETURNS timestamptz
|
|
AS 'MODULE_PATHNAME', 'satellite_next_eclipse_entry'
|
|
LANGUAGE C STABLE STRICT PARALLEL SAFE;
|
|
COMMENT ON FUNCTION satellite_next_eclipse_entry(tle, timestamptz) IS
|
|
'Next time the satellite enters Earth shadow (up to 7-day search). NULL if none found.';
|
|
|
|
CREATE FUNCTION satellite_next_eclipse_exit(tle, timestamptz) RETURNS timestamptz
|
|
AS 'MODULE_PATHNAME', 'satellite_next_eclipse_exit'
|
|
LANGUAGE C STABLE STRICT PARALLEL SAFE;
|
|
COMMENT ON FUNCTION satellite_next_eclipse_exit(tle, timestamptz) IS
|
|
'Next time the satellite exits Earth shadow (up to 7-day search). NULL if none found.';
|
|
|
|
CREATE FUNCTION satellite_eclipse_fraction(tle, timestamptz, timestamptz) RETURNS float8
|
|
AS 'MODULE_PATHNAME', 'satellite_eclipse_fraction'
|
|
LANGUAGE C STABLE STRICT PARALLEL SAFE;
|
|
COMMENT ON FUNCTION satellite_eclipse_fraction(tle, timestamptz, timestamptz) IS
|
|
'Fraction of the given time window the satellite spends in eclipse [0.0, 1.0].';
|
|
|
|
-- ============================================================
|
|
-- Observing night quality (1)
|
|
-- ============================================================
|
|
|
|
CREATE FUNCTION observing_night_quality(observer, timestamptz DEFAULT NOW())
|
|
RETURNS text AS $$
|
|
DECLARE
|
|
astro_dusk timestamptz;
|
|
astro_dawn timestamptz;
|
|
dark_hours float8;
|
|
illum float8;
|
|
moon_up bool;
|
|
score int := 100;
|
|
BEGIN
|
|
-- Astronomical darkness window
|
|
astro_dusk := sun_astronomical_dusk($1, $2);
|
|
IF astro_dusk IS NULL THEN
|
|
RETURN 'poor'; -- No astronomical darkness (polar summer)
|
|
END IF;
|
|
astro_dawn := sun_astronomical_dawn($1, astro_dusk);
|
|
IF astro_dawn IS NULL THEN
|
|
RETURN 'poor';
|
|
END IF;
|
|
|
|
dark_hours := extract(epoch FROM astro_dawn - astro_dusk) / 3600.0;
|
|
|
|
-- Short dark window penalty
|
|
IF dark_hours < 2.0 THEN score := score - 40;
|
|
ELSIF dark_hours < 4.0 THEN score := score - 20;
|
|
ELSIF dark_hours < 6.0 THEN score := score - 10;
|
|
END IF;
|
|
|
|
-- Moon illumination penalty
|
|
illum := moon_illumination(astro_dusk);
|
|
IF illum > 0.75 THEN
|
|
-- Check if Moon is above horizon during darkness
|
|
moon_up := topo_elevation(moon_observe($1, astro_dusk)) > 0
|
|
OR topo_elevation(moon_observe($1, astro_dusk + (astro_dawn - astro_dusk) / 2)) > 0;
|
|
IF moon_up THEN
|
|
score := score - (illum * 30)::int; -- Up to -30 for full moon
|
|
END IF;
|
|
END IF;
|
|
|
|
-- Classify
|
|
IF score >= 80 THEN RETURN 'excellent';
|
|
ELSIF score >= 60 THEN RETURN 'good';
|
|
ELSIF score >= 40 THEN RETURN 'fair';
|
|
ELSE RETURN 'poor';
|
|
END IF;
|
|
END;
|
|
$$ LANGUAGE plpgsql STABLE STRICT PARALLEL SAFE;
|
|
COMMENT ON FUNCTION observing_night_quality(observer, timestamptz) IS
|
|
'Composite observing quality assessment: excellent/good/fair/poor based on darkness duration and Moon interference.';
|
|
|
|
-- ============================================================
|
|
-- Lunar libration (5)
|
|
-- ============================================================
|
|
|
|
CREATE FUNCTION moon_libration_longitude(timestamptz) RETURNS float8
|
|
AS 'MODULE_PATHNAME', 'moon_libration_longitude'
|
|
LANGUAGE C IMMUTABLE STRICT PARALLEL SAFE;
|
|
COMMENT ON FUNCTION moon_libration_longitude(timestamptz) IS
|
|
'Optical libration in longitude (degrees, typically [-8, +8]). Meeus Ch. 53.';
|
|
|
|
CREATE FUNCTION moon_libration_latitude(timestamptz) RETURNS float8
|
|
AS 'MODULE_PATHNAME', 'moon_libration_latitude'
|
|
LANGUAGE C IMMUTABLE STRICT PARALLEL SAFE;
|
|
COMMENT ON FUNCTION moon_libration_latitude(timestamptz) IS
|
|
'Optical libration in latitude (degrees, typically [-7, +7]). Meeus Ch. 53.';
|
|
|
|
CREATE FUNCTION moon_libration_position_angle(timestamptz) RETURNS float8
|
|
AS 'MODULE_PATHNAME', 'moon_libration_position_angle'
|
|
LANGUAGE C IMMUTABLE STRICT PARALLEL SAFE;
|
|
COMMENT ON FUNCTION moon_libration_position_angle(timestamptz) IS
|
|
'Position angle of the Moon axis (degrees, [0, 360)). Meeus Ch. 53.';
|
|
|
|
CREATE FUNCTION moon_libration(timestamptz,
|
|
OUT l float8, OUT b float8, OUT p float8) RETURNS record
|
|
AS 'MODULE_PATHNAME', 'moon_libration'
|
|
LANGUAGE C IMMUTABLE STRICT PARALLEL SAFE;
|
|
COMMENT ON FUNCTION moon_libration(timestamptz) IS
|
|
'All three libration values: longitude (l), latitude (b), position angle (p) in degrees.';
|
|
|
|
CREATE FUNCTION moon_subsolar_longitude(timestamptz) RETURNS float8
|
|
AS 'MODULE_PATHNAME', 'moon_subsolar_longitude'
|
|
LANGUAGE C IMMUTABLE STRICT PARALLEL SAFE;
|
|
COMMENT ON FUNCTION moon_subsolar_longitude(timestamptz) IS
|
|
'Selenographic longitude of the sub-solar point (degrees, [0, 360)). Determines the lunar terminator position.';
|