fenris_geometry/primitives/
hexahedron.rs

1use crate::{
2    AxisAlignedBoundingBox, BoundedGeometry, ConvexPolyhedron, Distance, Quad3d, SignedDistance, SignedDistanceResult,
3};
4use fenris_traits::Real;
5use nalgebra::{OPoint, Point3, Scalar, U3};
6use numeric_literals::replace_float_literals;
7
8#[derive(Debug, Copy, Clone, PartialEq, Hash)]
9pub struct Hexahedron<T>
10where
11    T: Scalar,
12{
13    // Ordering uses same conventions as Hex8Connectivity
14    vertices: [Point3<T>; 8],
15}
16
17impl<T> BoundedGeometry<T> for Hexahedron<T>
18where
19    T: Real,
20{
21    type Dimension = U3;
22
23    fn bounding_box(&self) -> AxisAlignedBoundingBox<T, U3> {
24        AxisAlignedBoundingBox::from_points(&self.vertices).unwrap()
25    }
26}
27
28impl<T> Hexahedron<T>
29where
30    T: Scalar,
31{
32    pub fn from_vertices(vertices: [Point3<T>; 8]) -> Self {
33        Self { vertices }
34    }
35}
36
37impl<T> Hexahedron<T>
38where
39    T: Real,
40{
41    #[replace_float_literals(T::from_f64(literal).unwrap())]
42    pub fn reference() -> Self {
43        Self::from_vertices([
44            Point3::new(-1.0, -1.0, -1.0),
45            Point3::new(1.0, -1.0, -1.0),
46            Point3::new(1.0, 1.0, -1.0),
47            Point3::new(-1.0, 1.0, -1.0),
48            Point3::new(-1.0, -1.0, 1.0),
49            Point3::new(1.0, -1.0, 1.0),
50            Point3::new(1.0, 1.0, 1.0),
51            Point3::new(-1.0, 1.0, 1.0),
52        ])
53    }
54}
55
56impl<T> Distance<T, Point3<T>> for Hexahedron<T>
57where
58    T: Real,
59{
60    fn distance(&self, point: &Point3<T>) -> T {
61        let signed_dist = self.compute_signed_distance(point).signed_distance;
62        T::max(signed_dist, T::zero())
63    }
64}
65
66impl<T> SignedDistance<T, U3> for Hexahedron<T>
67where
68    T: Real,
69{
70    fn query_signed_distance(&self, point: &OPoint<T, U3>) -> Option<SignedDistanceResult<T, U3>> {
71        Some(self.compute_signed_distance(point))
72    }
73}
74
75impl<'a, T> ConvexPolyhedron<'a, T> for Hexahedron<T>
76where
77    T: Real,
78{
79    type Face = Quad3d<T>;
80
81    fn num_faces(&self) -> usize {
82        6
83    }
84
85    fn get_face(&self, index: usize) -> Option<Self::Face> {
86        let v = &self.vertices;
87        let quad = |i, j, k, l| Some(Quad3d::from_vertices([v[i], v[j], v[k], v[l]]));
88
89        // Must choose faces carefully so that they point towards the interior
90        match index {
91            0 => quad(0, 1, 2, 3),
92            1 => quad(4, 5, 1, 0),
93            2 => quad(5, 6, 2, 1),
94            3 => quad(6, 7, 3, 2),
95            4 => quad(0, 3, 7, 4),
96            5 => quad(4, 7, 6, 5),
97            _ => None,
98        }
99    }
100}