mirror of
https://github.com/emilk/egui.git
synced 2026-08-31 22:00:03 -04:00
Add new Rect::intersects_ray_from_center method (#5415)
<!-- Please read the "Making a PR" section of [`CONTRIBUTING.md`](https://github.com/emilk/egui/blob/master/CONTRIBUTING.md) before opening a Pull Request! * Keep your PR:s small and focused. * The PR title is what ends up in the changelog, so make it descriptive! * If applicable, add a screenshot or gif. * If it is a non-trivial addition, consider adding a demo for it to `egui_demo_lib`, or a new example. * Do NOT open PR:s from your `master` branch, as that makes it hard for maintainers to test and add commits to your PR. * Remember to run `cargo fmt` and `cargo clippy`. * Open the PR as a draft until you have self-reviewed it and run `./scripts/check.sh`. * When you have addressed a PR comment, mark it as resolved. Please be patient! I will review your PR, but my time is limited! --> Title. * [x] I have followed the instructions in the PR template
This commit is contained in:
@@ -649,6 +649,8 @@ impl Rect {
|
||||
///
|
||||
/// A ray that starts inside the rect will return `true`.
|
||||
pub fn intersects_ray(&self, o: Pos2, d: Vec2) -> bool {
|
||||
debug_assert!(d.is_normalized(), "expected normalized direction");
|
||||
|
||||
let mut tmin = -f32::INFINITY;
|
||||
let mut tmax = f32::INFINITY;
|
||||
|
||||
@@ -670,6 +672,32 @@ 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 {
|
||||
debug_assert!(d.is_normalized(), "expected normalized direction");
|
||||
|
||||
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);
|
||||
self.center() + t * -d
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Debug for Rect {
|
||||
@@ -792,4 +820,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"
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user