1use crate::Polygon;
6
7pub fn point_in_polygon<T>(point: &crate::Point<T, T>, polygon: &Polygon<T>) -> bool
36where
37 T: Clone
38 + Copy
39 + PartialOrd
40 + std::ops::Sub<Output = T>
41 + std::ops::Mul<Output = T>
42 + std::ops::Div<Output = T>
43 + std::ops::Add<Output = T>
44 + num_traits::Zero
45 + num_traits::Num
46 + std::ops::AddAssign
47 + Ord,
48{
49 let vertices = polygon.get_vertices();
50 let n = vertices.len();
51
52 if n < 3 {
53 return false;
54 }
55
56 let mut inside = false;
57 let mut j = n - 1;
58
59 for i in 0..n {
60 let xi = vertices[i].xcoord;
61 let yi = vertices[i].ycoord;
62 let xj = vertices[j].xcoord;
63 let yj = vertices[j].ycoord;
64
65 let intersect = ((yi > point.ycoord) != (yj > point.ycoord))
66 && (point.xcoord < (xj - xi) * (point.ycoord - yi) / (yj - yi) + xi);
67
68 if intersect {
69 inside = !inside;
70 }
71
72 j = i;
73 }
74
75 inside
76}
77
78pub fn polygon_centroid<T>(polygon: &Polygon<T>) -> crate::Point<T, T>
105where
106 T: Clone
107 + Copy
108 + std::ops::Add<Output = T>
109 + std::ops::Div<Output = T>
110 + From<i32>
111 + num_traits::Zero
112 + num_traits::Num
113 + std::ops::AddAssign
114 + Ord,
115{
116 let vertices = polygon.get_vertices();
117 let n = vertices.len();
118
119 if n == 0 {
120 return crate::Point::new(T::from(0), T::from(0));
121 }
122
123 let mut sum_x = T::from(0);
124 let mut sum_y = T::from(0);
125
126 for vertex in &vertices {
127 sum_x += vertex.xcoord;
128 sum_y += vertex.ycoord;
129 }
130
131 let n_t = T::from(n as i32);
132 crate::Point::new(sum_x / n_t, sum_y / n_t)
133}
134
135pub fn polygon_perimeter<T>(polygon: &Polygon<T>) -> T
163where
164 T: Clone
165 + Copy
166 + std::ops::Add<Output = T>
167 + std::ops::Sub<Output = T>
168 + std::ops::Mul<Output = T>
169 + num_traits::Zero
170 + num_traits::Num
171 + std::ops::AddAssign
172 + Ord,
173{
174 let vertices = polygon.get_vertices();
175 let n = vertices.len();
176
177 if n < 2 {
178 return T::zero();
179 }
180
181 let mut perimeter = T::zero();
182
183 for i in 0..n {
184 let current = vertices[i];
185 let next = vertices[(i + 1) % n];
186
187 let dx = if current.xcoord > next.xcoord {
188 current.xcoord - next.xcoord
189 } else {
190 next.xcoord - current.xcoord
191 };
192
193 let dy = if current.ycoord > next.ycoord {
194 current.ycoord - next.ycoord
195 } else {
196 next.ycoord - current.ycoord
197 };
198
199 perimeter = perimeter + dx + dy;
200 }
201
202 perimeter
203}
204
205#[cfg(test)]
206mod tests {
207 use super::*;
208
209 #[test]
210 fn test_point_in_polygon() {
211 let points = vec![
212 crate::Point::new(0, 0),
213 crate::Point::new(10, 0),
214 crate::Point::new(10, 10),
215 crate::Point::new(0, 10),
216 ];
217 let polygon = Polygon::new(&points);
218
219 assert!(point_in_polygon(&crate::Point::new(5, 5), &polygon));
220 assert!(!point_in_polygon(&crate::Point::new(15, 15), &polygon));
221 assert!(!point_in_polygon(&crate::Point::new(-5, 5), &polygon));
222 }
223
224 #[test]
225 fn test_polygon_centroid() {
226 let points = vec![
227 crate::Point::new(0, 0),
228 crate::Point::new(3, 0),
229 crate::Point::new(3, 3),
230 ];
231 let polygon = Polygon::new(&points);
232
233 let centroid = polygon_centroid(&polygon);
234 assert_eq!(centroid.xcoord, 2);
235 assert_eq!(centroid.ycoord, 1);
236 }
237
238 #[test]
239 fn test_polygon_perimeter() {
240 let points = vec![
241 crate::Point::new(0, 0),
242 crate::Point::new(3, 0),
243 crate::Point::new(3, 4),
244 crate::Point::new(0, 4),
245 ];
246 let polygon = Polygon::new(&points);
247
248 let perimeter = polygon_perimeter(&polygon);
249 assert_eq!(perimeter, 14);
250 }
251}