1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
//! Ellipsoidal coordinate types.
//!
//! - [`Position<C, F, U>`]: an ellipsoidal **position** (longitude, latitude,
//! height above the reference ellipsoid)
//!
//! This module is the ellipsoidal analogue of [`spherical`](crate::spherical) and
//! [`cartesian`](crate::cartesian). The reference frame `F` determines _which_
//! ellipsoid is used via the [`HasEllipsoid`](crate::ellipsoid::HasEllipsoid)
//! trait, so conversions to Cartesian are compile-time gated on the frame.
//!
//! # Why a separate coordinate family?
//!
//! An ellipsoidal (geodetic) position cannot be represented as a spherical
//! `Position<C, F, U>` without silently losing meaning:
//!
//! - In a spherical position, `distance` is the **radial distance** from the
//! origin, *not* the height above an ellipsoid.
//! - Calling `.to_cartesian()` on a spherical position performs a spherical →
//! Cartesian conversion, which is **geometrically wrong** for geodetic
//! heights.
//!
//! By using a dedicated `ellipsoidal::Position`, callers must go through an
//! explicit, ellipsoid-aware conversion.
pub use Position;
// =============================================================================
// Shared normalisation helpers
// =============================================================================
/// Normalise geodetic longitude/latitude to their canonical ranges.
///
/// - `lon` → `[-180°, +180°)`
/// - `lat` → `[-90°, +90°]` (pole-crossing reflected into longitude)
pub