1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
use fmt;
/// Error indicating that a geometric query is not supported between certain shape combinations.
///
/// Many geometric queries in Parry (like distance calculation, contact detection, or time-of-impact)
/// are implemented using specialized algorithms for specific pairs of shapes. When you attempt a
/// query between two shapes for which no implementation exists, this error is returned.
///
/// # When This Error Occurs
///
/// This error typically occurs in two situations:
///
/// 1. **Missing Implementation**: The query has not been implemented for the specific pair of shapes.
/// For example, some advanced queries might not support all combinations of composite shapes.
///
/// 2. **Complex Shape Combinations**: Certain queries involving composite shapes (like [`Compound`],
/// [`TriMesh`], or [`HeightField`]) may not be fully supported, especially for less common operations.
///
/// # Common Scenarios
///
/// - Computing contact manifolds between two custom shapes that don't have a specialized implementation
/// - Using non-linear shape casting with certain composite shapes
/// - Querying distance between shapes that require more complex algorithms not yet implemented
///
/// # How to Handle This Error
///
/// When you encounter this error, you have several options:
///
/// ## 1. Use a Different Query Type
///
/// Try a more basic query that's more widely supported:
///
/// ```no_run
/// # #[cfg(all(feature = "dim3", feature = "f32"))] {
/// # use parry3d::query::{contact, distance};
/// # use parry3d::shape::{Ball, Cuboid};
/// # use parry3d::math::{Pose, Vector};
/// # let shape1 = Ball::new(1.0);
/// # let shape2 = Cuboid::new(Vector::splat(1.0));
/// # let pos1 = Pose::identity();
/// # let pos2 = Pose::identity();
/// // If contact manifolds are unsupported, try basic contact:
/// if let Ok(contact) = contact(&pos1, &shape1, &pos2, &shape2, 0.0) {
/// // Process the contact point
/// }
///
/// // Or try distance computation:
/// let dist = distance(&pos1, &shape1, &pos2, &shape2);
/// # }
/// ```
///
/// ## 2. Decompose Complex Shapes
///
/// Break down complex shapes into simpler components:
///
/// ```no_run
/// # #[cfg(all(feature = "dim3", feature = "f32"))] {
/// # use parry3d::shape::{TriMesh, Ball, Compound, SharedShape};
/// # use parry3d::query::distance;
/// # use parry3d::math::{Pose, Vector};
/// # let mesh = TriMesh::new(vec![], vec![]).unwrap();
/// # let ball = Ball::new(1.0);
/// # let pos1 = Pose::identity();
/// # let pos2 = Pose::identity();
/// // Instead of querying against a complex mesh directly,
/// // iterate through its triangles:
/// for triangle in mesh.triangles() {
/// let dist = distance(&pos1, &triangle, &pos2, &ball);
/// // Process each triangle-ball pair
/// }
/// # }
/// ```
///
/// ## 3. Use the BVH for Composite Shapes
///
/// For shapes with BVH acceleration structures (like [`TriMesh`]), use specialized traversal methods:
///
/// ```no_run
/// # #[cfg(all(feature = "dim3", feature = "f32"))] {
/// # use parry3d::shape::TriMesh;
/// # use parry3d::bounding_volume::Aabb;
/// # use parry3d::math::Vector;
/// # let mesh = TriMesh::new(vec![Vector::ZERO], vec![[0, 0, 0]]).unwrap();
/// # let query_aabb = Aabb::new(Vector::ZERO, Vector::ZERO);
/// // Use BVH queries instead of direct shape queries:
/// for leaf_id in mesh.bvh().intersect_aabb(&query_aabb) {
/// let triangle = mesh.triangle(leaf_id);
/// // Process the triangle
/// }
/// # }
/// ```
///
/// ## 4. Implement a Custom Query Dispatcher
///
/// For advanced use cases, implement the [`QueryDispatcher`] trait to add support for your specific
/// shape combinations:
///
/// ```no_run
/// # #[cfg(all(feature = "dim3", feature = "f32"))] {
/// # use parry3d::query::{QueryDispatcher, DefaultQueryDispatcher};
/// # use parry3d::shape::Shape;
/// # use parry3d::math::{Pose, Real};
/// struct MyQueryDispatcher {
/// default: DefaultQueryDispatcher,
/// }
///
/// // Implement QueryDispatcher and add your custom query implementations
/// # }
/// ```
///
/// # Example: Catching and Handling the Error
///
/// ```
/// # #[cfg(all(feature = "dim3", feature = "f32"))] {
/// # use parry3d::query::{contact, Unsupported};
/// # use parry3d::shape::{Ball, Cuboid};
/// # use parry3d::math::{Pose, Vector};
/// let ball = Ball::new(1.0);
/// let cuboid = Cuboid::new(Vector::splat(1.0));
/// let pos1 = Pose::identity();
/// let pos2 = Pose::identity();
///
/// // Most queries return Result<T, Unsupported>
/// match contact(&pos1, &ball, &pos2, &cuboid, 0.0) {
/// Ok(Some(contact)) => {
/// // Query succeeded and found a contact
/// println!("Contact found at distance: {}", contact.dist);
/// }
/// Ok(None) => {
/// // Query succeeded but no contact found
/// println!("No contact");
/// }
/// Err(Unsupported) => {
/// // Query not supported for this shape combination
/// println!("This query is not supported between these shapes");
/// // Fall back to an alternative approach
/// }
/// }
/// # }
/// ```
///
/// [`Compound`]: crate::shape::Compound
/// [`TriMesh`]: crate::shape::TriMesh
/// [`HeightField`]: crate::shape::HeightField
/// [`QueryDispatcher`]: crate::query::QueryDispatcher
;