spaceform/
point.rs

1//! Points in 3D space.
2
3use std::{
4	fmt::{Debug, Display},
5	ops::{Add, AddAssign, Mul, MulAssign, Sub, SubAssign},
6};
7
8use crate::{base::Vector, direction::Direction, is_shuffle_arg, shuffle_mask, transform::Transform, Check, True};
9
10#[repr(transparent)]
11#[derive(Copy, Clone, PartialEq)]
12/// A point in 3D space, with a W coordinate of 1.
13pub struct Point(pub(crate) Vector);
14
15impl Add<Direction> for Point {
16	type Output = Self;
17
18	#[inline(always)]
19	fn add(self, rhs: Direction) -> Self::Output { Self(self.0 + rhs.0) }
20}
21
22impl AddAssign<Direction> for Point {
23	#[inline(always)]
24	fn add_assign(&mut self, rhs: Direction) { *self = *self + rhs }
25}
26
27impl Debug for Point {
28	#[inline(always)]
29	fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
30		write!(f, "Point [{}, {}, {}]", self.x(), self.y(), self.z())
31	}
32}
33
34impl Default for Point {
35	#[inline(always)]
36	fn default() -> Self { Self(Vector::new(0f32, 0f32, 0f32, 1f32)) }
37}
38
39impl Display for Point {
40	#[inline(always)]
41	fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
42		write!(f, "Point [{}, {}, {}]", self.x(), self.y(), self.z())
43	}
44}
45
46impl Mul<Transform> for Point {
47	type Output = Self;
48
49	#[inline(always)]
50	fn mul(self, rhs: Transform) -> Self::Output { Self(self.0 * rhs.matrix) }
51}
52
53impl MulAssign<Transform> for Point {
54	#[inline(always)]
55	fn mul_assign(&mut self, rhs: Transform) { *self = *self * rhs }
56}
57
58impl Sub for Point {
59	type Output = Direction;
60
61	#[inline(always)]
62	fn sub(self, rhs: Self) -> Self::Output { Direction(self.0 - rhs.0) }
63}
64
65impl Sub<Direction> for Point {
66	type Output = Self;
67
68	#[inline(always)]
69	fn sub(self, rhs: Direction) -> Self::Output { Self(self.0 - rhs.0) }
70}
71
72impl SubAssign<Direction> for Point {
73	#[inline(always)]
74	fn sub_assign(&mut self, rhs: Direction) { *self = *self - rhs }
75}
76
77impl Point {
78	#[inline(always)]
79	/// Create a new [`Point`] with the given `x`, `y`, and `z` values.
80	pub fn new(x: f32, y: f32, z: f32) -> Self { Self(Vector::new(x, y, z, 1f32)) }
81
82	#[inline(always)]
83	/// Get the x value of the [`Point`].
84	pub fn x(self) -> f32 { self.0.x() }
85
86	#[inline(always)]
87	/// Get the y value of the [`Point`].
88	pub fn y(self) -> f32 { self.0.y() }
89
90	#[inline(always)]
91	/// Get the z value of the [`Point`].
92	pub fn z(self) -> f32 { self.0.z() }
93
94	#[inline(always)]
95	/// Set the x value of the [`Point`].
96	pub fn set_x(&mut self, val: f32) { self.0.set_x(val) }
97
98	#[inline(always)]
99	/// Set the y value of the [`Point`].
100	pub fn set_y(&mut self, val: f32) { self.0.set_y(val) }
101
102	#[inline(always)]
103	/// Set the z value of the [`Point`].
104	pub fn set_z(&mut self, val: f32) { self.0.set_z(val) }
105
106	#[inline(always)]
107	/// Shuffle the components of a [`Point`].
108	pub fn shuffle<const X: u32, const Y: u32, const Z: u32>(self) -> Self
109	where
110		Check<{ is_shuffle_arg(X, Y, Z, 3) }>: True,
111		[(); shuffle_mask(3, Z, Y, X) as usize]:,
112		[(); X as usize]:,
113		[(); Y as usize]:,
114		[(); Z as usize]:,
115	{
116		Self(self.0.shuffle::<X, Y, Z, 3>())
117	}
118
119	#[inline(always)]
120	/// Linear interpolate from `from` to `to` with a factor `t`.
121	pub fn lerp(from: Point, to: Point, t: f32) -> Point { Point(Vector::lerp(from.0, to.0, t)) }
122}