### 3D Ray Casting Example Source: https://parry.rs/docs/user_guide/geometric_queries Demonstrates 3D ray casting on a cuboid with different `solid` flag settings. ```APIDOC ## 3D Ray Casting Example ### Description This example illustrates 3D ray casting against a cuboid. Similar to the 2D example, `ray_inside` originates within the cuboid, and `ray_miss` is designed not to intersect. ### Code ```rust let cuboid = Cuboid::new(Vector3::new(1.0, 2.0, 1.0)); let ray_inside = Ray::new(Point3::origin(), Vector3::y()); let ray_miss = Ray::new(Point3::new(2.0, 2.0, 2.0), Vector3::new(1.0, 1.0, 1.0)); // Solid cast with ray_inside assert!(cuboid.toi_with_ray(&Isometry3::identity(), &ray_inside, true).unwrap() == 0.0); // Non-solid cast with ray_inside assert!(cuboid.toi_with_ray(&Isometry3::identity(), &ray_inside, false).unwrap() == 2.0); // Casting ray_miss fails in both solid and non-solid modes assert!(cuboid.toi_with_ray(&Isometry3::identity(), &ray_miss, false).is_none()); assert!(cuboid.toi_with_ray(&Isometry3::identity(), &ray_miss, true).is_none()); ``` ``` -------------------------------- ### Complete Cargo.toml Example for Parry3D Source: https://parry.rs/docs/user_guide/getting_started A full Cargo.toml example demonstrating how to include the parry3d dependency for a Rust project. Ensure to replace '*' with the latest version number. ```toml [package] name = "example-using-Parry" version = "0.0.0" authors = [ "You" ] [dependencies] // TODO: replace the * by the latest version number. parry3d = "*" [[bin]] name = "example" path = "./example.rs" ``` -------------------------------- ### 2D Ray Casting Example Source: https://parry.rs/docs/user_guide/geometric_queries Demonstrates 2D ray casting on a cuboid with different `solid` flag settings. ```APIDOC ## 2D Ray Casting Example ### Description This example shows ray casting against a 2D cuboid. `ray_inside` starts within the cuboid, while `ray_miss` does not intersect. ### Code ```rust let cuboid = Cuboid::new(Vector2::new(1.0, 2.0)); let ray_inside = Ray::new(Point2::origin(), Vector2::y()); let ray_miss = Ray::new(Point2::new(2.0, 2.0), Vector2::new(1.0, 1.0)); // Solid cast with ray_inside assert_eq!( cuboid.toi_with_ray(&Isometry2::identity(), &ray_inside, true).unwrap(), 0.0 ); // Non-solid cast with ray_inside assert_eq!( cuboid.toi_with_ray(&Isometry2::identity(), &ray_inside, false).unwrap(), 2.0 ); // Casting ray_miss fails in both solid and non-solid modes assert!(cuboid.toi_with_ray(&Isometry2::identity(), &ray_miss, false).is_none()); assert!(cuboid.toi_with_ray(&Isometry2::identity(), &ray_miss, true).is_none()); ``` ``` -------------------------------- ### Complete Cargo.toml Example for Parry2D Source: https://parry.rs/docs/user_guide/getting_started A full Cargo.toml example demonstrating how to include the parry2d dependency for a Rust project. Ensure to replace '*' with the latest version number. ```toml [package] name = "example-using-Parry" version = "0.0.0" authors = [ "You" ] [dependencies] // TODO: replace the * by the latest version number. parry2d = "*" [[bin]] name = "example" path = "./example.rs" ``` -------------------------------- ### Compute and test bounding spheres Source: https://parry.rs/docs/user_guide/bounding_volumes Examples demonstrating the creation, merging, and testing of bounding spheres for 2D and 3D cuboids. ```rust /* * Initialize the shapes. */ let cube1 = Cuboid::new(Vector2::repeat(0.5)); let cube2 = Cuboid::new(Vector2::new(1.0, 0.5)); let cube1_pos = Isometry2::new(Vector2::y(), na::zero()); // 1.0 along the `y` axis. let cube2_pos = Isometry2::identity(); // Identity transformation. /* * Compute their bounding spheres. */ let bounding_sphere_cube1 = bounding_volume::bounding_sphere(&cube1, &cube1_pos); let bounding_sphere_cube2 = bounding_volume::bounding_sphere(&cube2, &cube2_pos); // Merge the two spheres. let bounding_bounding_sphere = bounding_sphere_cube1.merged(&bounding_sphere_cube2); // Enlarge the cube2 bounding sphere. let loose_bounding_sphere_cube2 = bounding_sphere_cube2.loosened(1.0); // Intersection and inclusion tests. assert!(bounding_sphere_cube1.intersects(&bounding_sphere_cube2)); assert!(bounding_bounding_sphere.contains(&bounding_sphere_cube1)); assert!(bounding_bounding_sphere.contains(&bounding_sphere_cube2)); assert!(!bounding_sphere_cube2.contains(&bounding_bounding_sphere)); assert!(!bounding_sphere_cube1.contains(&bounding_bounding_sphere)); assert!(loose_bounding_sphere_cube2.contains(&bounding_sphere_cube2)); ``` ```rust /* * Initialize the shapes. */ let cube1 = Cuboid::new(Vector3::repeat(0.5)); let cube2 = Cuboid::new(Vector3::new(0.5, 1.0, 0.5)); let cube1_pos = Isometry3::new(Vector3::z(), na::zero()); // 1.0 along the `z` axis. let cube2_pos = Isometry3::identity(); // Identity transformation. /* * Compute their bounding spheres. */ let bounding_sphere_cube1 = bounding_volume::bounding_sphere(&cube1, &cube1_pos); let bounding_sphere_cube2 = bounding_volume::bounding_sphere(&cube2, &cube2_pos); // Merge the two spheres. let bounding_bounding_sphere = bounding_sphere_cube1.merged(&bounding_sphere_cube2); // Enlarge the cube2 bounding sphere. let loose_bounding_sphere_cube2 = bounding_sphere_cube2.loosened(1.0); // Intersection and inclusion tests. assert!(bounding_sphere_cube1.intersects(&bounding_sphere_cube2)); assert!(bounding_bounding_sphere.contains(&bounding_sphere_cube1)); assert!(bounding_bounding_sphere.contains(&bounding_sphere_cube2)); assert!(!bounding_sphere_cube2.contains(&bounding_bounding_sphere)); assert!(!bounding_sphere_cube1.contains(&bounding_bounding_sphere)); assert!(loose_bounding_sphere_cube2.contains(&bounding_sphere_cube2)); ``` -------------------------------- ### 3D Contact Determination Example Source: https://parry.rs/docs/user_guide/geometric_queries Illustrates the `query::contact` function for 3D shapes (Cuboid and Ball). It tests scenarios of penetration, proximity within prediction, and separation. Assertions validate the resulting contact depth. ```rust let cuboid = Cuboid::new(Vector3::new(1.0, 1.0, 1.0)); let ball = Ball::new(1.0); let prediction = 1.0; let cuboid_pos = na::one(); let ball_pos_penetrating = Isometry3::new(Vector3::new(1.0, 1.0, 1.0), na::zero()); let ball_pos_in_prediction = Isometry3::new(Vector3::new(2.0, 2.0, 2.0), na::zero()); let ball_pos_too_far = Isometry3::new(Vector3::new(3.0, 3.0, 3.0), na::zero()); let ctct_penetrating = query::contact(&ball_pos_penetrating, &ball, &cuboid_pos, &cuboid, prediction); let ctct_in_prediction = query::contact(&ball_pos_in_prediction, &ball, &cuboid_pos, &cuboid, prediction); let ctct_too_far = query::contact(&ball_pos_too_far, &ball, &cuboid_pos, &cuboid, prediction); assert!(ctct_penetrating.unwrap().depth > 0.0); assert!(ctct_in_prediction.unwrap().depth < 0.0); assert_eq!(ctct_too_far, None); ``` -------------------------------- ### 2D Contact Determination Example Source: https://parry.rs/docs/user_guide/geometric_queries Demonstrates the `query::contact` function for 2D shapes (Cuboid and Ball). It checks three scenarios: penetrating, within prediction distance, and too far apart. Asserts verify the expected depth values. ```rust let cuboid = Cuboid::new(Vector2::new(1.0, 1.0)); let ball = Ball::new(1.0); let prediction = 1.0; let cuboid_pos = na::one(); let ball_pos_penetrating = Isometry2::new(Vector2::new(1.0, 1.0), na::zero()); let ball_pos_in_prediction = Isometry2::new(Vector2::new(2.0, 2.0), na::zero()); let ball_pos_too_far = Isometry2::new(Vector2::new(3.0, 3.0), na::zero()); let ctct_penetrating = query::contact(&ball_pos_penetrating, &ball, &cuboid_pos, &cuboid, prediction); let ctct_in_prediction = query::contact(&ball_pos_in_prediction, &ball, &cuboid_pos, &cuboid, prediction); let ctct_too_far = query::contact(&ball_pos_too_far, &ball, &cuboid_pos, &cuboid, prediction); assert!(ctct_penetrating.unwrap().depth > 0.0); assert!(ctct_in_prediction.unwrap().depth < 0.0); assert_eq!(ctct_too_far, None); ``` -------------------------------- ### Perform 3D ray casting on a cuboid Source: https://parry.rs/docs/user_guide/geometric_queries Demonstrates solid and non-solid ray casting against a 3D cuboid, including cases where the ray starts inside or misses the shape. ```rust let cuboid = Cuboid::new(Vector3::new(1.0, 2.0, 1.0)); let ray_inside = Ray::new(Point3::origin(), Vector3::y()); let ray_miss = Ray::new(Point3::new(2.0, 2.0, 2.0), Vector3::new(1.0, 1.0, 1.0)); // Solid cast. assert!(cuboid.toi_with_ray(&Isometry3::identity(), &ray_inside, true).unwrap() == 0.0); // Non-solid cast. assert!(cuboid.toi_with_ray(&Isometry3::identity(), &ray_inside, false).unwrap() == 2.0); // The other ray does not intersect this shape. assert!(cuboid.toi_with_ray(&Isometry3::identity(), &ray_miss, false).is_none()); assert!(cuboid.toi_with_ray(&Isometry3::identity(), &ray_miss, true).is_none()); ``` -------------------------------- ### Perform 2D ray casting on a cuboid Source: https://parry.rs/docs/user_guide/geometric_queries Demonstrates solid and non-solid ray casting against a 2D cuboid, including cases where the ray starts inside or misses the shape. ```rust let cuboid = Cuboid::new(Vector2::new(1.0, 2.0)); let ray_inside = Ray::new(Point2::origin(), Vector2::y()); let ray_miss = Ray::new(Point2::new(2.0, 2.0), Vector2::new(1.0, 1.0)); // Solid cast. assert_eq!( cuboid.toi_with_ray(&Isometry2::identity(), &ray_inside, true).unwrap(), 0.0 ); // Non-solid cast. assert_eq!( cuboid.toi_with_ray(&Isometry2::identity(), &ray_inside, false).unwrap(), 2.0 ); // The other ray does not intersect this shape. assert!(cuboid.toi_with_ray(&Isometry2::identity(), &ray_miss, false).is_none()); assert!(cuboid.toi_with_ray(&Isometry2::identity(), &ray_miss, true).is_none()); ``` -------------------------------- ### Initialize a Cylinder Source: https://parry.rs/docs/user_guide/geometric_representations Create a 3D cylinder and verify its dimensions. ```rust let cylinder = Cylinder::new(0.5f32, 1.0); assert!(cylinder.half_height() == 0.5); assert!(cylinder.radius() == 1.0); ``` -------------------------------- ### Initialize a Capsule Source: https://parry.rs/docs/user_guide/geometric_representations Create a capsule and verify its half height and extremity radius. ```rust let capsule = Capsule::new(0.5f32, 0.75); assert!(capsule.half_height() == 0.5); assert!(capsule.radius() == 0.75); ``` -------------------------------- ### Initialize a Cone Source: https://parry.rs/docs/user_guide/geometric_representations Create a cone of revolution and verify its radius and half height. ```rust let cone = Cone::new(0.5f32, 0.75); assert!(cone.half_height() == 0.5); assert!(cone.radius() == 0.75); ``` -------------------------------- ### Initialize a Ball Source: https://parry.rs/docs/user_guide/geometric_representations Create a new Ball instance and verify its radius. ```rust let ball = Ball::new(1.0f32); assert!(ball.radius() == 1.0); ``` -------------------------------- ### ConvexPolygon and ConvexHull Creation Source: https://parry.rs/docs/user_guide/geometric_representations Demonstrates how to create 2D ConvexPolygon and 3D ConvexHull shapes from a set of points using `try_from_points` and `try_new` constructors. ```APIDOC ## ConvexPolygon and ConvexHull Creation ### Description This section covers the creation of `ConvexPolygon` (2D) and `ConvexHull` (3D) shapes. These structures represent the smallest convex envelope of a set of points. Two primary methods are available: `::try_from_points` which computes the convex hull, and `::try_new` which expects pre-computed hull data. ### `::try_from_points` Constructor Computes the convex hull directly from a given set of points. #### Example 2D ```rust let points = [ Point2::new(-1.0f32, 1.0), Point2::new(-0.5, -0.5), Point2::new(0.0, 0.5), Point2::new(0.5, -0.5), Point2::new(1.0, 1.0), ]; let convex = ConvexPolygon::try_from_points(&points).expect("Convex hull computation failed."); assert!(convex.points().len() == 4); ``` #### Example 3D ```rust let points = [ Point3::new(0.0f32, 0.0, 1.0), Point3::new(0.0, 0.0, -1.0), Point3::new(0.0, 1.0, 0.0), Point3::new(0.0, -1.0, 0.0), Point3::new(1.0, 0.0, 0.0), Point3::new(-1.0, 0.0, 0.0), Point3::new(0.0, 0.0, 0.0) ]; let convex = ConvexHull::try_from_points(&points).expect("Convex hull computation failed."); assert!(convex.points().len() == 6); ``` ### `::try_new` Constructor Creates a convex shape directly from provided vertices (and indices for 3D). This method assumes the input data already represents a valid convex hull. #### Example 2D ```rust let points = vec![ Point2::new(-1.0f32, 1.0), Point2::new(-0.5, -0.5), Point2::new(0.5, -0.5), Point2::new(1.0, 1.0), ]; let convex = ConvexPolygon::try_new(points).expect("Invalid convex polygon."); assert!(convex.points().len() == 4); ``` #### Example 3D ```rust let points = vec![ Point3::new(0.0f32, 0.0, 1.0), Point3::new(0.0, 0.0, -1.0), Point3::new(0.0, 1.0, 0.0), Point3::new(0.0, -1.0, 0.0), Point3::new(1.0, 0.0, 0.0), Point3::new(-1.0, 0.0, 0.0), ]; let indices = vec![ 0, 4, 2, 0, 3, 4, 5, 0, 2, 5, 3, 0, 1, 5, 2, 1, 3, 5, 4, 1, 2, 4, 3, 1, ]; let convex = ConvexHull::try_new(points, &indices).expect("Invalid convex shape."); assert!(convex.points().len() == 6); ``` ### Important Considerations - `::try_new` does not explicitly check for convexity. Ensure your input data is indeed convex to avoid unexpected results. - For `::try_new` in 2D, vertices must be ordered counterclockwise. - For `::try_new` in 3D, the index buffer must define triangles oriented counterclockwise, pointing outwards. ``` -------------------------------- ### Create TriMesh Shapes Source: https://parry.rs/docs/user_guide/geometric_representations Construct a 3D triangle mesh using vertex and index buffers. ```rust let points = vec![ Point3::new(0.0, 1.0, 0.0), Point3::new(-1.0, -0.5, 0.0), Point3::new(0.0, -0.5, -1.0), Point3::new(1.0, -0.5, 0.0), ]; let indices = vec![ Point3::new(0usize, 1, 2), Point3::new(0, 2, 3), Point3::new(0, 3, 1), ]; // Build the mesh. let mesh = TriMesh::new(points, indices, None); assert!(mesh.vertices().len() == 4); ``` -------------------------------- ### Initialize a Cuboid Source: https://parry.rs/docs/user_guide/geometric_representations Create 2D and 3D cuboids defined by their half extents. ```rust let cuboid = Cuboid::new(Vector2::new(2.0f32, 1.0)); assert!(cuboid.half_extents().x == 2.0); assert!(cuboid.half_extents().y == 1.0); ``` ```rust let cuboid = Cuboid::new(Vector3::new(2.0f32, 1.0, 3.0)); assert!(cuboid.half_extents().x == 2.0); assert!(cuboid.half_extents().y == 1.0); assert!(cuboid.half_extents().z == 3.0); ``` -------------------------------- ### Compute and Test AABBs in 2D and 3D Source: https://parry.rs/docs/user_guide/bounding_volumes Demonstrates initializing shapes, computing AABBs, merging them, and performing intersection and inclusion tests. ```rust /* * Initialize the shapes. */ let ball1 = Ball::new(0.5); let ball2 = Ball::new(1.0); let ball1_pos = Isometry2::new(Vector2::y(), na::zero()); // 1.0 along the `y` axis. let ball2_pos = Isometry2::identity(); // Identity matrix. /* * Compute their axis-aligned bounding boxes. */ let aabb_ball1 = bounding_volume::aabb(&ball1, &ball1_pos); let aabb_ball2 = bounding_volume::aabb(&ball2, &ball2_pos); // Merge the two boxes. let bounding_aabb = aabb_ball1.merged(&aabb_ball2); // Enlarge the ball2 aabb. let loose_aabb_ball2 = aabb_ball2.loosened(1.0); // Intersection and inclusion tests. assert!(aabb_ball1.intersects(&aabb_ball2)); assert!(bounding_aabb.contains(&aabb_ball1)); assert!(bounding_aabb.contains(&aabb_ball2)); assert!(!aabb_ball2.contains(&bounding_aabb)); assert!(!aabb_ball1.contains(&bounding_aabb)); assert!(loose_aabb_ball2.contains(&aabb_ball2)); ``` ```rust /* * Initialize the shapes. */ let ball1 = Ball::new(0.5); let ball2 = Ball::new(1.0); let ball1_pos = Isometry3::new(Vector3::y(), na::zero()); // 1.0 along the `y` axis. let ball2_pos = Isometry3::identity(); // Identity matrix. /* * Compute their axis-aligned bounding boxes. */ let aabb_ball1 = bounding_volume::aabb(&ball1, &ball1_pos); let aabb_ball2 = bounding_volume::aabb(&ball2, &ball2_pos); // Merge the two boxes. let bounding_aabb = aabb_ball1.merged(&aabb_ball2); // Enlarge the ball2 aabb. let loose_aabb_ball2 = aabb_ball2.loosened(1.0); // Intersection and inclusion tests. assert!(aabb_ball1.intersects(&aabb_ball2)); assert!(bounding_aabb.contains(&aabb_ball1)); assert!(bounding_aabb.contains(&aabb_ball2)); assert!(!aabb_ball2.contains(&bounding_aabb)); assert!(!aabb_ball1.contains(&bounding_aabb)); assert!(loose_aabb_ball2.contains(&aabb_ball2)); ``` -------------------------------- ### Add Parry2D Dependency to Cargo.toml Source: https://parry.rs/docs/user_guide/getting_started Add the parry2d crate to your Cargo.toml file to include 2D geometry functionalities. Replace '*' with the desired version. ```toml [dependencies] parry2d = "*" ``` -------------------------------- ### Add Parry3D Dependency to Cargo.toml Source: https://parry.rs/docs/user_guide/getting_started Add the parry3d crate to your Cargo.toml file to include 3D geometry functionalities. Replace '*' with the desired version. ```toml [dependencies] parry3d = "*" ``` -------------------------------- ### Calculate Time of Impact in 3D Source: https://parry.rs/docs/user_guide/geometric_queries Demonstrates calculating the time of impact for 3D shapes including intersecting, touching, and non-intersecting scenarios. ```rust let cuboid = Cuboid::new(Vector3::new(1.0, 1.0, 1.0)); let ball = Ball::new(1.0); let cuboid_pos = na::one(); let ball_pos_intersecting = Isometry3::new(Vector3::new(1.0, 1.0, 1.0), na::zero()); let ball_pos_will_touch = Isometry3::new(Vector3::new(2.0, 2.0, 2.0), na::zero()); let ball_pos_wont_touch = Isometry3::new(Vector3::new(3.0, 3.0, 3.0), na::zero()); let box_vel1 = Vector3::new(-1.0, 1.0, 1.0); let box_vel2 = Vector3::new(1.0, 1.0, 1.0); let ball_vel1 = Vector3::new(2.0, 2.0, 2.0); let ball_vel2 = Vector3::new(-0.5, -0.5, -0.5); let toi_intersecting = query::time_of_impact(&ball_pos_intersecting, &ball_vel1, &ball, &cuboid_pos, &box_vel1, &cuboid); let toi_will_touch = query::time_of_impact(&ball_pos_will_touch, &ball_vel2, &ball, &cuboid_pos, &box_vel2, &cuboid); let toi_wont_touch = query::time_of_impact(&ball_pos_wont_touch, &ball_vel1, &ball, &cuboid_pos, &box_vel1, &cuboid); assert_eq!(toi_intersecting, Some(0.0)); assert!(toi_will_touch.is_some() && toi_will_touch.unwrap() > 0.0); assert_eq!(toi_wont_touch, None); ``` -------------------------------- ### Create 3D Convex Hull Directly Source: https://parry.rs/docs/user_guide/geometric_representations Use `ConvexHull::try_new` when you can provide the points and indices for a 3D convex hull. The indices must define counterclockwise-oriented triangles. ```rust let points = vec![ Point3::new(0.0f32, 0.0, 1.0), Point3::new(0.0, 0.0, -1.0), Point3::new(0.0, 1.0, 0.0), Point3::new(0.0, -1.0, 0.0), Point3::new(1.0, 0.0, 0.0), Point3::new(-1.0, 0.0, 0.0), ]; let indices = vec![ 0, 4, 2, 0, 3, 4, 5, 0, 2, 5, 3, 0, 1, 5, 2, 1, 3, 5, 4, 1, 2, 4, 3, 1, ]; let convex = ConvexHull::try_new(points, &indices).expect("Invalid convex shape."); assert!(convex.points().len() == 6); ``` -------------------------------- ### Solid vs. Non-Solid Ray Casting Source: https://parry.rs/docs/user_guide/geometric_queries Explains the behavior of ray casting when the ray's origin is inside a shape, depending on the `solid` flag. ```APIDOC ## Solid vs. Non-Solid Ray Casting ### Description When the origin of a ray is inside a shape, the `solid` flag in ray casting methods dictates the outcome: - **`solid: true`**: A solid ray cast returns an intersection with `toi` set to 0.0 and an undefined normal. This is typically faster. - **`solid: false`**: A non-solid ray cast treats the shape as hollow and continues until it hits a boundary, returning a non-zero `toi`. If the ray origin is outside the shape, the `solid` flag has no effect. ``` -------------------------------- ### Calculate Time of Impact in 2D Source: https://parry.rs/docs/user_guide/geometric_queries Demonstrates calculating the time of impact for 2D shapes including intersecting, touching, and non-intersecting scenarios. ```rust let cuboid = Cuboid::new(Vector2::new(1.0, 1.0)); let ball = Ball::new(1.0); let cuboid_pos = na::one(); let ball_pos_intersecting = Isometry2::new(Vector2::new(1.0, 1.0), na::zero()); let ball_pos_will_touch = Isometry2::new(Vector2::new(2.0, 2.0), na::zero()); let ball_pos_wont_touch = Isometry2::new(Vector2::new(3.0, 3.0), na::zero()); let box_vel1 = Vector2::new(-1.0, 1.0); let box_vel2 = Vector2::new(1.0, 1.0); let ball_vel1 = Vector2::new(2.0, 2.0); let ball_vel2 = Vector2::new(-0.5, -0.5); let toi_intersecting = query::time_of_impact(&ball_pos_intersecting, &ball_vel1, &ball, &cuboid_pos, &box_vel1, &cuboid); let toi_will_touch = query::time_of_impact(&ball_pos_will_touch, &ball_vel2, &ball, &cuboid_pos, &box_vel2, &cuboid); let toi_wont_touch = query::time_of_impact(&ball_pos_wont_touch, &ball_vel1, &ball, &cuboid_pos, &box_vel1, &cuboid); assert_eq!(toi_intersecting, Some(0.0)); assert!(toi_will_touch.is_some() && toi_will_touch.unwrap() > 0.0); assert_eq!(toi_wont_touch, None); ``` -------------------------------- ### Projecting points on a 3D cuboid Source: https://parry.rs/docs/user_guide/geometric_queries Demonstrates distance calculation for points inside and outside a 3D cuboid using solid and non-solid projection modes. ```rust let cuboid = Cuboid::new(Vector3::new(1.0, 2.0, 2.0)); let pt_inside = Point3::origin(); let pt_outside = Point3::new(2.0, 2.0, 2.0); // Solid projection. assert_eq!(cuboid.distance_to_point(&Isometry3::identity(), &pt_inside, true), 0.0); // Non-solid projection. assert_eq!( cuboid.distance_to_point(&Isometry3::identity(), &pt_inside, false), -1.0 ); // The other point is outside of the cuboid so the `solid` flag has no effect. assert_eq!( cuboid.distance_to_point(&Isometry3::identity(), &pt_outside, false), 1.0 ); assert_eq!(cuboid.distance_to_point(&Isometry3::identity(), &pt_outside, true), 1.0); ``` -------------------------------- ### Projecting points on a 2D cuboid Source: https://parry.rs/docs/user_guide/geometric_queries Demonstrates distance calculation for points inside and outside a 2D cuboid using solid and non-solid projection modes. ```rust let cuboid = Cuboid::new(Vector2::new(1.0, 2.0)); let pt_inside = Point2::origin(); let pt_outside = Point2::new(2.0, 2.0); // Solid projection. assert_eq!(cuboid.distance_to_point(&Isometry2::identity(), &pt_inside, true), 0.0); // Non-solid projection. assert_eq!( cuboid.distance_to_point(&Isometry2::identity(), &pt_inside, false), -1.0 ); // The other point is outside of the cuboid so the `solid` flag has no effect. assert_eq!( cuboid.distance_to_point(&Isometry2::identity(), &pt_outside, false), 1.0 ); assert_eq!(cuboid.distance_to_point(&Isometry2::identity(), &pt_outside, true), 1.0); ``` -------------------------------- ### BoundingVolume Trait Methods Source: https://parry.rs/docs/user_guide/bounding_volumes Methods available for any type implementing the BoundingVolume trait, used for geometric queries and manipulations. ```APIDOC ## BoundingVolume Trait ### Description Provides methods for intersection tests, containment checks, merging, and morphological operations (dilation/erosion) on bounding volumes. ### Methods #### `.intersects(bv)` - **Description**: Checks `self` for intersection with `bv`. - **Parameters**: `bv` (BoundingVolume) - The other bounding volume to check for intersection. - **Returns**: `bool` - `true` if intersections occur, `false` otherwise. #### `.contains(bv)` - **Description**: Returns `true` if `bv` is completely inside of `self`. - **Parameters**: `bv` (BoundingVolume) - The bounding volume to check for containment. - **Returns**: `bool` - `true` if `bv` is contained within `self`, `false` otherwise. #### `.merge(bv)` - **Description**: Merge `self` and `bv` in-place. - **Parameters**: `bv` (BoundingVolume) - The bounding volume to merge with `self`. #### `.merged(bv)` - **Description**: Returns a bounding volume, result of the merge of `self` with `bv`. - **Parameters**: `bv` (BoundingVolume) - The bounding volume to merge with `self`. - **Returns**: `BoundingVolume` - A new bounding volume representing the merged result. #### `.loosen(m)` - **Description**: Dilates `self` by a ball of radius `m` in-place. - **Parameters**: `m` (f32) - The margin for dilation. #### `.loosened(m)` - **Description**: Returns a copy of `self` dilated by a ball of radius `m`. - **Parameters**: `m` (f32) - The margin for dilation. - **Returns**: `BoundingVolume` - A new, dilated bounding volume. #### `.tighten(m)` - **Description**: Erodes `self` by a ball of radius `m` in-place. - **Parameters**: `m` (f32) - The margin for erosion. #### `.tightened(m)` - **Description**: Returns a copy of `self` eroded by a ball of radius `m`. - **Parameters**: `m` (f32) - The margin for erosion. - **Returns**: `BoundingVolume` - A new, eroded bounding volume. ``` -------------------------------- ### Create Compound Shapes Source: https://parry.rs/docs/user_guide/geometric_representations Initialize a vector of shape handles with relative positions and orientations, then construct the Compound shape. ```rust // Delta transformation matrices. let delta1 = Isometry2::new(Vector2::new(0.0f32, -1.5), na::zero()); let delta2 = Isometry2::new(Vector2::new(-1.5f32, 0.0), na::zero()); let delta3 = Isometry2::new(Vector2::new(1.5f32, 0.0), na::zero()); // 1) Initialize the shape list. let mut shapes = Vec::new(); let horizontal_box = ShapeHandle::new(Cuboid::new(Vector2::new(1.5f32, 0.25))); let vertical_box = ShapeHandle::new(Cuboid::new(Vector2::new(0.25f32, 1.5))); shapes.push((delta1, horizontal_box)); shapes.push((delta2, vertical_box.clone())); shapes.push((delta3, vertical_box)); // 2) Create the compound shape. let compound = Compound::new(shapes); assert!(compound.shapes().len() == 3) ``` ```rust // Delta transformation matrices. let delta1 = Isometry3::new(Vector3::new(0.0f32, -1.5, 0.0), na::zero()); let delta2 = Isometry3::new(Vector3::new(-1.5f32, 0.0, 0.0), na::zero()); let delta3 = Isometry3::new(Vector3::new(1.5f32, 0.0, 0.0), na::zero()); // 1) Initialize the shape list. let mut shapes = Vec::new(); let horizontal_box = ShapeHandle::new(Cuboid::new(Vector3::new(1.5f32, 0.25, 0.25))); let vertical_box = ShapeHandle::new(Cuboid::new(Vector3::new(0.25f32, 1.5, 0.25))); shapes.push((delta1, horizontal_box)); shapes.push((delta2, vertical_box.clone())); shapes.push((delta3, vertical_box)); // 2) Create the compound shape. let compound = Compound::new(shapes); assert!(compound.shapes().len() == 3) ``` -------------------------------- ### Create 2D Convex Polygon Directly Source: https://parry.rs/docs/user_guide/geometric_representations Use `ConvexPolygon::try_new` when you can provide the vertices of a 2D convex polygon directly. Vertices must be ordered counterclockwise. ```rust let points = vec![ Point2::new(-1.0f32, 1.0), Point2::new(-0.5, -0.5), Point2::new(0.5, -0.5), Point2::new(1.0, 1.0), ]; let convex = ConvexPolygon::try_new(points).expect("Invalid convex polygon."); assert!(convex.points().len() == 4); ``` -------------------------------- ### Create 3D Convex Hull from Points Source: https://parry.rs/docs/user_guide/geometric_representations Use `ConvexHull::try_from_points` to compute the convex hull of a set of 3D points. This method explicitly calculates the hull. ```rust let points = [ Point3::new(0.0f32, 0.0, 1.0), Point3::new(0.0, 0.0, -1.0), Point3::new(0.0, 1.0, 0.0), Point3::new(0.0, -1.0, 0.0), Point3::new(1.0, 0.0, 0.0), Point3::new(-1.0, 0.0, 0.0), Point3::new(0.0, 0.0, 0.0) ]; let convex = ConvexHull::try_from_points(&points).expect("Convex hull computation failed."); assert!(convex.points().len() == 6); // The convex hull has only 6 vertices. ``` -------------------------------- ### Create Polyline Shapes Source: https://parry.rs/docs/user_guide/geometric_representations Construct a Polyline from an array of vertices representing contiguous segments. ```rust let points = vec![ Point2::new(0.0, 1.0), Point2::new(-1.0, -1.0), Point2::new(0.0, -0.5), Point2::new(1.0, -1.0), Point2::new(0.0, 1.0), // This forms a loop. ]; // Build the polyline. let polyline = Polyline::new(points); assert!(polyline.vertices().len() == 4); ``` ```rust let points = vec![ Point3::new(0.0, 1.0, 0.0), Point3::new(-1.0, -1.0, 1.0), Point3::new(0.0, -0.5, 0.0), Point3::new(1.0, -1.0, -1.0), Point3::new(0.0, 1.0, 0.0), // This forms a loop. ]; // Build the polyline. let polyline = Polyline::new(points); assert!(polyline.vertices().len() == 5); ``` -------------------------------- ### Create 2D Convex Polygon from Points Source: https://parry.rs/docs/user_guide/geometric_representations Use `ConvexPolygon::try_from_points` to compute the convex hull of a set of 2D points. This method explicitly calculates the hull. ```rust let points = [ Point2::new(-1.0f32, 1.0), Point2::new(-0.5, -0.5), Point2::new(0.0, 0.5), Point2::new(0.5, -0.5), Point2::new(1.0, 1.0), ]; let convex = ConvexPolygon::try_from_points(&points).expect("Convex hull computation failed."); assert!(convex.points().len() == 4); // The convex hull has only 4 vertices. ``` -------------------------------- ### AABB Construction and Manipulation Source: https://parry.rs/docs/user_guide/bounding_volumes Methods for creating, merging, and modifying Axis-Aligned Bounding Boxes. ```APIDOC ## AABB Construction ### Description Methods to initialize and manage AABB structures. ### Methods - **AABB::new(mins, maxs)**: Creates a new AABB. Fails if any component of mins is greater than maxs. - **AABB::new_invalid()**: Unsafe constructor creating an invalid AABB for merging purposes. - **bounding_volume::aabb(g, m)**: Computes the AABB for a shape g at position m. ### Manipulation - **.mins()**: Returns the vertex with smallest coordinates. - **.maxs()**: Returns the vertex with greatest coordinates. - **.merged(other)**: Merges two AABBs. - **.loosened(m)**: Returns an enlarged version of the AABB. - **.tighten(m)**: Returns a shrunk version of the AABB. ### Geometric Tests - **.intersects(other)**: Checks if two AABBs intersect. - **.contains(other)**: Checks if the AABB contains another volume. ``` -------------------------------- ### Support Mappings API Source: https://parry.rs/docs/user_guide/geometric_representations Details on the SupportMap trait and its methods for computing support points. ```APIDOC ## Support Mappings **Parry** supports generic algorithms that work for any (possibly user-defined) shape defined by a support map. The support map (argument) of a shape A is a function that returns the point p that maximises its dot product with a given direction v. Such a point sA(v) is called a _support point_ : sA(v) = argmax p∈A This can be seen as a function that returns a point of the support mapped shape which is _the furthest on the given direction_. Such a function is enough to describe completely a convex object. If several points are eligible to be support points for a given direction v, any one of them can be returned (preferably a corner). The support mapping function is exposed by the `SupportMap` trait. ### Methods - `.support_point(m, v)`: Computes the support point (in the direction `v`) of the caller transformed by the transformation matrix `m`. - `.support_point_toward(m, v)`: Same as `.support_point(...)` except that `v` is already a unit vector. Most basic geometric primitives like balls, cubes, cones, can be described by their support mappings. This allows a useful level of genericity for several geometric queries on **Parry**. ``` -------------------------------- ### Compute 2D Convex Hull Source: https://parry.rs/docs/user_guide/mesh_transformation Computes the convex hull of a set of points using the QuickHull algorithm. ```rust let mut points = Vec::new(); for _ in 0usize..100000 { points.push(rand::random() * 2.0); } let _ = transformation::convex_hull(&points[..]); ``` -------------------------------- ### Composite Shapes Source: https://parry.rs/docs/user_guide/geometric_representations Details on Parry's CompositeShape trait and its implementations: Compound, TriMesh, and Polyline. ```APIDOC ## Composite Shapes ### Description Composite shapes in Parry are formed by aggregating other shapes. They implement the `CompositeShape` trait, providing methods to access individual parts and their transformations. ### `CompositeShape` Trait Methods - `.nparts()`: Returns the number of constituent parts in the composite shape. - `.map_part_at(i, f)`: Applies a closure `f` to the i-th part and its local transformation matrix. - `.map_transformed_part_at(i, m, f)`: Applies a closure `f` to the i-th part, with a transformation matrix `m` prepended. - `.aabb_at(i)`: Returns the Axis-Aligned Bounding Box (AABB) of the i-th part. - `.bvt()`: Accesses the bounding volume tree (BVT) used for spatial partitioning. ### Available Composite Shapes - **`Compound`**: Represents the union of any supported shapes. - **`TriMesh`**: An assembly of triangles. - **`Polyline`**: An assembly of line segments. ### Note on BVT The current requirement to use a BVT for space-partitioning is restrictive and subject to future changes. ``` -------------------------------- ### Shape Trait Object Methods Source: https://parry.rs/docs/user_guide/geometric_representations This section outlines the various methods available on the Shape trait object for inspecting shape properties and capabilities. ```APIDOC ## Shape Trait Object Methods ### Description Methods to inspect shape representation and capabilities. ### Methods - `.aabb(m: &Isometry)` - **Description**: Computes the Axis-Aligned Bounding Box (AABB) of the shape transformed by the given isometry `m`. - **Type**: Method - `.bounding_sphere(m: &Isometry)` - **Description**: Computes the bounding sphere of the shape transformed by the given isometry `m`. - **Type**: Method - `.subshape_transform(i: usize)` - **Description**: If the shape is composite, returns the local transform of its `i`-th part. - **Type**: Method - `.as_ray_cast()` - **Description**: Converts `self` to a `RayCast` trait-object. Returns `None` if the shape does not implement `RayCast`. - **Type**: Method - `.as_point_query()` - **Description**: Converts `self` to a `PointQuery` trait-object. Returns `None` if the shape does not implement `PointQuery`. - **Type**: Method - `.as_convex_polyhedron()` - **Description**: Converts `self` to a `ConvexPolyhedron` trait-object. Returns `None` if the shape does not implement `ConvexPolyhedron`. - **Type**: Method - `.as_support_map()` - **Description**: Converts `self` to a `SupportMap` trait-object. Returns `None` if the shape does not implement `SupportMap`. - **Type**: Method - `.as_composite_shape()` - **Description**: Converts `self` to a `CompositeShape` trait-object. Returns `None` if the shape does not implement `CompositeShape`. - **Type**: Method - `.is_support_map()` - **Description**: Returns `true` if this shape has a support-mapping implementation. - **Type**: Method - `.is_convex_polyhedron()` - **Description**: Returns `true` if this shape has a `ConvexPolyhedron` representation. - **Type**: Method - `.is_composite_shape()` - **Description**: Returns `true` if this shape is a composite shape. - **Type**: Method ### Notes - All conversion methods (`as_*`) have a default implementation returning `None`. - Default implementations for bounding volumes are deduced from the AABB and may result in loose bounding volumes. It is advised to provide custom implementations for optimal performance. ```