geo_types/geometry/
coord.rs

1use crate::{coord, CoordNum, Point};
2
3/// A lightweight struct used to store coordinates on the 2-dimensional
4/// Cartesian plane.
5///
6/// Unlike `Point` (which in the future may contain additional information such
7/// as an envelope, a precision model, and spatial reference system
8/// information), a `Coord` only contains ordinate values and accessor
9/// methods.
10///
11/// This type implements the [vector space] operations:
12/// [`Add`], [`Sub`], [`Neg`], [`Zero`],
13/// [`Mul<T>`][`Mul`], and [`Div<T>`][`Div`] traits.
14///
15/// # Semantics
16///
17/// This type does not represent any geospatial primitive,
18/// but is used in their definitions. The only requirement
19/// is that the coordinates it contains are valid numbers
20/// (for eg. not `f64::NAN`).
21///
22/// [vector space]: //en.wikipedia.org/wiki/Vector_space
23#[derive(Eq, PartialEq, Clone, Copy, Hash, Default)]
24#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
25pub struct Coord<T: CoordNum = f64> {
26    /// Typically, `x` is the horizontal position, or longitude for geographic coordinates,
27    /// but its interpretation can vary across coordinate systems.
28    pub x: T,
29    /// Typically, `y` is the vertical position, or latitude for geographic coordinates,
30    /// but its interpretation can vary across coordinate systems.
31    pub y: T,
32}
33
34#[deprecated(note = "Renamed to `geo_types::Coord` (or `geo::Coord`)")]
35pub type Coordinate<T = f64> = Coord<T>;
36
37impl<T: CoordNum> From<(T, T)> for Coord<T> {
38    #[inline]
39    fn from(coords: (T, T)) -> Self {
40        coord! {
41            x: coords.0,
42            y: coords.1,
43        }
44    }
45}
46
47impl<T: CoordNum> From<[T; 2]> for Coord<T> {
48    #[inline]
49    fn from(coords: [T; 2]) -> Self {
50        coord! {
51            x: coords[0],
52            y: coords[1],
53        }
54    }
55}
56
57impl<T: CoordNum> From<Point<T>> for Coord<T> {
58    #[inline]
59    fn from(point: Point<T>) -> Self {
60        coord! {
61            x: point.x(),
62            y: point.y(),
63        }
64    }
65}
66
67impl<T: CoordNum> From<Coord<T>> for (T, T) {
68    #[inline]
69    fn from(coord: Coord<T>) -> Self {
70        (coord.x, coord.y)
71    }
72}
73
74impl<T: CoordNum> From<Coord<T>> for [T; 2] {
75    #[inline]
76    fn from(coord: Coord<T>) -> Self {
77        [coord.x, coord.y]
78    }
79}
80
81impl<T: CoordNum> Coord<T> {
82    /// Returns a tuple that contains the x/horizontal & y/vertical component of the coordinate.
83    ///
84    /// # Examples
85    ///
86    /// ```
87    /// use geo_types::coord;
88    ///
89    /// let c = coord! {
90    ///     x: 40.02f64,
91    ///     y: 116.34,
92    /// };
93    /// let (x, y) = c.x_y();
94    ///
95    /// assert_eq!(y, 116.34);
96    /// assert_eq!(x, 40.02f64);
97    /// ```
98    #[inline]
99    pub fn x_y(&self) -> (T, T) {
100        (self.x, self.y)
101    }
102}
103
104use core::ops::{Add, Div, Mul, Neg, Sub};
105
106/// Negate a coordinate.
107///
108/// # Examples
109///
110/// ```
111/// use geo_types::coord;
112///
113/// let p = coord! { x: 1.25, y: 2.5 };
114/// let q = -p;
115///
116/// assert_eq!(q.x, -p.x);
117/// assert_eq!(q.y, -p.y);
118/// ```
119impl<T> Neg for Coord<T>
120where
121    T: CoordNum + Neg<Output = T>,
122{
123    type Output = Self;
124
125    #[inline]
126    fn neg(self) -> Self {
127        coord! {
128            x: -self.x,
129            y: -self.y,
130        }
131    }
132}
133
134/// Add two coordinates.
135///
136/// # Examples
137///
138/// ```
139/// use geo_types::coord;
140///
141/// let p = coord! { x: 1.25, y: 2.5 };
142/// let q = coord! { x: 1.5, y: 2.5 };
143/// let sum = p + q;
144///
145/// assert_eq!(sum.x, 2.75);
146/// assert_eq!(sum.y, 5.0);
147/// ```
148impl<T: CoordNum> Add for Coord<T> {
149    type Output = Self;
150
151    #[inline]
152    fn add(self, rhs: Self) -> Self {
153        coord! {
154            x: self.x + rhs.x,
155            y: self.y + rhs.y,
156        }
157    }
158}
159
160/// Subtract a coordinate from another.
161///
162/// # Examples
163///
164/// ```
165/// use geo_types::coord;
166///
167/// let p = coord! { x: 1.5, y: 2.5 };
168/// let q = coord! { x: 1.25, y: 2.5 };
169/// let diff = p - q;
170///
171/// assert_eq!(diff.x, 0.25);
172/// assert_eq!(diff.y, 0.);
173/// ```
174impl<T: CoordNum> Sub for Coord<T> {
175    type Output = Self;
176
177    #[inline]
178    fn sub(self, rhs: Self) -> Self {
179        coord! {
180            x: self.x - rhs.x,
181            y: self.y - rhs.y,
182        }
183    }
184}
185
186/// Multiply coordinate wise by a scalar.
187///
188/// # Examples
189///
190/// ```
191/// use geo_types::coord;
192///
193/// let p = coord! { x: 1.25, y: 2.5 };
194/// let q = p * 4.;
195///
196/// assert_eq!(q.x, 5.0);
197/// assert_eq!(q.y, 10.0);
198/// ```
199impl<T: CoordNum> Mul<T> for Coord<T> {
200    type Output = Self;
201
202    #[inline]
203    fn mul(self, rhs: T) -> Self {
204        coord! {
205            x: self.x * rhs,
206            y: self.y * rhs,
207        }
208    }
209}
210
211/// Divide coordinate wise by a scalar.
212///
213/// # Examples
214///
215/// ```
216/// use geo_types::coord;
217///
218/// let p = coord! { x: 5., y: 10. };
219/// let q = p / 4.;
220///
221/// assert_eq!(q.x, 1.25);
222/// assert_eq!(q.y, 2.5);
223/// ```
224impl<T: CoordNum> Div<T> for Coord<T> {
225    type Output = Self;
226
227    #[inline]
228    fn div(self, rhs: T) -> Self {
229        coord! {
230            x: self.x / rhs,
231            y: self.y / rhs,
232        }
233    }
234}
235
236use num_traits::Zero;
237/// Create a coordinate at the origin.
238///
239/// # Examples
240///
241/// ```
242/// use geo_types::Coord;
243/// use num_traits::Zero;
244///
245/// let p: Coord = Zero::zero();
246///
247/// assert_eq!(p.x, 0.);
248/// assert_eq!(p.y, 0.);
249/// ```
250impl<T: CoordNum> Coord<T> {
251    #[inline]
252    pub fn zero() -> Self {
253        coord! {
254            x: T::zero(),
255            y: T::zero(),
256        }
257    }
258}
259
260impl<T: CoordNum> Zero for Coord<T> {
261    #[inline]
262    fn zero() -> Self {
263        Self::zero()
264    }
265    #[inline]
266    fn is_zero(&self) -> bool {
267        self.x.is_zero() && self.y.is_zero()
268    }
269}
270
271#[cfg(any(feature = "approx", test))]
272mod approx_integration {
273    use super::*;
274    use approx::{AbsDiffEq, RelativeEq, UlpsEq};
275
276    impl<T> AbsDiffEq for Coord<T>
277    where
278        T: CoordNum + AbsDiffEq<Epsilon = T>,
279    {
280        type Epsilon = T::Epsilon;
281
282        #[inline]
283        fn default_epsilon() -> T::Epsilon {
284            T::default_epsilon()
285        }
286
287        #[inline]
288        fn abs_diff_eq(&self, other: &Self, epsilon: T::Epsilon) -> bool {
289            T::abs_diff_eq(&self.x, &other.x, epsilon) && T::abs_diff_eq(&self.y, &other.y, epsilon)
290        }
291    }
292
293    impl<T> RelativeEq for Coord<T>
294    where
295        T: CoordNum + RelativeEq<Epsilon = T>,
296    {
297        #[inline]
298        fn default_max_relative() -> T::Epsilon {
299            T::default_max_relative()
300        }
301
302        #[inline]
303        fn relative_eq(&self, other: &Self, epsilon: T::Epsilon, max_relative: T::Epsilon) -> bool {
304            T::relative_eq(&self.x, &other.x, epsilon, max_relative)
305                && T::relative_eq(&self.y, &other.y, epsilon, max_relative)
306        }
307    }
308
309    impl<T> UlpsEq for Coord<T>
310    where
311        T: CoordNum + UlpsEq<Epsilon = T>,
312    {
313        #[inline]
314        fn default_max_ulps() -> u32 {
315            T::default_max_ulps()
316        }
317
318        #[inline]
319        fn ulps_eq(&self, other: &Self, epsilon: T::Epsilon, max_ulps: u32) -> bool {
320            T::ulps_eq(&self.x, &other.x, epsilon, max_ulps)
321                && T::ulps_eq(&self.y, &other.y, epsilon, max_ulps)
322        }
323    }
324}
325
326#[cfg(feature = "rstar_0_8")]
327impl<T> ::rstar_0_8::Point for Coord<T>
328where
329    T: ::num_traits::Float + ::rstar_0_8::RTreeNum,
330{
331    type Scalar = T;
332
333    const DIMENSIONS: usize = 2;
334
335    #[inline]
336    fn generate(generator: impl Fn(usize) -> Self::Scalar) -> Self {
337        coord! {
338            x: generator(0),
339            y: generator(1),
340        }
341    }
342
343    #[inline]
344    fn nth(&self, index: usize) -> Self::Scalar {
345        match index {
346            0 => self.x,
347            1 => self.y,
348            _ => unreachable!(),
349        }
350    }
351
352    #[inline]
353    fn nth_mut(&mut self, index: usize) -> &mut Self::Scalar {
354        match index {
355            0 => &mut self.x,
356            1 => &mut self.y,
357            _ => unreachable!(),
358        }
359    }
360}
361
362#[cfg(feature = "rstar_0_9")]
363impl<T> ::rstar_0_9::Point for Coord<T>
364where
365    T: ::num_traits::Float + ::rstar_0_9::RTreeNum,
366{
367    type Scalar = T;
368
369    const DIMENSIONS: usize = 2;
370
371    #[inline]
372    fn generate(mut generator: impl FnMut(usize) -> Self::Scalar) -> Self {
373        coord! {
374            x: generator(0),
375            y: generator(1),
376        }
377    }
378
379    #[inline]
380    fn nth(&self, index: usize) -> Self::Scalar {
381        match index {
382            0 => self.x,
383            1 => self.y,
384            _ => unreachable!(),
385        }
386    }
387
388    #[inline]
389    fn nth_mut(&mut self, index: usize) -> &mut Self::Scalar {
390        match index {
391            0 => &mut self.x,
392            1 => &mut self.y,
393            _ => unreachable!(),
394        }
395    }
396}
397
398#[cfg(feature = "rstar_0_10")]
399impl<T> ::rstar_0_10::Point for Coord<T>
400where
401    T: ::num_traits::Float + ::rstar_0_10::RTreeNum,
402{
403    type Scalar = T;
404
405    const DIMENSIONS: usize = 2;
406
407    #[inline]
408    fn generate(mut generator: impl FnMut(usize) -> Self::Scalar) -> Self {
409        coord! {
410            x: generator(0),
411            y: generator(1),
412        }
413    }
414
415    #[inline]
416    fn nth(&self, index: usize) -> Self::Scalar {
417        match index {
418            0 => self.x,
419            1 => self.y,
420            _ => unreachable!(),
421        }
422    }
423
424    #[inline]
425    fn nth_mut(&mut self, index: usize) -> &mut Self::Scalar {
426        match index {
427            0 => &mut self.x,
428            1 => &mut self.y,
429            _ => unreachable!(),
430        }
431    }
432}
433
434#[cfg(feature = "rstar_0_11")]
435impl<T> ::rstar_0_11::Point for Coord<T>
436where
437    T: ::num_traits::Float + ::rstar_0_11::RTreeNum,
438{
439    type Scalar = T;
440
441    const DIMENSIONS: usize = 2;
442
443    #[inline]
444    fn generate(mut generator: impl FnMut(usize) -> Self::Scalar) -> Self {
445        coord! {
446            x: generator(0),
447            y: generator(1),
448        }
449    }
450
451    #[inline]
452    fn nth(&self, index: usize) -> Self::Scalar {
453        match index {
454            0 => self.x,
455            1 => self.y,
456            _ => unreachable!(),
457        }
458    }
459
460    #[inline]
461    fn nth_mut(&mut self, index: usize) -> &mut Self::Scalar {
462        match index {
463            0 => &mut self.x,
464            1 => &mut self.y,
465            _ => unreachable!(),
466        }
467    }
468}
469
470#[cfg(feature = "rstar_0_12")]
471impl<T> ::rstar_0_12::Point for Coord<T>
472where
473    T: ::num_traits::Float + ::rstar_0_12::RTreeNum,
474{
475    type Scalar = T;
476
477    const DIMENSIONS: usize = 2;
478
479    #[inline]
480    fn generate(mut generator: impl FnMut(usize) -> Self::Scalar) -> Self {
481        coord! {
482            x: generator(0),
483            y: generator(1),
484        }
485    }
486
487    #[inline]
488    fn nth(&self, index: usize) -> Self::Scalar {
489        match index {
490            0 => self.x,
491            1 => self.y,
492            _ => unreachable!(),
493        }
494    }
495
496    #[inline]
497    fn nth_mut(&mut self, index: usize) -> &mut Self::Scalar {
498        match index {
499            0 => &mut self.x,
500            1 => &mut self.y,
501            _ => unreachable!(),
502        }
503    }
504}
505
506impl<T: CoordNum> AsRef<Coord<T>> for Coord<T> {
507    fn as_ref(&self) -> &Coord<T> {
508        self
509    }
510}