parry3d/shape/
polygonal_feature_map.rs1use crate::math::{Real, Vector};
2use crate::shape::{Cuboid, PolygonalFeature, Segment, SupportMap, Triangle};
3use na::Unit;
4#[cfg(feature = "dim3")]
5use {
6    crate::{
7        math::Point,
8        shape::{Cone, Cylinder, PackedFeatureId},
9    },
10    approx::AbsDiffEq,
11};
12
13#[cfg(not(feature = "alloc"))]
14use na::{ComplexField, RealField}; pub trait PolygonalFeatureMap: SupportMap {
18    fn local_support_feature(&self, dir: &Unit<Vector<Real>>, out_feature: &mut PolygonalFeature);
20
21    fn is_convex_polyhedron(&self) -> bool {
26        false
27    }
28}
29
30impl PolygonalFeatureMap for Segment {
31    fn local_support_feature(&self, _: &Unit<Vector<Real>>, out_feature: &mut PolygonalFeature) {
32        *out_feature = PolygonalFeature::from(*self);
33    }
34}
35
36impl PolygonalFeatureMap for Triangle {
37    fn local_support_feature(&self, dir: &Unit<Vector<Real>>, out_feature: &mut PolygonalFeature) {
38        *out_feature = self.support_face(**dir);
39    }
40}
41
42impl PolygonalFeatureMap for Cuboid {
43    fn local_support_feature(&self, dir: &Unit<Vector<Real>>, out_feature: &mut PolygonalFeature) {
44        *out_feature = self.support_face(**dir);
45    }
46}
47
48#[cfg(feature = "dim3")]
49impl PolygonalFeatureMap for Cylinder {
50    fn local_support_feature(&self, dir: &Unit<Vector<Real>>, out_features: &mut PolygonalFeature) {
51        use na::Vector2;
52
53        let dir2 = Vector2::new(dir.x, dir.z)
68            .try_normalize(Real::default_epsilon())
69            .unwrap_or(Vector2::x());
70
71        if dir.y.abs() < 0.5 {
72            out_features.vertices[0] = Point::new(
74                dir2.x * self.radius,
75                -self.half_height,
76                dir2.y * self.radius,
77            );
78            out_features.vertices[1] =
79                Point::new(dir2.x * self.radius, self.half_height, dir2.y * self.radius);
80            out_features.eids = PackedFeatureId::edges([0, 0, 0, 0]);
81            out_features.fid = PackedFeatureId::face(0);
82            out_features.num_vertices = 2;
83            out_features.vids = PackedFeatureId::vertices([1, 11, 11, 11]);
84        } else {
85            let y = self.half_height.copysign(dir.y);
87            out_features.vertices[0] = Point::new(dir2.x * self.radius, y, dir2.y * self.radius);
88            out_features.vertices[1] = Point::new(-dir2.y * self.radius, y, dir2.x * self.radius);
89            out_features.vertices[2] = Point::new(-dir2.x * self.radius, y, -dir2.y * self.radius);
90            out_features.vertices[3] = Point::new(dir2.y * self.radius, y, -dir2.x * self.radius);
91
92            if dir.y < 0.0 {
93                out_features.eids = PackedFeatureId::edges([2, 4, 6, 8]);
94                out_features.fid = PackedFeatureId::face(9);
95                out_features.num_vertices = 4;
96                out_features.vids = PackedFeatureId::vertices([1, 3, 5, 7]);
97            } else {
98                out_features.eids = PackedFeatureId::edges([12, 14, 16, 18]);
99                out_features.fid = PackedFeatureId::face(19);
100                out_features.num_vertices = 4;
101                out_features.vids = PackedFeatureId::vertices([11, 13, 15, 17]);
102            }
103        }
104    }
105}
106
107#[cfg(feature = "dim3")]
108impl PolygonalFeatureMap for Cone {
109    fn local_support_feature(&self, dir: &Unit<Vector<Real>>, out_features: &mut PolygonalFeature) {
110        use na::Vector2;
111
112        let dir2 = Vector2::new(dir.x, dir.z)
125            .try_normalize(Real::default_epsilon())
126            .unwrap_or(Vector2::x());
127
128        if dir.y > 0.0 {
129            out_features.vertices[0] = Point::new(
131                dir2.x * self.radius,
132                -self.half_height,
133                dir2.y * self.radius,
134            );
135            out_features.vertices[1] = Point::new(0.0, self.half_height, 0.0);
136            out_features.eids = PackedFeatureId::edges([0, 0, 0, 0]);
137            out_features.fid = PackedFeatureId::face(0);
138            out_features.num_vertices = 2;
139            out_features.vids = PackedFeatureId::vertices([1, 11, 11, 11]);
140        } else {
141            let y = -self.half_height;
143            out_features.vertices[0] = Point::new(dir2.x * self.radius, y, dir2.y * self.radius);
144            out_features.vertices[1] = Point::new(-dir2.y * self.radius, y, dir2.x * self.radius);
145            out_features.vertices[2] = Point::new(-dir2.x * self.radius, y, -dir2.y * self.radius);
146            out_features.vertices[3] = Point::new(dir2.y * self.radius, y, -dir2.x * self.radius);
147
148            out_features.eids = PackedFeatureId::edges([2, 4, 6, 8]);
149            out_features.fid = PackedFeatureId::face(9);
150            out_features.num_vertices = 4;
151            out_features.vids = PackedFeatureId::vertices([1, 3, 5, 7]);
152        }
153    }
154}