1use std::marker::PhantomData;
2
3use crate::iterator::PolygonInteriorIterator;
4use crate::line_string::UnimplementedLineString;
5use crate::{GeometryTrait, LineStringTrait};
6#[cfg(feature = "geo-types")]
7use geo_types::{CoordNum, LineString, Polygon};
8
9pub trait PolygonTrait: Sized + GeometryTrait {
17 type RingType<'a>: 'a + LineStringTrait<T = <Self as GeometryTrait>::T>
20 where
21 Self: 'a;
22
23 fn exterior(&self) -> Option<Self::RingType<'_>>;
25
26 fn interiors(&self) -> impl DoubleEndedIterator + ExactSizeIterator<Item = Self::RingType<'_>> {
28 PolygonInteriorIterator::new(self, 0, self.num_interiors())
29 }
30
31 fn num_interiors(&self) -> usize;
33
34 fn interior(&self, i: usize) -> Option<Self::RingType<'_>> {
37 if i >= self.num_interiors() {
38 None
39 } else {
40 unsafe { Some(self.interior_unchecked(i)) }
41 }
42 }
43
44 unsafe fn interior_unchecked(&self, i: usize) -> Self::RingType<'_>;
50}
51
52#[cfg(feature = "geo-types")]
53impl<T: CoordNum> PolygonTrait for Polygon<T> {
54 type RingType<'a>
55 = &'a LineString<<Self as GeometryTrait>::T>
56 where
57 Self: 'a;
58
59 fn exterior(&self) -> Option<Self::RingType<'_>> {
60 let ext_ring = Polygon::exterior(self);
61 if LineStringTrait::num_coords(&ext_ring) == 0 {
62 None
63 } else {
64 Some(ext_ring)
65 }
66 }
67
68 fn num_interiors(&self) -> usize {
69 Polygon::interiors(self).len()
70 }
71
72 unsafe fn interior_unchecked(&self, i: usize) -> Self::RingType<'_> {
73 unsafe { Polygon::interiors(self).get_unchecked(i) }
74 }
75}
76
77#[cfg(feature = "geo-types")]
78impl<'a, T: CoordNum> PolygonTrait for &'a Polygon<T> {
79 type RingType<'b>
80 = &'a LineString<<Self as GeometryTrait>::T>
81 where
82 Self: 'b;
83
84 fn exterior(&self) -> Option<Self::RingType<'_>> {
85 let ext_ring = Polygon::exterior(self);
86 if LineStringTrait::num_coords(&ext_ring) == 0 {
87 None
88 } else {
89 Some(ext_ring)
90 }
91 }
92
93 fn num_interiors(&self) -> usize {
94 Polygon::interiors(self).len()
95 }
96
97 unsafe fn interior_unchecked(&self, i: usize) -> Self::RingType<'_> {
98 unsafe { Polygon::interiors(self).get_unchecked(i) }
99 }
100}
101
102pub struct UnimplementedPolygon<T>(PhantomData<T>);
107
108impl<T> PolygonTrait for UnimplementedPolygon<T> {
109 type RingType<'a>
110 = UnimplementedLineString<<Self as GeometryTrait>::T>
111 where
112 Self: 'a;
113
114 fn exterior(&self) -> Option<Self::RingType<'_>> {
115 unimplemented!()
116 }
117
118 fn num_interiors(&self) -> usize {
119 unimplemented!()
120 }
121
122 unsafe fn interior_unchecked(&self, _i: usize) -> Self::RingType<'_> {
123 unimplemented!()
124 }
125}