C++实现三维空间中点到点、点到直线、点到平面的距离计算

前言

在空间解释几何中,点到点、点到直线、点到平面的距离是基本的计算。计算公式也有多种推导方法(详细参见任何线性代数教材或维基百科)。本文运用向量的內积(点乘)、外积(叉乘)来计算这三个距离。

向量的內积、外积和距离的定义

  • 向量的模用向量自身的內积的平方根定义。
    v = ( v v ) ||\overrightarrow{v}||=\sqrt{(\overrightarrow{v}\cdot\overrightarrow{v})}

  • 点到点的距离则为两向量差的模。
    P 1 P 2 = O P 2 O P 1 ||\overrightarrow{P_1P_2}||=||\overrightarrow{OP_2}-\overrightarrow{OP_1}||

  • P 0 P_0 到直线 P 1 P 2 P_1P_2 的距离用向量 P 1 P 0 \overrightarrow{P_1P_0} 和直线 P 1 P 2 \overrightarrow{P_1P_2} 叉乘的模除以向量 P 1 P 2 \overrightarrow{P_1P_2} 的模来计算。
    d = P 1 P 0 × P 1 P 2 P 1 P 2 d=\dfrac{||\overrightarrow{P_1P_0}\times{\overrightarrow{P_1P_2}}||}{||\overrightarrow{P_1P_2}||}

  • 点P到平面的距离用平面内一点Q到该定点P的向量 Q P \overrightarrow{QP} 和平面的法向量 n \overrightarrow{n} 的內积的绝对值除以法向量的模来计算。
    d = Q P n n d=\dfrac{|\overrightarrow{QP}\cdot\overrightarrow{n}|}{||\overrightarrow{n}||}

程序介绍

定义了两个类,平面方程类(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

原创文章 8 获赞 9 访问量 4万+

猜你喜欢

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