shapefile/record/
traits.rs

1use super::{Point, PointM, PointZ};
2use crate::writer::{f64_max, f64_min};
3
4/// Trait to access the x, and y values of a point
5///
6/// # Examples
7///
8/// ```
9/// use shapefile::record::traits::HasXY;
10/// use shapefile::{Point, NO_DATA, PointZ};
11/// fn mean_x_y<PointType: HasXY>(points: &[PointType]) -> (f64, f64) {
12///     let (sum_x, sum_y) = points.iter()
13///                                .fold((0.0, 0.0),
14///                                       |acc, point| (acc.0 + point.x(), acc.1 + point.y()));
15///
16///     (sum_x / points.len() as f64, sum_y / points.len() as f64)
17/// }
18/// let points = vec![PointZ::new(1.0, 2.0, 3.0, NO_DATA), PointZ::new(1.0, 2.0, 5.0, NO_DATA)];
19/// assert_eq!(mean_x_y(&points), (1.0, 2.0));
20///
21/// ```
22pub trait HasXY {
23    /// Returns the value of the x dimension
24    fn x(&self) -> f64;
25    /// Returns the value of the y dimension
26    fn y(&self) -> f64;
27}
28
29/// Trait to access the m value of a point
30pub trait HasM {
31    fn m(&self) -> f64;
32}
33
34/// Trait to access the z value of a point
35pub trait HasZ {
36    fn z(&self) -> f64;
37}
38
39pub(crate) trait HasMutXY {
40    fn x_mut(&mut self) -> &mut f64;
41    fn y_mut(&mut self) -> &mut f64;
42}
43
44pub(crate) trait HasMutM {
45    fn m_mut(&mut self) -> &mut f64;
46}
47
48pub(crate) trait HasMutZ {
49    fn z_mut(&mut self) -> &mut f64;
50}
51
52macro_rules! impl_has_xy_for {
53    ($PointType:ty) => {
54        impl HasXY for $PointType {
55            fn x(&self) -> f64 {
56                self.x
57            }
58            fn y(&self) -> f64 {
59                self.y
60            }
61        }
62    };
63}
64
65macro_rules! impl_has_mut_xy_for {
66    ($PointType:ty) => {
67        impl HasMutXY for $PointType {
68            fn x_mut(&mut self) -> &mut f64 {
69                &mut self.x
70            }
71            fn y_mut(&mut self) -> &mut f64 {
72                &mut self.y
73            }
74        }
75    };
76}
77
78macro_rules! impl_has_m_for {
79    ($PointType:ty) => {
80        impl HasM for $PointType {
81            fn m(&self) -> f64 {
82                self.m
83            }
84        }
85
86        impl HasMutM for $PointType {
87            fn m_mut(&mut self) -> &mut f64 {
88                &mut self.m
89            }
90        }
91    };
92}
93
94impl_has_xy_for!(Point);
95impl_has_xy_for!(PointM);
96impl_has_xy_for!(PointZ);
97
98impl_has_mut_xy_for!(Point);
99impl_has_mut_xy_for!(PointM);
100impl_has_mut_xy_for!(PointZ);
101
102impl_has_m_for!(PointM);
103impl_has_m_for!(PointZ);
104
105impl HasZ for PointZ {
106    fn z(&self) -> f64 {
107        self.z
108    }
109}
110
111impl HasMutZ for PointZ {
112    fn z_mut(&mut self) -> &mut f64 {
113        &mut self.z
114    }
115}
116
117pub trait ShrinkablePoint {
118    fn shrink(&mut self, other: &Self);
119}
120
121pub trait GrowablePoint {
122    fn grow(&mut self, other: &Self);
123}
124
125impl ShrinkablePoint for Point {
126    fn shrink(&mut self, other: &Self) {
127        self.x = f64_min(self.x, other.x);
128        self.y = f64_min(self.y, other.y);
129    }
130}
131
132impl ShrinkablePoint for PointM {
133    fn shrink(&mut self, other: &Self) {
134        self.x = f64_min(self.x, other.x);
135        self.y = f64_min(self.y, other.y);
136        self.m = f64_min(self.m, other.m);
137    }
138}
139
140impl ShrinkablePoint for PointZ {
141    fn shrink(&mut self, other: &Self) {
142        self.x = f64_min(self.x, other.x);
143        self.y = f64_min(self.y, other.y);
144        self.z = f64_min(self.z, other.z);
145        self.m = f64_min(self.m, other.m);
146    }
147}
148
149impl GrowablePoint for Point {
150    fn grow(&mut self, other: &Self) {
151        self.x = f64_max(self.x, other.x);
152        self.y = f64_max(self.y, other.y);
153    }
154}
155
156impl GrowablePoint for PointM {
157    fn grow(&mut self, other: &Self) {
158        self.x = f64_max(self.x, other.x);
159        self.y = f64_max(self.y, other.y);
160        self.m = f64_max(self.m, other.m);
161    }
162}
163
164impl GrowablePoint for PointZ {
165    fn grow(&mut self, other: &Self) {
166        self.x = f64_max(self.x, other.x);
167        self.y = f64_max(self.y, other.y);
168        self.z = f64_max(self.z, other.z);
169        self.m = f64_max(self.m, other.m);
170    }
171}