uva191 Intersection

来源:互联网 发布:c语言中=是什么意思 编辑:程序博客网 时间:2024/04/30 09:09

题意:给出线段的端点和矩形对角线的两个点,要判断线段和矩形是否相交

解题:Computational Geometry(计算几何);如果线段在矩形内部算是相交的,如果不是,就判断线段和矩形四条边是否有交点,所以重点就是如何判断两条线段相交

如图一:若(p1,p2)和(p3,p4)相交,他们相互跨越,那么p1,p2和(p3,p4)必然在(p3,p4)[或(p1,p2) 的两侧;就可以用向量来解决,(p1,p3)在(p1,p2)的逆时针方向,(p1,p4)在(p1,p2)的顺时针方向;就可以用叉积来解决,如图三,叉积是(0,0),a1,a2,a3(=a1+a2) 构成的平行四边形的有向面积,或者是a1*a2 = x1y2-x2y1;若a1*a2 >0 则则表示a1在a2的顺时针方向,否则是逆时针方向;

综上所述:判断两线段相交,1.看叉积,两个叉积不同号 2.如果叉积等于0,表示共线,但是由于是线段,所以在判断点是否在线段上。

代码:在图下面

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

//uva191 Intersection//AC By Warteac//Runtime:0.012s//2013-5-3#include<iostream>#include<cstdio> using namespace std; struct point{ int x,y; point(int x1 = 0, int y1 = 0){x = x1; y = y1;} void print(){cout << "x= " << x << " y= " << y << endl;} };//定义点结构体//求向量的叉积,p1*p2 > 0 => p1 在 p2的顺时针方向,< 0 逆时针 int direction(point pi,point pj,point pk){ return ((pj.x - pi.x)*(pk.y - pi.y)-(pk.x - pi.x)*(pj.y - pi.y)); } //向量共线的前提下,判断是点pk是否在线段(pi,pj)上 bool onSegment(point pi,point pj,point pk){ if((min(pi.x,pj.x) <= pk.x && pk.x <= max(pi.x,pj.x)) && (min(pi.y,pj.y) <= pk.y && pk.y <= max(pi.y,pj.y))){ return true; }else{ return false; } } //线段(p1,p2)和线段(p3,p4)是否相交 bool segmentsIntersect(point p1,point p2,point p3, point p4){ int  d1,d2,d3,d4; d1 = direction(p3,p4,p1); d2 = direction(p3,p4,p2); d3 = direction(p1,p2,p3); d4 = direction(p1,p2,p4); //cout << d1 << " " << d2 <<" " << d3 << " " << d4 << endl; if(((d1 > 0 && d2 < 0) || (d1 < 0 && d2 >0)) && ((d3 > 0 && d4 < 0)||(d3 < 0 && d4 > 0))) return true; else if((d1 == 0)&&(onSegment(p3,p4,p1))) return true;else if((d2 == 0)&&(onSegment(p3,p4,p2)))return true;else if((d3 == 0)&&(onSegment(p1,p2,p3)))return true;else if((d4 == 0)&&(onSegment(p1,p2,p4)))return true;else return false; } //线段(pa,pb)在矩形的内部 bool segmentInRectangle(point p1,point p3,point pa,point pb){ if( (min(p1.x,p3.x) <= pa.x && pa.x <= max(p1.x,p3.x)) &&     (min(p1.y,p3.y) <= pa.y && pa.y <= max(p1.y,p3.y)) &&      (min(p1.x,p3.x) <= pb.x && pb.x <= max(p1.x,p3.x)) &&      (min(p1.y,p3.y) <= pb.y && pb.y <= max(p1.y,p3.y)) )   return true; else return false; } int main(){ point p1,p2,p3,p4;//矩形的四个顶点 point pa,pb;//线段的端点 int caseNum; cin >> caseNum; int x1,y1,x2,y2,x3,y3,x4,y4; while(caseNum--){ cin >> x1 >> y1 >> x2 >> y2 >> x3 >> y3 >> x4 >> y4; pa = point(x1,y1);  pb = point(x2,y2); p1 = point(x3,y3); p3 = point(x4,y4); p2 = point(x3,y4); p4 = point(x4,y3);  if(segmentInRectangle(p1,p3,pa,pb) == true){//线段在矩形内部  cout << "T" << endl;  }else if( (segmentsIntersect(p1,p2,pa,pb))||            (segmentsIntersect(p1,p4,pa,pb))||            (segmentsIntersect(p3,p2,pa,pb))||            (segmentsIntersect(p3,p4,pa,pb)) )  cout << "T" << endl;//线段在外部,但是和矩形有交点  else cout << "F" << endl; } }