首页 文章

确定三角形和平面的交点

提问于
浏览
18

我有一个三角形和一个平面(在三维空间中),我如何计算两个交叉的线段,如果没有交叉,那么我需要检测这种情况 .

我正在寻找的最终结果是两个三维向量,它们定义了线段的起点和终点 .

为了帮助你,我已经计算了面的平面和平面之间的交叉射线,我只需要找到 endpoints 来将该光线剪切成线段 .

对于喜欢在代码中阅读内容的人:

Face face;        //a face, defined by 3 points
Plane plane;      //a plane, defined by a normal vector and a distance
Ray intersection; //a ray, defined by a point and a direction, initialised to the intersection of the face plane and the face

Segment s = CalculateSegment(face, plane, intersection); //this method needs defining

4 回答

  • 1

    这是一些建议的伪代码 . 首先是简单版本,后面是更强大的版本(只是为了帮助将原理与联盟分开) . 简单版本:

    // Assume the plane is given as the equation dot(N,X) + d = 0, where N is a (not
    // neccessarily normalized) plane normal, and d is a scalar. Any way the plane is given -
    // DistFromPlane should just let the input vector into the plane equation.
    
    vector3d planeN;
    float planeD;
    
    float DistFromPlane( vector3d P)
    {
    // if N is not normalized this is *not* really the distance, 
    // but the computations work just the same.
        return dot(planeN,P) + planeD;
    }
    
    bool GetSegmentPlaneIntersection( vector3d P1, vector3d P2, vector3d& outP)
    {
      float d1 = DistFromPlane(P1),
            d2 = DistFromPlane(P2);
    
      if (d1*d2 > 0)  // points on the same side of plane
         return false;
    
      float t = d1 / (d1 - d2); // 'time' of intersection point on the segment
      outP = P1 + t * (P2 - P1);
    
      return true;
    }
    
    void TrianglePlaneIntersection(vector3d triA, vector3d triB, vector3d triC,
                                   vector3dArray& outSegTips)
    {
       vector3d IntersectionPoint;
       if( GetSegmentPlaneIntersection( triA, triB, IntersectionPoint))
         outSegTips.Add(IntersectionPoint);
    
       if( GetSegmentPlaneIntersection( triB, triC, IntersectionPoint))
         outSegTips.Add(IntersectionPoint);
    
       if( GetSegmentPlaneIntersection( triC, triA, IntersectionPoint))
         outSegTips.Add(IntersectionPoint);
    }
    

    现在添加一些健壮性:
    [编辑:添加了对平面上单个顶点的具体情况的明确考虑]

    vector3d planeN;
     float planeD;
    
    float DistFromPlane( vector3d P)
    {
        return dot(planeN,P) + planeD;
    }
    
    void GetSegmentPlaneIntersection( vector3d P1, vector3d P2, vector3dArray& outSegTips)
    {
      float d1 = DistFromPlane(P1),
            d2 = DistFromPlane(P2);
    
      bool  bP1OnPlane = (abs(d1) < eps),
            bP2OnPlane = (abs(d2) < eps);
    
      if (bP1OnPlane)
         outSegTips.Add(P1);
    
      if (bP2OnPlane)
         outSegTips.Add(P2);
    
      if (bP1OnPlane && bP2OnPlane)
         return;
    
      if (d1*d2 > eps)  // points on the same side of plane
         return;
    
      float t = d1 / (d1 - d2); // 'time' of intersection point on the segment
      outSegTips.Add( P1 + t * (P2 - P1) );
    }
    
    void TrianglePlaneIntersection(vector3d triA, vector3d triB, vector3d triC,
                                   vector3dArray& outSegTips)
    {
       GetSegmentPlaneIntersection( triA, triB, outSegTips));
       GetSegmentPlaneIntersection( triB, triC, outSegTips));
       GetSegmentPlaneIntersection( triC, triA, outSegTips));
    
       RemoveDuplicates(outSegTips);  // not listed here - obvious functionality 
    }
    

    希望这能给出一个想法,但仍然有很多潜在的优化 . 例如,如果您正在为大型网格中的每个三角形计算这些交叉点,您可以计算并缓存每个顶点一次的DistanceFromPlane,并为顶点参与的每个边缘检索它 . 还可以有更高级的缓存,取决于您的方案和数据表示 .

  • 2

    将3个点插入平面方程(由列出的a,b,c,d中列出的4个参数定义),并确定哪些对位于平面的两侧 .

    鉴于平面方程:

    Ax + By + Cz + D = 0
    

    其中A,B,C是法线(单位长度),D是到原点IIRC的距离,插入点(x,y,z)并查看该结果是正还是负 . 对于平面上的点,它将为零,并且当结果不为0时,符号将告诉您哪一侧点在哪一侧 . 因此在相对侧拾取点对(最多将有2个)并计算交点使用标准射线/平面交叉公式的飞机的那两个区段现在逃脱了我 . 这些将是您寻求的细分市场的2个点 .

    EDIT 想想看,将点插入平面方程所得到的值对于在点对之间进行插值以获得与平面的线段交叉非常有用 .

    Len Fn = Axn Byn C * zn D是插入点n的结果 . 然后假设F1 = -4且F2 = 8.因此点P1和P2位于平面的相对侧 . 我们还将得到P = P1 * 2/3 P2 * 1/3是从P1到P2的平面与平面的交点 . 将其概括为适当的公式是留下来的 .

  • 1

    找到将三角形与平面限定的每个线段的交点 . 然后合并相同的点

    • 如果存在0个交叉点,则没有交叉点

    • 如果存在1个交叉点(即你发现了两个但是它们在公差范围内相同),你的三角形点就在接触平面

    • 如果是2点则它们之间的线段是交点

    下一步,搜索SO以获得线段到平面交叉算法(或者只使用框架提供的算法)......

  • 17

    这取决于您拥有的库 . 我创建了自己的几何库,可以计算线与平面的交点 . 在这种情况下,计算三角形的三个边的三个交点,然后计算它们中的哪一个位于顶点之间 . 这可能是0(没有交集),或者2是你想要的情况 . (有两种点重合的特殊情况 - 三角形的一个点) .

相关问题