Skip to content

Commit

Permalink
Do a cheap bouding box collission check before doing an expensive lin…
Browse files Browse the repository at this point in the history
…e intersection test
  • Loading branch information
manuelVo committed Oct 20, 2022
1 parent 0f0d78d commit f96c4e0
Show file tree
Hide file tree
Showing 2 changed files with 55 additions and 3 deletions.
43 changes: 43 additions & 0 deletions rust/src/geometry.rs
Original file line number Diff line number Diff line change
Expand Up @@ -179,9 +179,52 @@ impl LineSegment {
}
between(intersection.x, self.p1.x, self.p2.x)
}

pub fn bounding_rect(&self) -> Rect {
let (left, right) = minmax(self.p1.x, self.p2.x);
let (top, bottom) = minmax(self.p1.y, self.p2.y);
Rect {
left,
right,
top,
bottom,
}
}
}

pub fn between<T: Copy + PartialOrd>(num: T, a: T, b: T) -> bool {
let (min, max) = if a < b { (a, b) } else { (b, a) };
num >= min && num <= max
}

pub fn minmax<T: PartialOrd>(a: T, b: T) -> (T, T) {
if a <= b {
(a, b)
} else {
(b, a)
}
}

pub fn minmax_by_key<T, F: Fn(&T) -> K, K: PartialOrd>(a: T, b: T, f: F) -> (T, T) {
if f(&a) < f(&b) {
(a, b)
} else {
(b, a)
}
}

#[derive(Debug, Clone, Copy)]
pub struct Rect {
pub left: f64,
pub right: f64,
pub top: f64,
pub bottom: f64,
}

impl Rect {
pub fn intersects(&self, other: &Rect) -> bool {
let (left_rect, right_rect) = minmax_by_key(self, other, |rect| rect.left);
let (top_rect, bottom_rect) = minmax_by_key(self, other, |rect| rect.top);
left_rect.right >= right_rect.left && top_rect.bottom >= bottom_rect.top
}
}
15 changes: 12 additions & 3 deletions rust/src/pathfinder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -150,11 +150,20 @@ impl Pathfinder {
}

fn points_connected(p1: Point, p2: Point, walls: &[LineSegment]) -> bool {
!Self::collides_with_wall(&LineSegment::new(p1, p2), walls)
!Self::collides_with_any_wall(&LineSegment::new(p1, p2), walls)
}

fn collides_with_wall(line: &LineSegment, walls: &[LineSegment]) -> bool {
fn collides_with_any_wall(line: &LineSegment, walls: &[LineSegment]) -> bool {
// TODO Directional walls
walls.iter().any(|wall| line.intersection(wall).is_some())
walls
.iter()
.any(|wall| Self::collides_with_wall(line, wall))
}

fn collides_with_wall(line: &LineSegment, wall: &LineSegment) -> bool {
if !line.bounding_rect().intersects(&wall.bounding_rect()) {
return false;
}
line.intersection(wall).is_some()
}
}

0 comments on commit f96c4e0

Please sign in to comment.