来自:
http://www.azure.com.cn/article.asp?id=235
http://www.azure.com.cn/article.asp?id=236
一.快速判断点在2D三角形内
伪代码(Pseudocode) 如下:
bool pointIn2DTri(vec2 p, vec2 a, vec2 b, vec2 c)
{
vec2 v1, v2;
float area[3];
bool zero_area[3];
v1 = b - a;
v2 = p - a;
{
vec2 v1, v2;
float area[3];
bool zero_area[3];
v1 = b - a;
v2 = p - a;
//2D向量叉乘的几何意义在于,等于V1,V2向量组成三角形面积的两倍
area[0] = crossproduct(v1,v2);
//判断浮点数是否等于0
zero_area[0] = realequal(area[0], 0.0);
area[0] = crossproduct(v1,v2);
//判断浮点数是否等于0
zero_area[0] = realequal(area[0], 0.0);
v1 = c - b;
v2 = p - b;
v2 = p - b;
area[1] = crossproduct(v1, v2);
zero_area[1] = realequal(area[1], 0.0);
zero_area[1] = realequal(area[1], 0.0);
if(!zero_area[0] && !zero_area[1] &&
sign(area[0])!=sign(area[1])) //一个是正面积一个是负面积
{
return false;
}
sign(area[0])!=sign(area[1])) //一个是正面积一个是负面积
{
return false;
}
v1 = a - c;
v2 = p - c;
v2 = p - c;
area[2] = crossproduct(v1, v2);
zero_area[2] = realequal(area[2], 0.0);
zero_area[2] = realequal(area[2], 0.0);
//和相临的边再判断
if((!zero_area[0] && !zero_area[2] && sign(area[0])!=sign(area[2])) ||
(!zero_area[1] && !zero_area[2] && sign(area[1])!=sign(area[2])))
{
return false;
}
if((!zero_area[0] && !zero_area[2] && sign(area[0])!=sign(area[2])) ||
(!zero_area[1] && !zero_area[2] && sign(area[1])!=sign(area[2])))
{
return false;
}
return true;
}
}
二.快速判断点在3D三角形内
伪代码(Pseudocode) 如下:
比2D的判断稍微复杂一点点。
bool pointIn3DTri(vec3 p, vec3 a, vec3 b, vec3 c)
{
vec3 v1, v2;
float dot[3];
bool zeroDot[3];
//生成三角形的法线,任意两条边叉积
vec3 normal = makenormal(a, b, c);
v1 = b - a;
v2 = p - a;
dot[0] = dotproduct(crossproduct(v1, v2), normal);
zeroDot[0] = realequal(dot[0], 0.0);
v1 = c - b;
v2 = p - b;
dot[1] = dotproduct(crossproduct(v1, v2), normal);
zeroDot[1] = realequal(dot[1], 0.0);
{
vec3 v1, v2;
float dot[3];
bool zeroDot[3];
//生成三角形的法线,任意两条边叉积
vec3 normal = makenormal(a, b, c);
v1 = b - a;
v2 = p - a;
dot[0] = dotproduct(crossproduct(v1, v2), normal);
zeroDot[0] = realequal(dot[0], 0.0);
v1 = c - b;
v2 = p - b;
dot[1] = dotproduct(crossproduct(v1, v2), normal);
zeroDot[1] = realequal(dot[1], 0.0);
if(!zeroDot[0] && !zeroDot[1] &&
sign(dot[0] != sign(dot[1]))
return false;
sign(dot[0] != sign(dot[1]))
return false;
v1 = a - c;
v2 = p - c;
dot[2] = dotproduct(crossproduct(v1, v2), normal);
zeroDot[2] = realequal(dot[2], 0.0);
bool ifs1 = !zeroDot[0] && !zeroDot[2] && sign(dot[0]) != sign(dot[2]);
bool ifs2 = !zeroDot[1] && !zeroDot[2] && sign(dot[1]) != sign(dot[2]);
v2 = p - c;
dot[2] = dotproduct(crossproduct(v1, v2), normal);
zeroDot[2] = realequal(dot[2], 0.0);
bool ifs1 = !zeroDot[0] && !zeroDot[2] && sign(dot[0]) != sign(dot[2]);
bool ifs2 = !zeroDot[1] && !zeroDot[2] && sign(dot[1]) != sign(dot[2]);
if(ifs1 || ifs2)
return false;
return false;
return true;
}