use geometry_model::{
Box, Linestring, MultiLinestring, MultiPoint, MultiPolygon, Point, Polygon, Ring, Segment,
};
#[inline]
#[must_use]
pub fn num_geometries<G: NumGeometries>(g: &G) -> usize {
g.num_geometries()
}
#[doc(hidden)]
pub trait NumGeometries {
fn num_geometries(&self) -> usize;
}
impl<T, const D: usize, Cs> NumGeometries for Point<T, D, Cs>
where
T: geometry_coords::CoordinateScalar,
Cs: geometry_cs::CoordinateSystem,
{
fn num_geometries(&self) -> usize {
1
}
}
impl<P: geometry_trait::Point> NumGeometries for Linestring<P> {
fn num_geometries(&self) -> usize {
1
}
}
impl<P: geometry_trait::Point, const CW: bool, const CL: bool> NumGeometries for Ring<P, CW, CL> {
fn num_geometries(&self) -> usize {
1
}
}
impl<P: geometry_trait::Point, const CW: bool, const CL: bool> NumGeometries
for Polygon<P, CW, CL>
{
fn num_geometries(&self) -> usize {
1
}
}
impl<P: geometry_trait::Point> NumGeometries for Segment<P> {
fn num_geometries(&self) -> usize {
1
}
}
impl<P: geometry_trait::Point> NumGeometries for Box<P> {
fn num_geometries(&self) -> usize {
1
}
}
impl<P: geometry_trait::Point> NumGeometries for MultiPoint<P> {
fn num_geometries(&self) -> usize {
self.0.len()
}
}
impl<L: geometry_trait::Linestring> NumGeometries for MultiLinestring<L> {
fn num_geometries(&self) -> usize {
self.0.len()
}
}
impl<Pg: geometry_trait::Polygon> NumGeometries for MultiPolygon<Pg> {
fn num_geometries(&self) -> usize {
self.0.len()
}
}
#[cfg(test)]
mod tests {
use super::num_geometries;
use geometry_cs::Cartesian;
use geometry_model::{
Linestring, MultiPoint, MultiPolygon, Point2D, Polygon, linestring, polygon,
};
type Pt = Point2D<f64, Cartesian>;
type Ls = Linestring<Pt>;
type Poly = Polygon<Pt>;
#[test]
fn point_is_one() {
assert_eq!(num_geometries(&Pt::new(0.0, 0.0)), 1);
}
#[test]
fn linestring_is_one() {
let ls: Ls = linestring![(0.0, 0.0), (1.0, 1.0)];
assert_eq!(num_geometries(&ls), 1);
}
#[test]
fn polygon_with_holes_is_one() {
let pg: Poly = polygon![
[(0.0, 0.0), (5.0, 0.0), (5.0, 5.0), (0.0, 5.0), (0.0, 0.0)],
[(1.0, 1.0), (2.0, 1.0), (2.0, 2.0), (1.0, 2.0), (1.0, 1.0)],
];
assert_eq!(num_geometries(&pg), 1);
}
#[test]
fn multi_point_returns_member_count() {
let mp = MultiPoint(vec![
Pt::new(0.0, 0.0),
Pt::new(1.0, 1.0),
Pt::new(2.0, 2.0),
]);
assert_eq!(num_geometries(&mp), 3);
}
#[test]
fn other_single_kinds_are_one() {
use geometry_model::{Box, Ring, Segment};
let ring: Ring<Pt> = Ring::from_vec(vec![
Pt::new(0.0, 0.0),
Pt::new(1.0, 0.0),
Pt::new(0.0, 0.0),
]);
assert_eq!(num_geometries(&ring), 1);
assert_eq!(
num_geometries(&Segment::new(Pt::new(0.0, 0.0), Pt::new(1.0, 1.0))),
1
);
assert_eq!(
num_geometries(&Box::from_corners(Pt::new(0.0, 0.0), Pt::new(1.0, 1.0))),
1
);
}
#[test]
fn multi_linestring_returns_member_count() {
use geometry_model::MultiLinestring;
let mls: MultiLinestring<Ls> = MultiLinestring(vec![
linestring![(0.0, 0.0), (1.0, 1.0)],
linestring![(2.0, 2.0), (3.0, 3.0)],
linestring![(4.0, 4.0), (5.0, 5.0)],
]);
assert_eq!(num_geometries(&mls), 3);
}
#[test]
fn multi_polygon_returns_member_count() {
let mpg: MultiPolygon<Poly> = MultiPolygon(vec![
polygon![[(0.0, 0.0), (1.0, 0.0), (1.0, 1.0), (0.0, 0.0)]],
polygon![[(2.0, 2.0), (3.0, 2.0), (3.0, 3.0), (2.0, 2.0)]],
]);
assert_eq!(num_geometries(&mpg), 2);
}
}