假如平面上有三个不同点P1(x1,y1,z1),P2(x2,y2,z2),P3(x3,y3,z3),则该平面的法向量n是一个跟向量P1P2,向量P2P3,向量P1P3,都垂直的向量。之前用垂直向量的数量积(点积)为0的方法,解方程求得法向量,算法复杂性较高,参见之前写的文章:http://blog.csdn.net/u011442652/article/details/37727977
其实,除了数量积的思想外,法向量还可以向量积(矢量积)的思想求解。两个向量的向量积是跟这两个向量都垂直的向量,方向遵循右手法则。所以,我可以通过求解两个向量的向量积来求解法向量。
定义浮点0为:
#define MYFLOAT0 1e-6//在-FLOAT_0_到FLOAT_0_范围内都认为是0
两个向量的向量积求解函数如下:
void cross(double v1x,double v1y,double v1z,double v2x,double v2y,double v2z,double &nx,double &ny,double &nz)//v1^v2
{
nx=v1y*v2z-v1z*v2y;
ny=v1z*v2x-v1x*v2z;
nz=v1x*v2y-v1y*v2x;
}
两个向量的数量积求解函数如下:
double dot(double v1x,double v1y,double v1z,double v2x,double v2y,double v2z)
{
double result=v1x*v2x+v1y*v2y+v1z*v2z;
return result;
}
向量标准化函数如下:
bool normalize(double vx,double vy,double vz,double &nx,double &ny,double &nz)
{
double len=sqrt(vx*vx+vy*vy+vz*vz);
if (len>-MYFLOAT0&&len<MYFLOAT0)
{
return false;
}
nx=vx/len;
ny=vy/len;
nz=vz/len;
return true;
}
求解法向量函数如下:
bool CalNormalVector(double x1,double y1,double z1,double x2,double y2,double z2,double x3,double y3,double z3,double &dx,double &dy,double &dz)
{
double pt1pt2[3]={x2-x1,y2-y1,z2-z1};
double pt2pt3[3]={x3-x2,y3-y2,z3-z2};
double pt1pt3[3]={x3-x1,y3-y1,z3-z1};
double nx=0.0,ny=0.0,nz=0.0f;
cross(pt1pt2[0],pt1pt2[1],pt1pt2[2],pt2pt3[0],pt2pt3[1],pt2pt3[2],nx,ny,nz);
if (nx>-MYFLOAT0&&nx<MYFLOAT0&&
ny>-MYFLOAT0&&ny<MYFLOAT0&&
nz>-MYFLOAT0&&nz<MYFLOAT0)
{
return false;
}
//
bool flag=normalize(nx,ny,nz,dx,dy,dz);
if (!flag)
{
return false;
}
//测试,三向量与法向量数量积都是0
double dot1n1=dot(dx,dy,dz,pt1pt2[0],pt1pt2[1],pt1pt2[2]);
double dot2n1=dot(dx,dy,dz,pt2pt3[0],pt2pt3[1],pt2pt3[2]);
double dot3n1=dot(dx,dy,dz,pt1pt3[0],pt1pt3[1],pt1pt3[2]);
if (!(dot1n1>-MYFLOAT0&&dot1n1<MYFLOAT0&&
dot2n1>-MYFLOAT0&&dot2n1<MYFLOAT0&&
dot2n1>-MYFLOAT0&&dot2n1<MYFLOAT0))
{
return false;
}
return true;
}