20

Preferably without using any kind of loop, as this'll be used in a game.

I wish to intersect a line with a rectangle, of arbitrary size. But I also wish for the intersection point[s] to be returned.

It's possible, I've done a little googling, but still have not worked it out.

The line is defined using (x1,y1,x2,y2). The rectangle has these two points too.

Steffan Donal
  • 2,244
  • 4
  • 24
  • 47
  • 3
    Start with an easier problem. Do you know how to intersect an infinite line with another infinite line? – Eric Lippert Sep 19 '10 at 15:31
  • 2
    It's not that I think you learn better by the Socratic method; I understand that not everyone does. Rather, I am trying to gauge your level of existing knowledge. If you don't know how to intersect two lines then you're probably going to have to learn that first before you try to intersect more complex geometries. – Eric Lippert Sep 20 '10 at 18:03
  • 6
    I fundamentally disagree. Sometimes it's better to just implement someone else's solution in code, verify that it works and forget all about it, than to learn the theory behind the solution and implement it yourself. You don't learn as much, but not everyone wants or needs to learn everything. – Minthos Dec 11 '12 at 11:20

1 Answers1

50

I would recommend simply doing a line-segment-line-segment intersection check on each line segment (edge) that makes up the rectangle. Here is a line segment intersection detection algorithm I wrote ages ago, dredged up from one of my old XNA projects:

// a1 is line1 start, a2 is line1 end, b1 is line2 start, b2 is line2 end
static bool Intersects(Vector2 a1, Vector2 a2, Vector2 b1, Vector2 b2, out Vector2 intersection)
{
    intersection = Vector2.Zero;

    Vector2 b = a2 - a1;
    Vector2 d = b2 - b1;
    float bDotDPerp = b.X * d.Y - b.Y * d.X;

    // if b dot d == 0, it means the lines are parallel so have infinite intersection points
    if (bDotDPerp == 0)
        return false;

    Vector2 c = b1 - a1;
    float t = (c.X * d.Y - c.Y * d.X) / bDotDPerp;
    if (t < 0 || t > 1)
        return false;

    float u = (c.X * b.Y - c.Y * b.X) / bDotDPerp;
    if (u < 0 || u > 1)
        return false;

    intersection = a1 + t * b;

    return true;
}

I will leave inputting each edge into the above method and collecting the results as an exercise to the reader :)


Edit 1 year later now I've gone to university and done a Graphics course:

Take a look at the Cohen–Sutherland algorithm to do this efficiently when you have a large set of lines where most do not intersect the rectangle. It uses a 9 segment grid and you place each endpoint of the line in a region of said grid:

grid

Using this we can tell if there will not be any line intersections:

grid with lines

For example here CD will not intersect the rectangle (shown in red in the first image) as both C and D are in the top row and neither will AB. For the ones where the line may intersect the the rectangle we have to try the line-line intersections.

They way the sections are numbered/labelled allows us to simply do x AND y != 0 (where x and y are the labels of the sections for each of the line's endpoints) to determine if there will not be an intersection.

Using this method means we have to many, many fewer line-line intersections which speeds up the whole thing massively.

Callum Rogers
  • 15,630
  • 17
  • 67
  • 90
  • That'll be easy enough to do. Thank you very much. – Steffan Donal Sep 19 '10 at 18:45
  • 1
    In the above code example, those are actually cross products, not dot products. – Nathanael Weiss Aug 15 '12 at 21:47
  • Cohen–Sutherland algorithm seems to be about clipping and finding intersection rather than is there any intersection - so surely this would be slower? – paulm Jan 21 '14 at 13:39
  • Hmm, the Cohen-Sutherland algorithm assumes a finite space is divided in 9 equal regions (or 27 in 3d). What happens when your space is infinite? – Matt Esch Jan 30 '14 at 13:46
  • @MattEsch: I would guess you just make the outer 8 (26) regions infinite. – Moberg Feb 17 '14 at 14:57
  • What if the lines are infinite? – rxantos Apr 03 '14 at 10:25
  • @rxantos: Then you're dealing with halfspaces and halfspace intersections. – Deco Sep 30 '14 at 08:13
  • If you think about it, a rectangle is `everything subtract [intersection of four halfspaces]`. If you remove one of those halfspaces (to get infinite lines), is it still a rectangle? – Deco Sep 30 '14 at 08:15
  • (...I just realised you probably mean the LINES are infinite, rather than the rectangle's lines. In that case, there is surely a way to figure out which of the outer regions the line would intersect.) – Deco Sep 30 '14 at 08:23