mapping_algorithms/polygons/
mod.rs1pub use graham_scan::graham_scan;
25pub use jarvis_march::jarvis_march;
26pub use point_in_polygon::{are_multiple_points_in_polygon, is_single_point_in_polygon};
27
28use nalgebra::{ComplexField, Point, Point2, RealField, Scalar};
29use num_traits::{AsPrimitive, Bounded, NumOps};
30
31use crate::{array, ops::RangeInclusive, types::PolygonExtents};
32
33mod graham_scan;
34mod jarvis_march;
35mod point_in_polygon;
36
37#[cfg(feature = "pregenerated")]
38#[doc = "This module contains polygon mapping-algorithms that are pregenerated for single precision floating points."]
39pub mod single_precision {
40 pub use super::graham_scan::single_precision::*;
41 pub use super::jarvis_march::single_precision::*;
42 pub use super::point_in_polygon::single_precision::*;
43}
44
45#[cfg(feature = "pregenerated")]
46#[doc = "This module contains polygon mapping-algorithms that are pregenerated for double precision floating points."]
47pub mod double_precision {
48 pub use super::graham_scan::double_precision::*;
49 pub use super::jarvis_march::double_precision::*;
50 pub use super::point_in_polygon::double_precision::*;
51}
52
53#[cfg_attr(
65 feature = "tracing",
66 tracing::instrument("Calculate Polygon Extents", skip_all, level = "info")
67)]
68pub fn calculate_polygon_extents<T, const N: usize>(
69 polygon: &[Point<T, N>],
70) -> Option<PolygonExtents<T, N>>
71where
72 T: Bounded + Copy + RealField,
73{
74 let mut extents_accumulator: [RangeInclusive<T>; N] =
75 array::from_fn(|_| <T as Bounded>::max_value()..=<T as Bounded>::min_value());
76
77 if polygon.len() < 3 {
78 return None;
79 }
80
81 for vertex in polygon {
82 for (extent_for_dimension, vertex_coord) in
83 extents_accumulator.iter_mut().zip(vertex.coords.iter())
84 {
85 *extent_for_dimension = extent_for_dimension.start().min(*vertex_coord)
86 ..=extent_for_dimension.end().max(*vertex_coord);
87 }
88 }
89
90 Some(extents_accumulator)
91}
92
93fn calculate_determinant<O: ComplexField + Copy, T: Scalar + NumOps + AsPrimitive<O>>(
94 point_a: &Point2<T>,
95 point_b: &Point2<T>,
96 point_c: &Point2<T>,
97) -> O {
98 T::as_(
99 ((point_b.y - point_a.y) * (point_c.x - point_b.x))
100 - ((point_b.x - point_a.x) * (point_c.y - point_b.y)),
101 )
102}
103
104#[cfg(test)]
105mod tests {
106 use nalgebra::{Point, Point2};
107
108 use crate::Vec;
109
110 use super::*;
111
112 #[test]
113 fn test_calculate_polygon_extents() {
114 let polygon = Vec::from([
117 Point2::new(1.0, 1.0),
118 Point2::new(1.0, 4.0),
119 Point2::new(5.0, 4.0),
120 Point2::new(5.0, 1.0),
121 ]);
122
123 let extents = calculate_polygon_extents(&polygon);
126 assert_eq!(
127 extents,
128 Some([RangeInclusive::new(1.0, 5.0), RangeInclusive::new(1.0, 4.0)])
129 );
130 }
131
132 #[test]
133 fn test_calculate_polygon_extents_empty_polygon() {
134 let polygon: Vec<Point<f64, 2>> = Vec::new();
136
137 let extents = calculate_polygon_extents(&polygon);
139
140 assert_eq!(extents, None);
142 }
143}