#![allow(dead_code)] use std::cmp::PartialEq; use std::ops::{Add, Sub}; use crate::vector::Vector; use crate::wide4::Float4; use crate::xform::XformFull; /// A position in 3D space. #[derive(Debug, Copy, Clone)] #[repr(transparent)] pub struct Point(pub Float4); impl Point { #[inline(always)] pub fn new(x: f32, y: f32, z: f32) -> Self { Self(Float4::new(x, y, z, 0.0)) } #[inline(always)] pub fn min(self, other: Self) -> Self { Self(self.0.min(other.0)) } #[inline(always)] pub fn max(self, other: Self) -> Self { Self(self.0.max(other.0)) } #[inline(always)] pub fn into_vector(self) -> Vector { Vector(self.0) } #[inline(always)] pub fn x(self) -> f32 { self.0.a() } #[inline(always)] pub fn y(self) -> f32 { self.0.b() } #[inline(always)] pub fn z(self) -> f32 { self.0.c() } #[inline(always)] #[must_use] pub fn set_x(self, x: f32) -> Self { Self(self.0.set_a(x)) } #[inline(always)] #[must_use] pub fn set_y(self, y: f32) -> Self { Self(self.0.set_b(y)) } #[inline(always)] #[must_use] pub fn set_z(self, z: f32) -> Self { Self(self.0.set_c(z)) } //------------- // Transforms. pub fn xform(self, xform: &XformFull) -> Self { Self(self.0.vec_mul_affine(&xform.m, xform.t)) } pub fn xform_inv(self, xform: &XformFull) -> Self { Self(self.0.vec_mul_affine_rev(&xform.m_inv, -xform.t)) } pub fn xform_fast(self, xform: &XformFull) -> Self { Self(self.0.vec_mul_affine_fast(&xform.m, xform.t)) } pub fn xform_inv_fast(self, xform: &XformFull) -> Self { Self(self.0.vec_mul_affine_rev_fast(&xform.m_inv, -xform.t)) } } impl Add for Point { type Output = Self; #[inline(always)] fn add(self, other: Vector) -> Self { Self(self.0 + other.0) } } impl Sub for Point { type Output = Vector; #[inline(always)] fn sub(self, other: Self) -> Vector { Vector(self.0 - other.0) } } impl Sub for Point { type Output = Self; #[inline(always)] fn sub(self, other: Vector) -> Self { Self(self.0 - other.0) } } impl PartialEq for Point { #[inline(always)] fn eq(&self, rhs: &Self) -> bool { self.0.a() == rhs.0.a() && self.0.b() == rhs.0.b() && self.0.c() == rhs.0.c() } } //------------------------------------------------------------- #[cfg(test)] mod tests { use super::*; use crate::{Vector, Xform}; #[test] fn add() { let p1 = Point::new(1.0, 2.0, 3.0); let v1 = Vector::new(1.5, 4.5, 2.5); let p2 = Point::new(2.5, 6.5, 5.5); assert_eq!(p2, p1 + v1); } #[test] fn sub() { let p1 = Point::new(1.0, 2.0, 3.0); let p2 = Point::new(1.5, 4.5, 2.5); let v1 = Vector::new(-0.5, -2.5, 0.5); assert_eq!(v1, p1 - p2); } #[test] fn xform() { let p = Point::new(1.0, 2.5, 4.0); let m = Xform::new(1.0, 3.0, 9.0, 2.0, 6.0, 2.0, 2.0, 7.0, 11.0, 1.5, 8.0, 12.0) .into_full() .unwrap(); assert_eq!(p.xform(&m), Point::new(15.5, 54.0, 70.0)); assert_eq!(p.xform(&m).xform_inv(&m), p); } #[test] fn xform_fast() { let p = Point::new(1.0, 2.5, 4.0); let m = Xform::new(1.0, 3.0, 9.0, 2.0, 6.0, 2.0, 2.0, 7.0, 11.0, 1.5, 8.0, 12.0) .into_full() .unwrap(); assert_eq!(p.xform_fast(&m), Point::new(15.5, 54.0, 70.0)); assert_eq!(p.xform_fast(&m).xform_inv_fast(&m), p); } }