#[derive(Clone, Copy, Debug, PartialEq, PartialOrd)]
pub struct Point {
pub x: f32,
pub y: f32,
}
impl Point {
pub fn new(x: f32, y: f32) -> Point {
Point { x, y }
}
#[inline]
pub fn distance_sq(self, other: Point) -> f32 {
let dx = self.x - other.x;
let dy = self.y - other.y;
dx * dx + dy * dy
}
#[inline]
pub fn approx_eq(self, other: Point) -> bool {
let dx = self.x - other.x;
let dy = self.y - other.y;
dx.abs() <= std::f32::EPSILON && dy.abs() <= std::f32::EPSILON
}
}
impl Into<(i32, i32)> for Point {
fn into(self) -> (i32, i32) {
(self.x as i32, self.y as i32)
}
}
impl Into<(f32, f32)> for Point {
fn into(self) -> (f32, f32) {
(self.x, self.y)
}
}
#[derive(Clone, Copy, Debug, PartialEq)]
pub struct Triangle(pub Point, pub Point, pub Point);
impl Triangle {
#[inline]
fn circumcircle_delta(self) -> (f32, f32) {
let p = Point {
x: self.1.x - self.0.x,
y: self.1.y - self.0.y,
};
let q = Point {
x: self.2.x - self.0.x,
y: self.2.y - self.0.y,
};
let p2 = p.x * p.x + p.y * p.y;
let q2 = q.x * q.x + q.y * q.y;
let d = 2.0 * (p.x * q.y - p.y * q.x);
if d == 0.0 {
return (std::f32::INFINITY, std::f32::INFINITY);
}
let dx = (q.y * p2 - p.y * q2) / d;
let dy = (p.x * q2 - q.x * p2) / d;
(dx, dy)
}
#[inline]
pub fn circumradius_sq(self) -> f32 {
let (x, y) = self.circumcircle_delta();
x * x + y * y
}
#[inline]
pub fn circumcenter(self) -> Point {
let (x, y) = self.circumcircle_delta();
Point {
x: x + self.0.x,
y: y + self.0.y,
}
}
#[inline]
pub fn orientation(self) -> f32 {
let v21x = self.0.x - self.1.x;
let v21y = self.0.y - self.1.y;
let v23x = self.2.x - self.1.x;
let v23y = self.2.y - self.1.y;
v21x * v23y - v21y * v23x
}
#[inline]
pub fn is_right_handed(self) -> bool {
self.orientation() > 0.0
}
#[inline]
pub fn is_left_handed(self) -> bool {
self.orientation() < 0.0
}
#[inline]
pub fn in_circumcircle(self, point: Point) -> bool {
let dx = self.0.x - point.x;
let dy = self.0.y - point.y;
let ex = self.1.x - point.x;
let ey = self.1.y - point.y;
let fx = self.2.x - point.x;
let fy = self.2.y - point.y;
let ap = dx * dx + dy * dy;
let bp = ex * ex + ey * ey;
let cp = fx * fx + fy * fy;
dx * (ey * cp - bp * fy) - dy * (ex * cp - bp * fx) + ap * (ex * fy - ey * fx) < 0.0
}
}
pub fn pseudo_angle(dx: f32, dy: f32) -> f32 {
let p = dx / (dx.abs() + dy.abs());
if dy > 0.0 {
(3.0 - p) / 4.0
} else {
(1.0 + p) / 4.0
}
}