From 71ebce27a99223189a709193ba706d112e92c437 Mon Sep 17 00:00:00 2001 From: William Linna Date: Wed, 1 May 2024 22:00:09 +0300 Subject: [PATCH 1/3] Treat TriMesh as solid in project_local_point_and_get_feature with = dim2 --- crates/parry2d/tests/query/mod.rs | 1 + .../tests/query/point_composite_shape.rs | 26 +++++++++++++++++++ src/query/point/point_composite_shape.rs | 7 ++++- 3 files changed, 33 insertions(+), 1 deletion(-) create mode 100644 crates/parry2d/tests/query/point_composite_shape.rs diff --git a/crates/parry2d/tests/query/mod.rs b/crates/parry2d/tests/query/mod.rs index b06213c4..e74740f2 100644 --- a/crates/parry2d/tests/query/mod.rs +++ b/crates/parry2d/tests/query/mod.rs @@ -1 +1,2 @@ +mod point_composite_shape; mod point_triangle; diff --git a/crates/parry2d/tests/query/point_composite_shape.rs b/crates/parry2d/tests/query/point_composite_shape.rs new file mode 100644 index 00000000..53064c6c --- /dev/null +++ b/crates/parry2d/tests/query/point_composite_shape.rs @@ -0,0 +1,26 @@ +use na::Point2; +use parry2d::{query::PointQuery, shape::TriMesh}; + +#[test] +fn project_local_point_and_get_feature_gets_the_enclosing_triangle() { + let vertices = vec![ + Point2::new(0.0, 1.0), + Point2::new(0.0, 0.0), + Point2::new(1.0, 0.0), + Point2::new(1.0, 1.0), + ]; + + let mesh = TriMesh::new(vertices, vec![[0, 1, 2], [3, 0, 2]]); + let query_pt = Point2::new(0.6, 0.6); // Inside the top-right triangle (index 1) + + let (proj, feat) = mesh.project_local_point_and_get_feature(&query_pt); + + let correct_tri_idx = 1; + let correct_tri = mesh.triangle(correct_tri_idx); + + let is_inside_correct = correct_tri.contains_local_point(&query_pt); + + assert!(is_inside_correct); + assert_eq!(proj.is_inside, is_inside_correct); + assert_eq!(feat.unwrap_face(), correct_tri_idx); +} diff --git a/src/query/point/point_composite_shape.rs b/src/query/point/point_composite_shape.rs index d28dd5b5..1f2d8e26 100644 --- a/src/query/point/point_composite_shape.rs +++ b/src/query/point/point_composite_shape.rs @@ -61,8 +61,13 @@ impl PointQuery for TriMesh { return (proj, feature_id); } + #[cfg(feature = "dim3")] + let solid = false; + #[cfg(feature = "dim2")] + let solid = true; + let mut visitor = - PointCompositeShapeProjWithFeatureBestFirstVisitor::new(self, point, false); + PointCompositeShapeProjWithFeatureBestFirstVisitor::new(self, point, solid); let (proj, (id, _feature)) = self.qbvh().traverse_best_first(&mut visitor).unwrap().1; let feature_id = FeatureId::Face(id); (proj, feature_id) From ea29ba519a5b2c706e265503c114973eb9cc9d98 Mon Sep 17 00:00:00 2001 From: William Linna Date: Wed, 1 May 2024 23:00:07 +0300 Subject: [PATCH 2/3] Clean replace two cfg-feature checks with one Co-authored-by: Benjamin Saunders --- src/query/point/point_composite_shape.rs | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/query/point/point_composite_shape.rs b/src/query/point/point_composite_shape.rs index 1f2d8e26..8ddcf5b2 100644 --- a/src/query/point/point_composite_shape.rs +++ b/src/query/point/point_composite_shape.rs @@ -61,10 +61,7 @@ impl PointQuery for TriMesh { return (proj, feature_id); } - #[cfg(feature = "dim3")] - let solid = false; - #[cfg(feature = "dim2")] - let solid = true; + let solid = cfg!(feature = "dim2"); let mut visitor = PointCompositeShapeProjWithFeatureBestFirstVisitor::new(self, point, solid); From edeca5e45fcf246712116486306d4584b9c902af Mon Sep 17 00:00:00 2001 From: William Linna Date: Wed, 1 May 2024 23:11:30 +0300 Subject: [PATCH 3/3] Add tests to ensure project_local_point_and_get_feature works from outside --- .../tests/query/point_composite_shape.rs | 43 +++++++++++++++++++ 1 file changed, 43 insertions(+) diff --git a/crates/parry2d/tests/query/point_composite_shape.rs b/crates/parry2d/tests/query/point_composite_shape.rs index 53064c6c..a289a50b 100644 --- a/crates/parry2d/tests/query/point_composite_shape.rs +++ b/crates/parry2d/tests/query/point_composite_shape.rs @@ -24,3 +24,46 @@ fn project_local_point_and_get_feature_gets_the_enclosing_triangle() { assert_eq!(proj.is_inside, is_inside_correct); assert_eq!(feat.unwrap_face(), correct_tri_idx); } + +#[test] +fn project_local_point_and_get_feature_projects_correctly_from_outside() { + let vertices = vec![ + Point2::new(0.0, 1.0), + Point2::new(0.0, 0.0), + Point2::new(1.0, 0.0), + Point2::new(1.0, 1.0), + ]; + + let mesh = TriMesh::new(vertices, vec![[0, 1, 2], [3, 0, 2]]); + + { + let query_pt = Point2::new(-1.0, 0.0); // Inside the top-right triangle (index 1) + + let (proj, feat) = mesh.project_local_point_and_get_feature(&query_pt); + + let correct_tri_idx = 0; + let correct_tri = mesh.triangle(correct_tri_idx); + + let is_inside_correct = correct_tri.contains_local_point(&query_pt); + + assert_eq!(is_inside_correct, false); + assert_eq!(proj.is_inside, is_inside_correct); + assert_eq!(proj.point, Point2::origin()); + assert_eq!(feat.unwrap_face(), correct_tri_idx); + } + { + let query_pt = Point2::new(0.5, 2.0); // Inside the top-right triangle (index 1) + + let (proj, feat) = mesh.project_local_point_and_get_feature(&query_pt); + + let correct_tri_idx = 1; + let correct_tri = mesh.triangle(correct_tri_idx); + + let is_inside_correct = correct_tri.contains_local_point(&query_pt); + + assert_eq!(is_inside_correct, false); + assert_eq!(proj.is_inside, is_inside_correct); + assert_eq!(proj.point, Point2::new(0.5, 1.0)); + assert_eq!(feat.unwrap_face(), correct_tri_idx); + } +}