一个平面通常是由一个平面法线向量,如v1(1,2,3),和点到原点(0,0,0)到平面的距离确定的。
当然数学中还有其他定义方法,但是DirectX和OpenGL都是使用这种定义方法的。这样定义的平面叫一般平面,其实是由点法式平面变形来的。
点我们可以使用Vector3类来确定,这个类既可以确定点,也可以确定向量。
Vector3这个类定义:http://blog.youkuaiyun.com/kenden23/article/details/16901331
下面定义一个平面:
class Plane
{
public:
float a, b, c, d;
enum PLAN_STATES
{
PLANT_FRONT,
PLANT_BACK,
PLANT_ON_PLANE
};
Plane():a(0), b(0), c(0), d(0){}
Plane(float a1, float b1, float c1, float d1):a(a1), b(b1), c(c1), d(d1){}
void createPlane(Vector3 v1, Vector3 v2, Vector3 v3);
float distance(float x, float y, float z);
float distance(Vector3 v);
PLAN_STATES classifyPoint(float x, float y, float z, float &dist);
};
CreatePlane函数是用三个点确定一个平面,并计算成一般平面,存储好。classfyPoint这个函数就是用来计算点和平面的关系的。
实现代码:
void Plane::createPlane(Vector3 v1, Vector3 v2, Vector3 v3)
{
Vector3 t1, t2, n;
t1 = v2 - v1;
t2 = v3 - v1;
n = t1.crossProduct(t2);
n.normalize();
a = n.x;
b = n.y;
c = n.z;
d = -(a*v1.x + b*v1.y + c*v1.z);
}
float Plane::distance(float x, float y, float z)
{
return a*x+b*y+c*z+d;
}
float Plane::distance(Vector3 v)
{
return a*v.x+b*v.y+c*v.z+d;
}
//Claaisyf a point's position about the plane
Plane::PLAN_STATES Plane::classifyPoint(float x, float y, float z, float &dist)
{
dist = distance(x,y,z);
if (dist > uZero)
{
return PLANT_FRONT;
}
if (dist < -uZero)
{
return PLANT_BACK;
}
return PLANT_ON_PLANE;
}
以平面的法向量为标准,如果在法向量正方向,那么就是在平面前面,如果在法向量反方向就是在平面后面,在Vector3文件中定义了个uZero = 1e-6 (=0.000001);如果距离少于uZero,那么就是在平面上。因为浮点数是有误差的,所以最好不用0作为比较。
测试代码:
#include<iostream>
#include"Plane.h"
using namespace std;
int main()
{
Plane p1;
Vector3 v1(1.0f, 0.0f, 0.0f);
Vector3 v2(0.0f, 1.0f, 0.0f);
Vector3 v3(0.0f, 0.0f, 1.0f);
p1.createPlane(v1, v2, v3);
cout<<"We have create a plane:\n";
cout<<"Plane's a = "<<p1.a<<endl;
cout<<"Plane's b = "<<p1.b<<endl;
cout<<"Plane's c = "<<p1.c<<endl;
cout<<"Plane's d = "<<p1.d<<endl;
cout<<"v1 to Plane's distance is: "<<p1.distance(v1)<<endl;
Vector3 v4(8.0f, 8.0f, 8.0f);
cout<<"Vector3 v4 is: ";
v4.printVec3();
cout<<"v4's relationship with plane is: ";
float dist = 0;
switch (p1.classifyPoint(v4.x, v4.y, v4.z, dist))
{
case Plane::PLANT_BACK:
cout<<"on the back of the plane.\n";
break;
case Plane::PLANT_FRONT:
cout<<"on the front of the plane.\n";
break;
case Plane::PLANT_ON_PLANE:
cout<<"right on the plane\n";
break;
default:
break;
}
cout<<"v4 to plane's distance is: "<<dist<<endl;
system("pause");
return 0;
}
运行结果: