三維歐幾里得空間中,直線的關係爲:相交、平行和異面直線三種情況。設點A、B決定了直線 ,點C、D決定了直線 。求直線 和 間的距離可以用以下方法實現。
令直線 的向量方程:
這裏, 是直線 上的一點(向量), 是直線 的方向向量。
類似地,令直線 的向量方程:
同樣, 是直線 上的一點(向量), 是直線 的方向向量。
令: ,則直線間距離:
注:如果 ,則表示直線 和 平行。不能用此公式計算。這時候,只要任取直線 上一點,例如A點,那麼點A到直線 的距離就是兩平行線 和 間的距離。
程序說明
定義了一個類:點類。定義了向量的基本操作,如類初始化、參數參數的設置和讀取、重載了“+”、“-”、“*”運算符實現向量的加、減、叉乘運算、定義了向量的點乘、模等運算。點到點、點到直線、直線到直線的距離在主程序中定義。
點類
定義了向量加(+)、減(-)、叉乘(*)、點乘、向量的模等。
頭文件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-(const Point&);
Point operator-(); // opposite number
Point operator-=(const Point&);
Point operator*(const Point&); // cross product
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(const Point &pt) { return (pt.X*X+pt.Y*Y+pt.Z*Z); }
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; // self assignment
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)
{
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-() // opposite number
{
return Point(-X, -Y, -Z);
}
Point Point::operator-=(const Point &rhs)
{
X-=rhs.X;
Y-=rhs.Y;
Z-=rhs.Z;
return (*this);
}
std::ostream &operator<<(std::ostream &output, const Point &rhs)
{
output<<"("<<rhs.X<<","<<rhs.Y<<","<<rhs.Z<<")";
return output;
}
Point Point::operator*(const Point &pt) // cross product
{
double x1,x2,y1,y2,z1,z2,vx,vy,vz;
x1=X;
x2=pt.X;
y1=Y;
y2=pt.Y;
z1=Z;
z2=pt.Z;
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 <fstream>
#include "Point.h"
using namespace std;
const double EPS=1e-10; // zero
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() >= EPS) { 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 &ptA, Point &ptB, Point &ptC, Point &ptD) //Distance between line AB to line CD.
{
double d=0.0;
Point ab, cd, ad, axd;
ab=ptB-ptA;
cd=ptD-ptC;
ad=ptD-ptA;
axd=ab * cd;
if ((axd.mod()) >= EPS) { d = abs((axd.dotX(ad)))/axd.mod(); } //skew lines
else { d=dist(ptA, ptC, ptD); } //parallel lines
return d;
}
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);
Point p5(1.0, 1.0, 0.0), p6(0.0, 1.0, 1.0), p7(1.0, 0.0, 1.0);
cout<<"\n---------------- Line to line --------------------"<<endl;
cout<<"\nThe distance between the line p1p2 and the line p3p4 is : "<<dist(p1,p2,p3,p4)<<endl;
cout<<"\nThe distance between the line p1p3 and the line p4p7 is : "<<dist(p1,p3,p4,p7)<<endl;
cout<<"\nThe distance between the line p1p3 and the line p5p6 is : "<<dist(p1,p3,p5,p6)<<endl;
cout<<"\nThe distance between the line p2p3 and the line p5p6 is : "<<dist(p2,p3,p5,p6)<<endl;
cout<<"\nThe distance between the line p1p3 and the line p1p7 is : "<<dist(p1,p3,p1,p7)<<endl;
return 0;
}