use geometry_coords::CoordinateScalar;
use geometry_cs::Cartesian;
use geometry_trait::Point;
use crate::Point2D;
#[derive(Debug, Clone, Copy, PartialEq)]
pub struct InfiniteLine<T: CoordinateScalar = f64> {
pub a: T,
pub b: T,
pub c: T,
pub normalized: bool,
}
impl<T: CoordinateScalar> InfiniteLine<T> {
#[inline]
#[must_use]
pub const fn new(a: T, b: T, c: T) -> Self {
Self {
a,
b,
c,
normalized: false,
}
}
#[inline]
#[must_use]
pub fn from_coordinates(x1: T, y1: T, x2: T, y2: T) -> Self {
let a = y1 - y2;
let b = x2 - x1;
let c = -(a * x1) - b * y1;
Self::new(a, b, c)
}
#[inline]
#[must_use]
pub fn from_points<P>(start: &P, end: &P) -> Self
where
P: Point<Scalar = T>,
{
Self::from_coordinates(
start.get::<0>(),
start.get::<1>(),
end.get::<0>(),
end.get::<1>(),
)
}
#[inline]
#[must_use]
pub fn side_value(&self, x: T, y: T) -> T {
self.a * x + self.b * y + self.c
}
#[inline]
#[must_use]
pub fn is_degenerate(&self) -> bool {
self.a == T::ZERO && self.b == T::ZERO
}
#[inline]
#[must_use]
pub fn intersection(&self, other: &Self) -> Option<Point2D<T, Cartesian>> {
let denominator = self.a * other.b - self.b * other.a;
if denominator == T::ZERO {
return None;
}
let x = (self.b * other.c - self.c * other.b) / denominator;
let y = (self.c * other.a - self.a * other.c) / denominator;
Some(Point2D::new(x, y))
}
}
impl<T: CoordinateScalar> Default for InfiniteLine<T> {
#[inline]
fn default() -> Self {
Self::new(T::ZERO, T::ZERO, T::ZERO)
}
}