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
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
// SPDX-License-Identifier: AGPL-3.0-or-later
// Copyright (C) 2026 Vallés Puig, Ramon
//! # Ellipsoid Module
//!
//! Provides the [`Ellipsoid`] trait for defining geodetic reference ellipsoids,
//! the [`HasEllipsoid`] trait for associating an ellipsoid with a reference frame,
//! and predefined ellipsoid constants ([`Wgs84`], [`Grs80`]).
//!
//! ## Architectural Rationale
//!
//! In geodesy and astrometry:
//!
//! - The **Center** represents the physical origin (e.g., geocenter).
//! - The **Frame** represents the terrestrial reference realization (e.g., ITRF2014).
//! - The **ellipsoid** is tied to the datum / realization of the frame, not
//! to the physical center.
//!
//! Therefore the ellipsoid is a property of the Frame. This allows:
//!
//! - Multiple terrestrial realizations with different ellipsoids
//! - Avoiding proliferation of datum-specific centers
//! - Future compatibility with dynamic terrestrial frames (e.g., ITRF20xx)
//!
//! ## Example
//!
//! ```rust,ignore
//! use affn::ellipsoid::{Ellipsoid, HasEllipsoid, Wgs84};
//!
//! // Frames with an ellipsoid attribute get HasEllipsoid for free via derive:
//! // #[derive(ReferenceFrame)]
//! // #[frame(ellipsoid = "Wgs84")]
//! // pub struct ECEF;
//! //
//! // This generates:
//! // impl HasEllipsoid for ECEF {
//! // type Ellipsoid = Wgs84;
//! // }
//! ```
use ;
// =============================================================================
// Ellipsoid trait
// =============================================================================
/// A geodetic reference ellipsoid defined by its semi-major axis and flattening.
///
/// Implementations are zero-sized marker types carrying the ellipsoid constants
/// as associated `const` items.
///
/// # Parameters
///
/// | Constant | Symbol | Meaning |
/// |----------|--------|---------|
/// | [`A`](Ellipsoid::A) | *a* | Semi-major axis (equatorial radius) in **metres** |
/// | [`F`](Ellipsoid::F) | *f* | Flattening (*f = (a − b) / a*) |
///
/// # Provided Methods
///
/// | Method | Formula | Meaning |
/// |--------|---------|---------|
/// | [`e2`](Ellipsoid::e2) | *2f − f²* | First eccentricity squared |
/// | [`b`](Ellipsoid::b) | *a(1 − f)* | Semi-minor axis (polar radius) in metres |
///
/// # Example
///
/// ```rust
/// use affn::ellipsoid::{Ellipsoid, Wgs84};
///
/// assert!((Wgs84::A - 6_378_137.0).abs() < 1e-6);
/// assert!((Wgs84::e2() - 0.006_694_379_990_14).abs() < 1e-12);
/// ```
// =============================================================================
// HasEllipsoid trait
// =============================================================================
/// Marker trait associating a [`ReferenceFrame`](crate::frames::ReferenceFrame)
/// with a specific [`Ellipsoid`].
///
/// The `#[derive(ReferenceFrame)]` macro generates this impl automatically
/// when the `ellipsoid` attribute is present:
///
/// ```rust,ignore
/// #[derive(ReferenceFrame)]
/// #[frame(ellipsoid = "Wgs84")]
/// pub struct ECEF;
///
/// // Expands to:
/// // impl HasEllipsoid for ECEF {
/// // type Ellipsoid = Wgs84;
/// // }
/// ```
///
/// Geodetic conversions are trait-gated on `F: HasEllipsoid`, so they are
/// only available when the frame defines an associated ellipsoid.
// =============================================================================
// Predefined ellipsoids
// =============================================================================
/// WGS 84 (World Geodetic System 1984) reference ellipsoid.
///
/// The standard ellipsoid used by GPS and most global mapping systems.
///
/// | Parameter | Value |
/// |-----------|-------|
/// | Semi-major axis (*a*) | 6 378 137.0 m |
/// | Flattening (*f*) | 1 / 298.257 223 563 |
/// | First eccentricity² (*e²*) | 0.006 694 379 990 14 |
///
/// # References
///
/// * NIMA TR8350.2, Third Edition (2000)
/// * <https://epsg.org/ellipsoid_7030/WGS-84.html>
;
/// GRS 80 (Geodetic Reference System 1980) reference ellipsoid.
///
/// The reference ellipsoid adopted by the IUGG in 1979 and used by ITRF
/// realizations. Numerically almost identical to WGS 84 (they share the
/// same semi-major axis; the flattening differs in the 9th decimal place).
///
/// | Parameter | Value |
/// |-----------|-------|
/// | Semi-major axis (*a*) | 6 378 137.0 m |
/// | Flattening (*f*) | 1 / 298.257 222 101 |
///
/// # References
///
/// * H. Moritz, "Geodetic Reference System 1980", *Bulletin Géodésique* 54 (1980)
/// * <https://epsg.org/ellipsoid_7019/GRS-1980.html>
;
// =============================================================================
// Tests
// =============================================================================