gistools/geometry/tools/points/
center.rs

1use s2json::{
2    BBox3D, Feature, Features, Geometry, GetXY, GetZ, MultiLineString, MultiLineString3D,
3    MultiLineString3DGeometry, MultiLineStringGeometry, MultiPoint, MultiPoint3D,
4    MultiPoint3DGeometry, MultiPointGeometry, MultiPolygon, MultiPolygon3D, MultiPolygon3DGeometry,
5    MultiPolygonGeometry, Point, Point3D, Point3DGeometry, PointGeometry, VectorFeature,
6    VectorGeometry, VectorMultiLineString, VectorMultiLineStringGeometry, VectorMultiPoint,
7    VectorMultiPointGeometry, VectorMultiPolygon, VectorMultiPolygonGeometry, VectorPoint,
8    VectorPointGeometry,
9};
10
11/// Get the center of a bounding box from 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/// - [`s2json::VectorLineStringGeometry`]
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 CenterOfPoints {
41    /// Get the center of a bounding box from a collection of [`VectorPoint`]
42    fn center_of_points(&self) -> VectorPoint;
43}
44
45impl<P: GetXY + GetZ> CenterOfPoints for &[P] {
46    fn center_of_points(&self) -> VectorPoint {
47        let mut bbox = BBox3D::default();
48        for p in self.iter() {
49            bbox.extend_from_point(p)
50        }
51        bbox_center(bbox)
52    }
53}
54
55// Feature and below
56
57impl<M, P: Clone + Default, D: Clone + Default> CenterOfPoints for Feature<M, P, D> {
58    fn center_of_points(&self) -> VectorPoint {
59        self.geometry.center_of_points()
60    }
61}
62impl<M: Clone + Default> CenterOfPoints for Geometry<M> {
63    fn center_of_points(&self) -> VectorPoint {
64        match self {
65            Geometry::Point(g) => g.center_of_points(),
66            Geometry::MultiPoint(g) => g.center_of_points(),
67            Geometry::LineString(g) => g.center_of_points(),
68            Geometry::MultiLineString(g) => g.center_of_points(),
69            Geometry::Polygon(g) => g.center_of_points(),
70            Geometry::MultiPolygon(g) => g.center_of_points(),
71            Geometry::Point3D(g) => g.center_of_points(),
72            Geometry::MultiPoint3D(g) => g.center_of_points(),
73            Geometry::LineString3D(g) => g.center_of_points(),
74            Geometry::MultiLineString3D(g) => g.center_of_points(),
75            Geometry::Polygon3D(g) => g.center_of_points(),
76            Geometry::MultiPolygon3D(g) => g.center_of_points(),
77        }
78    }
79}
80impl<M: Clone + Default> CenterOfPoints for PointGeometry<M> {
81    fn center_of_points(&self) -> VectorPoint {
82        self.coordinates.center_of_points()
83    }
84}
85impl<M: Clone + Default> CenterOfPoints for MultiPointGeometry<M> {
86    fn center_of_points(&self) -> VectorPoint {
87        self.coordinates.center_of_points()
88    }
89}
90impl<M: Clone + Default> CenterOfPoints for MultiLineStringGeometry<M> {
91    fn center_of_points(&self) -> VectorPoint {
92        self.coordinates.center_of_points()
93    }
94}
95impl<M: Clone + Default> CenterOfPoints for MultiPolygonGeometry<M> {
96    fn center_of_points(&self) -> VectorPoint {
97        self.coordinates.center_of_points()
98    }
99}
100impl<M: Clone + Default> CenterOfPoints for Point3DGeometry<M> {
101    fn center_of_points(&self) -> VectorPoint {
102        self.coordinates.center_of_points()
103    }
104}
105impl<M: Clone + Default> CenterOfPoints for MultiPoint3DGeometry<M> {
106    fn center_of_points(&self) -> VectorPoint {
107        self.coordinates.center_of_points()
108    }
109}
110impl<M: Clone + Default> CenterOfPoints for MultiLineString3DGeometry<M> {
111    fn center_of_points(&self) -> VectorPoint {
112        self.coordinates.center_of_points()
113    }
114}
115impl<M: Clone + Default> CenterOfPoints for MultiPolygon3DGeometry<M> {
116    fn center_of_points(&self) -> VectorPoint {
117        self.coordinates.center_of_points()
118    }
119}
120
121// Feature Point types
122
123impl CenterOfPoints for Point {
124    fn center_of_points(&self) -> VectorPoint {
125        VectorPoint::new_xy(self.0, self.1, None)
126    }
127}
128impl CenterOfPoints for MultiPoint {
129    fn center_of_points(&self) -> VectorPoint {
130        let mut bbox = BBox3D::default();
131        for p in self {
132            bbox.extend_from_point(&VectorPoint::<()>::from(p))
133        }
134        bbox_center(bbox)
135    }
136}
137impl CenterOfPoints for MultiLineString {
138    fn center_of_points(&self) -> VectorPoint {
139        let mut bbox = BBox3D::default();
140        for line in self {
141            for p in line {
142                bbox.extend_from_point(&VectorPoint::<()>::from(p))
143            }
144        }
145        bbox_center(bbox)
146    }
147}
148impl CenterOfPoints for MultiPolygon {
149    fn center_of_points(&self) -> VectorPoint {
150        let mut bbox = BBox3D::default();
151        for poly in self {
152            for line in poly {
153                for p in line {
154                    bbox.extend_from_point(&VectorPoint::<()>::from(p))
155                }
156            }
157        }
158        bbox_center(bbox)
159    }
160}
161impl CenterOfPoints for Point3D {
162    fn center_of_points(&self) -> VectorPoint {
163        VectorPoint::new_xyz(self.0, self.1, self.2, None)
164    }
165}
166impl CenterOfPoints for MultiPoint3D {
167    fn center_of_points(&self) -> VectorPoint {
168        let mut bbox = BBox3D::default();
169        for p in self {
170            bbox.extend_from_point(&VectorPoint::<()>::from(p))
171        }
172        bbox_center(bbox)
173    }
174}
175impl CenterOfPoints for MultiLineString3D {
176    fn center_of_points(&self) -> VectorPoint {
177        let mut bbox = BBox3D::default();
178        for line in self {
179            for p in line {
180                bbox.extend_from_point(&VectorPoint::<()>::from(p))
181            }
182        }
183        bbox_center(bbox)
184    }
185}
186impl CenterOfPoints for MultiPolygon3D {
187    fn center_of_points(&self) -> VectorPoint {
188        let mut bbox = BBox3D::default();
189        for poly in self {
190            for line in poly {
191                for p in line {
192                    bbox.extend_from_point(&VectorPoint::<()>::from(p))
193                }
194            }
195        }
196        bbox_center(bbox)
197    }
198}
199
200// Vector Feature and below
201
202impl<M, P: Clone + Default, D: Clone + Default> CenterOfPoints for VectorFeature<M, P, D> {
203    fn center_of_points(&self) -> VectorPoint {
204        self.geometry.center_of_points()
205    }
206}
207impl<M: Clone + Default> CenterOfPoints for VectorGeometry<M> {
208    fn center_of_points(&self) -> VectorPoint {
209        match self {
210            VectorGeometry::Point(g) => g.center_of_points(),
211            VectorGeometry::MultiPoint(g) => g.center_of_points(),
212            VectorGeometry::LineString(g) => g.center_of_points(),
213            VectorGeometry::MultiLineString(g) => g.center_of_points(),
214            VectorGeometry::Polygon(g) => g.center_of_points(),
215            VectorGeometry::MultiPolygon(g) => g.center_of_points(),
216        }
217    }
218}
219impl<M: Clone + Default> CenterOfPoints for VectorPointGeometry<M> {
220    fn center_of_points(&self) -> VectorPoint {
221        self.coordinates.center_of_points()
222    }
223}
224impl<M: Clone + Default> CenterOfPoints for VectorMultiPointGeometry<M> {
225    fn center_of_points(&self) -> VectorPoint {
226        self.coordinates.center_of_points()
227    }
228}
229impl<M: Clone + Default> CenterOfPoints for VectorMultiLineStringGeometry<M> {
230    fn center_of_points(&self) -> VectorPoint {
231        self.coordinates.center_of_points()
232    }
233}
234impl<M: Clone + Default> CenterOfPoints for VectorMultiPolygonGeometry<M> {
235    fn center_of_points(&self) -> VectorPoint {
236        self.coordinates.center_of_points()
237    }
238}
239
240// Vector Point Types
241
242impl<M: Clone + Default> CenterOfPoints for VectorPoint<M> {
243    fn center_of_points(&self) -> VectorPoint {
244        VectorPoint::new(self.x, self.y, self.z, None)
245    }
246}
247impl<M: Clone + Default> CenterOfPoints for VectorMultiPoint<M> {
248    fn center_of_points(&self) -> VectorPoint {
249        let bbox = BBox3D::from_linestring(self);
250        bbox_center(bbox)
251    }
252}
253impl<M: Clone + Default> CenterOfPoints for VectorMultiLineString<M> {
254    fn center_of_points(&self) -> VectorPoint {
255        let bbox = BBox3D::from_multi_linestring(self);
256        bbox_center(bbox)
257    }
258}
259impl<M: Clone + Default> CenterOfPoints for VectorMultiPolygon<M> {
260    fn center_of_points(&self) -> VectorPoint {
261        let bbox = BBox3D::from_multi_polygon(self);
262        bbox_center(bbox)
263    }
264}
265
266fn bbox_center(bbox: BBox3D) -> VectorPoint {
267    if bbox.near != f64::MAX && bbox.far != f64::MIN {
268        VectorPoint::new_xyz(
269            (bbox.right + bbox.left) / 2.,
270            (bbox.top + bbox.bottom) / 2.,
271            (bbox.far + bbox.near) / 2.,
272            None,
273        )
274    } else {
275        VectorPoint::new_xy((bbox.right + bbox.left) / 2., (bbox.top + bbox.bottom) / 2., None)
276    }
277}
278
279// Features
280
281impl<M, P: Clone + Default, D: Clone + Default> CenterOfPoints for Features<M, P, D> {
282    fn center_of_points(&self) -> VectorPoint {
283        match self {
284            Features::Feature(f) => f.center_of_points(),
285            Features::VectorFeature(f) => f.center_of_points(),
286        }
287    }
288}