确定一个三角形和一个平面的交点 [英] Determining the intersection of a triangle and a plane

查看:129
本文介绍了确定一个三角形和一个平面的交点的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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



我要查找的最终结果是两个三维矢量,它们定义了线段的起点和终点。



帮助你一点点,我已经计算了脸部平面与飞机之间的交叉线,我只需找到端点将该线剪辑成线段即可。



对于那些喜欢阅读代码的人来说:

 面对面; //一张脸,由3个点定义
平面飞机; //由法向量和距离定义的平面
Ray交点; //由点和方向定义的射线,初始化为面平面和面的交点

段s = CalculateSegment(面,平面,交点); //这个方法需要定义


解决方案

。首先是简单的版本,后来更强大的版本(只是为了帮助将原则与细微差别分开)。
简单版本:

  //假设平面的方程为点(N,X)+ d = 0,其中N是一个(不是
//必须标准化的)平面法线,而d是一个标量。任何方式给飞机 -
// DistFromPlane应该让输入矢量进入平面方程。

vector3d planeN;
float planeD;

Float DistFromPlane(vector3d P)
{
//如果N没有被标准化,这*不是真正的距离,
//但是计算工作只是一样。
return dot(planeN,P)+ planeD;
}

bool GetSegmentPlaneIntersection(vector3d P1,vector3d P2,vector3d& outP)
{
float d1 = DistFromPlane(P1),
d2 = DistFromPlane (P2);

if(d1 * d2> 0)//指向飞机同一侧
返回false;

float t = d1 /(d1 - d2); //段中交点的'时间'
outP = P1 + t *(P2 - P1);

返回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); (abs(d1) bP2OnPlane =(abs(d2)
if(bP1OnPlane)
outSegTips.Add(P1);

if(bP2OnPlane)
outSegTips.Add(P2);

if(bP1OnPlane& bP2OnPlane)
return;

if(d1 * d2> eps)//指向飞机的同一侧
return;

float t = d1 /(d1 - d2); //段中交点的'时间'
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); //这里没有列出 - 明显的功能
}

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

I have a single triangle and a plane (in 3 dimensional space), How would I calculate the line segment where the two cross, if there is no crossing then I need to detect this case.

The end result I'm looking for is two 3 dimensional vectors, which define the start and end points of the line segment.

To help you out a little, I have already calculated the intersection ray between the plane of the face, and the plane, I simply need to find the endpoints to clip that ray into a line segment.

For those who like reading things in code:

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

解决方案

Here's some suggested pseudo code. Simple version first, more robust version later (just to help separate the principle from the neuances). Simple version:

// 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);
}

Now adding some robustness:
[Edit: Added explicit consideration for the case of a single vertex on the plane]

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 
}

Hopefully that gives an idea, but there are still quite a few potential optimizations. If, for example, you're calculating these intersections for every triangle in a large mesh, you might calculate and cache the DistanceFromPlane once per vertex, and just retrieve it for every edge the vertex participates in. There can be more advanced caching too, depending on your scenario and data representation.

这篇关于确定一个三角形和一个平面的交点的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