空间点、线和面

实现三维解析几何中的点、直线和平面类,
1 ) 能够实现直线的不同创建方式(例如,两个点确定一条直线,两个相交的平面确定一条直线,空间曲线的点斜式)和平面的 不同创建方式(例如,三个不共线的点确定一个平面,一个点和一个法向量确定一个平面;
(2) 能够计算相应的距离:两点之间的距离,点到直线的距离,点到平面的距离;
(3) 能够计算空间直线的单位方向向量(长度为 1 ),空间平面的 单位法向量(长度为1 );
(4) 能够判断点和线的关系,线和线的关系,点和平面的关系, 线和平面的关系,平面和平面的关系。
(5) 注意:要考虑计算机中实数计算的精度误差(不同精度的数 值相等判断不能使用 == )。

提示:
      点、直线和平面分别用类来封装,每个类的数据为该表示该类 需要的参数,例如,对于空间平面的一般方程为ax+by+cz+d = 0,那么私有数据成员为 a, b, c d ; 空间直线和平面的不同创建方式定义为对应类的成员函数;  空间点和点、点和直线、点和平面、直线和直线、直线和平 面、平面和平面位置关系的判断定义为一般的函数; 要在main 函数中对上述功能进行调用和验证。

代码如下:

#include<iostream>
#include<iomanip>
#include<cmath>

using namespace std;

class CPoint
{
public:
    double dPosX;   //x坐标
    double dPosY;  //y坐标
    double dPosZ;  //z坐标
    CPoint( double x=0,double y=0,double z=0 ):dPosX(x),dPosY(y),dPosZ(z) {}
    CPoint( CPoint &cpo )
    {
        dPosX = cpo.dPosX;
        dPosY = cpo.dPosY;
        dPosZ = cpo.dPosZ;
    }
    bool operator == ( CPoint &cpo )    //判断两点是否相等
    {
        return dPosX==cpo.dPosX && dPosY==cpo.dPosY &&
               dPosZ==cpo.dPosZ;
    }
    friend double Pdistance( CPoint &A, CPoint &B );//计算两点间距离
    ~CPoint() {}
};

/*  计算两点间距离  */
double Pdistance( CPoint &A, CPoint &B )
{
    return sqrt( pow(A.dPosX-B.dPosX,2) + pow(A.dPosY-B.dPosY,2) + pow(A.dPosZ-B.dPosZ,2));
}

class CLine : public CPoint
{
public:
    CPoint cpoA;    //A点
    CPoint cpoB;    //B点
    CLine( double x=0,double y=0,double z=0,double xx=0,double yy=0,double zz=0)
        :cpoA(x,y,z), cpoB(xx,yy,zz) {}
    CLine( CPoint &cpo1, CPoint &cpo2 ):cpoA(cpo1),cpoB(cpo2) {}
    void TwoPoint();    //两点式
    void PointDirection();  //点向式
    void Parameter();   //参数式
    void LineDirection();   //计算空间直线的单位方向向量
    friend double Ldistance( CPoint & S, CLine & L );  //计算点到直线距离
    ~CLine() {}
};

class CPlane : public CPoint
{
public:
    //对于一般方程ax+by+cz+d=0
    double da;
    double db;
    double dc;
    double dd;
    CPoint cpoC;    //平面上一点
    CPlane( double x=0,double y=0,double z=0,double a=0,double b=0,double c=0,double d=0)
        :cpoC(x,y,z),da(a),db(b),dc(c),dd(d) {}
    void ThreePoint();  //三点创建一个平面
    void PointNormal();  //点法式
    void PlaneNormal();  //计算空间平面的单位法向量
    friend double PLdistance( CPoint &S, CPlane &P );  //计算点到平面的距离
    ~CPlane() {}
};

/*  两点式创建直线  */
void CLine::TwoPoint()
{
    if( cpoA == cpoB )
    {
        cout<<"两点相同,无法构成直线"<<endl;
    }
    else
    {
        cout<<"直线方程为: ";
        cout<<"x-"<<cpoA.dPosX<<"/"<<cpoB.dPosX - cpoA.dPosX<<" = ";
        cout<<"y-"<<cpoA.dPosY<<"/"<<cpoB.dPosY - cpoA.dPosY<<" = ";
        cout<<"z-"<<cpoA.dPosZ<<"/"<<cpoB.dPosZ - cpoA.dPosZ<<endl;
    }
}

/*  点向式创建直线  */
void CLine::PointDirection()
{
    if( cpoA == cpoB )
    {
        cout<<"两点相同,无法构成直线"<<endl;
    }
    else
    {
        //(dm,dn,dp)为直线的方向向量
        double dm = cpoB.dPosX - cpoA.dPosX;
        double dn = cpoB.dPosY - cpoA.dPosY;
        double dp = cpoB.dPosZ - cpoA.dPosZ;
        cout<<"直线方程为: ";
        cout<<"x-"<<cpoA.dPosX<<"/"<<dm<<" = ";
        cout<<"y-"<<cpoA.dPosY<<"/"<<dn<<" = ";
        cout<<"z-"<<cpoA.dPosZ<<"/"<<dp<<endl;
    }
}

/*  参数式创建直线  */
void CLine::Parameter()
{
    if( cpoA == cpoB )
    {
        cout<<"两点相同,无法构成直线"<<endl;
    }
    else
    {
        //(dm,dn,dp)为直线的方向向量
        double dm = cpoB.dPosX - cpoA.dPosX;
        double dn = cpoB.dPosY - cpoA.dPosY;
        double dp = cpoB.dPosZ - cpoA.dPosZ;
        cout<<"直线方程为: ";
        cout<<"x=";
        if(dm!=0)
        {
            if(dm!=1)
            {
                if(dm==-1)
                {
                    cout<<"-";
                }
                else
                {
                    cout<<dm;
                }
            }
            cout<<"t";
            if(cpoA.dPosX>0)
            {
                cout<<"+";
            }
        }
        cout<<cpoA.dPosX<<"   y=";
        if(dn!=0)
        {
            if(dn!=1)
            {
                if(dn==-1)
                {
                    cout<<"-";
                }
                else
                {
                    cout<<dn;
                }
            }
            cout<<"t";
            if(cpoA.dPosY>0)
            {
                cout<<"+";
            }
        }
        cout<<cpoA.dPosY<<"   z=";
        if(dp!=0)
        {
            if(dp!=1)
            {
                if(dp==-1)
                {
                    cout<<"-";
                }
                else
                {
                    cout<<dp;
                }
            }
            cout<<"t";
            if(cpoA.dPosZ>0)
            {
                cout<<"+";
            }
        }
        cout<<cpoA.dPosZ<<endl;
    }
}

/*  计算空间直线的单位方向向量  */
void CLine::LineDirection()
{
    //(dm,dn,dp)为直线的方向向量
    double dm = cpoB.dPosX - cpoA.dPosX;
    double dn = cpoB.dPosY - cpoA.dPosY;
    double dp = cpoB.dPosZ - cpoA.dPosZ;
    cout<<"直线的单位方向向量为: ";
    double ds = sqrt( dm*dm + dn*dn + dp*dp );
    cout<<"("<<dm/ds<<","<<dn/ds<<","<<dp/ds<<")"<<endl;
}

/*  计算点到直线距离  */
double Ldistance( CPoint & S, CLine & L )
{
    double dLAB = Pdistance( L.cpoA, L.cpoB );
    double dLAS = Pdistance( S, L.cpoA );
    double dLBS = Pdistance( S, L.cpoB );
    double cost = (dLAB*dLAB + dLAS*dLAS - dLBS*dLBS) / ( 2*dLAB*dLAS );
    double sint = sqrt(1-cost*cost);
    return dLAS*sint;
}

/*  三点创建一个平面  */
void CPlane::ThreePoint()
{
    cout<<"请输入三个点的x,y,z坐标: ";
    double x1,y1,z1,x2,y2,z2,x3,y3,z3;
    cin>>x1>>y1>>z1>>x2>>y2>>z2>>x3>>y3>>z3;
    da = y1*z2 - y1*z3 - y2*z1 + y2*z3 + y3*z1 - y3*z2;
    db = x1*z3 - x1*z2 + x2*z1 - x2*z3 - x3*z1 + x3*z2;
    dc = x1*y2 - x1*y3 - x2*y1 + x2*y3 + x3*y1 - x3*y2;
    dd = x1*y3*z2 - x1*y2*z3 + x2*y1*z3 - x2*y3*z1 - x3*y1*z2 + x3*y2*z1;
    cout<<"平面方程为: ";
    if(da!=0)
    {
        if(da!=1)
        {
            if(da==-1)
            {
                cout<<"-";
            }
            else
            {
                cout<<da;
            }
        }
        cout<<"x";
        if(db>=0)
        {
            cout<<"+";
        }
    }
    if(db!=0)
    {
        if(db!=1)
        {
            if(db==-1)
            {
                cout<<"-";
            }
            else
            {
                cout<<db;
            }
        }
        cout<<"y";
        if(dc>=0)
        {
            cout<<"+";
        }
    }
    if(dc!=0)
    {
        if(dc!=1)
        {
            if(dc==-1)
            {
                cout<<"-";
            }
            else
            {
                cout<<dc;
            }
        }
        cout<<"z";
        if(dd>0)
        {
            cout<<"+";
        }
    }
    if(dd!=0)
    {
        cout<<dd;
    }
    cout<<"=0"<<endl;
}

/*  点法式创建平面  */
void CPlane::PointNormal()
{
    cout<<"平面方程为: ";
    if(da!=0)
    {
        if(da!=1)
        {
            if(da==-1)
            {
                cout<<"-";
            }
            else
            {
                cout<<da;
            }
        }
        cout<<"(x";
        if(cpoC.dPosX>=0)
        {
            cout<<"-"<<cpoC.dPosX<<")+";
        }
        if(cpoC.dPosX<0)
        {
            cout<<cpoC.dPosX<<")+";
        }
    }
    if(db!=0)
    {
        if(db!=1)
        {
            if(db==-1)
            {
                cout<<"-";
            }
            else
            {
                cout<<db;
            }
        }
        cout<<"(y";
        if(cpoC.dPosY>=0)
        {
            cout<<"-"<<cpoC.dPosY<<")+";
        }
        if(cpoC.dPosY<0)
        {
            cout<<cpoC.dPosY<<")+";
        }
    }
    if(dc!=0)
    {
        if(dc!=1)
        {
            if(dc==-1)
            {
                cout<<"-";
            }
            else
            {
                cout<<dc;
            }
        }
        cout<<"(z";
        if(cpoC.dPosZ>=0)
        {
            cout<<"-"<<cpoC.dPosZ<<")=0";
        }
        if(cpoC.dPosZ<0)
        {
            cout<<cpoC.dPosZ<<")=0";
        }
    }
    cout<<endl;
}

/*  计算空间平面的单位法向量  */
void CPlane::PlaneNormal()
{
    double ds = sqrt( da*da + db*db +dc*dc );
    cout<<"平面的单位法向量为: ";
    cout<<"("<<da/ds<<","<<db/ds<<","<<dc/ds<<")"<<endl;
}

/*  计算点到平面的距离  */
double PLdistance( CPoint &S, CPlane &P )
{
    return abs( S.dPosX*P.da + S.dPosY*P.db + S.dPosZ*P.dc + P.dd) /
           sqrt( P.da*P.da + P.db*P.db + P.dc*P.dc );
}

/*  判断点与线的位置关系  */
void JudgePL( CPoint &cpo, CLine &cli )
{
    cout<<"点与线的位置关系为: ";
    double da1 = (cpo.dPosX-cli.cpoA.dPosX)/(cli.cpoB.dPosX-cli.cpoA.dPosX);
    double da2 = (cpo.dPosY-cli.cpoA.dPosY)/(cli.cpoB.dPosY-cli.cpoA.dPosY);
    double da3 = (cpo.dPosZ-cli.cpoA.dPosZ)/(cli.cpoB.dPosZ-cli.cpoA.dPosZ);
    if(da1==da2&&da2==da3)
    {
        cout<<"点在线上"<<endl;
    }
    else
    {
        cout<<"点在线外"<<endl;
    }
}

/*  判断线与线的位置关系  */
void JudgeLL( CLine &cli1, CLine &cli2 )
{
    cout<<"两线的位置关系为: ";
    if( cli1.cpoA==cli2.cpoA && cli1.cpoB==cli2.cpoB )
    {
        cout<<"两线重合"<<endl;
        return ;
    }
    double dm1 = cli1.cpoB.dPosX - cli1.cpoA.dPosX;
    double dn1 = cli1.cpoB.dPosY - cli1.cpoA.dPosY;
    double dp1 = cli1.cpoB.dPosZ - cli1.cpoA.dPosZ;
    double dm2 = cli2.cpoB.dPosX - cli2.cpoA.dPosX;
    double dn2 = cli2.cpoB.dPosY - cli2.cpoA.dPosY;
    double dp2 = cli2.cpoB.dPosZ - cli2.cpoA.dPosZ;
    if( dm1/dm2==dn1/dn2 && dn1/dn2==dp1/dp2 )
    {
        cout<<"两线平行"<<endl;
    }
    else
    {
        if( (dm1*dm2 + dn1*dn2 + dp1*dp2) == 0 )
        {
            cout<<"两线垂直"<<endl;
        }
        else
        {
            cout<<"两线相交"<<endl;
        }
    }
}

/*  判断点与面的位置关系  */
void JudgePP( CPoint & cpo, CPlane & cpl )
{
    cout<<"点与面的位置关系为: ";
    if( (cpo.dPosX*cpl.da + cpo.dPosY*cpl.db + cpo.dPosZ*cpl.dc + cpl.dd) == 0 )
    {
        cout<<"点在面上"<<endl;
    }
    else
    {
        cout<<"点在面外"<<endl;
    }
}

/*  判断线与面的位置关系  */
void JudgeLP( CLine &cli, CPlane &cpl )
{
    cout<<"线与面的位置关系为: ";
    bool b1 = (cli.cpoA.dPosX*cpl.da + cli.cpoA.dPosY*cpl.db + cli.cpoA.dPosZ*cpl.dc + cpl.dd) == 0;
    bool b2 = (cli.cpoB.dPosX*cpl.da + cli.cpoB.dPosY*cpl.db + cli.cpoB.dPosZ*cpl.dc + cpl.dd) == 0;
    if(b1&&b2)
    {
        cout<<"线在面内"<<endl;
        return ;
    }
    double dm = cli.cpoB.dPosX - cli.cpoA.dPosX;
    double dn = cli.cpoB.dPosY - cli.cpoA.dPosY;
    double dp = cli.cpoB.dPosZ - cli.cpoA.dPosZ;
    if( ( dm*cpl.da + dn*cpl.db + dp*cpl.dc ) == 0 )
    {
        cout<<"线与面平行"<<endl;
    }
    else
    {
        if(dm/cpl.da==dn/cpl.db && dn/cpl.db==dp/cpl.dc )
        {
            cout<<"线与面垂直"<<endl;
        }
        else
        {
            cout<<"线与面相交"<<endl;
        }
    }
}

/*  判断面与面的位置关系  */
void JudgePPL( CPlane & cpl1, CPlane & cpl2 )
{
    cout<<"面与面的位置关系为: ";
    if( cpl1.da/cpl2.da==cpl1.db/cpl2.db && cpl1.db/cpl2.db==cpl1.dc/cpl2.dc )
    {
        cout<<"面与面平行"<<endl;
    }
    else
    {
        if( (cpl1.da*cpl2.da + cpl1.db*cpl2.db + cpl1.dc*cpl2.dc) == 0 )
        {
            cout<<"面与面垂直"<<endl;
        }
        else
        {
            cout<<"面与面斜交"<<endl;
        }
    }
}
int main()
{
    CPoint cpoa1(1,3,2),cpoa2(2,4,3);

    //计算cpoa1,cpoa2两点间距离
    double s1;
    s1=Pdistance( cpoa1, cpoa2 );
    cout<<"两点间距离为: "<<s1<<endl;

    CLine clia1(cpoa1,cpoa2);
    clia1.TwoPoint();    //两点式
    clia1.PointDirection();  //点向式
    clia1.Parameter();   //参数式
    clia1.LineDirection();   //计算空间直线的单位方向向量

    //计算点cpoa3到直线clia1距离
    CPoint cpoa3(1,2,3);
    double s2;
    s2=Ldistance( cpoa3, clia1 );
    cout<<"点到直线距离为: "<<s2<<endl;

    CPlane cpla1,cpla2(2,3,5,1,2,4,-28);
    cpla1.ThreePoint();  //三点创建一个平面
    cpla2.PointNormal();  //点法式
    cpla2.PlaneNormal();  //计算空间平面的单位法向量

    //计算点cpoa3到平面cpla2的距离
    double s3;
    s3=PLdistance( cpoa3, cpla2 );
    cout<<"点到平面的距离为: "<<s3<<endl;

    //判断点cpoa3与线clia1的位置关系
    JudgePL( cpoa3, clia1 );

    //判断线clia2与线clia3的位置关系
    CLine clia2(2,6,4,5,1,2),clia3( cpoa1, cpoa3);
    JudgeLL( clia2, clia3 );

    //判断点cpoa3与面cpla1的位置关系
    JudgePP( cpoa3, cpla1 );

    //判断线clia3与面cpla1的位置关系
    JudgeLP( clia3, cpla1 );

    //判断面与面的位置关系
    JudgePPL( cpla1, cpla2 );
    return 0;
}

 

  • 0
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值