给出三维空间上的四个点(点与点的位置均不相同),判断这4个点是否在同一个平面内(4点共线也算共面)。如果共面,输出"Yes",否则输出"No"。
输入
第1行:一个数T,表示输入的测试数量(1 <= T <= 1000)
第2 - 4T + 1行:每行4行表示一组数据,每行3个数,x, y, z, 表示该点的位置坐标(-1000 <= x, y, z <= 1000)。
输出
输出共T行,如果共面输出"Yes",否则输出"No"。
输入样例
1
1 2 0
2 3 0
4 0 0
0 0 0
输出样例
Yes
题解:
确定空间中的四个点(三维)是否共面
对于四个点, 以一个点为原点,对于其他三个点有A,B, C三个向量, 求出 A X B (cross product), 就是以A B构成的平面的一个法向量(如果 AB共线,则法向量为0), 在求其与C之间的点积, 如果为0, 则表示两个向量为0。 所以四点共面。
#include<bits/stdc++.h>
using namespace std;
const double EPS=1e-8;
struct Point{//点 二维三维
double x,y,z;
Point(){};
Point(double x,double y,double z=0):x(x),y(y),z(z){}
Point operator - (const Point &a)const //向量减
{
return Point(x-a.x,y-a.y,z-a.z);
}
/*double operator ^(const Point &a)const//向量积sin
{
//二维 三维
return x*a.y-y*a.x//+y*a.z-z*a.y-x*a.z+z*a.x;//值
} */
Point operator ^(const Point &a)const//向量积sin
{
return Point(y*a.z-z*a.y,z*a.x-x*a.z,x*a.y-y*a.x);//法向量
}
double operator *(const Point &a)const//点积cos
{
// 二维 三维
return x*a.x+y*a.y+z*a.z;
}
};
/*
struct Circle{//圆
double x,y,r;
Circle(){}
Circle(double x,double y,double r):x(x),y(y),r(r){}
};
//默认 是 返还true 否 返回false
bool Cross(const Point&p1,const Point&p2,const Point&p3,const Point&p4)
{
//判断向量p1p2是否跨立p3p4
double a1=(p3-p1)^(p2-p1);
double a2=(p4-p1)^(p2-p1);
if(a1*a2>0)//同向
return false;
return true;
}
//判断线段p1p2与圆是否相交
bool Lcc(Point p1,Point p2,Circle c)
{
bool flag1=(p1.x-c.x)*(p1.x-c.x)+(p1.y-c.y)*(p1.y-c.y)<=c.r*c.r;
//判断点p1是否在圆内
bool flag2=(p2.x-c.x)*(p2.x-c.x)+(p2.y-c.y)*(p2.y-c.y)<=c.r*c.r;
//判断点p2是否在圆内
if(flag1&&flag2)//两点都在圆内,不相交
return false;
if(flag1||flag2)//一点在圆内,一点在圆外,相交
return true;
//两点在圆外,判断形成的线段是否与圆相交
double A,B,C,dis1,dis2,angle1,angle2;
//将直线p1p2化为一般式:Ax+By+C=0的形式,先化为两点式,然后由两点式得出一般式
A=p1.y-p2.y;
B=p2.x-p1.x;
C=p1.x*p2.y-p2.x*p1.y;
//使用距离公式判断圆心到直线ax+by+c=0的距离是否大于半径
dis1=A*c.x+B*c.y+C;
dis1*=dis1;
dis2=(A*A+B*B)*c.r*c.r;
if(dis1>dis2)//距离大于半径
return false;
angle1=(c.x-p1.x)*(p2.x-p1.x)+(c.y-p1.y)*(p2.y-p1.y);//c-p1与p1p2夹角
angle2=(c.x-p2.x)*(p1.x-p2.x)+(c.y-p2.y)*(p1.y-p2.y);//c-p2与p1p2夹角
if(angle1>0&&angle2>0)//都是锐角 相交
return true;
return false;
} */
//判断四点是否共面
int main()
{
int t;
cin>>t;
while(t--)
{
Point p[4];
for(int i=0;i<4;i++)
cin>>p[i].x>>p[i].y>>p[i].z;
double tmp=((p[1]-p[0])^(p[2]-p[0]))*(p[3]-p[0]);
if(fabs(tmp)<EPS)
cout<<"Yes\n";
else cout<<"No\n";
}
return 0;
}