1use crate::{BoundingBox, Object, RealField};
2use nalgebra as na;
3use num_traits::Float;
4
5pub trait Axis: std::fmt::Debug + Clone + Sync + Send {
6 fn value() -> usize;
7 fn inverted() -> bool;
8}
9
10#[derive(Clone, Debug)]
11pub struct AxisX {}
12impl Axis for AxisX {
13 fn value() -> usize {
14 0
15 }
16 fn inverted() -> bool {
17 false
18 }
19}
20
21#[derive(Clone, Debug)]
22pub struct AxisNegX {}
23impl Axis for AxisNegX {
24 fn value() -> usize {
25 0
26 }
27 fn inverted() -> bool {
28 true
29 }
30}
31
32#[derive(Clone, Debug)]
33pub struct AxisY {}
34impl Axis for AxisY {
35 fn value() -> usize {
36 1
37 }
38 fn inverted() -> bool {
39 false
40 }
41}
42
43#[derive(Clone, Debug)]
44pub struct AxisNegY {}
45impl Axis for AxisNegY {
46 fn value() -> usize {
47 1
48 }
49 fn inverted() -> bool {
50 true
51 }
52}
53
54#[derive(Clone, Debug)]
55pub struct AxisZ {}
56impl Axis for AxisZ {
57 fn value() -> usize {
58 2
59 }
60 fn inverted() -> bool {
61 false
62 }
63}
64
65#[derive(Clone, Debug)]
66pub struct AxisNegZ {}
67impl Axis for AxisNegZ {
68 fn value() -> usize {
69 2
70 }
71 fn inverted() -> bool {
72 true
73 }
74}
75
76#[derive(Clone, Debug, PartialEq)]
77pub struct Plane<A: Axis, S: RealField> {
78 distance_from_zero: S,
79 bbox: BoundingBox<S>,
80 normal: na::Vector3<S>,
81 _phantom: std::marker::PhantomData<A>,
82}
83
84impl<A: Axis, S: From<f32> + RealField + Float> Plane<A, S> {
85 pub fn new(distance_from_zero: S) -> Self {
86 let d = distance_from_zero;
87 let mut p_neg = na::Point3::new(S::neg_infinity(), S::neg_infinity(), S::neg_infinity());
88 let mut p_pos = na::Point3::new(S::infinity(), S::infinity(), S::infinity());
89 let zero: S = From::from(0f32);
90 let mut normal = na::Vector3::new(zero, zero, zero);
91
92 if A::inverted() {
93 p_neg[A::value()] = -d;
94 normal[A::value()] = From::from(-1.);
95 } else {
96 p_pos[A::value()] = d;
97 normal[A::value()] = From::from(1.);
98 }
99
100 Plane {
101 distance_from_zero: d,
102 bbox: BoundingBox::new(&p_neg, &p_pos),
103 normal,
104 _phantom: std::marker::PhantomData,
105 }
106 }
107}
108
109impl<A: 'static + Axis, S: Float + From<f32> + RealField> Object<S> for Plane<A, S> {
110 fn approx_value(&self, p: &na::Point3<S>, _: S) -> S {
111 let p: S = p[A::value()];
112 let ap: S = Float::abs(p);
113 if Float::is_sign_positive(p) != A::inverted() {
114 ap - self.distance_from_zero
115 } else {
116 -ap - self.distance_from_zero
117 }
118 }
119 fn bbox(&self) -> &BoundingBox<S> {
120 &self.bbox
121 }
122 fn normal(&self, _: &na::Point3<S>) -> na::Vector3<S> {
123 self.normal
124 }
125}
126
127pub type PlaneX<S> = Plane<AxisX, S>;
129pub type PlaneNegX<S> = Plane<AxisNegX, S>;
131pub type PlaneY<S> = Plane<AxisY, S>;
133pub type PlaneNegY<S> = Plane<AxisNegY, S>;
135pub type PlaneZ<S> = Plane<AxisZ, S>;
137pub type PlaneNegZ<S> = Plane<AxisNegZ, S>;
139
140#[derive(Clone, Debug, PartialEq)]
142pub struct NormalPlane<S: RealField> {
143 bbox: BoundingBox<S>,
144 normal: na::Vector3<S>,
145 p: S,
146}
147
148impl<S: From<f32> + RealField + Float> NormalPlane<S> {
149 pub fn from_normal_and_p(normal: na::Vector3<S>, p: S) -> Self {
151 NormalPlane {
152 bbox: BoundingBox::infinity(),
153 normal,
154 p,
155 }
156 }
157 pub fn from_3_points(a: &na::Point3<S>, b: &na::Point3<S>, c: &na::Point3<S>) -> Self {
159 let v1 = a - c;
160 let v2 = b - c;
161 let normal = v1.cross(&v2).normalize();
162 let p = normal.dot(&a.coords);
163 NormalPlane {
164 bbox: BoundingBox::infinity(),
165 normal,
166 p,
167 }
168 }
169}
170
171impl<S: Float + From<f32> + RealField> Object<S> for NormalPlane<S> {
172 fn approx_value(&self, x0: &na::Point3<S>, _: S) -> S {
173 self.normal.dot(&x0.coords) - self.p
174 }
175 fn bbox(&self) -> &BoundingBox<S> {
176 &self.bbox
177 }
178 fn normal(&self, _: &na::Point3<S>) -> na::Vector3<S> {
179 self.normal
180 }
181}
182
183#[cfg(test)]
184mod test {
185 use approx::assert_ulps_eq;
186 use crate::*;
187 use nalgebra as na;
188
189 #[test]
190 fn simple() {
191 let px = PlaneX::new(10.);
192 assert_ulps_eq!(px.approx_value(&na::Point3::new(0., 0., 0.), 0.), -10.);
193 assert_ulps_eq!(px.approx_value(&na::Point3::new(10., 0., 0.), 0.), 0.);
194 assert_ulps_eq!(px.approx_value(&na::Point3::new(20., 0., 0.), 0.), 10.);
195 assert_ulps_eq!(
196 px.approx_value(&na::Point3::new(20., 1000., 1000.), 0.),
197 10.
198 );
199 }
200
201 #[test]
202 fn hessian_x() {
203 let px = NormalPlane::from_normal_and_p(na::Vector3::new(1., 0., 0.), 0.);
204 assert_ulps_eq!(px.approx_value(&na::Point3::new(0., 0., 0.), 0.), 0.);
205 assert_ulps_eq!(px.approx_value(&na::Point3::new(0., 10., 100.), 0.), 0.);
206 assert_ulps_eq!(px.approx_value(&na::Point3::new(10., 0., 0.), 0.), 10.);
207 }
208
209 #[test]
210 fn hessian_xyz() {
211 let p = NormalPlane::from_normal_and_p(na::Vector3::new(1., 1., 1.).normalize(), 1.);
212 assert_ulps_eq!(p.approx_value(&na::Point3::new(0., 0., 0.), 0.), -1.);
213 assert_ulps_eq!(
214 p.approx_value(&na::Point3::new(1., 1., 1.), 0.),
215 Float::sqrt(3.) - 1.0
216 );
217 assert_ulps_eq!(
218 p.approx_value(&na::Point3::new(2., 2., 2.), 0.),
219 Float::sqrt(12.) - 1.0
220 );
221 }
222
223 #[test]
224 fn hessian_3points_x() {
225 let p = NormalPlane::from_3_points(
226 &na::Point3::new(10., 0., 0.),
227 &na::Point3::new(10., 1., 0.),
228 &na::Point3::new(10., 0., 1.),
229 );
230 assert_ulps_eq!(p.approx_value(&na::Point3::new(0., 0., 0.), 0.), -10.);
231 assert_ulps_eq!(p.approx_value(&na::Point3::new(1., 1., 1.), 0.), -9.0);
232 assert_ulps_eq!(p.approx_value(&na::Point3::new(100., 100., 100.), 0.), 90.);
233 }
234
235 #[test]
236 fn hessian_3points() {
237 let p = NormalPlane::from_3_points(
238 &na::Point3::new(0., 1., 1.),
239 &na::Point3::new(1., 0., 1.),
240 &na::Point3::new(1., 1., 0.),
241 );
242 assert_ulps_eq!(
243 p.approx_value(&na::Point3::new(0., 0., 0.), 0.),
244 -Float::sqrt(4. / 3.)
245 );
246 assert_ulps_eq!(
247 p.approx_value(&na::Point3::new(1., 1., 1.), 0.),
248 Float::sqrt(3.) - Float::sqrt(4. / 3.)
249 );
250 assert_ulps_eq!(
251 p.approx_value(&na::Point3::new(2., 2., 2.), 0.),
252 Float::sqrt(12.) - Float::sqrt(4. / 3.)
253 );
254 }
255}