views:

312

answers:

3

I'm trying to find if a rectangle intersects a concave polygon. I found this algorithm:

double determinant(Vector2D vec1, Vector2D vec2){
    return vec1.x*vec2.y-vec1.y*vec2.x;
}

//one edge is a-b, the other is c-d
Vector2D edgeIntersection(Vector2D a, Vector2D b, Vector2D c, Vector2D d){
    double det=determinant(b-a,c-d);
    double t=determinant(c-a,c-d)/det;
    double u=determinant(b-a,c-a)/det;
    if ((t<0)||(u<0)||(t>1)||(u>1))return NO_INTERSECTION;
    return a*(1-t)+t*b;
}

If I perform this 4 times (Top to Right, Top to bottom left, top to bottom right, bottom to right) * (all edges of my polygon) would this effectively and accurately tell me if the rectangle has part of or all the concave polygon inside? If not what would be missing?

Thanks

+1  A: 

I think the following should work:

(1) for each e1 in rectangle_edges, e2 in polygon_edges
    (1.1) if edgeIntersection(e1,e2) != NO_INTERSECTION
        (1.1.1) return true
(2) if (max_polygon_x < max_rectangle_x) and (min_polygon_x > min_rectangle_x) and (max_polygon_y < max_rectangle_y) and (min_polygon_y > min_rectangle_y)
    (2.1) return true
(2) return false

Edit: Added check for whether the polygon is inside the rectangle.

Amir Rachum
Alright thanks, I was going to do this but didn't want to run into any debugging issues if it wasn't going to work.
Milo
You have to handle cases where the polygon is fully contained in the rectangle or vice versa.
jpalecek
I will do point in polygon for fully
Milo
+11  A: 

The code attempts to find the intersection point of two segments - AB and CD.

There are many different ways to explain how it is doing it, depending on how you interpret these operations.

Let's say point A has coordinates (xa, ya), B - (xb, yb) and so on. Let's say

dxAB = xb - xa
dyAB = yb - ya
dxCD = xd - xc
dyCD = yd - yc

The the following system of two linear equations

| dxAB dxCD |   | t |   | xc-xa |
|           | * |   | = |       |
| dyAB dyCD |   | u |   | yc-ya |

if solved for t and u, will give you the proportional position of the intersection point on line AB (value t) and on line CD (value u). These values will lie in range of [0, 1] if the point belongs to the corresponding segment and outside of that range if the point lies outside the segment (on the line containing the segment).

In order to solve this system of linear equations we can use the well-known Cramer's rule. For that we will need the determinant of

| dxAB dxCD |
|           |
| dyAB dyCD |

which is exactly determinant(b - a, c - d) from your code. (Actually, what I have here is determinant(b - a, d - c), but it is not really important for the purposes of this explanation. The code you posted for some reason swaps C and D, see P.S. note below).

And we will also need determinant of

| xc-xa dxCD |
|            |
| yc-ya dyCD |

which is exactly determinant(c-a,c-d) from your code, and determinant of

| dxAB xc-xa |
|            |
| dyAB yc-ya |

which is exactly determinant(b-a,c-a).

Dividing these determinants in accordance with the Cramer's rule will give us the values of t and u, which is exactly what is done in the code you posted.

The code then proceeds to test the values of t and u to check if the segments actually intersect, i.e. whether both t and u belong to [0, 1] range. And if they do, if calculated the actual intersection point by evaluating a*t+b*(1-t) (equivalently, it could evaluate c*u+d*(1-u)). (Again, see the P.S. note below).

P.S. In the original code the points D and C are "swapped" in a sense that the code does c - d, where I do d - c in my explanation. But this makes no difference for the general idea of the algorithm, as long as one's careful with signs.

This swap of C and D point is also the reason for a*(1-t)+t*b expression used when evaluating the intersection point. Normally, as in my explanation, one'd expect to see something like a*t+b*(1-t) there. (I have my doubts about this though. I would expect to see a*t+b*(1-t) there even in your version. Could be a bug.)

P.P.S. The author if the code forgot to check for det == 0 (or very close to 0), which will happen in case when the segments are parallel.

AndreyT
Well that fully answers the question :) thanks!
Milo
A: 

As far as I can tell after a quick glance, it tries to determine if 2 line segments intersect, and if they do, what the coordinates of the intersection point are.

No, it is not good enough to determine if your rectangle and your polygon intersect, because you'd still miss the case where either the polygon is completely inside the rectangle, or the other way around.

bart