目录
直线的向量方程
三维欧几里得空间中,直线的关系为:相交、平行和异面直线三种情况。设点A、B决定了直线 L 1 L_1 L1,点C、D决定了直线 L 2 L_2 L2。求直线 L 1 L_1 L1和 L 2 L_2 L2间的距离可以用以下方法实现。
令直线 L 1 L_1 L1的向量方程: x = a + λ b , ( a 、 b 、 x ∈ R 3 , λ ∈ R , a = O A ‾ , b = A B ‾ = O B ‾ − O A ‾ ) x=a+\lambda{b}, ({a、b、x}\in{R^3}, \lambda\in{R}, a=\overline{OA}, b=\overline{AB}=\overline{OB}-\overline{OA}) x=a+λb,(a、b、x∈R3,λ∈R,a=OA,b=AB=OB−OA)
这里, a a a是直线 L 1 L_1 L1上的一点(向量), b b b是直线 L 1 L_1 L1的方向向量。
类似地,令直线 L 2 L_2 L2的向量方程: y = c + μ d , ( c 、 d 、 y ∈ R 3 , μ ∈ R , c = O C ‾ , d = C D ‾ = O D ‾ − O C ‾ ) y=c+\mu{d},({c、d、y}\in{R^3}, \mu\in{R}, c=\overline{OC}, d=\overline{CD}=\overline{OD}-\overline{OC}) y=c+μd,(c、d、y∈R3,μ∈R,c=OC,d=CD=OD−OC)
同样, c c c是直线 L 2 L_2 L2上的一点(向量), d d d是直线 L 2 L_2 L2的方向向量。
令: n = b × d ∣ ∣ b × d ∣ ∣ n=\dfrac{ {b}\times{d}}{||{b}\times{d}||} n=∣∣b×d∣∣b×d,则直线间距离: l = ∣ n ⋅ ( c − a ) ∣ l=|{n}\cdot{(c-a)}| l=∣n⋅(c−a)∣
注:如果 ∣ ∣ b × d ∣ ∣ = 0 ||{b}\times{d}||=0 ∣∣b×d∣∣=0,则表示直线 L 1 L_1 L1和 L 2 L_2 L2平行。不能用此公式计算。这时候,只要任取直线 L 1 L_1 L1上一点,例如A点,那么点A到直线 L 2 L_2 L2的距离就是两平行线 L 1 L_1 L1和 L 2 L_2 L2间的距离。
程序说明
定义了一个类:点类。定义了向量的基本操作,如类初始化、参数参数的设置和读取、重载了“+”、“-”、“*”运算符实现向量的加、减、叉乘运算、定义了向量的点乘、模等运算。点到点、点到直线、直线到直线的距离在主程序中定义。
点类
定义了向量加(+)、减(-)、叉乘(*)、点乘、向量的模等。
头文件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;
}
计算公式参考:https://en.wikipedia.org/wiki/Skew_lines