pix_engine/shape/
sphere.rs1use crate::prelude::*;
24#[cfg(feature = "serde")]
25use serde::{Deserialize, Serialize};
26
27#[derive(Default, Debug, Copy, Clone, Eq, PartialEq, Hash)]
33#[repr(transparent)]
34#[must_use]
35#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
36pub struct Sphere<T = i32>(pub(crate) [T; 4]);
37
38#[macro_export]
56macro_rules! sphere {
57 ($p:expr, $r:expr$(,)?) => {
58 $crate::prelude::Sphere::with_position($p, $r)
59 };
60 ($x:expr, $y:expr, $z:expr, $r:expr$(,)?) => {
61 $crate::prelude::Sphere::new($x, $y, $z, $r)
62 };
63}
64
65impl<T> Sphere<T> {
66 pub const fn new(x: T, y: T, z: T, radius: T) -> Self {
68 Self([x, y, z, radius])
69 }
70}
71
72impl<T: Copy> Sphere<T> {
73 #[inline]
75 pub fn coords(&self) -> [T; 4] {
76 self.0
77 }
78
79 #[inline]
81 pub fn coords_mut(&mut self) -> &mut [T; 4] {
82 &mut self.0
83 }
84}
85
86impl<T: Num> Sphere<T> {
87 pub fn with_position<P: Into<Point<T, 3>>>(p: P, radius: T) -> Self {
89 let p = p.into();
90 Self::new(p.x(), p.y(), p.z(), radius)
91 }
92
93 #[inline]
95 pub fn x(&self) -> T {
96 self.0[0]
97 }
98
99 #[inline]
101 pub fn set_x(&mut self, x: T) {
102 self.0[0] = x;
103 }
104
105 #[inline]
107 pub fn y(&self) -> T {
108 self.0[1]
109 }
110
111 #[inline]
113 pub fn set_y(&mut self, y: T) {
114 self.0[1] = y;
115 }
116
117 #[inline]
119 pub fn z(&self) -> T {
120 self.0[2]
121 }
122
123 #[inline]
125 pub fn set_z(&mut self, z: T) {
126 self.0[2] = z;
127 }
128
129 #[inline]
131 pub fn radius(&self) -> T {
132 self.0[3]
133 }
134
135 #[inline]
137 pub fn set_radius(&mut self, radius: T) {
138 self.0[3] = radius;
139 }
140
141 pub fn center(&self) -> Point<T, 3> {
143 point!(self.x(), self.y(), self.z())
144 }
145}
146
147impl<T: Num> Contains<Point<T>> for Sphere<T> {
148 fn contains(&self, p: Point<T>) -> bool {
150 let px = p.x() - self.x();
151 let py = p.y() - self.y();
152 let pz = p.z() - self.z();
153 let r = self.radius() * self.radius();
154 (px * px + py * py + pz * pz) < r
155 }
156}
157
158impl<T: Num> Contains<Sphere<T>> for Sphere<T> {
159 fn contains(&self, sphere: Sphere<T>) -> bool {
161 let px = sphere.x() - self.x();
162 let py = sphere.y() - self.y();
163 let pz = sphere.z() - self.z();
164 let r = self.radius() * self.radius();
165 (px * px + py * py + pz * pz) < r
166 }
167}
168
169impl<T: Num> Intersects<Sphere<T>> for Sphere<T> {
170 type Result = ();
172
173 fn intersects(&self, sphere: Sphere<T>) -> Option<Self::Result> {
175 let px = sphere.x() - self.x();
176 let py = sphere.y() - self.y();
177 let pz = sphere.z() - self.z();
178 let r = sphere.radius() + self.radius();
179 if (px * px + py * py + pz * pz) < r * r {
180 Some(())
181 } else {
182 None
183 }
184 }
185}