您的位置:首页 > 其它

HOJ1102 计算几何 判断两个线段是否会相交

2009-03-27 17:44 633 查看
}
/********************************************************************************************
Date:2009-3-27
Place:HIT
Author:Min,Liu
Function:桌面上有n个吸管,判断任意两根是否相交
Main Method:计算几何 并查集
********************************************************************************************/
#include <iostream>
#include <stdio.h>

using namespace std;

struct point
{
int x;
int y;
};

struct line
{
point a;
point b;
};

point duandian1
;//用于存一条线的一个端点(x1,y1)
point duandian2
;//用于存一条线的;另一个端点(x2,y2)

const int N = 30010;
int set
, rank
;

//并查集的初始化,所有结点的父节点是自己而且秩为1
void init(int n)
{
for (int i = 0; i <= n; i++)
{
set[i] = i;
rank[i] = 1;
}
}

//寻找根
int root(int i)
{
if (set[i] == i)
return i;
set[i] = root(set[i]);
return set[i];
}

//合并,这个程序是合并线段,一个线段有自己的号码代表自己
void join(int i, int j)
{
i = root(i);
j = root(j);
if (i == j)
return;
if (i<j)
{
set[j] = i;
}
else
set[i] = j;
}

void Input( int n )
{
int i;
for(i=1;i<=n;i++)
{
scanf("%d %d", &duandian1[i].x, &duandian1[i].y );
scanf("%d %d", &duandian2[i].x, &duandian2[i].y );
}

}

void ceshi()
{
int i;
int j;
while(scanf("%d %d", &i, &j)==2 )
{
if(i==0&&j==0)
break;
if(root(i)==root(j))
printf("CONNECTED/n");
else
printf("NOT CONNECTED/n");
}
}
//判断不在两边时,是不是属于一个端点恰好在另一个线段上
int onSegment(point* pi, point* pj, point* pk)
{
int minx, miny, maxx, maxy;
if (pi->x > pj->x)
{
minx = pj->x;
maxx = pi->x;
}
else
{
minx = pi->x;
maxx = pj->x;
}

if (pi->y > pj->y)
{
miny = pj->y;
maxy = pi->y;
}
else
{
miny = pi->y;
maxy = pj->y;
}

if (minx <= pk->x && pk->x <= maxx && miny <= pk->y && pk->y <= maxy)
return 1;
else
return 0;
}
//计算两个向量的叉积
int crossProduct(line* v1, line* v2)
{
line vt1, vt2;
int result = 0;

vt1.a.x = 0;
vt1.a.y = 0;
vt1.b.x = v1->b.x - v1->a.x;
vt1.b.y = v1->b.y - v1->a.y;

vt2.a.x = 0;
vt2.a.y = 0;
vt2.b.x = v2->b.x - v2->a.x;
vt2.b.y = v2->b.y - v2->a.y;

result = vt1.b.x * vt2.b.y - vt2.b.x * vt1.b.y;
return result;
}
//三个点求出两个向量,再调用crossProduct函数算叉积,从而知道三个点的位置
int direction(point* pi, point* pj, point* pk)
{
line l1, l2;

l1.a.x = 0;
l1.a.y = 0;
l1.b.x = pk->x - pi->x;
l1.b.y = pk->y - pi->y;

l2.a.x = 0;
l2.a.y = 0;
l2.b.x = pj->x - pi->x;
l2.b.y = pj->y - pi->y;

return crossProduct(&l1, &l2);
}
//中心函数,通过调用其他函数判断两个线段是否相交
int segmentIntersect(point* p1, point* p2, point* p3, point* p4)
{
int d1 = direction(p3, p4, p1);
int d2 = direction(p3, p4, p2);
int d3 = direction(p1, p2, p3);
int d4 = direction(p1, p2, p4);
if (d1 * d2 < 0 && d3 * d4 < 0)
return 1;
else if (!d1 && onSegment(p3, p4, p1))
return 1;
else if (!d2 && onSegment(p3, p4, p2))
return 1;
else if (!d3 && onSegment(p1, p2, p3))
return 1;
else if (!d4 && onSegment(p1, p2, p4))
return 1;
else
return 0;
}

int main()
{
int n;
while( scanf("%d",&n)==1 && n )
{
init( n );
int i;
int j;
Input(n);
for(i=1;i<=n;i++)
{
for(j=1;j<i;j++)
{
int flag=segmentIntersect(  &duandian1[i],  &duandian2[i], &duandian1[j], &duandian2[j] );
if(flag==1)
join(i,j);
else
;
}
}
//for(i=1;i<=7;i++)
//	printf("root[%d]=%d/n",i,root(i));
ceshi();
}
return 0;
}


第一次写计算几何,写得很辛苦,继续努力!!
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: