use super::{Scalar, Vector};
pub trait Vector2D: Vector<Self::S, 2> {
type S: Scalar;
fn new(x: Self::S, y: Self::S) -> Self;
#[inline(always)]
fn convex(&self, prev: Self, next: Self) -> bool {
(*self - prev).perp_dot(&(next - *self)).is_positive()
}
fn collinear(&self, a: Self, b: Self, eps: Self::S) -> bool {
let ab = b - a;
let ac = *self - a;
ab.perp_dot(&ac).abs() <= eps
}
fn angle_tri(&self, a: Self, b: Self) -> Self::S {
Vector::angle_between(&(a - *self), b - *self)
}
#[inline(always)]
fn barycentric_sign(a: Self, b: Self, c: Self) -> Self::S {
(a - c).perp_dot(&(b - c))
}
#[inline(always)]
fn perp_dot(&self, other: &Self) -> Self::S {
self.x() * other.y() - self.y() * other.x()
}
#[inline(always)]
fn is_inside_triangle(&self, a: Self, b: Self, c: Self) -> bool {
let bs1 = Self::barycentric_sign(*self, a, b);
let bs2 = Self::barycentric_sign(*self, b, c);
let bs3 = Self::barycentric_sign(*self, c, a);
let inside_ccw = bs1.is_positive() && bs2.is_positive() && bs3.is_positive();
let inside_cw = bs1.is_negative() && bs2.is_negative() && bs3.is_negative();
inside_ccw || inside_cw
}
fn xy(&self) -> Self {
Self::new(self.x(), self.y())
}
fn yx(&self) -> Self {
Self::new(self.y(), self.x())
}
}