uva191 Intersection

題意:給出線段的端點和矩形對角線的兩個點,要判斷線段和矩形是否相交

解題: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;
 	}
 }
 
 


 

發佈了55 篇原創文章 · 獲贊 8 · 訪問量 3萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章