1use geometry_model::{
9 Box, Linestring, MultiLinestring, MultiPoint, MultiPolygon, Point, Polygon, Ring, Segment,
10};
11
12#[inline]
21#[must_use]
22pub fn num_geometries<G: NumGeometries>(g: &G) -> usize {
23 g.num_geometries()
24}
25
26#[doc(hidden)]
30pub trait NumGeometries {
31 fn num_geometries(&self) -> usize;
33}
34
35impl<T, const D: usize, Cs> NumGeometries for Point<T, D, Cs>
37where
38 T: geometry_coords::CoordinateScalar,
39 Cs: geometry_cs::CoordinateSystem,
40{
41 fn num_geometries(&self) -> usize {
42 1
43 }
44}
45
46impl<P: geometry_trait::Point> NumGeometries for Linestring<P> {
47 fn num_geometries(&self) -> usize {
48 1
49 }
50}
51
52impl<P: geometry_trait::Point, const CW: bool, const CL: bool> NumGeometries for Ring<P, CW, CL> {
53 fn num_geometries(&self) -> usize {
54 1
55 }
56}
57
58impl<P: geometry_trait::Point, const CW: bool, const CL: bool> NumGeometries
59 for Polygon<P, CW, CL>
60{
61 fn num_geometries(&self) -> usize {
62 1
63 }
64}
65
66impl<P: geometry_trait::Point> NumGeometries for Segment<P> {
67 fn num_geometries(&self) -> usize {
68 1
69 }
70}
71
72impl<P: geometry_trait::Point> NumGeometries for Box<P> {
73 fn num_geometries(&self) -> usize {
74 1
75 }
76}
77
78impl<P: geometry_trait::Point> NumGeometries for MultiPoint<P> {
80 fn num_geometries(&self) -> usize {
81 self.0.len()
82 }
83}
84
85impl<L: geometry_trait::Linestring> NumGeometries for MultiLinestring<L> {
86 fn num_geometries(&self) -> usize {
87 self.0.len()
88 }
89}
90
91impl<Pg: geometry_trait::Polygon> NumGeometries for MultiPolygon<Pg> {
92 fn num_geometries(&self) -> usize {
93 self.0.len()
94 }
95}
96
97#[cfg(test)]
98mod tests {
99 use super::num_geometries;
103 use geometry_cs::Cartesian;
104 use geometry_model::{
105 Linestring, MultiPoint, MultiPolygon, Point2D, Polygon, linestring, polygon,
106 };
107
108 type Pt = Point2D<f64, Cartesian>;
109 type Ls = Linestring<Pt>;
110 type Poly = Polygon<Pt>;
111
112 #[test]
114 fn point_is_one() {
115 assert_eq!(num_geometries(&Pt::new(0.0, 0.0)), 1);
116 }
117
118 #[test]
120 fn linestring_is_one() {
121 let ls: Ls = linestring![(0.0, 0.0), (1.0, 1.0)];
122 assert_eq!(num_geometries(&ls), 1);
123 }
124
125 #[test]
127 fn polygon_with_holes_is_one() {
128 let pg: Poly = polygon![
129 [(0.0, 0.0), (5.0, 0.0), (5.0, 5.0), (0.0, 5.0), (0.0, 0.0)],
130 [(1.0, 1.0), (2.0, 1.0), (2.0, 2.0), (1.0, 2.0), (1.0, 1.0)],
131 ];
132 assert_eq!(num_geometries(&pg), 1);
133 }
134
135 #[test]
137 fn multi_point_returns_member_count() {
138 let mp = MultiPoint(vec![
139 Pt::new(0.0, 0.0),
140 Pt::new(1.0, 1.0),
141 Pt::new(2.0, 2.0),
142 ]);
143 assert_eq!(num_geometries(&mp), 3);
144 }
145
146 #[test]
149 fn other_single_kinds_are_one() {
150 use geometry_model::{Box, Ring, Segment};
151 let ring: Ring<Pt> = Ring::from_vec(vec![
152 Pt::new(0.0, 0.0),
153 Pt::new(1.0, 0.0),
154 Pt::new(0.0, 0.0),
155 ]);
156 assert_eq!(num_geometries(&ring), 1);
157 assert_eq!(
158 num_geometries(&Segment::new(Pt::new(0.0, 0.0), Pt::new(1.0, 1.0))),
159 1
160 );
161 assert_eq!(
162 num_geometries(&Box::from_corners(Pt::new(0.0, 0.0), Pt::new(1.0, 1.0))),
163 1
164 );
165 }
166
167 #[test]
169 fn multi_linestring_returns_member_count() {
170 use geometry_model::MultiLinestring;
171 let mls: MultiLinestring<Ls> = MultiLinestring(vec![
172 linestring![(0.0, 0.0), (1.0, 1.0)],
173 linestring![(2.0, 2.0), (3.0, 3.0)],
174 linestring![(4.0, 4.0), (5.0, 5.0)],
175 ]);
176 assert_eq!(num_geometries(&mls), 3);
177 }
178
179 #[test]
181 fn multi_polygon_returns_member_count() {
182 let mpg: MultiPolygon<Poly> = MultiPolygon(vec![
183 polygon![[(0.0, 0.0), (1.0, 0.0), (1.0, 1.0), (0.0, 0.0)]],
184 polygon![[(2.0, 2.0), (3.0, 2.0), (3.0, 3.0), (2.0, 2.0)]],
185 ]);
186 assert_eq!(num_geometries(&mpg), 2);
187 }
188}