Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
### Fixed

- Fix `clip_aabb_line` crashing when given incorrect inputs (zero length direction or NAN).
- Fix `Segment::intersects_ray` returning false-positive when the segment is zero-length. ([#31](https://github.com/dimforge/parry/issues/31)).

## 0.21.1

Expand Down
9 changes: 7 additions & 2 deletions src/query/ray/ray_support_map.rs
Original file line number Diff line number Diff line change
Expand Up @@ -229,10 +229,15 @@ impl RayCast for Segment {
} else if s >= 0.0 && s <= max_time_of_impact && t >= 0.0 && t <= 1.0 {
let normal = self.normal().map(|n| *n).unwrap_or_else(Vector::zeros);

if normal.dot(&ray.dir) > 0.0 {
let dot = normal.dot(&ray.dir);
if dot > 0.0 {
Some(RayIntersection::new(s, -normal, FeatureId::Face(1)))
} else {
} else if dot < 0.0 {
Some(RayIntersection::new(s, normal, FeatureId::Face(0)))
} else {
// dot == 0 happens when lines are parallel, which is normally handled before,
// but this may happen if segment is zero length, as the ray is not considered parallel.
None
}
} else {
// The closest points are outside of
Expand Down
83 changes: 83 additions & 0 deletions src/shape/segment.rs
Original file line number Diff line number Diff line change
Expand Up @@ -359,3 +359,86 @@ impl ConvexPolyhedron for Segment {
}
}
*/

#[cfg(test)]
mod test {
use crate::query::{Ray, RayCast};

pub use super::*;
#[test]
fn segment_intersect_zero_length_issue_31() {
// never intersect each other
let ray = Ray::new(Point::origin(), Vector::x());
let segment = Segment {
a: Point::new(
10.0,
10.0,
#[cfg(feature = "dim3")]
10.0,
),
b: Point::new(
10.0,
10.0,
#[cfg(feature = "dim3")]
10.0,
),
};

let hit = segment.intersects_ray(&Isometry::identity(), &ray, Real::MAX);
assert_eq!(hit, false);
}
#[test]
fn segment_very_close_points_hit() {
let epsilon = 1.1920929e-7;
// intersect each other
let ray = Ray::new(
Point::new(
epsilon * 0.5,
0.3,
#[cfg(feature = "dim3")]
0.0,
),
-Vector::y(),
);
let segment = Segment {
a: Point::origin(),
b: Point::new(
// Theoretically, epsilon would suffice but imprecisions force us to add some more offset.
epsilon * 1.01,
0.0,
#[cfg(feature = "dim3")]
0.0,
),
};

let hit = segment.intersects_ray(&Isometry::identity(), &ray, Real::MAX);
assert_eq!(hit, true);
}
#[test]
fn segment_very_close_points_no_hit() {
let epsilon = 1.1920929e-7;
// never intersect each other
let ray = Ray::new(
Point::new(
// Theoretically, epsilon would suffice but imprecisions force us to add some more offset.
epsilon * 11.0,
0.1,
#[cfg(feature = "dim3")]
0.0,
),
-Vector::y(),
);
let segment = Segment {
a: Point::origin(),
b: Point::new(
epsilon * 0.9,
0.0,
#[cfg(feature = "dim3")]
0.0,
),
};

let hit = segment.intersects_ray(&Isometry::identity(), &ray, Real::MAX);
assert_eq!(hit, false);
}
}
Loading