use crate::fix_float::FixFloat;
use crate::fix_vec::FixVec;
use crate::int::point::IntPoint;
use core::cmp::Ordering;
pub struct Triangle;
impl Triangle {
#[inline(always)]
pub fn area_two(p0: FixVec, p1: FixVec, p2: FixVec) -> i64 {
(p1 - p0).cross_product(p1 - p2)
}
#[inline(always)]
pub fn area(p0: FixVec, p1: FixVec, p2: FixVec) -> i64 {
Self::area_two(p0, p1, p2) / 2
}
#[inline(always)]
pub fn fix_area(p0: FixVec, p1: FixVec, p2: FixVec) -> FixFloat {
(p1 - p0).fix_cross_product(p1 - p2) / 2
}
#[inline(always)]
pub fn is_clockwise(p0: FixVec, p1: FixVec, p2: FixVec) -> bool {
Self::area_two(p0, p1, p2) > 0
}
#[inline(always)]
pub fn is_cw_or_line(p0: FixVec, p1: FixVec, p2: FixVec) -> bool {
Self::area_two(p0, p1, p2) >= 0
}
#[inline(always)]
pub fn is_not_line(p0: FixVec, p1: FixVec, p2: FixVec) -> bool {
Self::area_two(p0, p1, p2) != 0
}
#[inline(always)]
pub fn is_line(p0: FixVec, p1: FixVec, p2: FixVec) -> bool {
Self::area_two(p0, p1, p2) == 0
}
#[inline(always)]
pub fn clock_direction(p0: FixVec, p1: FixVec, p2: FixVec) -> i64 {
Self::area_two(p0, p1, p2).signum()
}
#[inline]
pub fn is_contain(p: FixVec, p0: FixVec, p1: FixVec, p2: FixVec) -> bool {
let q0 = (p - p1).cross_product(p0 - p1);
let q1 = (p - p2).cross_product(p1 - p2);
let q2 = (p - p0).cross_product(p2 - p0);
let has_neg = q0 < 0 || q1 < 0 || q2 < 0;
let has_pos = q0 > 0 || q1 > 0 || q2 > 0;
!(has_neg && has_pos)
}
#[inline]
pub fn is_not_contain(p: FixVec, p0: FixVec, p1: FixVec, p2: FixVec) -> bool {
let q0 = (p - p1).cross_product(p0 - p1);
let q1 = (p - p2).cross_product(p1 - p2);
let q2 = (p - p0).cross_product(p2 - p0);
let has_neg = q0 <= 0 || q1 <= 0 || q2 <= 0;
let has_pos = q0 >= 0 || q1 >= 0 || q2 >= 0;
has_neg && has_pos
}
#[inline(always)]
pub fn area_two_point(p0: IntPoint, p1: IntPoint, p2: IntPoint) -> i64 {
let x0 = p1.x as i64 - p0.x as i64;
let y0 = p1.y as i64 - p0.y as i64;
let x1 = p1.x as i64 - p2.x as i64;
let y1 = p1.y as i64 - p2.y as i64;
x0 * y1 - x1 * y0
}
#[inline(always)]
pub fn is_clockwise_point(p0: IntPoint, p1: IntPoint, p2: IntPoint) -> bool {
Self::area_two_point(p0, p1, p2) > 0
}
#[inline(always)]
pub fn is_cw_or_line_point(p0: IntPoint, p1: IntPoint, p2: IntPoint) -> bool {
Self::area_two_point(p0, p1, p2) >= 0
}
#[inline(always)]
pub fn is_line_point(p0: IntPoint, p1: IntPoint, p2: IntPoint) -> bool {
Self::area_two_point(p0, p1, p2) == 0
}
#[inline(always)]
pub fn is_not_line_point(p0: IntPoint, p1: IntPoint, p2: IntPoint) -> bool {
Self::area_two_point(p0, p1, p2) != 0
}
#[inline(always)]
pub fn clock_direction_point(p0: IntPoint, p1: IntPoint, p2: IntPoint) -> i64 {
Self::area_two_point(p0, p1, p2).signum()
}
#[inline]
pub fn is_contain_point(p: IntPoint, p0: IntPoint, p1: IntPoint, p2: IntPoint) -> bool {
let f = FixVec::new_point(p);
let f0 = FixVec::new_point(p0);
let f1 = FixVec::new_point(p1);
let f2 = FixVec::new_point(p2);
let q0 = (f - f1).cross_product(f0 - f1);
let q1 = (f - f2).cross_product(f1 - f2);
let q2 = (f - f0).cross_product(f2 - f0);
let has_neg = q0 < 0 || q1 < 0 || q2 < 0;
let has_pos = q0 > 0 || q1 > 0 || q2 > 0;
!(has_neg && has_pos)
}
#[inline]
pub fn is_contain_point_exclude_borders(p: IntPoint, p0: IntPoint, p1: IntPoint, p2: IntPoint) -> bool {
let f = FixVec::new_point(p);
let f0 = FixVec::new_point(p0);
let f1 = FixVec::new_point(p1);
let f2 = FixVec::new_point(p2);
let q0 = (f - f1).cross_product(f0 - f1);
let q1 = (f - f2).cross_product(f1 - f2);
let q2 = (f - f0).cross_product(f2 - f0);
let has_neg = q0 < 0 || q1 < 0 || q2 < 0;
let has_pos = q0 > 0 || q1 > 0 || q2 > 0;
!(has_neg && has_pos) && q0 != 0 && q1 != 0 && q2 != 0
}
#[inline]
pub fn is_not_contain_point(p: IntPoint, p0: IntPoint, p1: IntPoint, p2: IntPoint) -> bool {
let f = FixVec::new_point(p);
let f0 = FixVec::new_point(p0);
let f1 = FixVec::new_point(p1);
let f2 = FixVec::new_point(p2);
let q0 = (f - f1).cross_product(f0 - f1);
let q1 = (f - f2).cross_product(f1 - f2);
let q2 = (f - f0).cross_product(f2 - f0);
let has_neg = q0 <= 0 || q1 <= 0 || q2 <= 0;
let has_pos = q0 >= 0 || q1 >= 0 || q2 >= 0;
has_neg && has_pos
}
#[inline(always)]
pub fn clock_order_point(p0: IntPoint, p1: IntPoint, p2: IntPoint) -> Ordering {
0.cmp(&Self::area_two_point(p0, p1, p2))
}
}