Skip to content

Commit b4e5ec2

Browse files
committed
Add 2D segment intersection
1 parent ba73f66 commit b4e5ec2

File tree

1 file changed

+49
-0
lines changed
  • crates/bevy_math/src/primitives

1 file changed

+49
-0
lines changed

crates/bevy_math/src/primitives/dim2.rs

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1521,6 +1521,32 @@ impl Segment2d {
15211521
let t = projection_scaled / length_squared;
15221522
self.vertices[0] + t * segment_vector
15231523
}
1524+
1525+
/// Returns the point of intersection between this [`Segment2d`] and another, if it exists.
1526+
#[inline(always)]
1527+
pub fn intersect(&self, other: Self) -> Option<Vec2> {
1528+
let p = self.point1();
1529+
let q = other.point1();
1530+
let r = self.scaled_direction();
1531+
let s = other.scaled_direction();
1532+
1533+
let r_cross_s = r.perp_dot(s);
1534+
let q_minus_p = q - p;
1535+
1536+
if r_cross_s != 0.0 {
1537+
let t = q_minus_p.perp_dot(s / r_cross_s);
1538+
let u = q_minus_p.perp_dot(r / r_cross_s);
1539+
1540+
let t_in_range = (0.0..=1.0).contains(&t);
1541+
let u_in_range = (0.0..=1.0).contains(&u);
1542+
1543+
if t_in_range && u_in_range {
1544+
return Some(p + t * r);
1545+
}
1546+
}
1547+
1548+
None
1549+
}
15241550
}
15251551

15261552
impl From<[Vec2; 2]> for Segment2d {
@@ -2375,6 +2401,29 @@ mod tests {
23752401
}
23762402
}
23772403

2404+
#[test]
2405+
fn segment_intersect() {
2406+
let isec = Segment2d::new(Vec2::new(0.0, 0.0), Vec2::new(2.0, 2.0))
2407+
.intersect(Segment2d::new(Vec2::new(0.0, 2.0), Vec2::new(2.0, 0.0)));
2408+
assert_eq!(isec, Some(Vec2::new(1.0, 1.0)));
2409+
2410+
let isec = Segment2d::new(Vec2::new(0.0, 0.0), Vec2::new(2.0, 0.0))
2411+
.intersect(Segment2d::new(Vec2::new(0.0, 1.0), Vec2::new(2.0, 1.0)));
2412+
assert_eq!(isec, None);
2413+
2414+
let isec = Segment2d::new(Vec2::new(0.0, 0.0), Vec2::new(1.0, 1.0))
2415+
.intersect(Segment2d::new(Vec2::new(2.0, 2.0), Vec2::new(3.0, 3.0)));
2416+
assert_eq!(isec, None);
2417+
2418+
let isec = Segment2d::new(Vec2::new(0.0, 0.0), Vec2::new(1.0, 1.0))
2419+
.intersect(Segment2d::new(Vec2::new(1.0, 1.0), Vec2::new(2.0, 0.0)));
2420+
assert_eq!(isec, Some(Vec2::new(1.0, 1.0)));
2421+
2422+
let isec = Segment2d::new(Vec2::new(0.0, 0.0), Vec2::new(1.0, 0.0))
2423+
.intersect(Segment2d::new(Vec2::new(2.0, 0.0), Vec2::new(3.0, 0.0)));
2424+
assert_eq!(isec, None);
2425+
}
2426+
23782427
#[test]
23792428
fn circle_math() {
23802429
let circle = Circle { radius: 3.0 };

0 commit comments

Comments
 (0)