Intersection
http://poj.org/problem?id=1410
Time Limit: 1000MS | Memory Limit: 10000K | |
Total Submissions: 17591 | Accepted: 4516 |
Description
You are to write a program that has to decide whether a given line segment intersects a given rectangle.
An example:
line: start point: (4,9)
end point: (11,2)
rectangle: left-top: (1,5)
right-bottom: (7,1)
Figure 1: Line segment does not intersect rectangle
The line is said to intersect the rectangle if the line and the rectangle have at least one point in common. The rectangle consists of four straight lines and the area in between. Although all input values are integer numbers, valid intersection points do not have to lay on the integer grid.
An example:
line: start point: (4,9)
end point: (11,2)
rectangle: left-top: (1,5)
right-bottom: (7,1)
![](https://i-blog.csdnimg.cn/blog_migrate/3a3d9fd12fde3724889a3122da809fa7.jpeg)
Figure 1: Line segment does not intersect rectangle
The line is said to intersect the rectangle if the line and the rectangle have at least one point in common. The rectangle consists of four straight lines and the area in between. Although all input values are integer numbers, valid intersection points do not have to lay on the integer grid.
Input
The input consists of n test cases. The first line of the input file contains the number n. Each following line contains one test case of the format:
xstart ystart xend yend xleft ytop xright ybottom
where (xstart, ystart) is the start and (xend, yend) the end point of the line and (xleft, ytop) the top left and (xright, ybottom) the bottom right corner of the rectangle. The eight numbers are separated by a blank. The terms top left and bottom right do not imply any ordering of coordinates.
xstart ystart xend yend xleft ytop xright ybottom
where (xstart, ystart) is the start and (xend, yend) the end point of the line and (xleft, ytop) the top left and (xright, ybottom) the bottom right corner of the rectangle. The eight numbers are separated by a blank. The terms top left and bottom right do not imply any ordering of coordinates.
Output
For each test case in the input file, the output file should contain a line consisting either of the letter "T" if the line segment intersects the rectangle or the letter "F" if the line segment does not intersect the rectangle.
Sample Input
1 4 9 11 2 1 5 7 1
Sample Output
F
判断线是否在矩形内或与矩形的边相交
注意共线但是不相交的情况
Check为判断线段是否相交
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
1 #include<cstdio> 2 #include<iostream> 3 #include<cstring> 4 #include<cmath> 5 using namespace std; 6 const double eps=1e-8; 7 const double INF=1e20; 8 const double PI=acos(-1.0); 9 const int maxp=1010; 10 int sgn(double x){ 11 if(fabs(x)<eps) return 0; 12 if(x<0) return -1; 13 else return 1; 14 } 15 inline double sqr(double x){return x*x;} 16 struct Point{ 17 double x,y; 18 Point(){} 19 Point(double _x,double _y){ 20 x=_x; 21 y=_y; 22 } 23 void input(){ 24 scanf("%lf %lf",&x,&y); 25 } 26 void output(){ 27 printf("%.2f %.2f\n",x,y); 28 } 29 bool operator == (const Point &b)const{ 30 return sgn(x-b.x) == 0 && sgn(y-b.y)== 0; 31 } 32 bool operator < (const Point &b)const{ 33 return sgn(x-b.x)==0?sgn(y-b.y)<0:x<b.x; 34 } 35 Point operator - (const Point &b)const{ 36 return Point(x-b.x,y-b.y); 37 } 38 //叉积 39 double operator ^ (const Point &b)const{ 40 return x*b.y-y*b.x; 41 } 42 //点积 43 double operator * (const Point &b)const{ 44 return x*b.x+y*b.y; 45 } 46 //返回长度 47 double len(){ 48 return hypot(x,y); 49 } 50 //返回长度的平方 51 double len2(){ 52 return x*x+y*y; 53 } 54 //返回两点的距离 55 double distance(Point p){ 56 return hypot(x-p.x,y-p.y); 57 } 58 Point operator + (const Point &b)const{ 59 return Point(x+b.x,y+b.y); 60 } 61 Point operator * (const double &k)const{ 62 return Point(x*k,y*k); 63 } 64 Point operator / (const double &k)const{ 65 return Point(x/k,y/k); 66 } 67 68 //计算pa和pb的夹角 69 //就是求这个点看a,b所成的夹角 70 ///LightOJ1202 71 double rad(Point a,Point b){ 72 Point p=*this; 73 return fabs(atan2(fabs((a-p)^(b-p)),(a-p)*(b-p))); 74 } 75 //化为长度为r的向量 76 Point trunc(double r){ 77 double l=len(); 78 if(!sgn(l)) return *this; 79 r/=l; 80 return Point(x*r,y*r); 81 } 82 //逆时针转90度 83 Point rotleft(){ 84 return Point(-y,x); 85 } 86 //顺时针转90度 87 Point rotright(){ 88 return Point(y,-x); 89 } 90 //绕着p点逆时针旋转angle 91 Point rotate(Point p,double angle){ 92 Point v=(*this) -p; 93 double c=cos(angle),s=sin(angle); 94 return Point(p.x+v.x*c-v.y*s,p.y+v.x*s+v.y*c); 95 } 96 }; 97 98 struct Line{ 99 Point s,e; 100 Line(){} 101 Line(Point _s,Point _e){ 102 s=_s; 103 e=_e; 104 } 105 bool operator==(Line v){ 106 return (s==v.s)&&(e==v.e); 107 } 108 //根据一个点和倾斜角angle确定直线,0<=angle<pi 109 Line(Point p,double angle){ 110 s=p; 111 if(sgn(angle-PI/2)==0){ 112 e=(s+Point(0,1)); 113 } 114 else{ 115 e=(s+Point(1,tan(angle))); 116 } 117 } 118 //ax+by+c=0; 119 Line(double a,double b,double c){ 120 if(sgn(a)==0){ 121 s=Point(0,-c/b); 122 e=Point(1,-c/b); 123 } 124 else if(sgn(b)==0){ 125 s=Point(-c/a,0); 126 e=Point(-c/a,1); 127 } 128 else{ 129 s=Point(0,-c/b); 130 e=Point(1,(-c-a)/b); 131 } 132 } 133 void input(){ 134 s.input(); 135 e.input(); 136 } 137 void adjust(){ 138 if(e<s) swap(s,e); 139 } 140 //求线段长度 141 double length(){ 142 return s.distance(e); 143 } 144 //返回直线倾斜角 0<=angle<pi 145 double angle(){ 146 double k=atan2(e.y-s.y,e.x-s.x); 147 if(sgn(k)<0) k+=PI; 148 if(sgn(k-PI)==0) k-=PI; 149 return k; 150 } 151 //点和直线的关系 152 //1 在左侧 153 //2 在右侧 154 //3 在直线上 155 int relation(Point p){ 156 int c=sgn((p-s)^(e-s)); 157 if(c<0) return 1; 158 else if(c>0) return 2; 159 else return 3; 160 } 161 //点在线段上的判断 162 bool pointonseg(Point p){ 163 return sgn((p-s)^(e-s))==0&&sgn((p-s)*(p-e))<=0; 164 } 165 //两向量平行(对应直线平行或重合) 166 bool parallel(Line v){ 167 return sgn((e-s)^(v.e-v.s))==0; 168 } 169 //两线段相交判断 170 //2 规范相交 171 //1 非规范相交 172 //0 不相交 173 int segcrossseg(Line v){ 174 int d1=sgn((e-s)^(v.s-s)); 175 int d2=sgn((e-s)^(v.e-s)); 176 int d3=sgn((v.e-v.s)^(s-v.s)); 177 int d4=sgn((v.e-v.s)^(e-v.s)); 178 if((d1^d2)==-2&&(d3^d4)==-2) return 2; 179 return (d1==0&&sgn((v.s-s)*(v.s-e))<=0|| 180 d2==0&&sgn((v.e-s)*(v.e-e))<=0|| 181 d3==0&&sgn((s-v.s)*(s-v.e))<=0|| 182 d4==0&&sgn((e-v.s)*(e-v.e))<=0); 183 } 184 //直线和线段相交判断 185 //-*this line -v seg 186 //2 规范相交 187 //1 非规范相交 188 //0 不相交 189 int linecrossseg(Line v){ 190 int d1=sgn((e-s)^(v.s-s)); 191 int d2=sgn((e-s)^(v.e-s)); 192 if((d1^d2)==-2) return 2; 193 return (d1==0||d2==0); 194 } 195 //两直线关系 196 //0 平行 197 //1 重合 198 //2 相交 199 int linecrossline(Line v){ 200 if((*this).parallel(v)) 201 return v.relation(s)==3; 202 return 2; 203 } 204 //求两直线的交点 205 //要保证两直线不平行或重合 206 Point crosspoint(Line v){ 207 double a1=(v.e-v.s)^(s-v.s); 208 double a2=(v.e-v.s)^(e-v.s); 209 return Point((s.x*a2-e.x*a1)/(a2-a1),(s.y*a2-e.y*a1)/(a2-a1)); 210 } 211 //点到直线的距离 212 double dispointtoline(Point p){ 213 return fabs((p-s)^(e-s))/length(); 214 } 215 //点到线段的距离 216 double dispointtoseg(Point p){ 217 if(sgn((p-s)*(e-s))<0||sgn((p-e)*(s-e))<0) 218 return min(p.distance(s),p.distance(e)); 219 return dispointtoline(p); 220 } 221 //返回线段到线段的距离 222 //前提是两线段不相交,相交距离就是0了 223 double dissegtoseg(Line v){ 224 return min(min(dispointtoseg(v.s),dispointtoseg(v.e)),min(v.dispointtoseg(s),v.dispointtoseg(e))); 225 } 226 //返回点P在直线上的投影 227 Point lineprog(Point p){ 228 return s+(((e-s)*((e-s)*(p-s)))/((e-s).len2())); 229 } 230 //返回点P关于直线的对称点 231 Point symmetrypoint(Point p){ 232 Point q=lineprog(p); 233 return Point(2*q.x-p.x,2*q.y-p.y); 234 } 235 }; 236 237 Line L[100005]; 238 int book[100005]; 239 int n; 240 241 bool Check(Line a,Line b){ 242 if(sgn((a.s-a.e)^(b.s-a.e))*sgn((a.s-a.e)^(b.e-a.e))>0) return false; 243 if(sgn((b.s-b.e)^(a.s-b.e))*sgn((b.s-b.e)^(a.e-b.e))>0) return false; 244 if(sgn(max(a.s.x,a.e.x)-min(b.s.x,b.e.x))>=0&&sgn(max(b.s.x,b.e.x)-min(a.s.x,a.e.x))>=0 245 &&sgn(max(a.s.y,a.e.y)-min(b.s.y,b.e.y))>=0&&sgn(max(b.s.y,b.e.y)-min(a.s.y,a.e.y))>=0) 246 return true; 247 else return false; 248 } 249 250 int main(){ 251 int T; 252 scanf("%d",&T); 253 while(T--){ 254 Line seg,L[5]; 255 double x1,y1,x2,y2,x11,y11,x22,y22; 256 scanf("%lf %lf %lf %lf",&seg.s.x,&seg.s.y,&seg.e.x,&seg.e.y); 257 scanf("%lf %lf %lf %lf",&x11,&y11,&x22,&y22); 258 x1=min(x11,x22); 259 x2=max(x11,x22); 260 y1=min(y11,y22); 261 y2=max(y11,y22); 262 //上下左右 263 L[1].s.x=x1,L[1].s.y=y1,L[1].e.x=x2,L[1].e.y=y1; 264 L[2].s.x=x2,L[2].s.y=y2,L[2].e.x=x1,L[2].e.y=y2; 265 L[3].s.x=x1,L[3].s.y=y2,L[3].e.x=x1,L[3].e.y=y1; 266 L[4].s.x=x2,L[4].s.y=y1,L[4].e.x=x2,L[4].e.y=y2; 267 int flag=0; 268 for(int i=1;i<=4;i++){ 269 if(Check(seg,L[i])){ 270 flag=1; 271 } 272 } 273 if(max(seg.s.x,seg.e.x)<=x2&&max(seg.s.y,seg.e.y)<=y2&&min(seg.s.x,seg.e.x)>=x1&&min(seg.s.y,seg.e.y)>=y1){ 274 flag=1; 275 } 276 if(flag) puts("T"); 277 else puts("F"); 278 } 279 return 0; 280 }