1. 程式人生 > 實用技巧 >GCompute - 計算三角形對的交點(3) - 共面三角形相交

GCompute - 計算三角形對的交點(3) - 共面三角形相交

GCompute - 計算三角形對的交點(3) - 共面三角形相交

在上兩篇文章中,我們介紹了使用不同的方法,計算空間中不共面的兩個三角形的交點,這篇文章將介紹如何對空間中共面的兩個三角形求交。

完整程式碼如下:

#include <iostream>
#include <cmath>
#include <algorithm>
#include <assert.h>
#include <vector>
#include <iterator>

#include <Eigen/Dense>

typedef Eigen::Vector2d Point2d;
typedef Eigen::Vector2d Vector2d;

struct Triangle2D
{
    Point2d m_pt[3];
};

struct Segment2D
{
    Point2d m_pt[2];
};

bool CalSegmentIntersectionPoint(const Segment2D& seg1, const Segment2D& seg2, Point2d& pt)
{
    // pt0, pt1 on segment
    // dir = pt1 - pt0
    // line(x,y) = pt0 + t * dir
    // line1 line2 intersection cal:
    // => 
    // 0 = pt0on1 - pt0on2 + ton1 * diron1 - ton2 * diron2 =>
    // pt0on2 - pt0on1 = ton1 * diron1 - ton2 * diron2  =>
    // mat(diron1.x, -diron2.x; diron1.y, -diron2.y) * mat(ton1; ton2) = mat(pt0on2.x - pt0on1.x; pt0on2.y - pt0on1.y) = mat(a, b)
    Vector2d dirOn1 = seg1.m_pt[1] - seg1.m_pt[0];
    Vector2d dirOn2 = seg2.m_pt[1] - seg2.m_pt[0];

    double a = seg2.m_pt[0].x() - seg1.m_pt[0].x();
    double b = seg2.m_pt[0].y() - seg1.m_pt[0].y();

    double denom = dirOn1.x() * (-dirOn2.y()) - (-dirOn2.x()) * (dirOn1.y());
    double denom_t1 = a * (-dirOn2.y()) - (-dirOn2.x()) * b;
    double denom_t2 = dirOn1.x() * b - a * (dirOn1.y());

    double t1 = denom_t1 / denom;
    double t2 = denom_t2 / denom;

    if (t1 >= 0 && t1 <= 1 && t2 >= 0 && t2 <= 1)
    {
        pt = seg1.m_pt[0] + t1 * dirOn1;
        return true;
    }

    return false;
}

void GetSegmentFromTriangle(const Triangle2D& tri, Segment2D (&seg)[3])
{
    seg[0].m_pt[0] = tri.m_pt[0];
    seg[0].m_pt[1] = tri.m_pt[1];

    seg[1].m_pt[0] = tri.m_pt[1];
    seg[1].m_pt[1] = tri.m_pt[2];

    seg[2].m_pt[0] = tri.m_pt[2];
    seg[2].m_pt[1] = tri.m_pt[0];
}

void GetTriangleIntersectionPoints(const Triangle2D& tri1, const Triangle2D& tri2, std::vector<Point2d>& pts)
{
    Segment2D seg1[3], seg2[3];
    GetSegmentFromTriangle(tri1, seg1);
    GetSegmentFromTriangle(tri2, seg2);

    Point2d pt;
    for (int i = 0; i < 3; ++i)
    {
        for (int j = 0; j < 3; ++j)
        {
            if (CalSegmentIntersectionPoint(seg1[i], seg2[j], pt))
            {
                pts.emplace_back(pt);
            }
        }
    }
}

void TriIntersectTestCase()
{
    Triangle2D tri1, tri2;
    tri1.m_pt[0] = Point2d(4, 3); tri1.m_pt[1] = Point2d(6, -2); tri1.m_pt[2] = Point2d(-2, 1);
    tri2.m_pt[0] = Point2d(1, -3); tri2.m_pt[1] = Point2d(2, 1); tri2.m_pt[2] = Point2d(13, -2);

    std::vector<Point2d> pts;
    GetTriangleIntersectionPoints(tri1, tri2, pts);
    std::cout << "Intersection points: \n";
    for (int i = 0; i < pts.size(); ++i)
    {
        std::cout << "=====" << "\n";
        std::cout << pts[i] << "\n";
    }
}

int main()
{
    TriIntersectTestCase();
    return 0;
}

得到結果如下:

Intersection points:
=====
 5.14286
0.142857
=====
  1.65714
-0.371429

示意圖如下: