use num_traits::Zero;
use std::cmp::Ordering;
use crate::{Coord, CoordNum, coord};
#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Clone, Copy)]
pub enum Orientation {
CounterClockwise,
Clockwise,
Collinear,
}
impl Orientation {
#[inline]
pub(crate) fn as_ordering(&self) -> Ordering {
match self {
Orientation::CounterClockwise => Ordering::Less,
Orientation::Clockwise => Ordering::Greater,
Orientation::Collinear => Ordering::Equal,
}
}
}
pub trait Kernel<T: CoordNum> {
fn orient2d(p: Coord<T>, q: Coord<T>, r: Coord<T>) -> Orientation {
let res = (q.x - p.x) * (r.y - q.y) - (q.y - p.y) * (r.x - q.x);
if res > Zero::zero() {
Orientation::CounterClockwise
} else if res < Zero::zero() {
Orientation::Clockwise
} else {
Orientation::Collinear
}
}
fn square_euclidean_distance(p: Coord<T>, q: Coord<T>) -> T {
(p.x - q.x) * (p.x - q.x) + (p.y - q.y) * (p.y - q.y)
}
fn dot_product_sign(u: Coord<T>, v: Coord<T>) -> Orientation {
let zero = Coord::zero();
let vdash = coord! {
x: T::zero() - v.y,
y: v.x,
};
Self::orient2d(zero, u, vdash)
}
}
pub mod robust;
pub use self::robust::RobustKernel;
pub mod simple;
pub use self::simple::SimpleKernel;