Intersection

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. 

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.

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

判断线是否在矩形内或与矩形的边相交

注意共线但是不相交的情况

  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 }
View Code

猜你喜欢

转载自www.cnblogs.com/Fighting-sh/p/9922670.html