Search code examples
c++3dintersectionplaneface

How to detect intersection of two faces in 3D


lets say

struct myFace
{
    3DPoint p0;
    3DPoint p1;
    3DPoint p2;
    3DPoint p3;
    3DPoint pNormal;

};

face1 and face2 is faces which type of myFace.

double ac = face1.pNormal * face2.pNormal;

if (!(ac<1.00000001 && ac>0.99999999) && !(ac>-1.00000001 && ac<-0.99999999))

then faces are not parallel.

but how can detect if they do intersect or do not ?


Solution

  • Oops ignore my comment: thought of another way to do this.


    • Step 1:

    For faces F1 and F2, take F2's points as two triangles, e.g. (p0, p1, p2) and (p1, p2, p3) respectively. Then take F1's edges, i.e. (p0, p1), (p1, p2), (p2, p3), and (p3, p0), then intersect each of them with both of the triangles.

    I found some code to do this: (adapted from http://geomalgorithms.com/a06-_intersect-2.html)

    #define SMALL_NUM   0.00000001
    
    /* 
       returns: 0 if no intersection 
                1 if parallel but disjoint
                2 if coplanar
    */
    int intersect3D_RayTriangle(Vector P0, Vector P1, Vector V0, Vector V1, Vector V2)
    {
        Vector    u, v, n;              // triangle vectors
        Vector    dir, w0, w;           // ray vectors
        float     r, a, b;              // params to calc ray-plane intersect
    
        // get triangle edge vectors and plane normal
        u = V1 - V0;
        v = V2 - V0;
        n = cross(u, v);
    
        dir = P1 - P0;             // ray direction vector
        w0 = P0 - V0;
        a = -dot(n, w0);
        b = dot(n, dir);
        if (fabs(b) < SMALL_NUM)   // ray is parallel to triangle plane
            return (fabs(a) < SMALL_NUM ? 2 : 0);
    
        // get intersect point of ray with triangle plane
        r = a / b;
        if (r < 0.0 || r > 1.0)
            return 0;                   // => no intersect
        Vector I = R.P0 + r * dir;      // intersect point of ray and plane
    
        // is I inside T?
        float uu, uv, vv, wu, wv, D;
        uu = dot(u, u);
        uv = dot(u, v);
        vv = dot(v, v);
        w = I - V0;
        wu = dot(w, u);
        wv = dot(w, v);
        D = uv * uv - uu * vv;
    
        // get and test parametric coords
        float s, t;
        s = (uv * wv - vv * wu) / D;
        if (s < 0.0 || s > 1.0)         // I is outside T
            return 0;
        t = (uv * wu - uu * wv) / D;
        if (t < 0.0 || (s + t) > 1.0)  // I is outside T
            return 0;
    
        return 1;                       // I is in T
    }
    

    P0 and P1 form one of the edges from F1, while V0, V1 and V2 form one the F2's triangles.

    • If one of the checks (there should be 8) returns 1, then they definitely intersect (return true immediately).
    • If all of them return 0, then they don't intersect.
    • If one of the checks returns 2 (the first check will probably do that) then we need a different method. Stop these checks and immediately move onto step 2.

    • Step 2:

    This part is for if the polygons are coplanar (i.e. parallel and in the same plane). This time, take all of F1's edges and all of F2's edges; for each of F1's edges, check if it intersects with any of F2's edges, and if one pair intersects then return true immediately.

    To do such an edge intersection: (adapted from https://gist.github.com/hanigamal/6556506)

    A0, A1 form the edge from F1, and B0, B1 from F2.

    int intersection(Vector A0, Vector A1, Vector B0, Vector B1)
    {
       Vector dA = A1 - A0;
       Vector dB = B1 - B0;
       Vector dC = B0 - A0;
    
       double s = dot(cross(dC, dB), cross(dA, dB)) / norm2(cross(dA, dB));
        return (s >= 0.0 && s <= 1.0);
    }