Enum ClosestPoints

Source
pub enum ClosestPoints {
    Intersecting,
    WithinMargin(Point<f32>, Point<f32>),
    Disjoint,
}
Expand description

Result of a closest points query between two shapes.

This enum represents the outcome of computing closest points between two shapes, taking into account a user-defined maximum search distance. It’s useful for proximity-based gameplay mechanics, AI perception systems, and efficient spatial queries where you only care about nearby objects.

§Variants

The result depends on the relationship between the shapes and the max_dist parameter:

  • Intersecting: Shapes are overlapping (penetrating or touching)
  • WithinMargin: Shapes are separated but within the search distance
  • Disjoint: Shapes are too far apart (beyond the search distance)

§Use Cases

  • AI perception: Find nearest enemy within detection range
  • Trigger zones: Detect objects approaching a threshold distance
  • LOD systems: Compute detailed interactions only for nearby objects
  • Physics optimization: Skip expensive computations for distant pairs

§Example

use parry3d::query::{closest_points, ClosestPoints};
use parry3d::shape::Ball;
use nalgebra::Isometry3;

let ball1 = Ball::new(1.0);
let ball2 = Ball::new(1.0);

let pos1 = Isometry3::translation(0.0, 0.0, 0.0);
let pos2 = Isometry3::translation(5.0, 0.0, 0.0);

// Search for closest points within 10.0 units
let result = closest_points(&pos1, &ball1, &pos2, &ball2, 10.0).unwrap();

match result {
    ClosestPoints::Intersecting => {
        println!("Shapes are overlapping!");
    }
    ClosestPoints::WithinMargin(pt1, pt2) => {
        println!("Closest point on shape1: {:?}", pt1);
        println!("Closest point on shape2: {:?}", pt2);
        let distance = (pt2 - pt1).norm();
        println!("Distance between shapes: {}", distance);
    }
    ClosestPoints::Disjoint => {
        println!("Shapes are more than 10.0 units apart");
    }
}

§See Also

  • closest_points - Main function to compute this result
  • distance - For just the distance value
  • contact - For detailed contact information when intersecting

Variants§

§

Intersecting

The two shapes are intersecting (overlapping or touching).

When shapes intersect, their closest points are not well-defined, as there are infinitely many contact points. Use contact instead to get penetration depth and contact normals.

§Example

use parry3d::query::{closest_points, ClosestPoints};
use parry3d::shape::Ball;
use nalgebra::Isometry3;

let ball1 = Ball::new(2.0);
let ball2 = Ball::new(2.0);

// Overlapping balls (centers 3.0 apart, combined radii 4.0)
let pos1 = Isometry3::translation(0.0, 0.0, 0.0);
let pos2 = Isometry3::translation(3.0, 0.0, 0.0);

let result = closest_points(&pos1, &ball1, &pos2, &ball2, 10.0).unwrap();
assert_eq!(result, ClosestPoints::Intersecting);
§

WithinMargin(Point<f32>, Point<f32>)

The shapes are separated but within the specified maximum distance.

Contains the two closest points in world-space coordinates:

  • First point: Closest point on the surface of the first shape
  • Second point: Closest point on the surface of the second shape

The distance between the shapes equals the distance between these two points.

§Example

use parry3d::query::{closest_points, ClosestPoints};
use parry3d::shape::Ball;
use nalgebra::Isometry3;

let ball1 = Ball::new(1.0);
let ball2 = Ball::new(1.0);

// Balls separated by 3.0 units (centers 5.0 apart, combined radii 2.0)
let pos1 = Isometry3::translation(0.0, 0.0, 0.0);
let pos2 = Isometry3::translation(5.0, 0.0, 0.0);

let result = closest_points(&pos1, &ball1, &pos2, &ball2, 10.0).unwrap();

if let ClosestPoints::WithinMargin(pt1, pt2) = result {
    // Points are on the surface, facing each other
    assert!((pt1.x - 1.0).abs() < 1e-5); // ball1 surface at x=1.0
    assert!((pt2.x - 4.0).abs() < 1e-5); // ball2 surface at x=4.0

    // Distance between points
    let dist = (pt2 - pt1).norm();
    assert!((dist - 3.0).abs() < 1e-5);
} else {
    panic!("Expected WithinMargin");
}
§

