Skip to main content

irox_geometry/
polygon.rs

1// SPDX-License-Identifier: MIT
2// Copyright 2025 IROX Contributors
3//
4
5use 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}