overlaps_triangle_triangle.hpp

Back to Overlap testing

pastel/geometry/overlap/

#ifndef PASTELGEOMETRY_OVERLAPS_TRIANGLE_TRIANGLE_HPP
#define PASTELGEOMETRY_OVERLAPS_TRIANGLE_TRIANGLE_HPP

#include "pastel/geometry/overlap/overlaps_triangle_triangle.h"

#include "pastel/geometry/shape/triangle.h"
#include "pastel/geometry/shape/segment.h"
#include "pastel/geometry/shape/line.h"
#include "pastel/sys/vector/vector_tools.h"

#include "pastel/geometry/intersect/intersect_triangle_triangle.h"
#include "pastel/geometry/overlap/overlaps_plane_triangle.h"

namespace Pastel
{

    template <typename Real>
    bool overlaps(
        const PASTEL_TRIANGLE(Real, 1)& aTriangle,
        const PASTEL_TRIANGLE(Real, 1)& bTriangle)
    {
        Real aMin(0);
        Real aMax(0);

        minMax(
            aTriangle[0][0],
            aTriangle[1][0],
            aTriangle[2][0], aMin, aMax);

        Real bMin(0);
        Real bMax(0);

        minMax(
            bTriangle[0][0],
            bTriangle[1][0],
            bTriangle[2][0], bMin, bMax);

        return (aMin <= bMin && bMin <= aMax) ||
            (aMin <= bMax && bMax <= aMax);
    }

    template <typename Real>
    bool overlaps(
        const PASTEL_TRIANGLE(Real, 2)& aTriangle,
        const PASTEL_TRIANGLE(Real, 2)& bTriangle)
    {
        // Using the separating axis theorem.
        // There are six edge normals to
        // test, 3 from each triangle.

        // Test for triangle 'a' edge normals
        // ----------------------------------

        for (integer i = 0;i < 3;++i)
        {
            integer i2 = (i + 1) % 3;
            integer i3 = (i + 2) % 3;

            Vector<Real, 2> edge(
                cross(evaluate(aTriangle[i2] - aTriangle[i])));

            Real a(
                dot(edge, aTriangle[i3] - aTriangle[i]));

            Real aMin(0);
            Real aMax(0);

            if (a > 0)
            {
                aMin = 0;
                aMax = a;
            }
            else
            {
                aMin = a;
                aMax = 0;
            }

            Real b1(
                dot(edge, bTriangle[0] - aTriangle[i]));
            Real b2(
                dot(edge, bTriangle[1] - aTriangle[i]));
            Real b3(
                dot(edge, bTriangle[2] - aTriangle[i]));

            Real bMin(0);
            Real bMax(0);

            minMax(b1, b2, b3, bMin, bMax);

            if (bMin > aMax || aMin > bMax)
            {
                // Found separating axis

                return false;
            }
        }

        // Test for triangle 'b' edge normals
        // ----------------------------------

        for (integer i = 0;i < 3;++i)
        {
            integer i2 = (i + 1) % 3;
            integer i3 = (i + 2) % 3;

            Vector<Real, 2> edge(
                cross(bTriangle[i2] - bTriangle[i]));

            Real a(
                dot(edge, bTriangle[i3] - bTriangle[i]));

            Real aMin(0);
            Real aMax(0);

            if (a > 0)
            {
                aMin = 0;
                aMax = a;
            }
            else
            {
                aMin = a;
                aMax = 0;
            }

            Real b1(
                dot(edge, aTriangle[0] - bTriangle[i]));
            Real b2(
                dot(edge, aTriangle[1] - bTriangle[i]));
            Real b3(
                dot(edge, aTriangle[2] - bTriangle[i]));

            Real bMin(0);
            Real bMax(0);

            minMax(b1, b2, b3, bMin, bMax);

            if (bMin > aMax || aMin > bMax)
            {
                // Found separating axis

                return false;
            }
        }

        return true;
    }

    template <typename Real>
    bool overlaps(
        const PASTEL_TRIANGLE(Real, 3)& aTriangle,
        const PASTEL_TRIANGLE(Real, 3)& bTriangle)
    {
        Line<Real, 3> intersectionLine;
        AlignedBox<Real, 1> intersectionRange;

        return Pastel::intersect(
            aTriangle, bTriangle,
            intersectionLine,
            intersectionRange);
    }

}

#endif