1use crate::CoordinateType;
9
10use crate::edge::Edge;
11use crate::point::Point;
12use crate::rect::Rect;
13
14pub use crate::traits::{BoundingBox, DoubledOrientedArea, MapPointwise, WindingNumber};
15
16pub use crate::simple_polygon::*;
17use crate::types::*;
18
19use crate::traits::TryCastCoord;
20use itertools::Itertools;
21use num_traits::{Num, NumCast};
22use std::cmp::{Ord, PartialEq};
23use std::iter::FromIterator;
24
25#[derive(Clone, Hash, Debug, Eq, PartialEq)]
28#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
29pub struct Polygon<T> {
30 pub exterior: SimplePolygon<T>,
32 pub interiors: Vec<SimplePolygon<T>>,
34}
35
36#[macro_export]
49macro_rules! polygon {
50 ($($x:expr),*) => {Polygon::new((vec![$($x),*]))}
51}
52
53impl<'a, T, P> From<&'a Vec<P>> for Polygon<T>
55where
56 T: CoordinateType,
57 Point<T>: From<&'a P>,
58{
59 fn from(vec: &'a Vec<P>) -> Self {
60 Polygon {
61 exterior: vec.into(),
62 interiors: Vec::new(),
63 }
64 }
65}
66
67impl<T, P> From<Vec<P>> for Polygon<T>
69where
70 T: Copy + PartialOrd,
71 Point<T>: From<P>,
72{
73 fn from(vec: Vec<P>) -> Self {
74 Polygon {
75 exterior: vec.into(),
76 interiors: Vec::new(),
77 }
78 }
79}
80
81impl<T, P> FromIterator<P> for Polygon<T>
83where
84 T: Copy,
85 P: Into<Point<T>>,
86{
87 fn from_iter<I>(iter: I) -> Self
88 where
89 I: IntoIterator<Item = P>,
90 {
91 let exterior: SimplePolygon<T> = SimplePolygon::from_iter(iter);
92 Polygon {
93 exterior,
94 interiors: Vec::new(),
95 }
96 }
97}
98
99impl<T> From<SimplePolygon<T>> for Polygon<T> {
101 fn from(simple_polygon: SimplePolygon<T>) -> Self {
102 Polygon {
103 exterior: simple_polygon,
104 interiors: Vec::new(),
105 }
106 }
107}
108
109impl<T> From<&SimplePolygon<T>> for Polygon<T>
111where
112 T: Copy,
113{
114 fn from(simple_polygon: &SimplePolygon<T>) -> Self {
115 simple_polygon.clone().into()
116 }
117}
118
119impl<T> From<Rect<T>> for Polygon<T>
121where
122 T: Copy,
123{
124 fn from(rect: Rect<T>) -> Self {
125 Self::from(&rect)
126 }
127}
128
129impl<T> From<&Rect<T>> for Polygon<T>
131where
132 T: Copy,
133{
134 fn from(rect: &Rect<T>) -> Self {
135 SimplePolygon::new_raw(vec![
136 rect.lower_left(),
137 rect.lower_right(),
138 rect.upper_right(),
139 rect.upper_left(),
140 ])
141 .into()
142 }
143}
144
145pub trait ToPolygon<T> {
147 fn to_polygon(&self) -> Polygon<T>;
149}
150
151impl<T> Polygon<T> {
152 pub fn new_raw(exterior: Vec<Point<T>>) -> Self {
155 Self {
156 exterior: SimplePolygon::new_raw(exterior),
157 interiors: Default::default(),
158 }
159 }
160
161 pub fn new_raw_with_holes<E, I>(exterior: E, holes: Vec<I>) -> Self
164 where
165 E: Into<SimplePolygon<T>>,
166 I: Into<SimplePolygon<T>>,
167 {
168 Polygon {
169 exterior: exterior.into(),
170 interiors: holes.into_iter().map(|i| i.into()).collect(),
171 }
172 }
173
174 pub fn empty() -> Self {
176 Polygon {
177 exterior: SimplePolygon::empty(),
178 interiors: Vec::new(),
179 }
180 }
181
182 pub fn len(&self) -> usize {
184 self.exterior.len()
185 }
186
187 pub fn is_empty(&self) -> bool {
189 self.exterior.is_empty()
190 }
191}
192
193impl<T: Copy> Polygon<T> {
194 pub fn edges(&self) -> Vec<Edge<T>> {
196 self.exterior.edges()
197 }
198
199 pub fn all_edges_iter(&self) -> impl Iterator<Item = Edge<T>> + '_ {
201 self.exterior.edges_iter().chain(
202 self.interiors
203 .iter()
204 .flat_map(|interior| interior.edges_iter()),
205 )
206 }
207}
208
209impl<T: PartialOrd> Polygon<T> {
210 pub fn new<I>(i: I) -> Self
212 where
213 I: Into<Self>,
214 {
215 i.into().normalized()
216 }
217
218 pub fn new_with_holes<E, I>(exterior: E, holes: Vec<I>) -> Self
220 where
221 E: Into<SimplePolygon<T>>,
222 I: Into<SimplePolygon<T>>,
223 {
224 Polygon {
225 exterior: exterior.into(),
226 interiors: holes.into_iter().map(|i| i.into()).collect(),
227 }
228 .normalized()
229 }
230
231 pub fn normalize(&mut self) {
234 self.exterior.normalize();
235 self.interiors.iter_mut().for_each(|p| p.normalize());
236 self.interiors.sort_by(|a, b| {
237 a.points()
238 .partial_cmp(b.points())
239 .unwrap_or(std::cmp::Ordering::Less)
240 })
241 }
242
243 pub fn normalized(mut self) -> Self {
246 self.normalize();
247 self
248 }
249}
250
251impl<T: CoordinateType> Polygon<T> {
252 pub fn convex_hull(&self) -> SimplePolygon<T>
257 where
258 T: Ord,
259 {
260 self.exterior.convex_hull()
261 }
262
263 pub fn lower_left_vertex(&self) -> Point<T> {
279 self.exterior.lower_left_vertex()
280 }
281
282 pub fn orientation<Area>(&self) -> Orientation
298 where
299 Area: Num + From<T> + PartialOrd,
300 {
301 self.exterior.orientation::<Area>()
302 }
303}
304
305impl<T> TryBoundingBox<T> for Polygon<T>
306where
307 T: Copy + PartialOrd,
308{
309 fn try_bounding_box(&self) -> Option<Rect<T>> {
310 let bbox = self.exterior.try_bounding_box();
312
313 if let Some(bbox) = &bbox {
314 debug_assert!(
315 self.interiors.iter()
316 .filter_map(|p| p.try_bounding_box())
317 .all(|internal_bbox| bbox.contains_rectangle(&internal_bbox)),
318 "Bounding boxes of interior polygons exceed the bounding box of the exterior polygon."
319 );
320 } else {
321 let num_internal_bboxes = self
324 .interiors
325 .iter()
326 .filter_map(|p| p.try_bounding_box())
327 .count();
328 debug_assert_eq!(
329 num_internal_bboxes, 0,
330 "Polygon with empty zero-vertex hull cannot contain holes."
331 );
332 }
333
334 bbox
335 }
336}
337
338impl<T> WindingNumber<T> for Polygon<T>
339where
340 T: CoordinateType,
341{
342 fn winding_number(&self, point: Point<T>) -> isize {
348 let ext = self.exterior.winding_number(point);
349 let int: isize = self.interiors.iter().map(|p| p.winding_number(point)).sum();
350 ext + int
351 }
352}
353
354impl<T> MapPointwise<T> for Polygon<T>
355where
356 T: CoordinateType,
357{
358 fn transform<F: Fn(Point<T>) -> Point<T>>(&self, tf: F) -> Self {
359 Polygon {
360 exterior: self.exterior.transform(&tf),
361 interiors: self.interiors.iter().map(|p| p.transform(&tf)).collect(),
362 }
363 }
364}
365
366impl<T, A> DoubledOrientedArea<A> for Polygon<T>
367where
368 T: CoordinateType,
369 A: Num + From<T>,
370{
371 fn area_doubled_oriented(&self) -> A {
394 let ext: A = self.exterior.area_doubled_oriented();
395 let int = self
396 .interiors
397 .iter()
398 .map(|p| p.area_doubled_oriented())
399 .fold(A::zero(), |a, b| a + b);
400 ext + int
401 }
402}
403
404impl<T: CoordinateType + NumCast, Dst: CoordinateType + NumCast> TryCastCoord<T, Dst>
405 for Polygon<T>
406{
407 type Output = Polygon<Dst>;
408
409 fn try_cast(&self) -> Option<Self::Output> {
410 if let Some(new_hull) = self.exterior.try_cast() {
411 let new_holes: Vec<_> = self
412 .interiors
413 .iter()
414 .map(|hole| hole.try_cast())
415 .while_some()
416 .collect();
417 if new_holes.len() == self.interiors.len() {
418 Some(Polygon::new_with_holes(new_hull, new_holes))
419 } else {
420 None
422 }
423 } else {
424 None
426 }
427 }
428}
429
430#[cfg(test)]
431mod tests {
432 use crate::prelude::*;
433
434 #[test]
435 fn test_create_polygon() {
436 let coords = vec![(0, 0), (1, 0), (1, 1), (0, 1)];
437
438 let poly: Polygon<i32> = (&coords).into();
439
440 assert_eq!(poly.exterior.len(), coords.len());
441 }
442
443 #[test]
444 fn test_area() {
445 let coords = vec![(0, 0), (1, 0), (1, 1), (0, 1)];
446
447 let poly: Polygon<i32> = (&coords).into();
448
449 let doubled_area: i64 = poly.area_doubled_oriented();
450 assert_eq!(doubled_area, 2);
451 }
452
453 #[test]
454 fn test_orientation() {
455 use crate::types::Orientation;
456 let coords = vec![(0, 0), (1, 0), (1, 1)];
457
458 let poly: Polygon<i32> = (&coords).into();
459
460 assert_eq!(poly.orientation::<i64>(), Orientation::CounterClockWise);
461 }
462
463 #[test]
464 fn test_bounding_box() {
465 use crate::rect::Rect;
466 use crate::traits::TryBoundingBox;
467 let coords = vec![(1, 0), (-1, -2), (1, 0), (42, 37)];
468
469 let poly: Polygon<i32> = (&coords).into();
470
471 assert_eq!(poly.try_bounding_box(), Some(Rect::new((-1, -2), (42, 37))))
472 }
473
474 #[test]
475 fn test_winding_number() {
476 let coords = vec![(0, 0), (2, 0), (2, 2), (0, 2)];
477
478 let poly: Polygon<i32> = (&coords).into();
479
480 assert_eq!(poly.winding_number(Point::new(1, 1)), 1);
481 assert_eq!(poly.winding_number(Point::new(-1, -1)), 0);
482 assert_eq!(poly.winding_number(Point::new(10, 10)), 0);
483
484 assert_eq!(poly.winding_number(Point::new(1, 0)), 1); assert_eq!(poly.winding_number(Point::new(2, 1)), 0); assert_eq!(poly.winding_number(Point::new(1, 2)), 0); assert_eq!(poly.winding_number(Point::new(0, 1)), 1); assert_eq!(poly.winding_number(Point::new(0, 0)), 1);
492 assert_eq!(poly.winding_number(Point::new(2, 0)), 0);
493 assert_eq!(poly.winding_number(Point::new(2, 2)), 0);
494 assert_eq!(poly.winding_number(Point::new(0, 2)), 0);
495 }
496
497 #[test]
498 fn test_convex_hull() {
499 let poly = Polygon::new(vec![(0, 0), (1, 1), (2, 0), (2, 2), (0, 2)]);
500 let exp_hull = Polygon::new(vec![(0, 0), (2, 0), (2, 2), (0, 2)])
501 .exterior
502 .normalized();
503 assert_eq!(poly.convex_hull(), exp_hull);
504
505 let poly = Polygon::new(vec![(1, 0), (2, 1), (1, 2), (1, 1), (0, 1)]);
506 let exp_hull = Polygon::new(vec![(1, 0), (2, 1), (1, 2), (0, 1)])
507 .exterior
508 .normalized();
509 assert_eq!(poly.convex_hull(), exp_hull);
510
511 let poly = Polygon::new(vec![(0, 0), (0, 1), (0, 7)]);
513 let exp_hull = Polygon::new(vec![(0, 0), (0, 7)]).exterior.normalized();
514 assert_eq!(poly.convex_hull(), exp_hull);
515
516 let poly = Polygon::new(vec![(0, 0), (1, 0), (7, 0)]);
518 let exp_hull = Polygon::new(vec![(0, 0), (7, 0)]).exterior.normalized();
519 assert_eq!(poly.convex_hull(), exp_hull);
520
521 let poly4 = Polygon::new(vec![(0, 0), (0, 0), (0, 0)]);
523 let exp_hull4 = Polygon::new(vec![(0, 0)]).exterior.normalized();
524 assert_eq!(poly4.convex_hull(), exp_hull4);
525 }
526
527 #[test]
528 fn test_normalized_eq() {
529 let poly1 = Polygon::new(vec![(0, 0), (1, 0), (1, 1)]);
530 let poly2 = Polygon::new(vec![(1, 1), (0, 0), (1, 0)]);
531 let poly3 = Polygon::new(vec![(0, 0), (1, 0), (1, 2)]);
532
533 assert_eq!(poly1, poly2);
534 assert_eq!(poly2, poly1);
535
536 assert_ne!(poly1, poly3)
537 }
538}