前言
在空间解释几何中,点到点、点到直线、点到平面的距离是基本的计算。计算公式也有多种推导方法(详细参见任何线性代数教材或维基百科)。本文运用向量的內积(点乘)、外积(叉乘)来计算这三个距离。
向量的內积、外积和距离的定义
-
向量的模用向量自身的內积的平方根定义。
-
点到点的距离则为两向量差的模。
-
点 到直线 的距离用向量 和直线 叉乘的模除以向量 的模来计算。
-
点P到平面的距离用平面内一点Q到该定点P的向量 和平面的法向量 的內积的绝对值除以法向量的模来计算。
程序介绍
定义了两个类,平面方程类(PlaneEquation)和点类(Point)。PlaneEquation类定义了平面方程的基本操作,例如类初始化、参数的设置和读取。重载了"<<"操作符以输出平面方程式。Point类定义了向量的基本操作,如类初始化、参数参数的设置和读取、重载了“+”、“-”、“*”运算符实现向量的加、减、叉乘运算、定义了向量的点乘、模等运算。
点到点、点到直线、点到平面的距离的计算在主程序中定义。考虑了直线退化为点、平面退化为原点的特殊情况下距离的计算。
全部程序源文件如下。
平面方程类
头文件:PlaneEquation.h
#ifndef PLANEEQUATION_H
#define PLANEEQUATION_H
#include<iostream>
class PlaneEquation
{
public:
PlaneEquation(double _A=0.0,double _B=0.0,double _C=0.0,double _D=0.0):A(_A),B(_B),C(_C),D(_D){};
virtual ~PlaneEquation(){};
PlaneEquation(const PlaneEquation&);
PlaneEquation &operator=(const PlaneEquation&);
friend std::ostream &operator<<(std::ostream&, const PlaneEquation&);
double GetA() { return A; }
void SetA(double val) { A = val; }
double GetB() { return B; }
void SetB(double val) { B = val; }
double GetC() { return C; }
void SetC(double val) { C = val; }
double GetD() { return D; }
void SetD(double val) { D = val; }
protected:
private:
double A;
double B;
double C;
double D;
};
#endif // PLANEEQUATION_H
类的实现:PlaneEquation.cpp
#include "PlaneEquation.h"
PlaneEquation::PlaneEquation(const PlaneEquation &other)
{
//copy ctor
A=other.A;
B=other.B;
C=other.C;
D=other.D;
}
PlaneEquation &PlaneEquation::operator=(const PlaneEquation &rhs)
{
if (this == &rhs) return *this; // handle self assignment
//assignment operator
A=rhs.A;
B=rhs.B;
C=rhs.C;
D=rhs.D;
return *this;
}
std::ostream &operator<<(std::ostream &output, const PlaneEquation &rhs)
{
if (rhs.A!=0.0) {
if (rhs.A==-1.0) output<<"-";
else if (rhs.A!=1.0) output<<rhs.A;
output<<"X";
}
if (rhs.B!=0.0) {
if (rhs.B>0.0) {
output<<"+";
if (rhs.B!=1.0) output<<rhs.B;
} else if (rhs.B!=-1.0) output<<rhs.B;
else output<<"-";
output<<"Y";
}
if (rhs.C!=0.0) {
if (rhs.C>0.0) {
output<<"+";
if (rhs.C!=1.0) output<<rhs.C;
} else if (rhs.C!=-1.0) output<<rhs.C;
else output<<"-";
output<<"Z";
}
if (rhs.D!=0.0) {
if (rhs.D>0.0) output<<"+";
output<<rhs.D;
}
output<<"=0";
return output;
}
点类
点类定义了向量加(+)、减(-)、叉乘(*)、点乘、向量的模等。
头文件:Point.h
#ifndef POINT_H
#define POINT_H
#include<iostream>
#include<cmath>
class Point
{
public:
Point(double _x=0.0,double _y=0.0,double _z=0.0):X(_x),Y(_y),Z(_z){};
virtual ~Point(){};
Point(const Point &other) { X=other.X; Y=other.Y; Z=other.Z; };
Point operator=(const Point&);
Point operator+(const Point&);
Point operator-(const Point&);
Point operator*(Point&);
friend std::ostream &operator<<(std::ostream &output, const Point &rhs);
double GetX() { return X; }
void SetX(double val) { X = val; }
double GetY() { return Y; }
void SetY(double val) { Y = val; }
double GetZ() { return Z; }
void SetZ(double val) { Z = val; }
double dotX(Point &pt) { return (pt.GetX()*GetX()+pt.GetY()*GetY()+pt.GetZ()*GetZ()); }
double mod() { return sqrt(dotX(*this)); }
protected:
private:
double X;
double Y;
double Z;
};
#endif // POINT_H
类的实现:Point.cpp
#include "Point.h"
Point Point::operator=(const Point &rhs)
{
if (this == &rhs) return *this; // handle self assignment
//assignment operator
X=rhs.X;
Y=rhs.Y;
Z=rhs.Z;
return *this;
}
Point Point::operator+(const Point &rhs)
{
return (Point(X+rhs.X,Y+rhs.Y,Z+rhs.Z));
}
Point Point::operator-(const Point &rhs)
{
return (Point(X-rhs.X,Y-rhs.Y,Z-rhs.Z));
}
std::ostream &operator<<(std::ostream &output, const Point &rhs)
{
output<<"("<<rhs.X<<","<<rhs.Y<<","<<rhs.Z<<")";
return output;
}
Point Point::operator*(Point &pt)
{
double x1,x2,y1,y2,z1,z2,vx,vy,vz;
x1=GetX();
x2=pt.GetX();
y1=GetY();
y2=pt.GetY();
z1=GetZ();
z2=pt.GetZ();
vx=y1*z2-y2*z1;
vy=-x1*z2+x2*z1;
vz=x1*y2-x2*y1;
return Point(vx,vy,vz);
}
主程序:main.cpp
#include <iostream>
#include <cmath>
#include "Point.h"
#include "PlaneEquation.h"
using namespace std;
double dist(Point &pt1, Point &pt2) //Distance between two points
{
return (pt2-pt1).mod();
}
double dist(Point &ptC, Point &ptA, Point &ptB) //Distance between point C to line AB.
{
double d=0.0;
Point ac,ab;
ac=ptC-ptA;
ab=ptB-ptA;
if (ab.mod()) { d=(ac*ab).mod()/ab.mod(); }
else { d=dist(ptC,ptA); } //The line is reduced to a point. point(ptC) to point(ptA) distance.
return d;
}
double dist(Point &pt, PlaneEquation &pe) //Distance between point and plane
{
double dt=0.0;
double mA,mB,mC,mD,mX,mY,mZ;
mA=pe.GetA();
mB=pe.GetB();
mC=pe.GetC();
mD=pe.GetD();
mX=pt.GetX();
mY=pt.GetY();
mZ=pt.GetZ();
if (mA*mA+mB*mB+mC*mC) { dt=abs(mA*mX+mB*mY+mC*mZ+mD)/sqrt(mA*mA+mB*mB+mC*mC); }
else { dt=pt.mod(); } // The plane is reduced to the origin. point(pt) to point(zero) distance.
return dt;
}
int main()
{
Point p0,p1(1.0,0.0,0.0),p2(0.0,1.0,0.0),p3(0.0,0.0,1.0),p4(1.0,1.0,1.0),p1p3,p1p2,p0p4;
PlaneEquation pL0, pL(1.0,1.0,1.0,-1.0);
cout<<"\n---------------- Points --------------------"<<endl;
cout<<"\nThe point P0 is : "<<p0<<" |P0|="<<p0.mod()<<endl;
cout<<"\nThe point P1 is : "<<p1<<" |P1|="<<p1.mod()<<endl;
cout<<"\nThe point P2 is : "<<p2<<" |P2|="<<p2.mod()<<endl;
cout<<"\nThe point P3 is : "<<p3<<" |P3|="<<p3.mod()<<endl;
cout<<"\nThe point P4 is : "<<p4<<" |P4|="<<p4.mod()<<endl;
cout<<"\n---------------- Point to point --------------------"<<endl;
cout<<"\nThe distance between point P0 and p1 : "<<dist(p0,p1)<<endl;
cout<<"\nThe distance between point P0 and p2 : "<<dist(p0,p2)<<endl;
cout<<"\nThe distance between point P0 and p3 : "<<dist(p0,p3)<<endl;
cout<<"\nThe distance between point P0 and p4 : "<<dist(p0,p4)<<endl;
cout<<"\n---------------- Point to line --------------------"<<endl;
cout<<"\nThe distance between point P3 and the line p1,p2 is : "<<dist(p3,p1,p2)<<endl;
cout<<"\nThe distance between point P3 and the line p1,p3 is : "<<dist(p3,p1,p3)<<endl;
cout<<"\nThe distance between point P3 and the line p2,p3 is : "<<dist(p3,p2,p3)<<endl;
cout<<"\nThe distance between point P3 and the line p1,p1 is : "<<dist(p3,p1,p1)<<endl;
cout<<"\n---------------- Point to plane --------------------"<<endl;
cout<<"\nThe plane equation is : "<<pL<<endl;
cout<<"\nThe distance between point P0 and the plane is : "<<dist(p0,pL)<<endl;
cout<<"\nThe distance between point P1 and the plane is : "<<dist(p1,pL)<<endl;
cout<<"\nThe plane equation is : "<<pL0<<endl;
cout<<"\nThe distance between point P4 and the plane is : "<<dist(p4,pL0)<<endl;
return 0;
}
计算公式参考
[1]https://en.wikipedia.org/wiki/Dot_product
[2]https://en.wikipedia.org/wiki/Cross_product
[3]https://en.wikipedia.org/wiki/Distance_from_a_point_to_a_line
[4]https://en.wikipedia.org/wiki/Distance_from_a_point_to_a_plane