通过叉乘的方法实现,下面是ogre中的实现代码,只给出2维的函数,三维是同样的道理:
代码
//判断一个点是否在一个2维三角形内,通过叉乘的方法来实现
bool Math::pointInTri2D(const Vector2& p, const Vector2& a,
const Vector2& b, const Vector2& c)
{
// Winding must be consistent from all edges for point to be inside
Vector2 v1, v2;
Real dot[3];
bool zeroDot[3];
v1 = b - a;
v2 = p - a;
// Note we don't care about normalisation here since sign is all we need
// It means we don't have to worry about magnitude of cross products either
dot[0] = v1.crossProduct(v2);
zeroDot[0] = Math::RealEqual(dot[0], 0.0f, 1e-3);
v1 = c - b;
v2 = p - b;
dot[1] = v1.crossProduct(v2);
zeroDot[1] = Math::RealEqual(dot[1], 0.0f, 1e-3);
// Compare signs (ignore colinear / coincident points)
if(!zeroDot[0] && !zeroDot[1]
&& Math::Sign(dot[0]) != Math::Sign(dot[1]))
{
return false;
}
v1 = a - c;
v2 = p - c;
dot[2] = v1.crossProduct(v2);
zeroDot[2] = Math::RealEqual(dot[2], 0.0f, 1e-3);
// Compare signs (ignore colinear / coincident points)
if((!zeroDot[0] && !zeroDot[2]
&& Math::Sign(dot[0]) != Math::Sign(dot[2])) ||
(!zeroDot[1] && !zeroDot[2]
&& Math::Sign(dot[1]) != Math::Sign(dot[2])))
{
return false;
}
return true;
}
bool Math::pointInTri2D(const Vector2& p, const Vector2& a,
const Vector2& b, const Vector2& c)
{
// Winding must be consistent from all edges for point to be inside
Vector2 v1, v2;
Real dot[3];
bool zeroDot[3];
v1 = b - a;
v2 = p - a;
// Note we don't care about normalisation here since sign is all we need
// It means we don't have to worry about magnitude of cross products either
dot[0] = v1.crossProduct(v2);
zeroDot[0] = Math::RealEqual(dot[0], 0.0f, 1e-3);
v1 = c - b;
v2 = p - b;
dot[1] = v1.crossProduct(v2);
zeroDot[1] = Math::RealEqual(dot[1], 0.0f, 1e-3);
// Compare signs (ignore colinear / coincident points)
if(!zeroDot[0] && !zeroDot[1]
&& Math::Sign(dot[0]) != Math::Sign(dot[1]))
{
return false;
}
v1 = a - c;
v2 = p - c;
dot[2] = v1.crossProduct(v2);
zeroDot[2] = Math::RealEqual(dot[2], 0.0f, 1e-3);
// Compare signs (ignore colinear / coincident points)
if((!zeroDot[0] && !zeroDot[2]
&& Math::Sign(dot[0]) != Math::Sign(dot[2])) ||
(!zeroDot[1] && !zeroDot[2]
&& Math::Sign(dot[1]) != Math::Sign(dot[2])))
{
return false;
}
return true;
}