#![deny(missing_docs, missing_debug_implementations)]
mod convex_polygon;
mod line;
mod polygon;
pub use crate::{convex_polygon::*, line::*, polygon::*};
use euclid::{point2, Point2D};
use num_traits::{Num, NumAssign, NumCast, Signed};
use std::cmp::Ordering;
#[inline]
fn area2<T, U>(a: Point2D<T, U>, b: Point2D<T, U>, c: Point2D<T, U>) -> T
where
T: Copy + Num,
{
(b.x - a.x) * (c.y - a.y) - (c.x - a.x) * (b.y - a.y)
}
pub fn center<T, U>(points: &[Point2D<T, U>]) -> Point2D<T, U>
where
T: Copy + NumAssign + NumCast,
{
assert!(!points.is_empty());
let mut sum_x = 0.0_f64;
let mut sum_y = 0.0_f64;
for p in points {
sum_x += p.x.to_f64().unwrap();
sum_y += p.y.to_f64().unwrap();
}
let n = points.len() as f64;
let cx = sum_x / n;
let cy = sum_y / n;
let (cx, cy) = if T::from(0.1) == T::from(0.9) {
(T::from(cx.round()).unwrap(), T::from(cy.round()).unwrap())
} else {
(T::from(cx).unwrap(), T::from(cy).unwrap())
};
point2(cx, cy)
}
pub fn sort_around<T, U>(pivot: Point2D<T, U>, points: &mut [Point2D<T, U>])
where
T: Copy + NumAssign + PartialOrd + Signed,
{
points.sort_by(|&a, &b| {
let zero = T::zero();
let a_dx = a.x - pivot.x;
let b_dx = b.x - pivot.x;
if a_dx >= zero && b_dx < zero {
Ordering::Greater
} else if a_dx < zero && b_dx >= zero {
Ordering::Less
} else if a_dx == zero && b_dx == zero {
if a.y - pivot.y >= zero || b.y - pivot.y >= zero {
a.y.partial_cmp(&b.y).unwrap()
} else {
b.y.partial_cmp(&a.y).unwrap()
}
} else {
let c = (a - pivot).cross(b - pivot);
if c < zero {
Ordering::Greater
} else if c > zero {
Ordering::Less
} else {
let d1 = a.to_vector().cross(pivot.to_vector());
let d2 = b.to_vector().cross(pivot.to_vector());
d1.partial_cmp(&d2).unwrap()
}
}
});
debug_assert!(is_counter_clockwise(points));
}
pub fn is_counter_clockwise<T, U>(vertices: &[Point2D<T, U>]) -> bool
where
T: Copy + NumAssign + Signed + PartialOrd,
{
let mut sum = T::zero();
for (i, j) in (0..vertices.len()).zip((1..vertices.len()).chain(Some(0))) {
let a = vertices[i];
let b = vertices[j];
sum += (b.x - a.x) * (b.y + a.y);
}
sum <= T::zero()
}