UVA 191 Intersection POJ 1410【向量法判斷線段相交】

題目大意:給出線段起點,終點,之後給出矩形對角線的起點與終點,千萬別天真按照樣例就理解爲是左上和右下點,不一定!

解題策略:今天下午開始看計算幾何,初看題目第一反應是解析幾何,但是誤差太大,向量法完美解決本體,wa了好久,終於圓滿解決,具體詳見註釋。

                    從這題開始AC所有計算幾何吧!


/*
   UVA 191 Intersection
   AC by J_Dark
   Time 0.016s
   ON 2013/5/1 23:28
*/
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <climits>
#include <vector>
#include <algorithm>
using namespace std;

struct point{
	int x, y;
	point(int a, int b){
		x = a;
		y = b;
	}
};
vector<point> line, rec; //定義線段, 矩形容器
bool ff;  //記錄線段與矩形相交標識
//////////////////////////////////
void Input(){
	line.clear();
	rec.clear();
	int cLine_x, cLine_y, dLine_x, dLine_y, aRec_x, aRec_y;
	int bRec_x, bRec_y, r1_x, r1_y, r2_x, r2_y;
	cin >> cLine_x >> cLine_y >> dLine_x >> dLine_y >> r1_x >> r1_y >> r2_x >> r2_y;
	//這裏是wa點,輸入矩形對角線的兩個點不一定是按照左上,右下輸入
	//構造矩形對角線左上點與右下點
	aRec_x = min(r1_x, r2_x);
	aRec_y = max(r1_y, r2_y);
	bRec_x = max(r1_x, r2_x);
	bRec_y = min(r1_y, r2_y);
	line.push_back(point(cLine_x, cLine_y));
	line.push_back(point(dLine_x, dLine_y));
	rec.push_back(point(aRec_x, aRec_y));
	rec.push_back(point(aRec_x, bRec_y));
	rec.push_back(point(bRec_x, aRec_y));
	rec.push_back(point(bRec_x, bRec_y));
}

//計算 向量(pi-> pj)與(pj->pk)叉積,判斷螺旋方向
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 && max(Pi.x, Pj.x) >= Pk.x &&
	   min(Pi.y, Pj.y) <= Pk.y && max(Pi.y, Pj.y) >= Pk.y)
	   return true;
	return false;
}

void Compute(){
	//線段與矩形內部有相交   =>  線段在矩形內
	if((line[0].x >= rec[0].x) && (line[0].x <= rec[3].x) &&
	   (line[1].x >= rec[0].x) && (line[1].x <= rec[3].x) &&
	   (line[0].y <= rec[0].y) && (line[0].y >= rec[3].y) &&
	   (line[1].y <= rec[0].y) && (line[1].y >= rec[3].y))
	    ff = true;
	//線段與矩形部分相交
	else{
	   ff = false;
	   //枚舉矩形四條邊向量rec[0]->rec[1], rec[0]->[2], rec[3]->[1], rec[3]->[2]
	   //與線段向量line[0]->line[1]進行判斷
	   for(int k=0; k<4; k+=3){
	       if(ff) break;
		   for(int i=1; i<=2; i++){
		      if(ff) break;
		      int d1, d2, d3, d4;
		      d1 = Direction(rec[k], rec[i], line[0]);
			  d2 = Direction(rec[k], rec[i], line[1]);
			  d3 = Direction(line[0], line[1], rec[k]);
			  d4 = Direction(line[0], line[1], rec[i]);
			  if(d1*d2<0 && d3*d4<0)  { ff = true;  break;}  //規範相交
			  //非規範相交
			  else if(d1==0 && OnSegment(rec[k], rec[i], line[0]))  {ff = true;}
			  else if(d2==0 && OnSegment(rec[k], rec[i], line[1]))  {ff = true;}
			  else if(d3==0 && OnSegment(line[0], line[1], rec[k]))  {ff = true;}
			  else if(d4==0 && OnSegment(line[0], line[1], rec[i]))  {ff = true;}
			  else ff = false;
		   }
	   }
	}
}

void Output(){
	if(ff)  cout << "T" << endl;
	else cout << "F" << endl;
}
//////////////////////////////////
int main(){
	int testCase;
	while(cin >> testCase)
	{
		while(testCase--)
		{
			Input();
			Compute();
			Output();
		}
	}
	return 0;
}


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章