1use crate::geometry::{Centroid, Geometry};
6use crate::line::LineSegment;
7use crate::point::Point;
8use crate::rectangle::Rectangle;
9use crate::Vector2D;
10use core::slice::Iter;
11use irox_tools::iterators::{LendingIterator, Windows};
12use irox_tools::FloatIsh;
13
14#[derive(Debug, Clone, PartialEq, PartialOrd, Default)]
15pub struct Polygon<T: FloatIsh> {
16 pub points: Vec<Point<T>>,
17}
18
19impl<T: FloatIsh> Polygon<T> {
20 pub fn new() -> Self {
21 Self { points: Vec::new() }
22 }
23 pub fn iter_points(&self) -> Iter<'_, Point<T>> {
24 self.points.iter()
25 }
26 pub fn iter_segments(&self) -> PolygonSegmentIter<'_, T> {
27 let wins = Windows::<2, Point<T>>::new(self.points.iter());
28 let first = self.points.first();
29 let last = self.points.last();
30 let last = match (first, last) {
31 (Some(first), Some(last)) => Some(LineSegment {
32 start: *last,
33 end: *first,
34 }),
35 _ => None,
36 };
37 PolygonSegmentIter { iter: wins, last }
38 }
39
40 pub fn is_clockwise(&self) -> bool {
41 false
42 }
43 #[must_use]
44 pub fn clip(&self, _other: &Self) -> Self {
45 todo!()
46 }
47}
48
49pub struct PolygonSegmentIter<'a, T: FloatIsh> {
50 iter: Windows<'a, 2, Point<T>>,
51 last: Option<LineSegment<T>>,
52}
53impl<T: FloatIsh> Iterator for PolygonSegmentIter<'_, T> {
54 type Item = LineSegment<T>;
55
56 fn next(&mut self) -> Option<Self::Item> {
57 if let Some([a, b]) = self.iter.next_ref() {
58 Some(LineSegment { start: *a, end: *b })
59 } else {
60 self.last.take()
61 }
62 }
63}
64impl<T: FloatIsh> Centroid<T> for Polygon<T> {
65 fn centroid(&self) -> Point<T> {
66 let mut out = Point::default().to_vector();
67 for p in &self.points {
68 out += p.to_vector();
69 }
70 out /= T::from_f64(self.points.len() as f64);
71
72 out.to_point()
73 }
74}
75
76impl<T: FloatIsh> Geometry<T> for Polygon<T> {
77 fn contains(&self, _point: &Point<T>) -> bool {
78 todo!()
79 }
80
81 fn distance_to(&self, _point: &Point<T>) -> T {
82 todo!()
83 }
84
85 fn intersects(&self, _point: &Point<T>) -> bool {
86 todo!()
87 }
88
89 fn bounding_rectangle(&self) -> Rectangle<T> {
90 todo!()
91 }
92}