#include<iostream>
#include<cmath>
#include<cstdio>
using namespace std;
//点类
class Point
{
public:
double x,y,z;
Point(double xp=0,double yp=0,double zp=0):x(xp),y(yp),z(zp){}
void display()
{
cout<<"("<<x<<","<<y<<","<<z<<") ";
}
};
//面类
class Plane
{
public:
double a,b,c,d;
//直接输入平面的一般式
Plane (double ap,double bp,double cp,double dp):a(ap),b(bp),c(cp),d(dp){}
//三个不共线的点确定一个平面
Plane(const Point& point1, const Point& point2, const Point& point3) {
Point v1(point2.x - point1.x, point2.y - point1.y, point2.z - point1.z);
Point v2(point3.x - point1.x, point3.y - point1.y, point3.z - point1.z);
Point normal((v1.y * v2.z - v1.z * v2.y), (v1.z * v2.x - v1.x * v2.z), (v1.x * v2.y - v1.y * v2.x));
a = normal.x;
b = normal.y;
c = normal.z;
d = -(a * point1.x + b * point1.y + c * point1.z);
}
//一个点和一个法向量确定一个平面
Plane(const Point &pp1,const Point &pp2)
{
a=pp2.x;
b=pp2.y;
c=pp2.z;
d=-(pp1.x*a+pp1.y*b+pp1.z*c);
}
//求该平面的单位法向量,返回值是Point类,此时表示的不是点,表示单位法向量
Point oneplane() const
{
double lengths=sqrt(a*a+b*b+c*c);
return Point(a/lengths,b/lengths,c/lengths);
}
void display()
{
cout<<"平面的一般方程为:("<<a<<")*x+("<<b<<")*y+("<<c<<")*z+("<<d<<")=0"<<endl;
}
};
//线类
class Line
{
public:
Point p1,p2;
//两点确定一条直线
Line(const Point & pp1,const Point & pp2):p1(pp1),p2(pp2){}
//两个平面确定一条直线
Line(const Plane &pp1,const Plane &pp2)
{
double d=(pp1.a)*(pp2.b)-(pp2.a)*(pp1.b);
if(d==0) cout<<"两平面重合或平行,没有交线"<<endl;
else
{
double x = (pp1.b * pp2.d - pp2.b * pp1.d) / d;
double y = (pp2.a * pp1.d - pp1.a * pp2.d) / d;
p1=Point(x,y,0);
p2=Point(x+1,y+1,0);
}
}
//点斜式
//pp1是点,pp2是斜率
//pp3是为了与两点式区分开来,没有其他意义pp3和pp2一样就行
Line(const Point &pp1,const Point &pp2,const Point &pp3)
{
p1=pp1;
p2=Point(pp1.x+pp2.x,pp1.y+pp2.y,pp1.z+pp2.z);
}
//求该线的方向向量,返回值是Point类,此时表示的不是点,表示方向向量
Point oneline() const
{
double lengths=sqrt(((p1.x-p2.x)*(p1.x-p2.x))+((p1.y-p2.y)*(p1.y-p2.y))+((p1.z-p2.z)*(p1.z-p2.z)));
return Point((p1.x-p2.x)/lengths,(p1.y-p2.y)/lengths,(p1.z-p2.z)/lengths);
}
void display()
{
cout<<"线上存在两点:p1";
p1.display();
cout<<"p2";
p2.display();
cout<<endl;
}
};
//两点间的距离
double d1(const Point &pp1,const Point &pp2)
{
double lengths=sqrt(((pp1.x-pp2.x)*(pp1.x-pp2.x))+((pp1.y-pp2.y)*(pp1.y-pp2.y))+((pp1.z-pp2.z)*(pp1.z-pp2.z)));
return lengths;
}
//点到直线的距离
double d2(const Point &point,const Line &line)
{
//设点p,和直线line,直线上两点o,d
Line op(point,line.p1);
Point oneop=op.oneline();//op的单位方向向量
Point oline=line.oneline();//line的单位方向向量
double coso=oneop.x*oline.x+oneop.y*oline.y+oneop.z*oline.z;
double sino=sqrt(1-coso*coso);
double length=d1(point,line.p1);
double d=abs(length*sino);
return d;
}
//点到面的距离
double d3(const Point &point,Plane &plane)
{
double pointd=-(point.x*plane.a+point.y*plane.b+point.z*plane.c);
double d=abs((pointd-plane.d)/sqrt(plane.a*plane.a+plane.b*plane.b+plane.c*plane.c));
return d;
}
//判断点和线的关系
void pointandline(const Point &point,const Line &line)
{
//设点p,和直线line,直线上两点o,d
Line op(point,line.p1);
Point oneop=op.oneline();//op的单位方向向量
Point oline=line.oneline();//line的单位方向向量
if((oneop.x/oline.x)==(oneop.y/oline.y)&&(oneop.x/oline.x)==(oneop.z/oline.z))
{
cout<<"点在线上"<<endl;
}
else cout<<"点在线外"<<endl;
}
//判断线和线的关系
void lineandline(const Line &line1,const Line &line2)
{
Point oline1=line1.oneline();//line1的单位方向向量
Point oline2=line2.oneline();//line2的单位方向向量
if((oline1.x/oline2.x)==(oline1.y/oline2.y)&&(oline1.x/oline2.x)==(oline1.z/oline2.z))
{
cout<<"两条直线平行或重合"<<endl;
}
else if((oline1.x*oline2.x+oline1.y*oline2.y+oline1.z*oline2.z)==0)
{
cout<<"两条直线垂直"<<endl;
}
else
cout<<"两条直线相交但不垂直"<<endl;
}
//判断点和平面的关系
void pointandplane(const Point &point,const Plane &plane)
{
if(point.x*plane.a+point.y*plane.b+point.z*plane.c+plane.d==0)
cout<<"点在面上"<<endl;
else
cout<<"点不在面上"<<endl;
}
//判断线和平面的关系
void lineandplane(const Line &line,const Plane &plane)
{
Point oline=line.oneline();//线的单位方向向量
Point oplane=plane.oneplane();//面的法向量
if((line.p1.x*plane.a+line.p1.y*plane.b+line.p1.z*plane.c+plane.d==0)&&(line.p2.x*plane.a+line.p2.y*plane.b+line.p2.z*plane.c+plane.d==0))
cout<<"现在面上"<<endl;
else if((oline.x/oplane.x)==(oline.y/oplane.y)&&(oline.x/oplane.x)==(oline.z/oplane.z))
cout<<"线与面平行"<<endl;
else if((oline.x*oplane.x+oline.y*oplane.y+oline.z*oplane.z)==0)
cout<<"线垂直于面"<<endl;
else
cout<<"线交于面但不垂直"<<endl;
}
//判断平面和平面的关系
void planeandplane(const Plane &plane1,const Plane &plane2)
{
double a1=plane1.a,b1=plane1.b,c1=plane1.c,d1=plane1.d;
double a2=plane2.a,b2=plane2.b,c2=plane2.c,d2=plane2.d;
if((a1/a2==b1/b2)&&(a1/a2==c1/c2)&&(a1/a2==d1/d2))
cout<<"两平面重合"<<endl;
else if((a1/a2==b1/b2)&&(a1/a2==c1/c2))
cout<<"两平面平行"<<endl;
else if(a1*a2+b1*b2+c1*c2==0)
cout<<"两平面垂直"<<endl;
else
cout<<"两平面相交但不垂直"<<endl;
}
int main()
{
cout<<"创建四个点:例(x,y,z)"<<endl;
double x1,x2,x3,x4,y1,y2,y3,y4,z1,z2,z3,z4;
scanf("(%lf,%lf,%lf)(%lf,%lf,%lf)(%lf,%lf,%lf)(%lf,%lf,%lf)",&x1,&y1,&z1,&x2,&y2,&z2,&x3,&y3,&z3,&x4,&y4,&z4);
Point p1(x1,y1,z1),p2(x2,y2,z2),p3(x3,y3,z3),p4(x4,y4,z4);
cout<<"p1";
p1.display();
cout<<"p2";
p2.display();
cout<<"p3";
p3.display();
cout<<"p4";
p4.display();
cout<<endl;
cout<<"用两个点(p1、p2)创建一条直线line1:"<<endl;
Line line1(p1,p2);
line1.display();
cout<<"直线line1的单位方向向量为:"<<endl;
Point oline1=line1.oneline();
oline1.display();
cout<<endl;
cout<<"用三个点(p1、p2、p3)创建一个平面plane1:"<<endl;
Plane plane1(p1,p2,p3);
plane1.display();
cout<<"平面plane1的单位法向量为:"<<endl;
Point oplane1=plane1.oneplane();
oplane1.display();
cout<<endl;
cout<<"请输入一个单位方向向量:例x,y,z"<<endl;
double xp,yp,zp;
scanf("%ld,%ld,%ld",&xp,&yp,&zp);
Point oplane(xp,yp,zp);
cout<<"用p1和以上面的单位向量为斜率创建一条直线line2:"<<endl;
Line line2(p1,oplane,oplane);
line2.display();
cout<<"用p1和以上面的单位向量为法向量创建一个平面plane2:"<<endl;
Plane plane2(p1,oplane);
plane2.display();
cout<<"用两个平面(plane1和plane2)创建一条直线(line3):"<<endl;
Line line3(plane1,plane2);
line3.display();
cout<<"两点(p1,p2)之间的距离为:"<<d1(p1,p2)<<endl;
cout<<"点p3到直线line1的距离为:"<<d2(p3,line1)<<endl;
cout<<"点p4到平面plane1的距离为:"<<d3(p4,plane1)<<endl;
cout<<"判断点p1和线line1的关系:"<<endl;
pointandline(p1,line1);
cout<<"判断线line1与线line2的关系:"<<endl;
lineandline(line1,line2);
cout<<"判断点p1和平面plane1的关系:"<<endl;
pointandplane(p1,plane1);
cout<<"判断线line2和平面plane2的关系:"<<endl;
lineandplane(line2,plane2);
cout<<"判断平面和平面的关系:"<<endl;
planeandplane(plane1,plane2);
return 0;
}
//(1,2,3)(3,2,1)(1,3,5)(2,4,6)
//1,1,1