Skip to content

Commit

Permalink
Add new Rect::intersects_ray_from_center method
Browse files Browse the repository at this point in the history
  • Loading branch information
grtlr committed Nov 29, 2024
1 parent 10791cc commit cbf64d5
Showing 1 changed file with 77 additions and 0 deletions.
77 changes: 77 additions & 0 deletions crates/emath/src/rect.rs
Original file line number Diff line number Diff line change
Expand Up @@ -671,6 +671,30 @@ impl Rect {

0.0 <= tmax && tmin <= tmax
}

/// Where does a ray from the center intersect the rectangle?
///
/// `d` is the direction of the ray and assumed to be normalized.
pub fn intersects_ray_from_center(&self, d: Vec2) -> Pos2 {
let mut tmin = f32::NEG_INFINITY;
let mut tmax = f32::INFINITY;

for i in 0..2 {
let inv_d = 1.0 / -d[i];
let mut t0 = (self.min[i] - self.center()[i]) * inv_d;
let mut t1 = (self.max[i] - self.center()[i]) * inv_d;

if inv_d < 0.0 {
std::mem::swap(&mut t0, &mut t1);
}

tmin = tmin.max(t0);
tmax = tmax.min(t1);
}

let t = tmax.min(tmin); // Pick the first intersection
self.center() + t * -d
}
}

impl fmt::Debug for Rect {
Expand Down Expand Up @@ -793,4 +817,57 @@ mod tests {
println!("Leftward ray from right:");
assert!(rect.intersects_ray(pos2(4.0, 2.0), Vec2::LEFT));
}

#[test]
fn test_ray_from_center_intersection() {
let rect = Rect::from_min_max(pos2(1.0, 1.0), pos2(3.0, 3.0));

assert_eq!(
rect.intersects_ray_from_center(Vec2::RIGHT),
pos2(3.0, 2.0),
"rightward ray"
);

assert_eq!(
rect.intersects_ray_from_center(Vec2::UP),
pos2(2.0, 1.0),
"upward ray"
);

assert_eq!(
rect.intersects_ray_from_center(Vec2::LEFT),
pos2(1.0, 2.0),
"leftward ray"
);

assert_eq!(
rect.intersects_ray_from_center(Vec2::DOWN),
pos2(2.0, 3.0),
"downward ray"
);

assert_eq!(
rect.intersects_ray_from_center((Vec2::LEFT + Vec2::DOWN).normalized()),
pos2(1.0, 3.0),
"bottom-left corner ray"
);

assert_eq!(
rect.intersects_ray_from_center((Vec2::LEFT + Vec2::UP).normalized()),
pos2(1.0, 1.0),
"top-left corner ray"
);

assert_eq!(
rect.intersects_ray_from_center((Vec2::RIGHT + Vec2::DOWN).normalized()),
pos2(3.0, 3.0),
"bottom-right corner ray"
);

assert_eq!(
rect.intersects_ray_from_center((Vec2::RIGHT + Vec2::UP).normalized()),
pos2(3.0, 1.0),
"top-right corner ray"
);
}
}

0 comments on commit cbf64d5

Please sign in to comment.