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
//! # Adapting your own types
//!
//! Three paths get a user type into the geometry kernel, ordered from
//! least to most indirect. Pick the first one that applies.
//!
//! ## Path 1 — Direct `impl Point for MyPoint`
//!
//! If you own the type, implement [`geometry_trait::Geometry`] and
//! [`geometry_trait::Point`] directly (add [`geometry_trait::PointMut`]
//! too if you need to *write* coordinates). This is the most explicit
//! form and the one with the smallest compile-time footprint — no
//! wrapper types, no macros.
//!
//! ```
//! use geometry_cs::Cartesian;
//! use geometry_tag::PointTag;
//! use geometry_trait::{Geometry, Point, PointMut};
//!
//! #[derive(Default)]
//! struct MyPoint { x: f64, y: f64 }
//!
//! impl Geometry for MyPoint {
//! type Kind = PointTag;
//! type Point = Self;
//! }
//!
//! impl Point for MyPoint {
//! type Scalar = f64;
//! type Cs = Cartesian;
//! const DIM: usize = 2;
//! fn get<const D: usize>(&self) -> f64 {
//! if D == 0 { self.x } else { self.y }
//! }
//! }
//!
//! impl PointMut for MyPoint {
//! fn set<const D: usize>(&mut self, v: f64) {
//! if D == 0 { self.x = v } else { self.y = v }
//! }
//! }
//! ```
//!
//! ## Path 2 — `#[derive(Point)]`
//!
//! For the common "struct with named coordinate fields" case the
//! `Point` proc-macro generates the impl. Mirrors the C++
//! `BOOST_GEOMETRY_REGISTER_POINT_2D` macro from
//! `boost/geometry/geometries/register/point.hpp`. The derive lives
//! in `geometry-derive` and is re-exported by the `geometry` facade
//! so downstream users only need a single dependency:
//!
//! ```ignore
//! use geometry::Point; // the derive macro
//! use geometry::prelude::*; // brings in the `Point` trait + algorithms
//!
//! #[derive(Default, Point)]
//! #[geometry(cs = "Cartesian", scalar = "f64")]
//! struct MyPoint { x: f64, y: f64 }
//!
//! let d = distance(&MyPoint { x: 0.0, y: 0.0 }, &MyPoint { x: 3.0, y: 4.0 });
//! assert_eq!(d, 5.0);
//! ```
//!
//! ## Path 3 — `Adapt<T>` + optional `WithCs<T, Cs>`
//!
//! When you do *not* own the type (a `[T; N]`, a `(T, T)`, a foreign
//! crate's point type), wrap it in [`Adapt<T>`]. `Adapt` is a
//! `#[repr(transparent)]` newtype that forwards coordinate access
//! into the foreign storage layout. Coherence forbids a blanket impl
//! on the foreign type directly; the wrapper sidesteps the orphan
//! rule with zero runtime cost.
//!
//! ```
//! use geometry_adapt::Adapt;
//! use geometry_trait::Point;
//!
//! let p = Adapt([3.0_f64, 4.0]);
//! assert_eq!(p.get::<0>(), 3.0);
//! assert_eq!(p.get::<1>(), 4.0);
//! ```
//!
//! [`Adapt<T>`] is **shape-only** and defaults the coordinate system
//! to [`Cartesian`](geometry_cs::Cartesian). For any other CS (latitude /
//! longitude in degrees, radians, …) layer [`WithCs<T, Cs>`] on top.
//! This is the orthogonality from proposal §3.7: `Adapt` answers
//! *"how do I read coordinates out of this foreign data layout?"*,
//! while `WithCs` answers *"what does that coordinate pair mean?"*.
//!
//! ```
//! use geometry_adapt::{Adapt, WithCs};
//! use geometry_algorithm::distance;
//! use geometry_cs::{Degree, Geographic};
//!
//! // [lon, lat] degrees on WGS84.
//! let ams = WithCs::<_, Geographic<Degree>>::new(Adapt([4.90_f64, 52.37]));
//! let par = WithCs::<_, Geographic<Degree>>::new(Adapt([2.35_f64, 48.86]));
//! let _ = distance(&ams, &par); // picks Andoyer for the geographic family
//! ```
//!
//! Either wrapper can also re-tag a user type that already
//! implements [`Point`](geometry_trait::Point), so a `MyPoint` from
//! Path 1 can be reused as a geographic point by writing
//! `WithCs::<MyPoint, Geographic<Degree>>::new(p)` instead of
//! defining a second adapter.
//!
//! ## Container adaptation — the `register_*!` macros
//!
//! Coherence also forbids a blanket impl on foreign sequence types
//! (`impl<P: Point, C: AsRef<[P]>> Linestring for C`). For that case,
//! `geometry-adapt` ships declarative macros `register_linestring!`,
//! `register_ring!`, `register_polygon!`, and the three `register_multi_*!`
//! forms, mirroring
//! `BOOST_GEOMETRY_REGISTER_LINESTRING` and siblings
//! (`boost/geometry/geometries/register/linestring.hpp` and co.).
//!
//! ---
//!
//! Module layout:
//!
//! * [`Adapt<T>`] — shape-only wrapper. Forwards coordinate access
//! into a foreign storage layout (array, tuple, third-party point).
//! Defaults to [`Cartesian`](geometry_cs::Cartesian); layer
//! [`WithCs`] on top for other systems.
//! * [`WithCs<T, Cs>`] — coordinate-system re-tagging wrapper.
//!
//! Mirrors the role of `boost/geometry/geometries/adapted/*.hpp`
//! (`c_array.hpp`, `std_array.hpp`, `boost_tuple.hpp`,
//! `boost_polygon.hpp`, …).
pub use Adapt;
pub use WithCs;
// Re-exported under `__macros` for the `register_*!` macros to expand
// against. Not part of the public API — users never name this path.
pub use __macros;