记录一下在三维空间计算中常用的点、线、面的计算函数。基于c++与Qt的类
1、基本数据类型
点数据类型,主要是使用Qt自带的三维点库#include<QVector3D>,没有使用Qt的可以自定义一个三维点的数据结构,如下:
struct QVector3D
{
float x;
float y;
float z;
};
线的表示,三维空间里直线主要由向量表示,可以用一个三维点和一个方向向量表示,一般方向向量取单位向量。
//Line
QVector3D p;// 起点
QVector3D dir;// 方向
当需要表示线段的时候,可以使用起点和终点两个QVector3D来表示,不过计算时一般用起点和方向附带min和max的范围来表示,线段上任意一点可以表示为:
p + t * dir, t∈(min,max)
其中t为float类型,使用了常数和三维向量的点乘。
平面的表示,与直线类似,三维空间里表示一个平面主要是用中心点和法向量表示,法向量一般取单位向量。
//Plane
QVector3D cen;// 中心点
QVector3D nor;// 法向量
2、基本计算函数
数乘,一个数和三维向量相乘,结果为这个三维向量每一个坐标轴都乘以这个数,当三维向量是单位向量时,结果可以表示三维空间中线的长度。
代码参考QT<QVector3D>库源码
inline QVector3D &QVector3D::operator*=(float factor)
{
v[0] *= factor;
v[1] *= factor;
v[2] *= factor;
return *this;
}
点乘,两个三维向量的点乘,结果为一个数,几何意义为一个向量在另外一个向量上投影后的长度与另外一个向量的乘积。如果另外一个向量为单位向量,则点乘结果的绝对值可以表示为向量的投影长度。如果两个向量都为单位向量,则可以表示为两向量夹角的余弦值。
代码参考QT<QVector3D>库源码
float QVector3D::dotProduct(const QVector3D& v1, const QVector3D& v2)
{
return v1.v[0] * v2.v[0] + v1.v[1] * v2.v[1] + v1.v[2] * v2.v[2];
}
叉乘,两个三维向量的叉乘,结果为一个向量,几何意义为与两个向量都垂直的以右手坐标系为方向的向量。叉乘经常在求法向量或者求某一个垂直向量时使用,且结果经常需要单位化成单位向量。
代码参考QT<QVector3D>库源码
QVector3D QVector3D::crossProduct(const QVector3D& v1, const QVector3D& v2)
{
return QVector3D(v1.v[1] * v2.v[2] - v1.v[2] * v2.v[1],
v1.v[2] * v2.v[0] - v1.v[0] * v2.v[2],
v1.v[0] * v2.v[1] - v1.v[1] * v2.v[0]);
}
3、点到点线面的距离
点到点的距离,点到点的距离可以表示为两个点为起点和终点组成的向量的长度。
代码参考QT<QVector3D>库源码
float QVector3D::length() const
{
double len = double(v[0]) * double(v[0]) +
double(v[1]) * double(v[1]) +
double(v[2]) * double(v[2]);
return float(std::sqrt(len));
}
float QVector3D::distanceToPoint(const QVector3D& point) const
{
return (*this - point).length();
}
点到直线的距离,直线用起点和单位方向向量表示,先将点投影到直线上得到投影点,然后计算点到投影点的距离,就是点到直线的距离。点投影到直线使用点乘计算,如图:
投影点P0'可以表示为p+t*dir,t表示P0'到p的距离,从图上可以看出,P0'p=P0p * cosθ,而dir表示P0'p方向的单位向量,所以t可以用P0-p与dir的点乘表示。求出t,再求出P0',最后得到P0P0'的长度就是点到直线的距离。
代码参考QT<QVector3D>库源码
float QVector3D::distanceToLine
(const QVector3D& point, const QVector3D& direction) const
{
if (direction.isNull())
return (*this - point).length();
QVector3D p = point + dotProduct(*this - point, direction) * direction;
return (*this - p).length();
}
点到平面的距离,点到平面的距离可以表示为点与平面上一点组成的向量在法向量上投影的长度,如图:
因为nor是单位向量,而P0的到平面的距离可以表示为P0cen * cosθ,用向量计算就为P0cen与nor的点乘,就是点到平面的距离。
代码参考QT<QVector3D>库源码
float QVector3D::distanceToPlane
(const QVector3D& plane, const QVector3D& normal) const
{
return dotProduct(*this - plane, normal);
}
下篇文章将介绍投影与相交的计算。