题目地址: UVa11275
首先:点在三角形内有两个模板 一个要求已经共面,一个可以帮助判断是否共面
这里是“三角面” 那么为了考虑完全包含且共面的情形,是应该判断一下是否有顶点在另一个三角形面上的。
比如测试数据
2
0 100 0
-100 -100 0
100 -100 0
0 1 0
-1 -1 0
1 -1 0
就应该输出1 但是测试数据却...
"ac" 代码:
#include<iostream>
#include<cmath>
#include<cstdio>
#include <vector>
using namespace std;
const double eps=1e-8;
const double PI=acos(-1.0);
int dcmp(double x)
{
if(fabs(x)<eps) return 0;
else return x<0?-1:1;
}
struct Point3
{
double x,y,z;
Point3(double x=0,double y=0,double z=0):x(x),y(y),z(z) {}
};
typedef Point3 Vector3;
Vector3 operator+(Point3 A,Point3 B)
{
return Point3(A.x+B.x,A.y+B.y,A.z+B.z);
}
Vector3 operator-(Point3 A,Point3 B)
{
return Point3(A.x-B.x,A.y-B.y,A.z-B.z);
}
Vector3 operator*(Point3 A,double p)
{
return Point3(A.x*p,A.y*p,A.z*p);
}
Vector3 operator/(Point3 A,double p)
{
return Point3(A.x/p,A.y/p,A.z/p);
}
bool operator<(Point3 &A,Point3 &B)
{
return A.x<B.x||(A.x==B.x&&A.y<B.y)||(A.x==B.x&&A.y==B.y&&A.z<B.z);
}
bool operator==(Point3 &A,Point3 &B)
{
return dcmp(A.x-B.x)==0&&dcmp(A.y-B.y)==0&&dcmp(A.z-B.z)==0;
}
ostream & operator<<(ostream & out,Vector3 A)
{
out<<A.x<<' '<<A.y<<' '<<A.z<<endl;
return out;
}
double Dot(Vector3 A,Vector3 B)
{
return A.x*B.x+A.y*B.y+A.z*B.z;
}
double Length(Vector3 A)
{
return sqrt(Dot(A,A));
}
double Angle(Vector3 A,Vector3 B)
{
return acos(Dot(A,B)/Length(A)/Length(B));
}
Vector3 Cross(Vector3 A,Vector3 B) // 真正的叉积
{
return Vector3(A.y*B.z-A.z*B.y,A.z*B.x-A.x*B.z,A.x*B.y-A.y*B.x);
}
double Area2(Point3 A,Point3 B,Point3 C) // 面积绝对值两倍
{
return Length(Cross(B-A,C-A));
}
double DistanceToPlane(const Point3 &p,const Point3 & p0,const Vector3 &n)
{
return fabs(Dot(p-p0,n))/Length(n);
}
Point3 GetPlaneProjection(Point3 p,Point3 p0,Vector3 n)
{
return p-n*Dot(p-p0,n)/Dot(n,n);
}
Point3 LinePlaneIntersection(Point3 p1,Point3 p2,Point3 p0,Vector3 n)
{
double t=Dot(n,p0-p1)/Dot(n,p2-p1);
return p1+(p2-p1)*t;
}
// 点在三角形内部
//bool PointInTri(Point3 p,Point3 p0,Point3 p1,Point3 p2)
//{
// double area1=Area2(p, p0, p1);
// double area2=Area2(p, p1, p2);
// double area3=Area2(p, p2, p0);
//
// return dcmp(area1+area2+area3-Area2(p0,p1,p2))==0;
//}
// 线段与三角形相交 不考虑共面情形
double DistanceToLine(Point3 P,Point3 A,Point3 B)
{
Vector3 v1=B-A;
Vector3 v2=P-A;
return Length(Cross(v1, v2))/Length(v1);
}
double DistanceToSegment(Point3 P,Point3 A,Point3 B)
{
if(A==B) return Length(P-A);
Vector3 v1=B-A,v2=P-A,v3=P-B;
if(dcmp(Dot(v1,v2))<0) return Length(v2);
else if(dcmp(Dot(v1,v3))>0) return Length(v3);
else return Length(Cross(v1,v2))/Length(v1);
}
double volume6(Point3 A,Point3 B,Point3 C,Point3 D)
{
return Dot(D-A,Cross(B-A,C-A));
}
struct Tri{
Point3 P[3];
Tri(Point3 A=Point3(0,0,0),Point3 B=Point3(0,0,0),Point3 C=Point3(0,0,0))
{
P[0]=A;
P[1]=B;
P[2]=C;
}
};
//bool SameSide(const Point3& p1, const Point3& p2, const Point3& a, const Point3& b) {
// return dcmp(Dot(Cross(b-a, p1-a), Cross(b-a, p2-a))) >= 0;
//}
//
点在三角形P0, P1, P2中
//bool PointInTri(const Point3& P, const Point3& P0, const Point3& P1, const Point3& P2) {
// return SameSide(P, P0, P1, P2) && SameSide(P, P1, P0, P2) && SameSide(P, P2, P0, P1);
//}
bool PointInTri(Point3 p,Point3 p0,Point3 p1,Point3 p2)
{
double area1=Area2(p, p0, p1);
double area2=Area2(p, p1, p2);
double area3=Area2(p, p2, p0);
return dcmp(area1+area2+area3-Area2(p0,p1,p2))==0;
}
//bool PointInTri(const Point3& P, Tri tri) {
// Point3& P0=tri.P[0];
// Point3& P1=tri.P[1];
// Point3& P2=tri.P[2];
//
// return SameSide(P, P0, P1, P2) && SameSide(P, P1, P0, P2) && SameSide(P, P2, P0, P1);
//}
// 线段与三角形相交 不考虑共面情形
bool TriSegIntersection(Point3 p0,Point3 p1,Point3 p2,Point3 A,Point3 B,Point3 & p)
{
Vector3 n=Cross(p1-p0, p2-p0);
if(dcmp(Dot(n,B-A))==0) return false;
else{
double t=Dot(n,p0-A)/Dot(n,B-A);
if(dcmp(t)<0||dcmp(t-1)>0) return false; // 端点也ok
else
{
p=A+(B-A)*t;
return PointInTri(p,p0,p1,p2);
}
}
}
bool TriSegIntersection(Tri tri,Point3 A,Point3 B,Point3 & p)
{
Point3 p0=tri.P[0];
Point3 p1=tri.P[1];
Point3 p2=tri.P[2];
Vector3 n=Cross(p1-p0, p2-p0);
if(dcmp(Dot(n,B-A))==0) return false;
else{
double t=Dot(n,p0-A)/Dot(n,B-A);
if(dcmp(t)<0||dcmp(t-1)>0) return false; // 端点也ok
else
{
p=A+(B-A)*t;
return PointInTri(p,p0,p1,p2);
}
}
}
Point3 read_point3()
{
Point3 ans;
scanf("%lf%lf%lf",&ans.x,&ans.y,&ans.z);
return ans;
}
//bool TriCommom(Tri A,Tri B)
//{
// Point3 sol;
//
// for(int i=0;i<3;i++)
// {
// if(PointInTri(A.P[i], B)) return 1;
// if(PointInTri(B.P[i], A)) return 1;
//
// if(TriSegIntersection(A, B.P[i],B.P[(i+1)%3] , sol)) return 1;
// if(TriSegIntersection(B, A.P[i],A.P[(i+1)%3] , sol)) return 1;
//
// }
//
// return 0;
//
//}
bool TriCommom(Point3 * A,Point3 * B)
{
Point3 sol;
for(int i=0;i<3;i++)
{
// 不应该注释的~!!
// if(PointInTri(A[i], B[0],B[1],B[2])) return 1;
// if(PointInTri(B[i], A[0],A[1],A[2])) return 1;
if(TriSegIntersection(A[0],A[1],A[2],B[i],B[(i+1)%3] , sol)) return 1;
if(TriSegIntersection(B[0],B[1],B[2], A[i],A[(i+1)%3] , sol)) return 1;
}
return 0;
}
int main()
{
int T;
cin>>T;
while(T--)
{
Point3 T1[3],T2[3];
for(int i=0;i<3;i++)
{
T1[i]=read_point3();
}
for(int i=0;i<3;i++)
{
T2[i]=read_point3();
}
// A=Tri(P[0],P[1],P[2]);
// B=Tri(P[3],P[4],P[5]);
printf("%d\n", TriCommom(T1, T2) ? 1 : 0);
}
}