判断线段与多边形是否相交。
模板:
#include <stdio.h>
#include <math.h>
#include <algorithm>
using namespace std;
#define Pi 3.14159265358979
#define PRECISION 1e-8
//点
typedef struct {
double x,y;
} POINT;
//直线两点的表达
struct LINE{
POINT p1,p2;
};
//多边形结构体
struct POLY{
int n;
double area;
POINT plist[15];
};
//与0作比较,小于精度则认为是和0相等
int cmpzero(double d){
return (fabs(d) < PRECISION)?0:(d>0?1:-1);
}
//向量点积
double dotdet(double x1,double y1,double x2,double y2){
return x1*x2 + y1 * y2;
}
//向量叉积
double cross_det(double x1,double y1,double x2,double y2){
return x1*y2 - x2*y1;
}
//右手螺旋定则,1:a在cd右侧;-1:a在cd左侧;0:三点共线
int cross(POINT &a,POINT &c,POINT &d){
return cmpzero(cross_det(a.x - c.x,a.y - c.y,d.x - c.x,d.y - c.y));
}
//在cross(a,c,d) == 0的基础上,可判断点a是否在cd内部
int between(POINT &a,POINT &c,POINT &d){
return cmpzero(dotdet(c.x - a.x,c.y - a.y, d.x - a.x, d.y - a.y)) != 1;
}
//两线段相交情况:0:不想交,1:规范相交,-1:不规范相交(交于端点或重合)
int seg_intersect(POINT &a,POINT &b,POINT &c,POINT &d){
int a_cd = cross(a,c,d);
if(a_cd == 0 && between(a,c,d)){return 2;}
int b_cd = cross(b,c,d);
if(b_cd == 0 && between(b,c,d)){return 2;}
int c_ab = cross(c,a,b);
if(c_ab == 0 && between(c,a,b)){return 2;}
int d_ab = cross(d,a,b);
if(d_ab == 0 && between(d,a,b)){return 2;}
if((a_cd^b_cd) == -2 && (c_ab ^ d_ab) == -2){
return 1;
}
return 0;
}
//使用有向面积法判断点是否在多边形内
int point_in_poly(POLY &p,POINT &pt){
double s = 0.0;
for(int i = 0; i < p.n; i++){
s += fabs(cross_det(p.plist[i].x - pt.x,p.plist[i].y - pt.y,p.plist[(i+1)%p.n].x - pt.x,p.plist[(i+1)%p.n].y - pt.y));
}
if(cmpzero(s - p.area) == 0 ){
return 1;
}
return 0;
}
//计算多边形面积
void area(POLY &p){
double s = p.plist[0].y * (p.plist[p.n - 1].x - p.plist[1].x);
for(int i = 1; i < p.n; i++){
s += p.plist[i].y * (p.plist[i - 1].x - p.plist[(i+1)%p.n].x);
}
p.area = s;
}
//判断线段是否与多边形相交
int rec_seg_intersect(POLY &p,LINE &l){
if(point_in_poly(p,l.p1) && point_in_poly(p,l.p2)){return 1;}
else if(seg_intersect(l.p1,l.p2,p.plist[0],p.plist[1])
|| seg_intersect(l.p1,l.p2,p.plist[1],p.plist[2])
|| seg_intersect(l.p1,l.p2,p.plist[2],p.plist[3])
|| seg_intersect(l.p1,l.p2,p.plist[3],p.plist[0]))
return 1;
return 0;
}
int main() {
int n,m,i,min;
int T;
POLY rec;
LINE l;
double xleft,ytop,xright,ybottom;
scanf("%d",&T);
while(T--){
scanf("%lf%lf%lf%lf",&l.p1.x,&l.p1.y,&l.p2.x,&l.p2.y);
scanf("%lf%lf%lf%lf",&xleft,&ytop,&xright,&ybottom);
if(xleft > xright){swap(xleft,xright);}
if(ytop < ybottom){swap(ytop,ybottom);}
rec.n = 4;
rec.plist[0].x = xleft, rec.plist[0].y = ytop;
rec.plist[1].x = xleft, rec.plist[1].y = ybottom;
rec.plist[2].x = xright, rec.plist[2].y = ybottom;
rec.plist[3].x = xright, rec.plist[3].y = ytop;
area(rec);
puts(rec_seg_intersect(rec,l)?"T":"F");
}
return 0;
}