use super::*;
#[derive(Copy, Clone, Debug, Default, Eq, PartialEq, Hash)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
#[repr(C)]
pub struct Line3<T> {
pub start: Point3<T>,
pub end: Point3<T>,
}
#[allow(non_snake_case)]
#[inline]
pub const fn Line3<T>(start: Point3<T>, end: Point3<T>) -> Line3<T> {
Line3 { start, end }
}
#[cfg(feature = "dataview")]
unsafe impl<T: dataview::Pod> dataview::Pod for Line3<T> {}
impl<T> Line3<T> {
#[inline]
pub const fn new(start: Point3<T>, end: Point3<T>) -> Line3<T> {
Line3 { start, end }
}
#[inline]
pub const fn pinch(self, pt: Point3<T>) -> (Line3<T>, Line3<T>) where T: Copy {
let Line3 { start, end } = self;
(Line3::new(start, pt), Line3::new(pt, end))
}
}
impl<T: ops::Sub<Output = T>> Line3<T> {
#[inline]
pub fn direction(self) -> Vec3<T> {
self.end - self.start
}
}
impl<T: Float> Line3<T> {
#[inline]
pub fn project(self, pt: Point3<T>) -> Point3<T> {
self.start + (pt - self.start).project(self.direction())
}
#[inline]
pub fn distance(self, pt: Point3<T>) -> T {
self.project(pt).distance(pt)
}
#[inline]
pub fn lerp(self, target: Line3<T>, t: T) -> Line3<T> {
Line3 {
start: self.start.lerp(target.start, t),
end: self.end.lerp(target.end, t),
}
}
}
#[cfg(feature = "urandom")]
impl<T> urandom::Distribution<Line3<T>> for urandom::distr::StandardUniform where
urandom::distr::StandardUniform: urandom::Distribution<Point3<T>>,
{
#[inline]
fn sample<R: urandom::Rng + ?Sized>(&self, rand: &mut urandom::Random<R>) -> Line3<T> {
let distr = urandom::distr::StandardUniform;
let start = distr.sample(rand);
let end = distr.sample(rand);
Line3 { start, end }
}
}
#[cfg(feature = "urandom")]
impl<T: urandom::distr::SampleUniform> urandom::distr::SampleUniform for Line3<T> {
type Sampler = Line3<urandom::distr::Uniform<T>>;
}
#[cfg(feature = "urandom")]
impl<T: urandom::distr::SampleUniform> urandom::distr::UniformSampler<Line3<T>> for Line3<urandom::distr::Uniform<T>> where Point3<T>: urandom::distr::SampleUniform {
#[inline]
fn try_new(low: Line3<T>, high: Line3<T>) -> Result<Self, urandom::distr::UniformError> {
let start = Vec3::try_new(low.start, high.start)?;
let end = Vec3::try_new(low.end, high.end)?;
Ok(Line3 { start, end })
}
#[inline]
fn try_new_inclusive(low: Line3<T>, high: Line3<T>) -> Result<Self, urandom::distr::UniformError> where Self: Sized {
let start = Vec3::try_new_inclusive(low.start, high.start)?;
let end = Vec3::try_new_inclusive(low.end, high.end)?;
Ok(Line3 { start, end })
}
}
#[cfg(feature = "urandom")]
impl<T: urandom::distr::SampleUniform> urandom::Distribution<Line3<T>> for Line3<urandom::distr::Uniform<T>> {
#[inline]
fn sample<R: urandom::Rng + ?Sized>(&self, rand: &mut urandom::Random<R>) -> Line3<T> {
let start = self.start.sample(rand);
let end = self.end.sample(rand);
Line3 { start, end }
}
}
impl<T: Float> Trace3<T> for Line3<T> {
#[inline]
fn inside(&self, _pt: Point3<T>) -> bool {
false
}
#[inline]
fn trace(&self, _ray: &Ray3<T>) -> Option<Hit3<T>> {
None
}
}