我正在实施一个由Moller计算三角形三角形交叉点的算法,而我无法完全绕过某些东西: 给定交叉三角形的两个平面,我们以N * P + d = 0的形式得到它们的对应方程,其中N是平面中的两个向量的叉积,P是平面上的任何点。 d也可以计算。
考虑到三角形不是共面的,它们的交点将是一条线L = P + tD,其中D是N(第一平面)* N(第二平面) - 这是线的方向,P是任意的点在线上,t是参数。该算法停止计算三角形的交叉区段与它们的相对三角形平面的t。现在,如果这些段重叠,则三角形相交。但同样,这些细分仅以t表示。但是,我想更进一步,实际得到交叉点的坐标。
所以这里有一个问题 - 给定两个平面,三个点位于平面上(三角形的点)和线L = P + tD,我们知道D和ts,我该如何计算细分点?
任何帮助将不胜感激, 谢谢
我正在添加到目前为止我所拥有的代码: { // Tomas Moller的剖面寻找算法的实施,增加了确定交叉点的coorninates
//Vertex vectors
Vector3f Va0(a.Point1.X, a.Point1.Y, a.Point1.Z);
Vector3f Va1(a.Point2.X, a.Point2.Y, a.Point2.Z);
Vector3f Va2(a.Point3.X, a.Point3.Y, a.Point3.Z);
Vector3f Vb0(b.Point1.X, b.Point1.Y, b.Point1.Z);
Vector3f Vb1(b.Point2.X, b.Point2.Y, b.Point2.Z);
Vector3f Vb2(b.Point3.X, b.Point3.Y, b.Point3.Z);
//First, find the plane equation of triangle b = Pb
//N dot X + d = 0 where X is any point on the plane
auto N2 = (Vb1 - Vb0).cross((Vb2 - Vb0));
N2.normalize();
float d2 = (N2 * (-1)).dot(Vb0);
//We'll then find the signed distance from each point of the triangle a to plane Pb
float da_0 = Round(N2.dot(Va0) + d2);
float da_1 = Round(N2.dot(Va1) + d2);
float da_2 = Round(N2.dot(Va2) + d2);
//reject intersetion if none of the points lie on the plane and all have the same sign
//meaning that the triangle a lies on one side of the triangle b
if (da_0 != 0 && da_1 != 0 && da_2 != 0 && da_0 > 0 && da_1 > 0 && da_2 > 0)
return nullptr;
if (da_0 != 0 && da_1 != 0 && da_2 != 0 && da_0 < 0 && da_1 < 0 && da_2 < 0)
return nullptr;
//do the same thing for the other triangle
auto N1 = (Va1 - Va0).cross((Va2 - Va0));
N1.normalize();
float d1 = (N1 * (-1)).dot(Va0);
float db_0 = Round(N1.dot(Vb0) + d1);
float db_1 = Round(N1.dot(Vb1) + d1);
float db_2 = Round(N1.dot(Vb2) + d1);
if (db_0 != 0 && db_1 != 0 && db_2 != 0 && db_0 > 0 && db_1 > 0 && db_2 > 0)
return nullptr;
if (db_0 != 0 && db_1 != 0 && db_2 != 0 && db_0 < 0 && db_1 < 0 && db_2 < 0)
return nullptr;
#pragma region Coplanar Triangles
if (db_0 == 0 && db_1 == 0 && db_2 == 0)
{
//if the triangles are coplanar we'll find the intersection in 2d space
return nullptr;
}
#pragma endregion
#pragma region Triangles are in 3D space
else
{
//Triangles are not coplanar and the intersection line is some line L = O + tD
//where D = N1 cross N2 - direction of the line and O is some point on it
//We will find the the intersection segment of the first triangle with the plane os the second triangle and visa versa
//If the two segments overlap, the triangles intesect
auto D = N1.cross(N2);
D.normalize();
#pragma region Point Contact Between the Triangles
//first reject intersection if one triangle only touches the other with one point
if ((da_0 == 0 && da_1 > 0 && da_2 > 0) || (da_0 == 0 && da_1 < 0 && da_2 < 0))
return nullptr;
if ((da_0 > 0 && da_1 == 0 && da_2 > 0) || (da_0 < 0 && da_1 == 0 && da_2 < 0))
return nullptr;
if ((da_0 > 0 && da_1 > 0 && da_2 == 0) || (0 > da_0 && da_1 < 0 && da_2 == 0))
return nullptr;
if ((db_0 == 0 && db_1 > 0 && db_2 > 0) || (db_0 == 0 && db_1 < 0 && db_2 < 0))
return nullptr;
if ((db_0 > 0 && db_1 == 0 && db_2 > 0) || (db_0 < 0 && db_1 == 0 && db_2 < 0))
return nullptr;
if ((db_0 > 0 && db_1 > 0 && db_2 == 0) || (0 > db_0 && db_1 < 0 && db_2 == 0))
return nullptr;
#pragma endregion
//If the above passes, proceed with 3d triangle intersection. Start with triangle a and plane Pb,
//there will be one point of a on one side of the Pb and two points of a on the other side of Pb. Let's find them:
#pragma region Triangle A
tuple<Vector3f, Vector3f> edgeA1;
tuple<Vector3f, Vector3f> edgeA2;
float dV0 = 1;
float dV1 = 1;
float dV2 = 1;
if ((da_0 > 0 && da_1 <= 0 && da_2 <= 0) || (da_0 < 0 && da_1 >= 0 && da_2 >= 0))
{
edgeA1 = make_tuple(Va1, Va0);
edgeA2 = make_tuple(Va0, Va2);
dV0 = da_1;
dV1 = da_0;
dV2 = da_2;
}
else if ((da_0 <= 0 && da_1 > 0 && da_2 <= 0) || (da_0 >= 0 && da_1 < 0 && da_2 >= 0))
{
edgeA1 = make_tuple(Va0, Va1);
edgeA2 = make_tuple(Va1, Va2);
dV0 = da_0;
dV1 = da_1;
dV2 = da_2;
}
else if ((da_0 <= 0 && da_1 <= 0 && da_2 > 0) || (da_0 >= 0 && da_1 >= 0 && da_2 < 0))
{
edgeA1 = make_tuple(Va0, Va2);
edgeA2 = make_tuple(Va2, Va1);
dV0 = da_0;
dV1 = da_2;
dV2 = da_1;
}
//pi = D * Vi where i = 0, 1, 2
auto pA_0 = D.dot(get<0>(edgeA1));
auto pA_1 = D.dot(get<0>(edgeA2));
auto pA_2 = D.dot(get<1>(edgeA2));
//The tA_1 and tA_2 define the interval of the intersection of triangle a with the line L
float tA_1 = pA_0 + (pA_1 - pA_0) * (dV0 / (dV0 - dV1));
float tA_2 = pA_1 + (pA_2 - pA_1) * (dV1 / (dV1 - dV2));
#pragma endregion
//Now repeat for triangle b
#pragma region Triangle B
tuple<Vector3f, Vector3f> edgeB1;
tuple<Vector3f, Vector3f> edgeB2;
if ((db_0 > 0 && db_1 <= 0 && db_2 <= 0) || (db_0 < 0 && db_1 >= 0 && db_2 >= 0))
{
edgeB1 = make_tuple(Vb1, Vb0);
edgeB2 = make_tuple(Vb0, Vb2);
dV0 = db_1;
dV1 = db_0;
dV2 = db_2;
}
else if ((db_0 <= 0 && db_1 > 0 && db_2 <= 0) || (db_0 >= 0 && db_1 < 0 && db_2 >= 0))
{
edgeB1 = make_tuple(Vb0, Vb1);
edgeB2 = make_tuple(Vb1, Vb2);
dV0 = db_0;
dV1 = db_1;
dV2 = db_2;
}
else if ((db_0 <= 0 && db_1 <= 0 && db_2 > 0) || (db_0 >= 0 && db_1 >= 0 && db_2 < 0))
{
edgeB1 = make_tuple(Vb0, Vb2);
edgeB2 = make_tuple(Vb2, Vb1);
dV0 = db_0;
dV1 = db_2;
dV2 = db_1;
}
//pi = D * Vi where i = 0, 1, 2
auto pB_0 = D.dot(get<0>(edgeB1));
auto pB_1 = D.dot(get<0>(edgeB2));
auto pB_2 = D.dot(get<1>(edgeB2));
//The tA_1 and tA_2 define the interval of the intersection of triangle a with the line L
float tB_1 = pB_0 + (pB_1 - pB_0) * (dV0 / (dV0 - dV1));
float tB_2 = pB_1 + (pB_2 - pB_1) * (dV1 / (dV1 - dV2));
#pragma endregion
#pragma region Determine Overlap
bool intersect = false;
float intPoint1;
float intPoint2;
//Order the segments
if (tA_1 > tA_2)
{
float temp = tA_1;
tA_1 = tA_2;
tA_2 = temp;
}
if (tB_1 > tB_2)
{
float temp = tB_1;
tB_1 = tB_2;
tB_2 = temp;
}
//Check for overlap
if (tB_1 >= tA_1 && tB_2 <= tA_2)
{
intPoint1 = tB_1;
intPoint2 = tB_2;
intersect = true;
}
else if (tA_1 >= tB_1 && tA_2 <= tB_2)
{
intPoint1 = tA_1;
intPoint2 = tA_2;
intersect = true;
}
else if (tB_1 >= tA_1 && tB_1 < tA_2 && tB_2 > tA_2)
{
intPoint1 = tB_1;
intPoint2 = tA_2;
intersect = true;
}
else if (tA_1 >= tB_1 && tA_1 < tB_2 && tA_2 > tB_2)
{
intPoint1 = tA_1;
intPoint2 = tB_2;
intersect = true;
}
#pragma endregion
if (!intersect)
return nullptr;
//If an overlap found, perform the last step of the algorithm and find the actual points of the intersection segment
else
{
}
}
#pragma endregion
}