Skip to main content

geometry_adapt/
adapt_tuple.rs

1//! [`Point`] impls for `Adapt<(T, T)>` and `Adapt<(T, T, T)>`.
2//!
3//! Mirrors `boost/geometry/geometries/adapted/boost_tuple.hpp`,
4//! which registers `boost::tuple<T, T>` and `boost::tuple<T, T, T>`
5//! as 2D and 3D Cartesian points. Rust's native tuples replace the
6//! Boost ones; we adapt the two arities the C++ header covers.
7//!
8//! # Silent-Cartesian warning
9//!
10//! Both impls pin `type Cs = Cartesian`. A raw `Adapt((lon, lat))`
11//! therefore satisfies *every* Cartesian-only strategy bound and
12//! will silently compute Pythagorean nonsense over lat/lon. Wrap
13//! geographic / spherical tuples with [`WithCs`](crate::WithCs) —
14//! see [`Adapt`](crate::Adapt)'s rustdoc for the worked example.
15//!
16//! The `_ => unreachable!()` arms below are dead at runtime because
17//! `D` is const-evaluated at the call site: a `get::<2>()` on
18//! `Adapt<(T, T)>` fails to typecheck against `Point::DIM = 2` in
19//! the bounds the algorithm layer enforces. A future `where D < N`
20//! clause via `generic_const_exprs` would let us delete them.
21
22use geometry_coords::CoordinateScalar;
23use geometry_cs::Cartesian;
24use geometry_tag::PointTag;
25use geometry_trait::{Geometry, Point, PointMut};
26
27use crate::Adapt;
28
29impl<T: CoordinateScalar> Geometry for Adapt<(T, T)> {
30    type Kind = PointTag;
31    type Point = Self;
32}
33
34impl<T: CoordinateScalar> Point for Adapt<(T, T)> {
35    type Scalar = T;
36    type Cs = Cartesian;
37    const DIM: usize = 2;
38
39    #[inline]
40    fn get<const D: usize>(&self) -> T {
41        match D {
42            0 => self.0.0,
43            1 => self.0.1,
44            _ => unreachable!(),
45        }
46    }
47}
48
49impl<T: CoordinateScalar> PointMut for Adapt<(T, T)> {
50    #[inline]
51    fn set<const D: usize>(&mut self, value: T) {
52        match D {
53            0 => self.0.0 = value,
54            1 => self.0.1 = value,
55            _ => unreachable!(),
56        }
57    }
58}
59
60impl<T: CoordinateScalar> Geometry for Adapt<(T, T, T)> {
61    type Kind = PointTag;
62    type Point = Self;
63}
64
65impl<T: CoordinateScalar> Point for Adapt<(T, T, T)> {
66    type Scalar = T;
67    type Cs = Cartesian;
68    const DIM: usize = 3;
69
70    #[inline]
71    fn get<const D: usize>(&self) -> T {
72        match D {
73            0 => self.0.0,
74            1 => self.0.1,
75            2 => self.0.2,
76            _ => unreachable!(),
77        }
78    }
79}
80
81impl<T: CoordinateScalar> PointMut for Adapt<(T, T, T)> {
82    #[inline]
83    fn set<const D: usize>(&mut self, value: T) {
84        match D {
85            0 => self.0.0 = value,
86            1 => self.0.1 = value,
87            2 => self.0.2 = value,
88            _ => unreachable!(),
89        }
90    }
91}