Skip to main content

geometry_algorithm/
is_empty.rs

1//! `is_empty(&g)` — true iff `num_points(g) == 0`.
2//!
3//! Mirrors `boost::geometry::is_empty` from
4//! `boost/geometry/algorithms/is_empty.hpp`. Boost's contract is
5//! exactly `num_points(g) == 0`
6//! (`boost/geometry/test/algorithms/is_empty.cpp:74`:
7//! `BOOST_CHECK_EQUAL(detected, bg::num_points(geometry) == 0)`), so
8//! this leans on [`crate::num_points::num_points`] rather
9//! than re-walking the kind hierarchy. Singletons (`Point` / `Box` /
10//! `Segment`) always return `false` because they carry an implicit
11//! point set.
12
13use crate::num_points::{NumPointsStrategy, NumPointsStrategyForKind, num_points};
14use geometry_trait::Geometry;
15
16/// True iff `g` has no points.
17///
18/// Mirrors `boost::geometry::is_empty(g)` from
19/// `boost/geometry/algorithms/is_empty.hpp`.
20#[inline]
21#[must_use]
22pub fn is_empty<G>(g: &G) -> bool
23where
24    G: Geometry,
25    G::Kind: NumPointsStrategyForKind,
26    <G::Kind as NumPointsStrategyForKind>::S: NumPointsStrategy<G>,
27{
28    num_points(g) == 0
29}
30
31#[cfg(test)]
32mod tests {
33    //! Reference values from
34    //! `geometry/test/algorithms/is_empty.cpp`.
35
36    use super::is_empty;
37    use geometry_cs::Cartesian;
38    use geometry_model::{Box, Linestring, MultiPoint, Point2D, Polygon, Segment, linestring};
39
40    type Pt = Point2D<f64, Cartesian>;
41
42    /// `is_empty.cpp:110-111` — points are never empty.
43    #[test]
44    fn point_is_never_empty() {
45        assert!(!is_empty(&Pt::new(0.0, 0.0)));
46        assert!(!is_empty(&Pt::new(1.0, 1.0)));
47    }
48
49    /// `is_empty.cpp:116` — a zero-length segment still has two points.
50    #[test]
51    fn segment_zero_length_is_not_empty() {
52        let s = Segment::new(Pt::new(0.0, 0.0), Pt::new(0.0, 0.0));
53        assert!(!is_empty(&s));
54    }
55
56    /// `is_empty.cpp:122` — a box is never empty.
57    #[test]
58    fn box_is_never_empty() {
59        let b = Box::from_corners(Pt::new(0.0, 0.0), Pt::new(1.0, 1.0));
60        assert!(!is_empty(&b));
61    }
62
63    /// `is_empty.cpp:134` — `LINESTRING()` (no points) is empty.
64    #[test]
65    fn empty_linestring_is_empty() {
66        let ls: Linestring<Pt> = Linestring::new();
67        assert!(is_empty(&ls));
68    }
69
70    /// `is_empty.cpp:135` — a non-empty linestring is not empty.
71    #[test]
72    fn nonempty_linestring_is_not_empty() {
73        let ls: Linestring<Pt> = linestring![(0.0, 0.0), (1.0, 1.0)];
74        assert!(!is_empty(&ls));
75    }
76
77    /// `is_empty.cpp:145` — `MULTIPOINT()` is empty.
78    #[test]
79    fn empty_multi_point_is_empty() {
80        let mp: MultiPoint<Pt> = MultiPoint(Vec::new());
81        assert!(is_empty(&mp));
82    }
83
84    /// `is_empty.cpp:226` — a polygon with an empty outer ring is empty.
85    #[test]
86    fn polygon_with_zero_point_outer_is_empty() {
87        let pg: Polygon<Pt> = Polygon::default();
88        assert!(is_empty(&pg));
89    }
90}