geo_traits/
multi_polygon.rs

1use std::marker::PhantomData;
2
3use crate::iterator::MultiPolygonIterator;
4use crate::polygon::UnimplementedPolygon;
5use crate::{GeometryTrait, PolygonTrait};
6#[cfg(feature = "geo-types")]
7use geo_types::{CoordNum, MultiPolygon, Polygon};
8
9/// A trait for accessing data from a generic MultiPolygon.
10///
11/// Refer to [geo_types::MultiPolygon] for information about semantics and validity.
12pub trait MultiPolygonTrait: Sized + GeometryTrait {
13    /// The type of each underlying Polygon, which implements [PolygonTrait]
14    type InnerPolygonType<'a>: 'a + PolygonTrait<T = Self::T>
15    where
16        Self: 'a;
17
18    /// An iterator over the Polygons in this MultiPolygon
19    fn polygons(
20        &self,
21    ) -> impl DoubleEndedIterator + ExactSizeIterator<Item = Self::InnerPolygonType<'_>> {
22        MultiPolygonIterator::new(self, 0, self.num_polygons())
23    }
24
25    /// The number of polygons in this MultiPolygon
26    fn num_polygons(&self) -> usize;
27
28    /// Access to a specified polygon in this MultiPolygon
29    /// Will return None if the provided index is out of bounds
30    fn polygon(&self, i: usize) -> Option<Self::InnerPolygonType<'_>> {
31        if i >= self.num_polygons() {
32            None
33        } else {
34            unsafe { Some(self.polygon_unchecked(i)) }
35        }
36    }
37
38    /// Access to a specified polygon in this MultiPolygon
39    ///
40    /// # Safety
41    ///
42    /// Accessing an index out of bounds is UB.
43    unsafe fn polygon_unchecked(&self, i: usize) -> Self::InnerPolygonType<'_>;
44}
45
46#[cfg(feature = "geo-types")]
47impl<T: CoordNum> MultiPolygonTrait for MultiPolygon<T> {
48    type InnerPolygonType<'a>
49        = &'a Polygon<Self::T>
50    where
51        Self: 'a;
52
53    fn num_polygons(&self) -> usize {
54        self.0.len()
55    }
56
57    unsafe fn polygon_unchecked(&self, i: usize) -> Self::InnerPolygonType<'_> {
58        self.0.get_unchecked(i)
59    }
60}
61
62#[cfg(feature = "geo-types")]
63impl<'a, T: CoordNum> MultiPolygonTrait for &'a MultiPolygon<T> {
64    type InnerPolygonType<'b>
65        = &'a Polygon<Self::T>
66    where
67        Self: 'b;
68
69    fn num_polygons(&self) -> usize {
70        self.0.len()
71    }
72
73    unsafe fn polygon_unchecked(&self, i: usize) -> Self::InnerPolygonType<'_> {
74        self.0.get_unchecked(i)
75    }
76}
77
78/// An empty struct that implements [MultiPolygonTrait].
79///
80/// This can be used as the `MultiPolygonType` of the `GeometryTrait` by implementations that don't
81/// have a MultiPolygon concept
82pub struct UnimplementedMultiPolygon<T>(PhantomData<T>);
83
84impl<T> MultiPolygonTrait for UnimplementedMultiPolygon<T> {
85    type InnerPolygonType<'a>
86        = UnimplementedPolygon<Self::T>
87    where
88        Self: 'a;
89
90    fn num_polygons(&self) -> usize {
91        unimplemented!()
92    }
93
94    unsafe fn polygon_unchecked(&self, _i: usize) -> Self::InnerPolygonType<'_> {
95        unimplemented!()
96    }
97}