use super::{Point, PointF};
#[repr(C)]
#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Hash)]
pub struct Line {
pub start: Point,
pub end: Point,
}
impl Line {
#[inline]
pub const fn new(start: Point, end: Point) -> Self {
Self { start, end }
}
#[inline]
pub const fn from_coords(x1: i32, y1: i32, x2: i32, y2: i32) -> Self {
Self {
start: Point::new(x1, y1),
end: Point::new(x2, y2),
}
}
#[inline]
pub const fn length_squared(&self) -> i64 {
self.start.distance_squared(&self.end)
}
#[inline]
pub fn length(&self) -> f32 {
rdsmath::sqrtf(self.length_squared() as f32)
}
#[inline]
pub const fn dx(&self) -> i32 {
self.end.x - self.start.x
}
#[inline]
pub const fn dy(&self) -> i32 {
self.end.y - self.start.y
}
#[inline]
pub const fn midpoint(&self) -> Point {
self.start.midpoint(&self.end)
}
#[inline]
pub const fn is_horizontal(&self) -> bool {
self.start.y == self.end.y
}
#[inline]
pub const fn is_vertical(&self) -> bool {
self.start.x == self.end.x
}
#[inline]
pub const fn is_point(&self) -> bool {
self.start.x == self.end.x && self.start.y == self.end.y
}
#[inline]
pub const fn to_float(&self) -> LineF {
LineF {
start: self.start.to_float(),
end: self.end.to_float(),
}
}
#[inline]
pub const fn reverse(&self) -> Self {
Self {
start: self.end,
end: self.start,
}
}
}
#[repr(C)]
#[derive(Clone, Copy, Debug, Default, PartialEq)]
pub struct LineF {
pub start: PointF,
pub end: PointF,
}
impl LineF {
#[inline]
pub const fn new(start: PointF, end: PointF) -> Self {
Self { start, end }
}
#[inline]
pub const fn from_coords(x1: f32, y1: f32, x2: f32, y2: f32) -> Self {
Self {
start: PointF::new(x1, y1),
end: PointF::new(x2, y2),
}
}
#[inline]
pub fn length_squared(&self) -> f32 {
self.start.distance_squared(&self.end)
}
#[inline]
pub fn length(&self) -> f32 {
self.start.distance(&self.end)
}
#[inline]
pub fn dx(&self) -> f32 {
self.end.x - self.start.x
}
#[inline]
pub fn dy(&self) -> f32 {
self.end.y - self.start.y
}
#[inline]
pub fn midpoint(&self) -> PointF {
self.start.midpoint(&self.end)
}
#[inline]
pub fn point_at(&self, t: f32) -> PointF {
self.start.lerp(&self.end, t)
}
#[inline]
pub fn direction(&self) -> PointF {
PointF::new(self.dx(), self.dy()).normalize()
}
#[inline]
pub fn normal(&self) -> PointF {
let d = self.direction();
PointF::new(-d.y, d.x)
}
#[inline]
pub fn angle(&self) -> f32 {
rdsmath::atan2f(self.dy(), self.dx())
}
#[inline]
pub fn reverse(&self) -> Self {
Self {
start: self.end,
end: self.start,
}
}
#[inline]
pub fn round(&self) -> Line {
Line {
start: self.start.round(),
end: self.end.round(),
}
}
}
impl From<Line> for LineF {
#[inline]
fn from(l: Line) -> Self {
l.to_float()
}
}