Disjoint

The shapes are separated by more than the specified maximum distance.

The actual distance between shapes is unknown (could be much larger than max_dist), and no closest points are computed. This saves computation when you only care about nearby objects.

§Example

use parry3d::query::{closest_points, ClosestPoints};
use parry3d::shape::Ball;
use nalgebra::Isometry3;

let ball1 = Ball::new(1.0);
let ball2 = Ball::new(1.0);

// Balls separated by 8.0 units
let pos1 = Isometry3::translation(0.0, 0.0, 0.0);
let pos2 = Isometry3::translation(10.0, 0.0, 0.0);

// Only search within 5.0 units
let result = closest_points(&pos1, &ball1, &pos2, &ball2, 5.0).unwrap();
assert_eq!(result, ClosestPoints::Disjoint);

// With larger search distance, we get the points
let result2 = closest_points(&pos1, &ball1, &pos2, &ball2, 10.0).unwrap();
assert!(matches!(result2, ClosestPoints::WithinMargin(_, _)));

Implementations§

Source§

impl ClosestPoints

Source

pub fn flip(&mut self)

Swaps the two closest points in-place.

This is useful when you need to reverse the perspective of the query result. If the result is WithinMargin, the two points are swapped. For Intersecting and Disjoint, this operation has no effect.

§Example
use parry3d::query::{closest_points, ClosestPoints};
use parry3d::shape::Ball;
use nalgebra::Isometry3;

let ball1 = Ball::new(1.0);
let ball2 = Ball::new(2.0);

let pos1 = Isometry3::translation(0.0, 0.0, 0.0);
let pos2 = Isometry3::translation(5.0, 0.0, 0.0);

let mut result = closest_points(&pos1, &ball1, &pos2, &ball2, 10.0).unwrap();

if let ClosestPoints::WithinMargin(pt1_before, pt2_before) = result {
    result.flip();
    if let ClosestPoints::WithinMargin(pt1_after, pt2_after) = result {
        assert_eq!(pt1_before, pt2_after);
        assert_eq!(pt2_before, pt1_after);
    }
}
Source

pub fn flipped(&self) -> Self

Returns a copy with the two closest points swapped.

This is the non-mutating version of flip. It returns a new ClosestPoints with swapped points if the result is WithinMargin, or returns self unchanged for Intersecting and Disjoint.

§Example
use parry3d::query::{closest_points, ClosestPoints};
use parry3d::shape::Ball;
use nalgebra::Isometry3;

let ball1 = Ball::new(1.0);
let ball2 = Ball::new(2.0);

let pos1 = Isometry3::translation(0.0, 0.0, 0.0);
let pos2 = Isometry3::translation(5.0, 0.0, 0.0);

let result = closest_points(&pos1, &ball1, &pos2, &ball2, 10.0).unwrap();
let flipped = result.flipped();

// Original is unchanged
if let ClosestPoints::WithinMargin(pt1_orig, pt2_orig) = result {
    if let ClosestPoints::WithinMargin(pt1_flip, pt2_flip) = flipped {
        assert_eq!(pt1_orig, pt2_flip);
        assert_eq!(pt2_orig, pt1_flip);
    }
}
Source

pub fn transform_by(self, pos1: &Isometry<f32>, pos2: &Isometry<f32>) -> Self

Transforms the closest points from local space to world space.

Applies the isometry transformations to convert closest points from their respective local coordinate frames to world-space coordinates. This is used internally by the query system.

  • Point 1 is transformed by pos1
  • Point 2 is transformed by pos2
  • Intersecting and Disjoint variants are returned unchanged
§Arguments
  • pos1 - Transformation for the first shape
  • pos2 - Transformation for the second shape
§Example
use parry3d::query::ClosestPoints;
use nalgebra::{Isometry3, Point3};

// Points in local space
let local_result = ClosestPoints::WithinMargin(
    Point3::new(1.0, 0.0, 0.0),
    Point3::new(-1.0, 0.0, 0.0),
);

// Transform to world space
let pos1 = Isometry3::translation(10.0, 0.0, 0.0);
let pos2 = Isometry3::translation(20.0, 0.0, 0.0);

let world_result = local_result.transform_by(&pos1, &pos2);

