From db8a0462a25753bb9b9bf05b9d83cfdddb18b7ff Mon Sep 17 00:00:00 2001 From: Francesco Magliocca Date: Mon, 9 Nov 2020 23:33:30 +0100 Subject: [PATCH] Start correct implementation of line-rect intersection test --- src/canvas.rs | 46 +++++++++++++++++++++++++++++++++++++++------- 1 file changed, 39 insertions(+), 7 deletions(-) diff --git a/src/canvas.rs b/src/canvas.rs index 01b843e..1ee8c13 100644 --- a/src/canvas.rs +++ b/src/canvas.rs @@ -1,17 +1,49 @@ use druid::kurbo::BezPath; +struct Interval { + start_pos: f64, + end_pos: f64, +} + +impl Interval { + fn new(x1: f64, x2: f64) -> Interval { + Interval { + start_pos: x1.min(x2), + end_pos: x1.max(x2), + } + } + + fn new_ordered(start: f64, end: f64) -> Interval { + Interval { + start_pos: start, + end_pos: end, + } + } + + fn overlaps(&self, other: &Self) -> bool { + self.start_pos < other.end_pos && other.start_pos < self.end_pos + } +} + // O(1) complexity -// TODO: This is only a toy implementation, this is not at all correct! +// TODO: Implement this in a way that is not so flamboyant +// TODO: Implement intersection test for bezier curves fn segment_intersects_rect(segment: &druid::kurbo::PathSeg, rect: druid::Rect) -> bool { match segment { - druid::kurbo::PathSeg::Line(line) => rect.contains(line.p0) || rect.contains(line.p1), + druid::kurbo::PathSeg::Line(line) => { + // A Segment intersects the rect + // if their projections on the x and y line both overlap + let line_x_proj = Interval::new(line.p0.x, line.p1.x); + let line_y_proj = Interval::new(line.p0.y, line.p1.y); - druid::kurbo::PathSeg::Quad(quad) => { - rect.contains(quad.p0) || rect.contains(quad.p1) || rect.contains(quad.p2) - } + let rect_x_proj = Interval::new_ordered(rect.min_x(), rect.max_x()); + let rect_y_proj = Interval::new_ordered(rect.min_y(), rect.max_y()); - druid::kurbo::PathSeg::Cubic(cubic) => { - rect.contains(cubic.p0) || rect.contains(cubic.p1) || rect.contains(cubic.p2) || rect.contains(cubic.p3) + line_x_proj.overlaps(&rect_x_proj) && line_y_proj.overlaps(&rect_y_proj) + }, + + _ => { + unimplemented!(); } } }