C++实现三维空间中直线间距离的计算

直线的向量方程

三维欧几里得空间中,直线的关系为:相交、平行和异面直线三种情况。设点A、B决定了直线 L 1 L_1 ,点C、D决定了直线 L 2 L_2 。求直线 L 1 L_1 L 2 L_2 间的距离可以用以下方法实现。

令直线 L 1 L_1 的向量方程: 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})
这里, a a 是直线 L 1 L_1 上的一点(向量), b b 是直线 L 1 L_1 的方向向量。

类似地,令直线 L 2 L_2 的向量方程: 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})
同样, c c 是直线 L 2 L_2 上的一点(向量), d d 是直线 L 2 L_2 的方向向量。

令: n = b × d b × d n=\dfrac{{b}\times{d}}{||{b}\times{d}||} ,则直线间距离: l = n ( c a ) l=|{n}\cdot{(c-a)}|
注:如果 b × d = 0 ||{b}\times{d}||=0 ,则表示直线 L 1 L_1 L 2 L_2 平行。不能用此公式计算。这时候,只要任取直线 L 1 L_1 上一点,例如A点,那么点A到直线 L 2 L_2 的距离就是两平行线 L 1 L_1 L 2 L_2 间的距离。

程序说明

定义了一个类:点类。定义了向量的基本操作,如类初始化、参数参数的设置和读取、重载了“+”、“-”、“*”运算符实现向量的加、减、叉乘运算、定义了向量的点乘、模等运算。点到点、点到直线、直线到直线的距离在主程序中定义。

点类

定义了向量加(+)、减(-)、叉乘(*)、点乘、向量的模等。
头文件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

扫描二维码关注公众号,回复: 11147807 查看本文章
原创文章 8 获赞 9 访问量 4万+

猜你喜欢

转载自blog.csdn.net/yang_deyuan/article/details/79152647