0

The intersection of two triangles is either empty or an n-gon (for n up to 6).

In theory, it is easy to come up with an algorithm to compute the intersection area. One can compute the possible intersections of all line segments and combine them with the points of the corner points of the triangles.

In practise, there are some numerical issues. If line segments are (nearly) parallel, they may or may not have an intersection point and its calculation can be imprecise (one usually divides by the determinant of the matrix, which is then approximately zero).

Any suggestions to avoid these numerical instabilities?

J Fabian Meier
  • 33,516
  • 10
  • 64
  • 142

1 Answers1

1

I don't know how to find the intersection area, but if what you want is just to know if they intersect, the algorithm in the article "Faster Triangle-Triangle Intersection Tests" by Olivier Devillers and Philippe Guigue is supposed to be very stable according to some polynomial order theory I don't quite understood nor looked up in the reference.

Follows my own JavaScript implementation of it. I can't guarantee it is correct because it hasn't seen enough real world action.

function det3(a, b, c)
{
    var a11 = a[0] - c[0]; var a12 = a[1] - c[1];
    var a21 = b[0] - c[0]; var a22 = b[1] - c[1];

    return a11 * a22 - a21 * a12;
}

function planar_intersect(vs, t1, t2)
{
    var p1, q1, r1;
    var p2, q2, r2;

    // I am doing this weird unpacking of the vertices because
    // originally they were on R³, and I had a code here to project
    // them to some orthogonal plane on R².
    p1 = t1.a; q1 = t1.b; r1 = t1.c;
    p2 = t2.a; q2 = t2.b; r2 = t2.c;

    // Ensure both triangles are counterclockwise
    var tmp;
    if(det3(p1, q1, r1) < 0) {
        tmp = q1;
        q1 = r1;
        r1 = tmp;
    }
    if(det3(p2, q2, r2) < 0) {
        tmp = q2;
        q2 = r2;
        r2 = tmp;
    }

    // Calculate signed areas of triangles
    var s1 = Array(3);

    // If 0, the vertex is on the edge of the other triangle
    s1[0] = det3(p1, p2, q2);
    if(s1[0] == 0)
        return true;

    s1[1] = det3(p1, q2, r2);
    if(s1[1] == 0)
        return true;

    s1[2] = det3(p1, r2, p2);
    if(s1[2] == 0)
        return true;

    // If all positive, the vertex is internal to the other triangle
    if(s1[0] > 0 && s1[1] > 0 && s1[2] > 0) {
        return true;
    }

    // Reorder t2 in order for a1 to be in the right area
    for(var i = 0; i < 2; ++i) {
        if(s1[0] > 0 && s1[2] <= 0) {
            break;
        }

        tmp = s1[0];
        s1[0] = s1[1];
        s1[1] = s1[2];
        s1[2] = tmp;

        tmp = p2;
        p2 = q2;
        q2 = r2;
        r2 = tmp;
    }

    if(s1[1] > 0) {
        // Follow Figure 9 tree.
        if(det3(r2, p2, q1) >= 0) {
            // II.a
            if(det3(r2, p1, q1) >= 0) {
                // III.a
                if(det3(p1, p2, q1) >= 0) {
                    return true;
                } else {
                    // IV.a
                    if(det3(p1, p2, r1) >= 0) {
                        // V
                        return det3(q1, r1, p2) >= 0;
                    } else {
                        return false;
                    }
                }
            } else {
                return false;
            }
        } else {
            // II.b
            if(det3(r2, p2, r1) >= 0) {
                // III.b
                if(det3(q1, r1, r2) >= 0) {
                    // IV.b
                    return det3(p1, p2, r1) <= 0;
                } else {
                    return false;
                }
            } else {
                return false;
            }
        }
    } else {
        // Follow Figure 10 tree.
        if(det3(r2, p2, q1) >= 0) {
            // II.a
            if(det3(q2, r2, q1) >= 0) {
                // III.a
                if(det3(p1, p2, q1) >= 0) {
                    // IV.a
                    return det3(p1, q2, q1) <= 0;
                } else {
                    // IV.b
                    if(det3(p1, p2, r1) >= 0) {
                        // V.a
                        return det3(r2, p2, r1) >= 0;
                    } else {
                        return false;
                    }
                }
            } else {
                // III.b
                if(det3(p1, q2, q1) <= 0) {
                    // IV.c
                    if(det3(q2, r2, r1) >= 0) {
                        // V.b
                        return det3(q1, r1, q2) >= 0;
                    } else {
                        return false;
                    }
                } else {
                    return false;
                }
            }
        } else {
            // II.b
            if(det3(r2, p2, r1) >= 0) {
                // III.c
                if(det3(q1, r1, r2) >= 0) {
                    // IV.d
                    return det3(r1, p1, p2) >= 0;
                } else {
                    // IV.c
                    if(det3(q1, r1, q2) >= 0) {
                        // V.c
                        return det3(q2, r2, r1) >= 0;
                    } else {
                        return false;
                    }
                }
            } else {
                return false;
            }
        }
    }
}
lvella
  • 12,754
  • 11
  • 54
  • 106