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