poj 1410 Intersection
蒻苣:弱弱很弱,路过的巨巨还不吝赐教!^.^...QAQ
题意:给出一个长方形和一条线段,判断线段是否与长方形相交。
题解:直接叉积就行了。
坑点:线段在长方形内也算相交,与长方形边重合也算相交,给出的长方形并不是一个左上角一个右上角。
由于这个坑点,找了一个高精确的模版:intersect_sign
代码:
1 #include <iostream> 2 #include <cstdlib> 3 #include <cstdio> 4 #include <cstring> 5 #include <algorithm> 6 #include <queue> 7 #include <cmath> 8 using namespace std; 9 const double INF = 1E200; 10 const double wc = 1E-8; 11 struct POINT{ 12 double x,y; 13 POINT( double a = 0,double b = 0 ) { x = a; y = b; } 14 }; 15 struct LINESEG{ 16 POINT e; 17 POINT s; 18 LINESEG( POINT x,POINT y ) { e = x; s = y; } 19 LINESEG(){} 20 }; 21 typedef POINT Vector; //引申为向量 22 23 Vector operator -(Vector a,Vector b) //向量减法 24 { 25 POINT v; 26 v.x=a.x-b.x; 27 v.y=a.y-b.y; 28 return v; 29 } 30 31 double dist(POINT p1,POINT p2) 32 { 33 return( sqrt( (p1.x-p2.x)*(p1.x-p2.x)+(p1.y-p2.y)*(p1.y-p2.y) ) ); 34 } 35 double multiply(POINT sp,POINT ep,POINT op) 36 { 37 return((sp.x-op.x)*(ep.y-op.y)-(ep.x-op.x)*(sp.y-op.y)); 38 } 39 bool online(LINESEG l,POINT p) 40 { 41 return( (multiply(l.e,p,l.s)==0) &&( ( (p.x-l.s.x)*(p.x-l.e.x)<=0 )&&( (p.y-l.s.y)*(p.y-l.e.y)<=0 ) ) ); 42 } 43 bool intersect(LINESEG u,LINESEG v) 44 { 45 return( (max(u.s.x,u.e.x)>=min(v.s.x,v.e.x))&& 46 (max(v.s.x,v.e.x)>=min(u.s.x,u.e.x))&& 47 (max(u.s.y,u.e.y)>=min(v.s.y,v.e.y))&& 48 (max(v.s.y,v.e.y)>=min(u.s.y,u.e.y))&& 49 (multiply(v.s,u.e,u.s)*multiply(u.e,v.e,u.s)>=wc)&& 50 (multiply(u.s,v.e,v.s)*multiply(v.e,u.e,v.s)>=wc)); 51 } 52 bool intersect_A(LINESEG u,LINESEG v) 53 { 54 return ((intersect(u,v))&& 55 (!online(u,v.s))&& 56 (!online(u,v.e))&& 57 (!online(v,u.e))&& 58 (!online(v,u.s))); 59 } 60 bool intersect_l(LINESEG u,LINESEG v) 61 { 62 return multiply(u.s,v.e,v.s)*multiply(v.e,u.e,v.s)>=wc; 63 } 64 bool zero(double x) 65 { 66 return fabs(x)<wc?true:false; 67 } 68 double fork_mul(Vector a,Vector b) //向量叉积 69 { 70 return (a.x*b.y-a.y*b.x); 71 } 72 int intersect_sign(LINESEG l1,LINESEG l2,POINT &result) //两线段位置关系的标志 73 { 74 POINT a,b,c,d; 75 a = l1.e; 76 b = l1.s; 77 c = l2.e; 78 d = l2.s; 79 double cba=fork_mul(b-c,a-c),dba=fork_mul(b-d,a-d),v12=fork_mul(b-a,d-c); 80 if(zero(v12)==true) //两线段方向相同 81 { 82 if(zero(cba)==true&&zero(dba)==true) //两线段共线 83 { 84 if(min(a.x,b.x)<max(c.x,d.x)&&min(c.x,d.x)<max(a.x,b.x)&&min(a.y,b.y)<max(c.y,d.y)&&min(c.y,d.y)<max(a.y,b.y)) 85 return -3; //重叠共线 86 if(min(a.x,b.x)>max(c.x,d.x)||min(c.x,d.x)>max(a.x,b.x)||min(a.y,b.y)>max(c.y,d.y)||min(c.y,d.y)>max(a.y,b.y)) 87 return -2; //分离共线 88 return -1; //首尾相接 89 } 90 else 91 return 0; //两线段平行 92 } 93 else //两线段方向不同,它们各自所在的直线相交 94 { 95 double bdc=fork_mul(d-b,c-b),adc=fork_mul(d-a,c-a); 96 result.x=(dba*c.x-cba*d.x)/(dba-cba); //求两线段所在直线的交点 97 result.y=(dba*c.y-cba*d.y)/(dba-cba); 98 if(dba*cba<=0&&bdc*adc<=0) 99 return 1; //线段相交 100 else 101 return 2; //线段不相交 102 } 103 } 104 105 int vis[100000+50]; 106 int main() 107 { 108 // freopen("out.txt","w",stdout); 109 int n; 110 cin>>n; 111 while(n--){ 112 LINESEG l; 113 LINESEG a,b,c,d; 114 double x1,x2,y1,y2; 115 scanf("%lf%lf%lf%lf%lf%lf%lf%lf",&l.e.x,&l.e.y,&l.s.x,&l.s.y,&x1,&y1,&x2,&y2); 116 if(x1>x2) swap(x1,x2); 117 if(y1<y2) swap(y1,y2); 118 a.e.x = d.s.x = x1; 119 a.e.y = d.s.y = y1; 120 a.s.x = b.e.x = x2; 121 a.s.y = b.e.y = y1; 122 b.s.x = c.e.x = x2; 123 b.s.y = c.e.y = y2; 124 c.s.x = d.e.x = x1; 125 c.s.y = d.e.y = y2; 126 POINT p; 127 if(intersect_sign(l,a,p)==1||intersect_sign(l,a,p)==-3||//intersect_sign(l,a,p)==-2|| 128 intersect_sign(l,b,p)==1||intersect_sign(l,b,p)==-3||//intersect_sign(l,b,p)==-2|| 129 intersect_sign(l,c,p)==1||intersect_sign(l,c,p)==-3||//intersect_sign(l,c,p)==-2|| 130 intersect_sign(l,d,p)==1||intersect_sign(l,d,p)==-3//||intersect_sign(l,d,p)==-2 131 ) 132 puts("T"); 133 else if(l.e.x>=x1&&l.e.x<=x2&&l.e.y>=y2&&l.e.y<=y1&& 134 l.s.x>=x1&&l.s.x<=x2&&l.s.y>=y2&&l.s.y<=y1 135 ) 136 puts("T"); 137 else puts("F"); 138 } 139 }
浙公网安备 33010602011771号