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;
}


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