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
//! The [`CoordinateSystem`] trait and its four concrete types.
//!
//! Mirrors the `cs::{cartesian,spherical,geographic,polar}` empty /
//! `<Unit>`-parameterised tag types in
//! `boost/geometry/core/cs.hpp:85-165`, together with the
//! `traits::cs_tag<Cs>` family classifier at `cs.hpp:194-225`.
//!
//! The `Family` associated type is the Rust analogue of Boost's
//! `cs_tag<Cs>::type`. Algorithm bounds key on the family
//! (`<P::Cs as CoordinateSystem>::Family`) so a strategy written for
//! `SphericalFamily` automatically applies to both
//! `Spherical<Degree>` and `Spherical<Radian>`.
use PhantomData;
use crate;
use crateAngleUnit;
/// A coordinate system.
///
/// Mirrors `traits::coordinate_system<Point>::type` from
/// `boost/geometry/core/coordinate_system.hpp:43-49`: the typedef every
/// point exposes that identifies *which* coordinate system its values
/// live in. The `Family` associated type is the analogue of Boost's
/// `traits::cs_tag<Cs>::type` (`cs.hpp:186-225`), the family-level
/// classifier that strategies actually dispatch on.
///
/// # Examples
///
/// ```
/// use geometry_cs::{Cartesian, CartesianFamily, CoordinateSystem};
/// // Every CS exposes its `Family`; strategies bind on the family.
/// fn _cartesian_family<C: CoordinateSystem<Family = CartesianFamily>>() {}
/// _cartesian_family::<Cartesian>();
/// ```
/// Cartesian / rectangular coordinates.
///
/// Mirrors `boost::geometry::cs::cartesian`
/// (`boost/geometry/core/cs.hpp:85-93`).
///
/// # Examples
///
/// ```
/// use geometry_cs::{Cartesian, CartesianFamily, CoordinateSystem};
/// let _: <Cartesian as CoordinateSystem>::Family = CartesianFamily;
/// ```
;
/// Spherical coordinates in unit `U`.
///
/// Mirrors `boost::geometry::cs::spherical<DegreeOrRadian>`
/// (`boost/geometry/core/cs.hpp:115-135`).
///
/// # Convention: latitude measured from the equator
///
/// Boost has *two* spherical tags
/// (`boost/geometry/core/tags.hpp:38-41`):
///
/// * `spherical_polar_tag` — colatitude. The second coordinate is
/// the angle from the **pole**, ranging `[0, π]`.
/// * `spherical_equatorial_tag` — latitude. The second coordinate
/// is the angle from the **equator**, ranging `[-π/2, π/2]`.
///
/// v1 collapses both into one [`Spherical<U>`] family and picks the
/// **equatorial** convention because that is what the OGC standard
/// and the Boost.Geometry quickstart use
/// (`doc/src/examples/quick_start.cpp` Amsterdam → Paris example).
///
/// In coordinate order:
///
/// ```text
/// get::<0>(p) → longitude (azimuth, around the polar axis)
/// get::<1>(p) → latitude (measured from the equator)
/// ```
///
/// In a `Spherical<Degree>` point, longitude ranges `-180.0..=180.0`
/// (east of Greenwich is positive) and latitude ranges
/// `-90.0..=90.0` (north of the equator is positive). Amsterdam
/// (≈ 4.90° E, 52.37° N) is `(4.90, 52.37)` — the "north of the
/// equator" component is the *second* coordinate.
///
/// # If you have colatitude data
///
/// Convert to latitude first: `latitude = 90° − colatitude`
/// (degrees) or `π/2 − colatitude` (radians). The dedicated
/// `SphericalPolar` / `SphericalEquatorial` split is deferred — see
/// `specs/FUTURE_ITERATIONS.md` §1.2.
///
/// # Examples
///
/// ```
/// use geometry_cs::{CoordinateSystem, Degree, Spherical, SphericalFamily};
/// fn _spherical<C: CoordinateSystem<Family = SphericalFamily>>() {}
/// _spherical::<Spherical<Degree>>();
/// ```
;
/// Geographic (lat / lon) coordinates on a spheroid in unit `U`.
///
/// Mirrors `boost::geometry::cs::geographic<DegreeOrRadian>`
/// (`boost/geometry/core/cs.hpp:98-110`).
///
/// # Convention: latitude measured from the equator
///
/// Same equatorial convention as [`Spherical<U>`] — the difference
/// is the *earth model*: `Geographic` distances run on a spheroid
/// (Andoyer / Vincenty / Thomas), `Spherical` on a perfect sphere
/// (Haversine). In coordinate order:
///
/// ```text
/// get::<0>(p) → longitude (east of Greenwich positive)
/// get::<1>(p) → latitude (north of the equator positive)
/// ```
///
/// In a `Geographic<Degree>` point, longitude ranges `-180.0..=180.0`
/// and latitude ranges `-90.0..=90.0`.
///
/// # Examples
///
/// ```
/// use geometry_cs::{CoordinateSystem, Degree, Geographic, GeographicFamily};
/// fn _geo<C: CoordinateSystem<Family = GeographicFamily>>() {}
/// _geo::<Geographic<Degree>>();
/// ```
;
/// Polar coordinates in unit `U`.
///
/// Mirrors `boost::geometry::cs::polar<DegreeOrRadian>`
/// (`boost/geometry/core/cs.hpp:155-165`).
///
/// # Examples
///
/// ```
/// use geometry_cs::{CoordinateSystem, Polar, PolarFamily, Radian};
/// fn _polar<C: CoordinateSystem<Family = PolarFamily>>() {}
/// _polar::<Polar<Radian>>();
/// ```
;