您的位置:首页 > 其它

判断两线段是否相交

2011-09-21 10:36 183 查看
转自:http://www.cnblogs.com/dxp498688071/archive/2011/3/2.html

几何题做的很少,以至于一个很简单的题目写了很久

若是判断直线和线段是否有交点,把on_segment去掉就可以了

  判断两线段是否相交:

  我们分两步确定两条线段是否相交:

  (1)快速排斥试验

    设以线段
P1P2 为对角线的矩形为R, 设以线段 Q1Q2 为对角线的矩形为T,如果R和T不相交,显然两线段不会相交。

  (2)跨立试验

    如果两线段相交,则两线段必然相互跨立对方。若P1P2跨立Q1Q2 ,则矢量 (P1 - Q1 ) 和(P2 - Q1 )位于矢量(Q2 - Q1 ) 的两侧,即(P1 - Q1 ) × (Q2 - Q1 ) * (P2 - Q1 ) × (Q2 - Q1 ) < 0。上式可改写成(P1 - Q1 ) × (Q2 - Q1 ) * (Q2 - Q1 ) × (P2 - Q1 ) >
0。当 (P1 - Q1 ) × (Q2 - Q1 ) = 0 时,说明 (P1 - Q1 ) 和 (Q2 - Q1 )共线,但是因为已经通过快速排斥试验,所以 P1 一定在线段 Q1Q2上;同理,(Q2 - Q1 ) ×(P2 - Q1 ) = 0 说明 P2 一定在线段 Q1Q2上。所以判断P1P2跨立Q1Q2的依据是:(P1 - Q1 ) × (Q2 - Q1 ) * (Q2 - Q1 ) × (P2 - Q1 ) >= 0。同理判断Q1Q2跨立P1P2的依据是:(Q1 - P1
) × (P2 - P1 ) * (P2 - P1 ) × (Q2 - P1 ) >= 0。具体情况如下图所示:



  在相同的原理下,对此算法的具体的实现细节可能会与此有所不同,除了这种过程外,大家也可以参考《算法导论》上的实现。

关于计算几何算法概述网站 http://dev.gameres.com/Program/Abstract/Geometry.htm 一个挺好的网站

view
sourceprint?

01
#include<stdio.h>
02
03
struct
point
04
{
05
double
x,y;
06
};
07
08
double
direction(
point p1,point p2,point p )
09
{
10
return
(
p1.x -p.x )*(p2.y-p.y) -  (p2.x -p.x )*(p1.y-p.y)   ;
11
}
12
13
int
on_segment(
point p1,point p2 ,point p )
14
{
15
double
max=p1.x
> p2.x ? p1.x : p2.x ;
16
double
min
=p1.x < p2.x ? p1.x : p2.x ;
17
18
if
(
p.x >=min && p.x <=max )
19
return
1;
20
else
21
return
0;
22
}
23
24
int
segments_intersert(
point p1,point p2,point p3,point p4 )
25
{
26
double
d1,d2,d3,d4;
27
d1
= direction (p1,p2,p3 );
28
d2
= direction (p1,p2,p4 );
29
d3
= direction (p3,p4,p1 );
30
d4
= direction (p3,p4,p2 );
31
if
(
d1*d2<0 && d3*d4<0 )
32
return
1;
33
else
if
(
d1==0 && on_segment(p1,p2,p3 ) )
34
return
1;
35
else
if
(
d2==0 && on_segment(p1,p2,p4 ) )
36
return
1;
37
else
if
(
d3==0 && on_segment(p3,p4,p1 ) )
38
return
1;
39
else
if
(
d4==0 && on_segment(p3,p4,p2 ) )
40
return
1;
41
42
return
0;
43
}
44
45
int
main()
46
{
47
int
n,i,j,num;
48
point
begin[105],end[105];
49
50
while
(
scanf
(
"%d"
,&n)
&& n!=0 )
51
{
52
num=0;
53
for
(
i=0;i<n;i++)
54
{
55
scanf
(
"%lf
%lf %lf %lf"
,&begin[i].x
,&begin[i].y ,&end[i].x ,&end[i].y );
56
}
57
for
(
i=0;i<n;i++)
58
for
(j=i+1;j<n;j++)
59
{
60
if
(
segments_intersert(begin[i],end[i],begin[j],end[j] ) )
61
num++;
62
}
63
printf
(
"%d\n"
,num);
64
}
65
return
0;
66
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  算法 ini