1use std::fmt;
4use std::ops::{Add, AddAssign, Sub};
5
6use crate::Vec3;
7
8#[derive(Clone, Copy, PartialEq)]
13#[repr(C)]
14pub struct Point3 {
15 pub x: f64,
17 pub y: f64,
19 pub z: f64,
21}
22
23impl Point3 {
24 pub const ORIGIN: Self = Self {
26 x: 0.0,
27 y: 0.0,
28 z: 0.0,
29 };
30
31 #[inline]
33 pub const fn new(x: f64, y: f64, z: f64) -> Self {
34 Self { x, y, z }
35 }
36
37 #[inline]
39 pub fn offset_from(self, other: Self) -> Vec3 {
40 Vec3::new(self.x - other.x, self.y - other.y, self.z - other.z)
41 }
42
43 #[inline]
45 pub fn distance_to(self, other: Self) -> f64 {
46 self.offset_from(other).length()
47 }
48
49 #[inline]
51 pub fn lerp(self, other: Self, t: f64) -> Self {
52 Self::new(
53 self.x + t * (other.x - self.x),
54 self.y + t * (other.y - self.y),
55 self.z + t * (other.z - self.z),
56 )
57 }
58
59 #[inline]
61 pub fn to_vec(self) -> Vec3 {
62 Vec3::new(self.x, self.y, self.z)
63 }
64
65 #[inline]
67 pub fn from_vec(v: Vec3) -> Self {
68 Self::new(v.x, v.y, v.z)
69 }
70}
71
72impl Add<Vec3> for Point3 {
76 type Output = Self;
77 #[inline]
78 fn add(self, v: Vec3) -> Self {
79 Self::new(self.x + v.x, self.y + v.y, self.z + v.z)
80 }
81}
82impl AddAssign<Vec3> for Point3 {
83 #[inline]
84 fn add_assign(&mut self, v: Vec3) {
85 *self = *self + v;
86 }
87}
88
89impl Sub for Point3 {
91 type Output = Vec3;
92 #[inline]
93 fn sub(self, other: Self) -> Vec3 {
94 self.offset_from(other)
95 }
96}
97
98impl Sub<Vec3> for Point3 {
100 type Output = Self;
101 #[inline]
102 fn sub(self, v: Vec3) -> Self {
103 Self::new(self.x - v.x, self.y - v.y, self.z - v.z)
104 }
105}
106
107impl fmt::Debug for Point3 {
108 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
109 write!(f, "Point3({:.6}, {:.6}, {:.6})", self.x, self.y, self.z)
110 }
111}
112impl fmt::Display for Point3 {
113 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
114 write!(f, "({:.4}, {:.4}, {:.4})", self.x, self.y, self.z)
115 }
116}
117
118impl From<[f64; 3]> for Point3 {
121 fn from(a: [f64; 3]) -> Self {
122 Self::new(a[0], a[1], a[2])
123 }
124}
125impl From<Point3> for [f64; 3] {
126 fn from(p: Point3) -> [f64; 3] {
127 [p.x, p.y, p.z]
128 }
129}
130
131#[cfg(test)]
132mod tests {
133 use super::*;
134
135 #[test]
136 fn subtraction_gives_vec() {
137 let a = Point3::new(3.0, 0.0, 0.0);
138 let b = Point3::ORIGIN;
139 let v = a - b;
140 assert_eq!(v, Vec3::new(3.0, 0.0, 0.0));
141 }
142
143 #[test]
144 fn add_vec_moves_point() {
145 let p = Point3::ORIGIN + Vec3::Z;
146 assert_eq!(p, Point3::new(0.0, 0.0, 1.0));
147 }
148}