geo_traits/
coord.rs

1use std::marker::PhantomData;
2
3#[cfg(feature = "geo-types")]
4use geo_types::{Coord, CoordNum};
5
6use crate::Dimensions;
7
8/// A trait for accessing data from a generic Coord.
9///
10/// Refer to [geo_types::Coord] for information about semantics and validity.
11pub trait CoordTrait {
12    /// The coordinate type of this geometry
13    type T;
14
15    /// Dimensions of the coordinate tuple
16    fn dim(&self) -> Dimensions;
17
18    /// Access the n'th (0-based) element of the CoordinateTuple.
19    /// Returns `None` if `n >= DIMENSION`.
20    ///
21    /// See also [`nth_or_panic()`](Self::nth_or_panic) and [`nth_unchecked()`](Self::nth_unchecked).
22    ///
23    /// # Panics
24    ///
25    /// This method may panic if [`dim()`](Self::dim) does not correspond to
26    /// the actual number of dimensions in this coordinate.
27    fn nth(&self, n: usize) -> Option<Self::T> {
28        if n < self.dim().size() {
29            Some(self.nth_or_panic(n))
30        } else {
31            None
32        }
33    }
34
35    /// x component of this coord.
36    fn x(&self) -> Self::T;
37
38    /// y component of this coord.
39    fn y(&self) -> Self::T;
40
41    /// Returns a tuple that contains the x/horizontal & y/vertical component of the coord.
42    fn x_y(&self) -> (Self::T, Self::T) {
43        (self.x(), self.y())
44    }
45
46    /// Access the n'th (0-based) element of the CoordinateTuple.
47    /// May panic if n >= DIMENSION.
48    /// See also [`nth()`](Self::nth).
49    fn nth_or_panic(&self, n: usize) -> Self::T;
50
51    /// Access the n'th (0-based) element of the CoordinateTuple.
52    /// May panic if n >= DIMENSION.
53    ///
54    /// See also [`nth()`](Self::nth), [`nth_or_panic()`](Self::nth_or_panic).
55    ///
56    /// You might want to override the default implementation of this method
57    /// if you can provide a more efficient implementation.
58    ///
59    /// # Safety
60    ///
61    /// Though it may panic, the default implementation actually is safe. However, implementors
62    /// are allowed to implement this method themselves with an unsafe implementation. See the
63    /// individual implementations for more information on their own Safety considerations.
64    unsafe fn nth_unchecked(&self, n: usize) -> Self::T {
65        self.nth_or_panic(n)
66    }
67}
68
69#[cfg(feature = "geo-types")]
70impl<T: CoordNum> CoordTrait for Coord<T> {
71    type T = T;
72
73    fn nth_or_panic(&self, n: usize) -> Self::T {
74        match n {
75            0 => self.x(),
76            1 => self.y(),
77            _ => panic!("Coord only supports 2 dimensions"),
78        }
79    }
80
81    fn dim(&self) -> Dimensions {
82        Dimensions::Xy
83    }
84
85    fn x(&self) -> Self::T {
86        self.x
87    }
88
89    fn y(&self) -> Self::T {
90        self.y
91    }
92}
93
94#[cfg(feature = "geo-types")]
95impl<T: CoordNum> CoordTrait for &Coord<T> {
96    type T = T;
97
98    fn nth_or_panic(&self, n: usize) -> Self::T {
99        match n {
100            0 => self.x(),
101            1 => self.y(),
102            _ => panic!("Coord only supports 2 dimensions"),
103        }
104    }
105
106    fn dim(&self) -> Dimensions {
107        Dimensions::Xy
108    }
109
110    fn x(&self) -> Self::T {
111        self.x
112    }
113
114    fn y(&self) -> Self::T {
115        self.y
116    }
117}
118
119impl<T: Copy> CoordTrait for (T, T) {
120    type T = T;
121
122    fn nth_or_panic(&self, n: usize) -> Self::T {
123        match n {
124            0 => self.x(),
125            1 => self.y(),
126            _ => panic!("(T, T) only supports 2 dimensions"),
127        }
128    }
129
130    fn dim(&self) -> Dimensions {
131        Dimensions::Xy
132    }
133
134    fn x(&self) -> Self::T {
135        self.0
136    }
137
138    fn y(&self) -> Self::T {
139        self.1
140    }
141}
142
143/// An empty struct that implements [CoordTrait].
144///
145/// This can be used as the `CoordType` of the `GeometryTrait` by implementations that don't have a
146/// Coord concept
147pub struct UnimplementedCoord<T>(PhantomData<T>);
148
149impl<T> CoordTrait for UnimplementedCoord<T> {
150    type T = T;
151
152    fn dim(&self) -> Dimensions {
153        unimplemented!()
154    }
155
156    fn nth_or_panic(&self, _n: usize) -> Self::T {
157        unimplemented!()
158    }
159
160    fn x(&self) -> Self::T {
161        unimplemented!()
162    }
163
164    fn y(&self) -> Self::T {
165        unimplemented!()
166    }
167}