pub use graham_scan::graham_scan;
pub use jarvis_march::jarvis_march;
pub use point_in_polygon::{are_multiple_points_in_polygon, is_single_point_in_polygon};
use nalgebra::{ComplexField, Point, Point2, RealField, Scalar};
use num_traits::{AsPrimitive, Bounded, NumOps};
use crate::{array, ops::RangeInclusive, types::PolygonExtents};
mod graham_scan;
mod jarvis_march;
mod point_in_polygon;
#[cfg(feature = "pregenerated")]
#[doc = "This module contains polygon mapping-algorithms that are pregenerated for single precision floating points."]
pub mod single_precision {
pub use super::graham_scan::single_precision::*;
pub use super::jarvis_march::single_precision::*;
pub use super::point_in_polygon::single_precision::*;
}
#[cfg(feature = "pregenerated")]
#[doc = "This module contains polygon mapping-algorithms that are pregenerated for double precision floating points."]
pub mod double_precision {
pub use super::graham_scan::double_precision::*;
pub use super::jarvis_march::double_precision::*;
pub use super::point_in_polygon::double_precision::*;
}
#[cfg_attr(
feature = "tracing",
tracing::instrument("Calculate Polygon Extents", skip_all, level = "info")
)]
pub fn calculate_polygon_extents<T, const N: usize>(
polygon: &[Point<T, N>],
) -> Option<PolygonExtents<T, N>>
where
T: Bounded + Copy + RealField,
{
let mut extents_accumulator: [RangeInclusive<T>; N] =
array::from_fn(|_| <T as Bounded>::max_value()..=<T as Bounded>::min_value());
if polygon.len() < 3 {
return None;
}
for vertex in polygon {
for (extent_for_dimension, vertex_coord) in
extents_accumulator.iter_mut().zip(vertex.coords.iter())
{
*extent_for_dimension = extent_for_dimension.start().min(*vertex_coord)
..=extent_for_dimension.end().max(*vertex_coord);
}
}
Some(extents_accumulator)
}
fn calculate_determinant<O: ComplexField + Copy, T: Scalar + NumOps + AsPrimitive<O>>(
point_a: &Point2<T>,
point_b: &Point2<T>,
point_c: &Point2<T>,
) -> O {
T::as_(
((point_b.y - point_a.y) * (point_c.x - point_b.x))
- ((point_b.x - point_a.x) * (point_c.y - point_b.y)),
)
}
#[cfg(test)]
mod tests {
use nalgebra::{Point, Point2};
use crate::Vec;
use super::*;
#[test]
fn test_calculate_polygon_extents() {
let polygon = Vec::from([
Point2::new(1.0, 1.0),
Point2::new(1.0, 4.0),
Point2::new(5.0, 4.0),
Point2::new(5.0, 1.0),
]);
let extents = calculate_polygon_extents(&polygon);
assert_eq!(
extents,
Some([RangeInclusive::new(1.0, 5.0), RangeInclusive::new(1.0, 4.0)])
);
}
#[test]
fn test_calculate_polygon_extents_empty_polygon() {
let polygon: Vec<Point<f64, 2>> = Vec::new();
let extents = calculate_polygon_extents(&polygon);
assert_eq!(extents, None);
}
}