1pub use self::simplex2::Simplex2;
2pub use self::simplex3::Simplex3;
3
4pub mod simplex2 {
6 #[cfg(feature = "derive_serdes")]
7 use serde::{Deserialize, Serialize};
8
9 use crate::*;
10 use crate::geometry::*;
11
12 #[cfg_attr(feature = "derive_serdes", derive(Serialize, Deserialize))]
17 #[derive(Clone, Copy, Debug, Eq, PartialEq)]
18 pub enum Simplex2 <S> {
19 Segment (Segment <S>),
20 Triangle (Triangle <S>)
21 }
22
23 #[cfg_attr(feature = "derive_serdes", derive(Serialize, Deserialize))]
27 #[derive(Clone, Copy, Debug, Eq, PartialEq)]
28 pub struct Segment <S> {
29 a : Point2 <S>,
30 b : Point2 <S>
31 }
32
33 #[cfg_attr(feature = "derive_serdes", derive(Serialize, Deserialize))]
37 #[derive(Clone, Copy, Debug, Eq, PartialEq)]
38 pub struct Triangle <S> {
39 a : Point2 <S>,
40 b : Point2 <S>,
41 c : Point2 <S>
42 }
43
44 impl <S : Ring> Segment <S> {
45 pub fn new (a : Point2 <S>, b : Point2 <S>) -> Self where S : std::fmt::Debug {
52 assert_ne!(a, b);
53 Segment { a, b }
54 }
55 pub fn unchecked (a : Point2 <S>, b : Point2 <S>) -> Self where S : std::fmt::Debug {
62 debug_assert_ne!(a, b);
63 Segment { a, b }
64 }
65 #[inline]
66 pub fn numcast <T> (self) -> Option <Segment <T>> where
67 S : num_traits::NumCast,
68 T : num_traits::NumCast
69 {
70 Some (Segment {
71 a: self.a.numcast()?,
72 b: self.b.numcast()?
73 })
74 }
75 #[inline]
76 pub const fn point_a (&self) -> &Point2 <S> {
77 &self.a
78 }
79 #[inline]
80 pub const fn point_b (&self) -> &Point2 <S> {
81 &self.b
82 }
83 #[inline]
84 pub fn length (&self) -> S where S : Field + Sqrt {
85 self.vector().norm()
86 }
87 #[inline]
88 pub fn length2 (&self) -> S {
89 self.vector().self_dot()
90 }
91 #[inline]
93 pub fn vector (&self) -> Vector2 <S> {
94 self.b - self.a
95 }
96 #[inline]
97 pub fn aabb2 (&self) -> Aabb2 <S> where S : std::fmt::Debug {
98 Aabb2::from_points (self.a, self.b)
99 }
100 #[inline]
101 pub fn line2 (&self) -> Line2 <S> where S : Real {
102 Line2::new (self.a, Unit2::normalize (self.vector()))
103 }
104 #[inline]
105 #[expect(clippy::type_complexity)]
106 pub fn intersect_aabb (&self, aabb : &Aabb2 <S>)
107 -> Option <((S, Point2 <S>), (S, Point2 <S>))>
108 where S : Real + std::fmt::Debug {
109 intersect::continuous_segment2_aabb2 (self, aabb)
110 }
111 #[inline]
112 #[expect(clippy::type_complexity)]
113 pub fn intersect_sphere (&self, sphere : &Sphere2 <S>)
114 -> Option <((S, Point2 <S>), (S, Point2 <S>))>
115 where S : Real + std::fmt::Debug {
116 intersect::continuous_segment2_sphere2 (self, sphere)
117 }
118 }
119 impl <S : Field> Default for Segment <S> {
120 fn default() -> Self {
131 Segment {
132 a: [-S::one(), S::zero()].into(),
133 b: [ S::one(), S::zero()].into()
134 }
135 }
136 }
137
138 impl <S : Field> Triangle <S> {
139 pub fn new (a : Point2 <S>, b : Point2 <S>, c : Point2 <S>) -> Self where
149 S : approx::RelativeEq + std::fmt::Debug
150 {
151 debug_assert_ne!(a, b);
152 debug_assert_ne!(a, c);
153 debug_assert_ne!(b, c);
154 assert!(!colinear_2d (&a, &b, &c));
155 Triangle { a, b, c }
156 }
157 pub fn unchecked (a : Point2 <S>, b : Point2 <S>, c : Point2 <S>) -> Self where
167 S : approx::RelativeEq + std::fmt::Debug
168 {
169 debug_assert_ne!(a, b);
170 debug_assert_ne!(a, c);
171 debug_assert_ne!(b, c);
172 debug_assert!(!colinear_2d (&a, &b, &c));
173 Triangle { a, b, c }
174 }
175 #[inline]
176 pub const fn point_a (&self) -> &Point2 <S> {
177 &self.a
178 }
179 #[inline]
180 pub const fn point_b (&self) -> &Point2 <S> {
181 &self.b
182 }
183 #[inline]
184 pub const fn point_c (&self) -> &Point2 <S> {
185 &self.c
186 }
187 }
188 impl <S : Field + Sqrt> Default for Triangle <S> {
189 fn default() -> Self {
207 let frac_1_sqrt_2 = S::one() / (S::one() + S::one()).sqrt();
208 Triangle {
209 a: [ S::zero(), S::one()].into(),
210 b: [-frac_1_sqrt_2, -frac_1_sqrt_2].into(),
211 c: [ frac_1_sqrt_2, -frac_1_sqrt_2].into()
212 }
213 }
214 }
215}
216
217pub mod simplex3 {
219 #[cfg(feature = "derive_serdes")]
220 use serde::{Deserialize, Serialize};
221
222 use crate::*;
223 use crate::geometry::*;
224 #[cfg_attr(feature = "derive_serdes", derive(Serialize, Deserialize))]
229 #[derive(Clone, Copy, Debug, Eq, PartialEq)]
230 pub enum Simplex3 <S> {
231 Segment (Segment <S>),
232 Triangle (Triangle <S>),
233 Tetrahedron (Tetrahedron <S>)
234 }
235
236 #[cfg_attr(feature = "derive_serdes", derive(Serialize, Deserialize))]
240 #[derive(Clone, Copy, Debug, Eq, PartialEq)]
241 pub struct Segment <S> {
242 a : Point3 <S>,
243 b : Point3 <S>
244 }
245
246 #[cfg_attr(feature = "derive_serdes", derive(Serialize, Deserialize))]
250 #[derive(Clone, Copy, Debug, Eq, PartialEq)]
251 pub struct Triangle <S> {
252 a : Point3 <S>,
253 b : Point3 <S>,
254 c : Point3 <S>
255 }
256
257 #[cfg_attr(feature = "derive_serdes", derive(Serialize, Deserialize))]
261 #[derive(Clone, Copy, Debug, Eq, PartialEq)]
262 pub struct Tetrahedron <S> {
263 a : Point3 <S>,
264 b : Point3 <S>,
265 c : Point3 <S>,
266 d : Point3 <S>
267 }
268
269 impl <S : Ring> Segment <S> {
270 pub fn new (a : Point3 <S>, b : Point3 <S>) -> Self where S : std::fmt::Debug {
277 assert_ne!(a, b);
278 Segment { a, b }
279 }
280 pub fn unchecked (a : Point3 <S>, b : Point3 <S>) -> Self where S : std::fmt::Debug {
287 debug_assert_ne!(a, b);
288 Segment { a, b }
289 }
290 #[inline]
291 pub fn numcast <T> (self) -> Option <Segment <T>> where
292 S : num_traits::NumCast,
293 T : num_traits::NumCast
294 {
295 Some (Segment {
296 a: self.a.numcast()?,
297 b: self.b.numcast()?
298 })
299 }
300 #[inline]
301 pub const fn point_a (&self) -> &Point3 <S> {
302 &self.a
303 }
304 #[inline]
305 pub const fn point_b (&self) -> &Point3 <S> {
306 &self.b
307 }
308 #[inline]
309 pub fn length (&self) -> S where S : Field + Sqrt {
310 self.vector().norm()
311 }
312 #[inline]
313 pub fn length2 (&self) -> S {
314 self.vector().self_dot()
315 }
316 #[inline]
318 pub fn vector (&self) -> Vector3 <S> {
319 self.b - self.a
320 }
321 #[inline]
322 pub fn aabb3 (&self) -> Aabb3 <S> where S : std::fmt::Debug {
323 Aabb3::from_points (self.a, self.b)
324 }
325 #[inline]
326 pub fn line3 (&self) -> Line3 <S> where S : Real {
327 Line3::new (self.a, Unit3::normalize (self.vector()))
328 }
329 #[inline]
330 #[expect(clippy::type_complexity)]
331 pub fn intersect_aabb (&self, aabb : &Aabb3 <S>)
332 -> Option <((S, Point3 <S>), (S, Point3 <S>))>
333 where S : Real + num_traits::Float + approx::RelativeEq <Epsilon=S> +
334 std::fmt::Debug
335 {
336 intersect::continuous_segment3_aabb3 (self, aabb)
337 }
338 #[inline]
339 #[expect(clippy::type_complexity)]
340 pub fn intersect_sphere (&self, sphere : &Sphere3 <S>)
341 -> Option <((S, Point3 <S>), (S, Point3 <S>))>
342 where S : Field + Sqrt {
343 intersect::continuous_segment3_sphere3 (self, sphere)
344 }
345 #[inline]
346 #[expect(clippy::type_complexity)]
347 pub fn intersect_cylinder (&self, sphere : &Cylinder3 <S>)
348 -> Option <((S, Point3 <S>), (S, Point3 <S>))>
349 where S : Real + std::fmt::Debug {
350 intersect::continuous_segment3_cylinder3 (self, sphere)
351 }
352 #[inline]
353 #[expect(clippy::type_complexity)]
354 pub fn intersect_capsule (&self, capsule : &Capsule3 <S>)
355 -> Option <((S, Point3 <S>), (S, Point3 <S>))>
356 where S : Real + std::fmt::Debug {
357 intersect::continuous_segment3_capsule3 (self, capsule)
358 }
359 }
360 impl <S : Field> Default for Segment <S> {
361 fn default() -> Self {
372 Segment {
373 a: [-S::one(), S::zero(), S::zero()].into(),
374 b: [ S::one(), S::zero(), S::zero()].into()
375 }
376 }
377 }
378
379 impl <S : Ring> Triangle <S> {
380 pub fn new (a : Point3 <S>, b : Point3 <S>, c : Point3 <S>) -> Self where
390 S : Field + Sqrt + approx::RelativeEq + std::fmt::Debug
391 {
392 debug_assert_ne!(a, b);
393 debug_assert_ne!(a, c);
394 debug_assert_ne!(b, c);
395 assert!(!colinear_3d (&a, &b, &c));
396 Triangle { a, b, c }
397 }
398 pub fn unchecked (a : Point3 <S>, b : Point3 <S>, c : Point3 <S>) -> Self where
408 S : Field + Sqrt + approx::RelativeEq + std::fmt::Debug
409 {
410 debug_assert_ne!(a, b);
411 debug_assert_ne!(a, c);
412 debug_assert_ne!(b, c);
413 debug_assert!(!colinear_3d (&a, &b, &c));
414 Triangle { a, b, c }
415 }
416 #[inline]
417 pub const fn point_a (&self) -> &Point3 <S> {
418 &self.a
419 }
420 #[inline]
421 pub const fn point_b (&self) -> &Point3 <S> {
422 &self.b
423 }
424 #[inline]
425 pub const fn point_c (&self) -> &Point3 <S> {
426 &self.c
427 }
428 }
429 impl <S : Field + Sqrt> Default for Triangle <S> {
430 fn default() -> Self {
457 let frac_1_sqrt_2 = S::one() / (S::one() + S::one()).sqrt();
458 Triangle {
459 a: [ S::zero(), S::one(), S::zero()].into(),
460 b: [-frac_1_sqrt_2, -frac_1_sqrt_2, S::zero()].into(),
461 c: [ frac_1_sqrt_2, -frac_1_sqrt_2, S::zero()].into()
462 }
463 }
464 }
465
466 impl <S : Ring> Tetrahedron <S> {
467 pub fn new (a : Point3 <S>, b : Point3 <S>, c : Point3 <S>, d : Point3 <S>)
478 -> Self
479 where
480 S : approx::RelativeEq
481 {
482 assert!(!coplanar_3d (&a, &b, &c, &d));
483 Tetrahedron { a, b, c, d }
484 }
485 pub fn unchecked (a : Point3 <S>, b : Point3 <S>, c : Point3 <S>, d : Point3 <S>)
496 -> Self
497 where
498 S : approx::RelativeEq
499 {
500 debug_assert!(!coplanar_3d (&a, &b, &c, &d));
501 Tetrahedron { a, b, c, d }
502 }
503 #[inline]
504 pub const fn point_a (&self) -> &Point3 <S> {
505 &self.a
506 }
507 #[inline]
508 pub const fn point_b (&self) -> &Point3 <S> {
509 &self.b
510 }
511 #[inline]
512 pub const fn point_c (&self) -> &Point3 <S> {
513 &self.c
514 }
515 #[inline]
516 pub const fn point_d (&self) -> &Point3 <S> {
517 &self.d
518 }
519 }
520 impl <S : Field + Sqrt> Default for Tetrahedron <S> {
521 fn default() -> Self {
552 let frac_1_3 = S::one() / S::three();
553 let sqrt_2_3 = (S::two() / S::three()).sqrt();
554 let sqrt_8_9 = (S::eight() / S::nine()).sqrt();
555 let sqrt_2_9 = (S::two() / S::nine()).sqrt();
556 Tetrahedron {
557 a: [S::zero(), S::zero(), S::one()].into(),
558 b: [S::zero(), sqrt_8_9, -frac_1_3].into(),
559 c: [ sqrt_2_3, -sqrt_2_9, -frac_1_3].into(),
560 d: [-sqrt_2_3, -sqrt_2_9, -frac_1_3].into()
561 }
562 }
563 }
564}