C++實現三維空間中直線間距離的計算

三維歐幾里得空間中,直線的關係爲:相交、平行和異面直線三種情況。設點A、B決定了直線L1 ,點C、D決定了直線L2 。求直線L1L2 間的距離可以用以下方法實現。

令直線L1 的向量方程:

x=a+λb,(abxR3,λR,a=OA¯,b=AB¯=OB¯OA¯)

這裏,a 是直線L1 上的一點(向量),b 是直線L1 的方向向量。

類似地,令直線L2 的向量方程:

y=c+μd,(cdyR3,μR,c=OC¯,d=CD¯=OD¯OC¯)

同樣,c 是直線L2 上的一點(向量),d 是直線L2 的方向向量。

令:n=b×d||b×d|| ,則直線間距離:l=|n(ca)|
注:如果||b×d||=0 ,則表示直線L1L2 平行。不能用此公式計算。這時候,只要任取直線L1 上一點,例如A點,那麼點A到直線L2 的距離就是兩平行線L1L2 間的距離。

程序說明

定義了一個類:點類。定義了向量的基本操作,如類初始化、參數參數的設置和讀取、重載了“+”、“-”、“*”運算符實現向量的加、減、叉乘運算、定義了向量的點乘、模等運算。點到點、點到直線、直線到直線的距離在主程序中定義。

點類

定義了向量加(+)、減(-)、叉乘(*)、點乘、向量的模等。
頭文件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

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章