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
//! The shape-only adapter newtype.
//!
//! Mirrors the role of the Boost `BOOST_GEOMETRY_REGISTER_*` macros
//! in `boost/geometry/geometries/adapted/c_array.hpp`,
//! `std_array.hpp`, and `boost_tuple.hpp`: those macros specialise
//! `traits::tag`, `traits::dimension`, `traits::coordinate_type`,
//! `traits::coordinate_system`, and `traits::access<P, D>` for a
//! foreign storage layout. Rust has no specialisation, so we wrap
//! the foreign value in [`Adapt`] and hang the trait impls off the
//! wrapper instead — coherence-safe and layout-free thanks to
//! `#[repr(transparent)]`.
/// Shape-only adapter wrapper.
///
/// `#[repr(transparent)]` so `&Adapt<T>` is layout-compatible with
/// `&T` — no boxing, no allocation, the wrapper is purely a place to
/// hang trait impls that coherence wouldn't allow on `T` directly.
///
/// Defaults to `Cs = Cartesian` for every shape this crate adapts.
/// Compose with [`WithCs<T, Cs>`](crate::WithCs) to re-tag with a
/// different coordinate system.
///
/// Mirrors `boost/geometry/geometries/adapted/{c_array,
/// std_array, boost_tuple}.hpp` collectively.
///
/// # Coordinate system default — silent-Cartesian warning
///
/// **`Adapt<T>` defaults to [`Cartesian`](geometry_cs::Cartesian).**
/// This matters for adapted containers like `[lat, lon]` arrays or
/// `(lat, lon)` tuples — by default the library will compute
/// *Cartesian Pythagorean* distances over them, **not** great-circle
/// distances. If your coordinates are spherical or geographic, wrap
/// them with [`WithCs`](crate::WithCs):
///
/// ```ignore
/// use geometry_adapt::{Adapt, WithCs};
/// use geometry_cs::{Degree, Geographic};
///
/// // WRONG — treats lon/lat as Cartesian, returns nonsense for distance.
/// let p = Adapt([4.9_f64, 52.4]);
///
/// // RIGHT — the Cs is in the type; distance() picks the right strategy
/// // (haversine / andoyer / vincenty) and Pythagoras refuses to compile.
/// let p = WithCs::<_, Geographic<Degree>>::new(Adapt([4.9_f64, 52.4]));
/// ```
///
/// The matching compile-time diagnostic that catches a bare
/// `Adapt<[lat, lon]>` from reaching `Pythagoras` lives on
/// [`SameAs`](geometry_tag::SameAs) — see proposal §3.7 and §8 for
/// the rationale and the mitigations.
///
/// # Borrowed arrays — read only
///
/// `Adapt<&[T; N]>` works just like `Adapt<[T; N]>` for the
/// read-only algorithm surface (`distance`, `length`, `area`, …),
/// without copying the storage. The borrow does not implement
/// `PointMut`, so any algorithm that needs to *output* a Point
/// (e.g. `envelope`) is a compile error — own your array if you
/// need mutation.
///
/// ```
/// use geometry_adapt::Adapt;
/// use geometry_algorithm::distance;
///
/// let a_storage = [0.0_f64, 0.0];
/// let b_storage = [3.0_f64, 4.0];
/// assert_eq!(distance(&Adapt(&a_storage), &Adapt(&b_storage)), 5.0);
/// ```
;