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
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
//! Query dispatcher system for extensible geometric queries.
//!
//! # Overview
//!
//! This module provides the **query dispatcher** abstraction, which allows Parry to perform
//! geometric queries (distance, contact, ray casting, etc.) between different shape types in
//! an extensible and customizable way.
//!
//! # What is a Query Dispatcher?
//!
//! A query dispatcher is an object that knows how to perform geometric queries between pairs
//! of shapes. When you ask "what is the distance between shape A and shape B?", the query
//! dispatcher:
//!
//! 1. Examines the types of both shapes (Ball, Cuboid, ConvexMesh, etc.)
//! 2. Selects the most appropriate algorithm for that shape pair
//! 3. Executes the query and returns the result
//!
//! For example, computing distance between two balls uses a simple formula, while computing
//! distance between two convex meshes requires the GJK algorithm. The query dispatcher
//! handles this selection automatically.
//!
//! # Why Do Query Dispatchers Exist?
//!
//! Query dispatchers provide **extensibility** for several use cases:
//!
//! 1. **Custom Shapes**: If you implement a custom shape type (e.g., a superellipsoid or
//! implicit surface), you can create a custom query dispatcher that knows how to handle
//! queries involving your shape, while delegating other queries to the default dispatcher.
//!
//! 2. **Specialized Algorithms**: You might have a faster algorithm for specific shape pairs
//! in your application domain. A custom dispatcher lets you override just those cases.
//!
//! 3. **Debugging and Profiling**: You can wrap the default dispatcher to log query calls,
//! collect statistics, or inject debug visualizations.
//!
//! 4. **Fallback Chains**: Multiple dispatchers can be chained together using the `chain()`
//! method, so if one dispatcher doesn't support a query, it automatically falls back to
//! the next one.
//!
//! # When to Use Query Dispatchers
//!
//! Most users will never need to directly use or implement query dispatchers. The high-level
//! query functions in [`crate::query`] use the [`DefaultQueryDispatcher`](crate::query::DefaultQueryDispatcher) automatically.
//!
//! You should implement a custom query dispatcher when:
//!
//! - You have custom shape types not supported by Parry
//! - You need specialized algorithms for specific shape pairs
//! - You're integrating Parry into a larger system that needs to intercept queries
//! - You want to add logging, profiling, or debugging to queries
//!
//! # Basic Usage
//!
//! ## Using the Default Dispatcher
//!
//! The simplest way is to use the free functions in [`crate::query`], which use the default
//! dispatcher internally:
//!
//! ```
//! # #[cfg(all(feature = "dim3", feature = "f32"))] {
//! use parry3d::query;
//! use parry3d::shape::Ball;
//! use parry3d::math::Pose;
//!
//! let ball1 = Ball::new(0.5);
//! let ball2 = Ball::new(1.0);
//! let pos1 = Pose::identity();
//! let pos2 = Pose::translation(5.0, 0.0, 0.0);
//!
//! // Uses DefaultQueryDispatcher automatically
//! let distance = query::distance(&pos1, &ball1, &pos2, &ball2);
//! # }
//! ```
//!
//! ## Using a Dispatcher Directly
//!
//! If you need explicit control, you can create and use a dispatcher:
//!
//! ```
//! # #[cfg(all(feature = "dim3", feature = "f32"))] {
//! use parry3d::query::{QueryDispatcher, DefaultQueryDispatcher};
//! use parry3d::shape::Ball;
//! use parry3d::math::Pose;
//!
//! let dispatcher = DefaultQueryDispatcher;
//! let ball1 = Ball::new(0.5);
//! let ball2 = Ball::new(1.0);
//!
//! let pos1 = Pose::identity();
//! let pos2 = Pose::translation(5.0, 0.0, 0.0);
//!
//! // Compute relative position of shape2 in shape1's local space
//! let pos12 = pos1.inv_mul(&pos2);
//!
//! let distance = dispatcher.distance(&pos12, &ball1, &ball2).unwrap();
//! # }
//! ```
//!
//! ## Chaining Dispatchers
//!
//! You can chain multiple dispatchers to create a fallback sequence:
//!
//! ```ignore
//! use parry3d::query::{QueryDispatcher, DefaultQueryDispatcher};
//!
//! // Create a custom dispatcher for your custom shapes
//! let custom = MyCustomDispatcher::new();
//!
//! // Chain it with the default dispatcher as a fallback
//! let dispatcher = custom.chain(DefaultQueryDispatcher);
//!
//! // Now dispatcher will try your custom dispatcher first,
//! // and fall back to the default if it returns Unsupported
//! ```
//!
//! # Implementing a Custom Query Dispatcher
//!
//! To implement a custom query dispatcher, implement the [`QueryDispatcher`] trait:
//!
//! ```ignore
//! use parry3d::query::{QueryDispatcher, Unsupported};
//! use parry3d::shape::Shape;
//! use parry3d::math::{Pose, Real};
//!
//! struct MyDispatcher {
//! // Your dispatcher state
//! }
//!
//! impl QueryDispatcher for MyDispatcher {
//! fn intersection_test(
//! &self,
//! pos12: &Pose,
//! g1: &dyn Shape,
//! g2: &dyn Shape,
//! ) -> Result<bool, Unsupported> {
//! // Try to downcast to your custom shape types
//! if let (Some(my_shape1), Some(my_shape2)) = (
//! g1.as_any().downcast_ref::<MyCustomShape>(),
//! g2.as_any().downcast_ref::<MyCustomShape>(),
//! ) {
//! // Implement your custom intersection test
//! Ok(my_custom_intersection_test(my_shape1, my_shape2, pos12))
//! } else {
//! // Return Unsupported for shape pairs you don't handle
//! Err(Unsupported)
//! }
//! }
//!
//! fn distance(
//! &self,
//! pos12: &Pose,
//! g1: &dyn Shape,
//! g2: &dyn Shape,
//! ) -> Result<Real, Unsupported> {
//! // Implement other query methods similarly
//! Err(Unsupported)
//! }
//!
//! // ... implement other required methods
//! }
//! ```
//!
//! # Important Notes
//!
//! ## The `pos12` Parameter
//!
//! All query methods take a `pos12` parameter, which is the **relative position** of shape 2
//! in shape 1's local coordinate frame. This is computed as:
//!
//! ```ignore
//! let pos12 = pos1.inv_mul(&pos2); // Transform from g2's space to g1's space
//! ```
//!
//! This convention reduces the number of transformations needed during queries.
//!
//! ## Thread Safety
//!
//! Query dispatchers must implement `Send + Sync` because they may be shared across threads
//! in parallel collision detection scenarios (e.g., when using Rapier physics engine).
//!
//! ## Error Handling
//!
//! Query methods return `Result<T, Unsupported>`. Return `Err(Unsupported)` when:
//! - The dispatcher doesn't know how to handle the given shape pair
//! - The shapes cannot be queried with the requested operation
//!
//! When chaining dispatchers, returning `Unsupported` allows the next dispatcher in the
//! chain to try handling the query.
use crate;
use crateShapeCastOptions;
use crate;
use crate;
use crateShape;
use Vec;
/// A query dispatcher for queries relying on spatial coherence, including contact-manifold computation.
///
/// This trait extends [`QueryDispatcher`] with methods that maintain persistent state between
/// queries to improve performance through **spatial and temporal coherence**.
///
/// # What is Spatial Coherence?
///
/// Spatial coherence is the principle that objects that are close to each other in one frame
/// are likely to remain close in subsequent frames. Contact manifolds exploit this by:
///
/// 1. Tracking contact points over multiple frames
/// 2. Reusing previous contact information to accelerate new queries
/// 3. Maintaining contact IDs for physics solvers to track persistent contacts
///
/// # Contact Manifolds vs Single Contacts
///
/// - **Single Contact** ([`QueryDispatcher::contact`]): Returns one contact point, suitable
/// for one-off queries or simple collision detection.
///
/// - **Contact Manifold** ([`PersistentQueryDispatcher::contact_manifolds`]): Returns multiple
/// contact points that persist across frames, essential for stable physics simulation.
///
/// # When to Use This Trait
///
/// Use `PersistentQueryDispatcher` when:
/// - Implementing physics simulation that needs stable contact tracking
/// - Building a custom physics engine on top of Parry
/// - Optimizing repeated collision queries between the same shape pairs
///
/// # Generic Parameters
///
/// - `ManifoldData`: Custom data attached to each contact manifold (default: `()`)
/// - `ContactData`: Custom data attached to each contact point (default: `()`)
///
/// These allow physics engines to attach solver-specific data to contacts without modifying
/// Parry's core types.
/// Dispatcher for pairwise geometric queries between shapes.
///
/// This is the core trait for performing geometric queries (distance, intersection, contact, etc.)
/// between pairs of shapes in Parry. It provides a uniform interface for querying different shape
/// combinations.
///
/// # Purpose
///
/// The `QueryDispatcher` trait serves as an abstraction layer that:
///
/// 1. **Decouples query algorithms from shape types**: Different shape pairs may require different
/// algorithms (e.g., sphere-sphere uses simple math, while convex-convex uses GJK/EPA).
///
/// 2. **Enables extensibility**: You can implement custom dispatchers to add support for custom
/// shape types or specialized algorithms without modifying Parry's core code.
///
/// 3. **Provides fallback mechanisms**: Dispatchers can be chained together using [`chain()`](Self::chain),
/// allowing graceful fallback when a query is not supported.
///
/// # The `pos12` Parameter Convention
///
/// All query methods in this trait take a `pos12` parameter, which represents the **relative
/// position** of shape 2 (`g2`) in shape 1's (`g1`) local coordinate frame:
///
/// ```ignore
/// pos12 = pos1.inverse() * pos2
/// ```
///
/// This convention is used because:
/// - It reduces redundant transformations during query execution
/// - Many algorithms naturally work in one shape's local space
/// - It's more efficient than passing two separate world-space positions
///
/// When using the high-level query functions, this transformation is done automatically.
///
/// # Query Methods Overview
///
/// The trait provides several categories of queries:
///
/// ## Basic Queries
/// - [`intersection_test`](Self::intersection_test): Boolean intersection check (fastest)
/// - [`distance`](Self::distance): Minimum separating distance
/// - [`closest_points`](Self::closest_points): Pair of closest points
/// - [`contact`](Self::contact): Contact point with penetration depth
///
/// ## Motion Queries (Time of Impact)
/// - [`cast_shapes`](Self::cast_shapes): Linear motion (translation only)
/// - [`cast_shapes_nonlinear`](Self::cast_shapes_nonlinear): Nonlinear motion (translation + rotation)
///
/// # Thread Safety
///
/// Query dispatchers must be `Send + Sync` because they're often shared across threads in:
/// - Parallel collision detection
/// - Physics simulations with multi-threaded broad phase
/// - Game engines with parallel scene queries
///
/// Ensure your custom dispatcher implementations are thread-safe or use appropriate synchronization.
///
/// # Error Handling with `Unsupported`
///
/// All query methods return `Result<T, Unsupported>`. The `Unsupported` error indicates:
///
/// - The dispatcher doesn't know how to handle the given shape pair
/// - The shapes don't support this type of query
/// - The query is mathematically undefined for these shapes
///
/// When chaining dispatchers with [`chain()`](Self::chain), returning `Unsupported` causes the
/// next dispatcher in the chain to be tried.
///
/// # Example: Using the Default Dispatcher
///
/// ```
/// # #[cfg(all(feature = "dim3", feature = "f32"))] {
/// use parry3d::query::{QueryDispatcher, DefaultQueryDispatcher};
/// use parry3d::shape::{Ball, Cuboid};
/// use parry3d::math::{Pose, Vector};
///
/// let dispatcher = DefaultQueryDispatcher;
///
/// let ball = Ball::new(1.0);
/// let cuboid = Cuboid::new(Vector::splat(2.0));
///
/// let pos1 = Pose::identity();
/// let pos2 = Pose::translation(5.0, 0.0, 0.0);
/// let pos12 = pos1.inv_mul(&pos2);
///
/// // Test intersection
/// let intersects = dispatcher.intersection_test(&pos12, &ball, &cuboid).unwrap();
///
/// // Compute distance
/// let dist = dispatcher.distance(&pos12, &ball, &cuboid).unwrap();
///
/// println!("Intersects: {}, Distance: {}", intersects, dist);
/// # }
/// ```
///
/// # Example: Chaining Dispatchers
///
/// ```ignore
/// # {
/// use parry3d::query::{QueryDispatcher, DefaultQueryDispatcher};
///
/// struct MyCustomDispatcher;
///
/// impl QueryDispatcher for MyCustomDispatcher {
/// fn distance(
/// &self,
/// pos12: &Pose,
/// g1: &dyn Shape,
/// g2: &dyn Shape,
/// ) -> Result<Real, Unsupported> {
/// // Handle custom shape types
/// if let Some(my_shape) = g1.as_any().downcast_ref::<MyShape>() {
/// // ... custom distance computation
/// Ok(computed_distance)
/// } else {
/// // Don't know how to handle this, let the next dispatcher try
/// Err(Unsupported)
/// }
/// }
///
/// // ... implement other methods
/// }
///
/// // Chain custom dispatcher with default as fallback
/// let dispatcher = MyCustomDispatcher.chain(DefaultQueryDispatcher);
///
/// // Now all queries try custom dispatcher first, then default
/// let dist = dispatcher.distance(pos12, shape1, shape2)?;
/// # }
/// ```
///
/// # See Also
///
/// - [`DefaultQueryDispatcher`](crate::query::DefaultQueryDispatcher): The built-in implementation used by Parry
/// - [`PersistentQueryDispatcher`]: Extended trait for contact manifold queries
/// - [`crate::query`]: High-level query functions that use dispatchers internally
/// A chain of two query dispatchers that provides fallback behavior.
///
/// This struct is created by calling [`QueryDispatcher::chain()`] and allows combining multiple
/// dispatchers into a fallback sequence. When a query is performed:
///
/// 1. The first dispatcher (`T`) is tried
/// 2. If it returns `Err(Unsupported)`, the second dispatcher (`U`) is tried
/// 3. If the second also returns `Unsupported`, the error is propagated
///
/// # Use Cases
///
/// Dispatcher chains are useful for:
///
/// - **Custom shapes with default fallback**: Handle your custom shapes specifically, but fall
/// back to Parry's default dispatcher for standard shapes
///
/// - **Performance optimization**: Try a fast specialized algorithm first, fall back to a general
/// but slower algorithm if needed
///
/// - **Progressive feature support**: Layer dispatchers that support different feature sets
///
/// - **Debugging**: Wrap the default dispatcher with a logging dispatcher that passes through
///
/// # Example
///
/// ```ignore
/// # {
/// use parry3d::query::{QueryDispatcher, DefaultQueryDispatcher};
///
/// // A dispatcher that handles only custom shapes
/// struct CustomShapeDispatcher;
/// impl QueryDispatcher for CustomShapeDispatcher {
/// fn distance(
/// &self,
/// pos12: &Pose,
/// g1: &dyn Shape,
/// g2: &dyn Shape,
/// ) -> Result<Real, Unsupported> {
/// // Try to handle custom shapes
/// match (g1.as_any().downcast_ref::<MyShape>(),
/// g2.as_any().downcast_ref::<MyShape>()) {
/// (Some(s1), Some(s2)) => Ok(custom_distance(s1, s2, pos12)),
/// _ => Err(Unsupported), // Let the next dispatcher handle it
/// }
/// }
/// // ... other methods return Err(Unsupported)
/// }
///
/// // Chain: try custom first, fall back to default
/// let dispatcher = CustomShapeDispatcher.chain(DefaultQueryDispatcher);
///
/// // This will use CustomShapeDispatcher if both are MyShape,
/// // otherwise DefaultQueryDispatcher handles it
/// let dist = dispatcher.distance(pos12, shape1, shape2)?;
/// # }
/// ```
///
/// # Performance Note
///
/// Chaining has minimal overhead - it's just two function calls in the worst case. The first
/// dispatcher is always tried first, so place your most likely-to-succeed dispatcher at the
/// front of the chain for best performance.
///
/// # Multiple Chains
///
/// You can chain more than two dispatchers by chaining chains:
///
/// ```ignore
/// let dispatcher = custom1
/// .chain(custom2)
/// .chain(DefaultQueryDispatcher);
/// ```
///
/// This creates a chain of three dispatchers: `custom1` -> `custom2` -> `DefaultQueryDispatcher`.
;
}
}