gistools/geometry/tools/points/
average.rs

1use s2json::{
2    Feature, Features, Geometry, GetXY, GetZ, MultiLineString, MultiLineString3D,
3    MultiLineString3DGeometry, MultiLineStringGeometry, MultiPoint, MultiPoint3D,
4    MultiPoint3DGeometry, MultiPointGeometry, MultiPolygon, MultiPolygon3D, MultiPolygon3DGeometry,
5    MultiPolygonGeometry, NewXY, NewXYZ, Point, Point3D, Point3DGeometry, PointGeometry,
6    VectorFeature, VectorGeometry, VectorMultiLineString, VectorMultiLineStringGeometry,
7    VectorMultiPoint, VectorMultiPointGeometry, VectorMultiPolygon, VectorMultiPolygonGeometry,
8    VectorPoint, VectorPointGeometry,
9};
10
11/// Get the average of a collection of [`VectorPoint`].
12///
13/// This trait is implemented for:
14/// - [`Feature`]
15/// - [`Geometry`]
16/// - [`PointGeometry`]
17/// - [`MultiPointGeometry`]
18/// - [`s2json::LineStringGeometry`]
19/// - [`MultiLineStringGeometry`]
20/// - [`MultiPolygonGeometry`]
21/// - [`Point3DGeometry`]
22/// - [`MultiPoint3DGeometry`]
23/// - [`s2json::LineString3DGeometry`]
24/// - [`MultiLineString3DGeometry`]
25/// - [`MultiPolygon3DGeometry`]
26/// - [`VectorFeature`]
27/// - [`VectorGeometry`]
28/// - [`VectorPointGeometry`]
29/// - [`VectorMultiPointGeometry`]
30/// - [`VectorPoint`]
31/// - [`VectorMultiLineStringGeometry`]
32/// - [`VectorMultiPolygonGeometry`]
33/// - [`VectorMultiPoint`]
34/// - [`VectorMultiLineString`]
35/// - [`VectorMultiPolygon`]
36/// - [`Features`]
37/// - `&[P]` where P implements [`GetXY`] and [`GetZ`]
38///
39/// And all specific geometries of the above enums
40pub trait AverageOfPoints<Q: NewXY> {
41    /// Get the average of a collection of [`VectorPoint`]
42    fn average_of_points(&self) -> Q;
43}
44
45impl<Q: NewXY + NewXYZ, P: GetXY + GetZ> AverageOfPoints<Q> for &[P] {
46    fn average_of_points(&self) -> Q {
47        let mut x = 0.;
48        let mut y = 0.;
49        let mut z = 0.;
50        for p in self.iter() {
51            x += p.x();
52            y += p.y();
53            z += p.z().unwrap_or(0.);
54        }
55        let len = self.len() as f64;
56        x /= len;
57        y /= len;
58        z /= len;
59        Q::new_xyz(x, y, z)
60    }
61}
62
63// Feature and below
64
65impl<M, P: Clone + Default, D: Clone + Default, Q: NewXY + NewXYZ> AverageOfPoints<Q>
66    for Feature<M, P, D>
67{
68    fn average_of_points(&self) -> Q {
69        self.geometry.average_of_points()
70    }
71}
72impl<M: Clone + Default, Q: NewXY + NewXYZ> AverageOfPoints<Q> for Geometry<M> {
73    fn average_of_points(&self) -> Q {
74        match self {
75            Geometry::Point(g) => g.average_of_points(),
76            Geometry::MultiPoint(g) => g.average_of_points(),
77            Geometry::LineString(g) => g.average_of_points(),
78            Geometry::MultiLineString(g) => g.average_of_points(),
79            Geometry::Polygon(g) => g.average_of_points(),
80            Geometry::MultiPolygon(g) => g.average_of_points(),
81            Geometry::Point3D(g) => g.average_of_points(),
82            Geometry::MultiPoint3D(g) => g.average_of_points(),
83            Geometry::LineString3D(g) => g.average_of_points(),
84            Geometry::MultiLineString3D(g) => g.average_of_points(),
85            Geometry::Polygon3D(g) => g.average_of_points(),
86            Geometry::MultiPolygon3D(g) => g.average_of_points(),
87        }
88    }
89}
90impl<M: Clone + Default, Q: NewXY> AverageOfPoints<Q> for PointGeometry<M> {
91    fn average_of_points(&self) -> Q {
92        self.coordinates.average_of_points()
93    }
94}
95impl<M: Clone + Default, Q: NewXY> AverageOfPoints<Q> for MultiPointGeometry<M> {
96    fn average_of_points(&self) -> Q {
97        self.coordinates.average_of_points()
98    }
99}
100impl<M: Clone + Default, Q: NewXY> AverageOfPoints<Q> for MultiLineStringGeometry<M> {
101    fn average_of_points(&self) -> Q {
102        self.coordinates.average_of_points()
103    }
104}
105impl<M: Clone + Default, Q: NewXY> AverageOfPoints<Q> for MultiPolygonGeometry<M> {
106    fn average_of_points(&self) -> Q {
107        self.coordinates.average_of_points()
108    }
109}
110impl<M: Clone + Default, Q: NewXY + NewXYZ> AverageOfPoints<Q> for Point3DGeometry<M> {
111    fn average_of_points(&self) -> Q {
112        self.coordinates.average_of_points()
113    }
114}
115impl<M: Clone + Default, Q: NewXY + NewXYZ> AverageOfPoints<Q> for MultiPoint3DGeometry<M> {
116    fn average_of_points(&self) -> Q {
117        self.coordinates.average_of_points()
118    }
119}
120impl<M: Clone + Default, Q: NewXY + NewXYZ> AverageOfPoints<Q> for MultiLineString3DGeometry<M> {
121    fn average_of_points(&self) -> Q {
122        self.coordinates.average_of_points()
123    }
124}
125impl<M: Clone + Default, Q: NewXY + NewXYZ> AverageOfPoints<Q> for MultiPolygon3DGeometry<M> {
126    fn average_of_points(&self) -> Q {
127        self.coordinates.average_of_points()
128    }
129}
130
131// Feature Point types
132
133impl<Q: NewXY> AverageOfPoints<Q> for Point {
134    fn average_of_points(&self) -> Q {
135        Q::new_xy(self.0, self.1)
136    }
137}
138impl<Q: NewXY> AverageOfPoints<Q> for MultiPoint {
139    fn average_of_points(&self) -> Q {
140        let mut x = 0.;
141        let mut y = 0.;
142        for p in self {
143            x += p.0;
144            y += p.1;
145        }
146        let len = self.len() as f64;
147        x /= len;
148        y /= len;
149        Q::new_xy(x, y)
150    }
151}
152impl<Q: NewXY> AverageOfPoints<Q> for MultiLineString {
153    fn average_of_points(&self) -> Q {
154        let mut x = 0.;
155        let mut y = 0.;
156        let mut total = 0;
157        for line in self {
158            for p in line {
159                x += p.0;
160                y += p.1;
161            }
162            total += line.len();
163        }
164        let len = total as f64;
165        x /= len;
166        y /= len;
167        Q::new_xy(x, y)
168    }
169}
170impl<Q: NewXY> AverageOfPoints<Q> for MultiPolygon {
171    fn average_of_points(&self) -> Q {
172        let mut x = 0.;
173        let mut y = 0.;
174        let mut total = 0;
175        for poly in self {
176            for line in poly {
177                for p in line {
178                    x += p.0;
179                    y += p.1;
180                }
181                total += line.len();
182            }
183        }
184        let len = total as f64;
185        x /= len;
186        y /= len;
187        Q::new_xy(x, y)
188    }
189}
190impl<Q: NewXY + NewXYZ> AverageOfPoints<Q> for Point3D {
191    fn average_of_points(&self) -> Q {
192        Q::new_xyz(self.0, self.1, self.2)
193    }
194}
195impl<Q: NewXY + NewXYZ> AverageOfPoints<Q> for MultiPoint3D {
196    fn average_of_points(&self) -> Q {
197        let mut x = 0.;
198        let mut y = 0.;
199        let mut z = 0.;
200        for p in self {
201            x += p.0;
202            y += p.1;
203            z += p.2;
204        }
205        let len = self.len() as f64;
206        x /= len;
207        y /= len;
208        z /= len;
209        Q::new_xyz(x, y, z)
210    }
211}
212impl<Q: NewXY + NewXYZ> AverageOfPoints<Q> for MultiLineString3D {
213    fn average_of_points(&self) -> Q {
214        let mut x = 0.;
215        let mut y = 0.;
216        let mut z = 0.;
217        let mut total = 0;
218        for line in self {
219            for p in line {
220                x += p.0;
221                y += p.1;
222                z += p.2;
223            }
224            total += line.len();
225        }
226        let len = total as f64;
227        x /= len;
228        y /= len;
229        z /= len;
230        Q::new_xyz(x, y, z)
231    }
232}
233impl<Q: NewXY + NewXYZ> AverageOfPoints<Q> for MultiPolygon3D {
234    fn average_of_points(&self) -> Q {
235        let mut x = 0.;
236        let mut y = 0.;
237        let mut z = 0.;
238        let mut total = 0;
239        for poly in self {
240            for line in poly {
241                for p in line {
242                    x += p.0;
243                    y += p.1;
244                    z += p.2;
245                }
246                total += line.len();
247            }
248        }
249        let len = total as f64;
250        x /= len;
251        y /= len;
252        z /= len;
253        Q::new_xyz(x, y, z)
254    }
255}
256
257// Vector Feature and below
258
259impl<M, P: Clone + Default, D: Clone + Default, Q: NewXY + NewXYZ> AverageOfPoints<Q>
260    for VectorFeature<M, P, D>
261{
262    fn average_of_points(&self) -> Q {
263        self.geometry.average_of_points()
264    }
265}
266impl<M: Clone + Default, Q: NewXY + NewXYZ> AverageOfPoints<Q> for VectorGeometry<M> {
267    fn average_of_points(&self) -> Q {
268        match self {
269            VectorGeometry::Point(g) => g.average_of_points(),
270            VectorGeometry::MultiPoint(g) => g.average_of_points(),
271            VectorGeometry::LineString(g) => g.average_of_points(),
272            VectorGeometry::MultiLineString(g) => g.average_of_points(),
273            VectorGeometry::Polygon(g) => g.average_of_points(),
274            VectorGeometry::MultiPolygon(g) => g.average_of_points(),
275        }
276    }
277}
278impl<M: Clone + Default, Q: NewXY + NewXYZ> AverageOfPoints<Q> for VectorPointGeometry<M> {
279    fn average_of_points(&self) -> Q {
280        self.coordinates.average_of_points()
281    }
282}
283impl<M: Clone + Default, Q: NewXY + NewXYZ> AverageOfPoints<Q> for VectorMultiPointGeometry<M> {
284    fn average_of_points(&self) -> Q {
285        self.coordinates.average_of_points()
286    }
287}
288impl<M: Clone + Default, Q: NewXY + NewXYZ> AverageOfPoints<Q>
289    for VectorMultiLineStringGeometry<M>
290{
291    fn average_of_points(&self) -> Q {
292        self.coordinates.average_of_points()
293    }
294}
295impl<M: Clone + Default, Q: NewXY + NewXYZ> AverageOfPoints<Q> for VectorMultiPolygonGeometry<M> {
296    fn average_of_points(&self) -> Q {
297        self.coordinates.average_of_points()
298    }
299}
300
301// Vector Point Types
302
303impl<M: Clone + Default, Q: NewXY + NewXYZ> AverageOfPoints<Q> for VectorPoint<M> {
304    fn average_of_points(&self) -> Q {
305        Q::new_xyz(self.x, self.y, self.z.unwrap_or_default())
306    }
307}
308impl<M: Clone + Default, Q: NewXY + NewXYZ> AverageOfPoints<Q> for VectorMultiPoint<M> {
309    fn average_of_points(&self) -> Q {
310        let mut x = 0.;
311        let mut y = 0.;
312        let mut z = 0.;
313        for p in self {
314            x += p.x;
315            y += p.y;
316            z += p.z.unwrap_or_default();
317        }
318        let len = self.len() as f64;
319        x /= len;
320        y /= len;
321        z /= len;
322        Q::new_xyz(x, y, z)
323    }
324}
325impl<M: Clone + Default, Q: NewXY + NewXYZ> AverageOfPoints<Q> for VectorMultiLineString<M> {
326    fn average_of_points(&self) -> Q {
327        let mut x = 0.;
328        let mut y = 0.;
329        let mut z = 0.;
330        let mut total = 0;
331
332        for line in self {
333            for point in line {
334                x += point.x;
335                y += point.y;
336                z += point.z.unwrap_or_default();
337            }
338            total += line.len();
339        }
340
341        let len = total as f64;
342        x /= len;
343        y /= len;
344        z /= len;
345        Q::new_xyz(x, y, z)
346    }
347}
348impl<M: Clone + Default, Q: NewXY + NewXYZ> AverageOfPoints<Q> for VectorMultiPolygon<M> {
349    fn average_of_points(&self) -> Q {
350        let mut x = 0.;
351        let mut y = 0.;
352        let mut z = 0.;
353        let mut total = 0;
354
355        for poly in self {
356            for line in poly {
357                for point in line {
358                    x += point.x;
359                    y += point.y;
360                    z += point.z.unwrap_or_default();
361                }
362                total += line.len();
363            }
364        }
365
366        let len = total as f64;
367        x /= len;
368        y /= len;
369        z /= len;
370        Q::new_xyz(x, y, z)
371    }
372}
373
374// Features
375
376impl<M, P: Clone + Default, D: Clone + Default, Q: NewXY + NewXYZ> AverageOfPoints<Q>
377    for Features<M, P, D>
378{
379    fn average_of_points(&self) -> Q {
380        match self {
381            Features::Feature(f) => f.average_of_points(),
382            Features::VectorFeature(f) => f.average_of_points(),
383        }
384    }
385}