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..a289a50b
--- /dev/null
+++ b/crates/parry2d/tests/query/point_composite_shape.rs
@@ -0,0 +1,69 @@
+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);
+}
+
+#[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);
+    }
+}
diff --git a/src/query/point/point_composite_shape.rs b/src/query/point/point_composite_shape.rs
index d28dd5b5..8ddcf5b2 100644
--- a/src/query/point/point_composite_shape.rs
+++ b/src/query/point/point_composite_shape.rs
@@ -61,8 +61,10 @@ impl PointQuery for TriMesh {
             return (proj, feature_id);
         }
 
+        let solid = cfg!(feature = "dim2");
+
         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)