if let ClosestPoints::WithinMargin(pt1, pt2) = world_result {
    assert!((pt1.x - 11.0).abs() < 1e-5); // 10.0 + 1.0
    assert!((pt2.x - 19.0).abs() < 1e-5); // 20.0 + (-1.0)
}

Trait Implementations§

Source§

impl Clone for ClosestPoints

Source§

fn clone(&self) -> ClosestPoints

Returns a duplicate of the value. Read more
1.0.0 · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl Debug for ClosestPoints

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl PartialEq for ClosestPoints

Source§

fn eq(&self, other: &ClosestPoints) -> bool

Tests for self and other values to be equal, and is used by ==.
1.0.0 · Source§

fn ne(&self, other: &Rhs) -> bool

Tests for !=. The default implementation is almost always sufficient, and should not be overridden without very good reason.
Source§

impl Copy for ClosestPoints

Source§

impl StructuralPartialEq for ClosestPoints

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dest: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dest. Read more
Source§

impl<T> Downcast for T
where T: Any,

Source§

fn into_any(self: Box<T>) -> Box<dyn Any>

Converts Box<dyn Trait> (where Trait: Downcast) to Box<dyn Any>, which can then be downcast into Box<dyn ConcreteType> where ConcreteType implements Trait.
Source§

fn into_any_rc(self: Rc<T>) -> Rc<dyn Any>

Converts Rc<Trait> (where Trait: Downcast) to Rc<Any>, which can then be further downcast into Rc<ConcreteType> where ConcreteType implements Trait.
Source§

fn as_any(&self) -> &(dyn Any + 'static)

Converts &Trait (where Trait: Downcast) to &Any. This is needed since Rust cannot generate &Any’s vtable from &Trait’s.
Source§

fn as_any_mut(&mut self) -> &mut (dyn Any + 'static)

Converts &mut Trait (where Trait: Downcast) to &Any. This is needed since Rust cannot generate &mut Any’s vtable from &mut Trait’s.
Source§

impl<T> DowncastSend for T
where T: Any + Send,

Source§

fn into_any_send(self: Box<T>) -> Box<dyn Any + Send>

Converts Box<Trait> (where Trait: DowncastSend) to Box<dyn Any + Send>, which can then be downcast into Box<ConcreteType> where ConcreteType implements Trait.
Source§

impl<T> DowncastSync for T
where T: Any + Send + Sync,

Source§

fn into_any_sync(self: Box<T>) -> Box<dyn Any + Sync + Send>

Converts Box<Trait> (where Trait: DowncastSync) to Box<dyn Any + Send + Sync>, which can then be downcast into Box<ConcreteType> where ConcreteType implements Trait.
Source§

fn into_any_arc(self: Arc<T>) -> Arc<dyn Any + Sync + Send>

Converts Arc<Trait> (where Trait: DowncastSync) to Arc<Any>, which can then be downcast into Arc<ConcreteType> where ConcreteType implements Trait.
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> IntoEither for T

Source§

fn into_either(self, into_left: bool) -> Either<Self, Self>

Converts self into a Left variant of Either<Self, Self> if into_left is true. Converts self into a Right variant of Either<Self, Self> otherwise. Read more
Source§

fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
where F: FnOnce(&Self) -> bool,

Converts self into a Left variant of Either<Self, Self> if into_left(&self) returns true. Converts self into a Right variant of Either<Self, Self> otherwise. Read more
Source§

impl<T> Same for T

Source§

type Output = T

Should always be Self
Source§

impl<SS, SP> SupersetOf<SS> for SP
where SS: SubsetOf<SP>,

Source§

fn to_subset(&self) -> Option<SS>

The inverse inclusion map: attempts to construct self from the equivalent element of its superset. Read more
Source§

fn is_in_subset(&self) -> bool

Checks if self is actually part of its subset T (and can be converted to it).
Source§

fn to_subset_unchecked(&self) -> SS

Use with care! Same as self.to_subset but without any property checks. Always succeeds.
Source§

fn from_subset(element: &SS) -> SP

The inclusion map: converts self to the equivalent element of its superset.
Source§

impl<T> ToOwned for T
where T: Clone,

Source§

type Owned = T

The resulting type after obtaining ownership.
Source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
Source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
Source§

impl<T> Scalar for T
where T: 'static + Clone + PartialEq + Debug,