实现三维解析几何中的点、直线和平面类,
(
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;
}