计算几何:线段判交模板--ACM


给定两个点:

typedef  struct {

  double  x, y;

} Point;

Point A1,A2,B1,B2;

首先引入两个实验:

a.快速排斥实验

设以线段A1A2和线段B1B2为对角线的矩形为M,N;

若M,N 不相交,则两个线段显然不相交;

所以:满足第一个条件时:两个线段可能相交。

 

b.跨立实验

如果两线段相交,则两线段必然相互跨立对方.若A1A2跨立B1B2,则矢量( A1 - B1 ) 和(A2-B1)位于矢量(B2-B1)的两侧,

即(A1-B1) × (B2-B1) * (A2-B1) × (B2-B1)<0。

上式可改写成(A1-B1) × (B2-B1) * (B2-B1) × (A2-A1)>0。

应该判断两次,即两条线段都要为直线,判断另一直线的两端点是否在它两边,若是则两线段相交。

若积极满跨立实验是不行的,如下面的情况:

即两条线段在同一条直线上。所以我们要同时满足两次跨立和快速排斥实验。

 

总体分析:

当(A1-B1) × (B2-B1)=0时,说明(A1-B1)和(B2-B1)共线,但是因为已经通过快速排斥试验,所以 A1一定在线段 B1B2上;同理,(B2-B1)×(A2-B1)=0 说明A2一定在线段B1B2上。所以判断A1A2跨立B1B2的依据是:(A1-B1) × (B2-B1) * (B2-B1) × (A2-B1) >= 0。

同理判断B1B2跨立A1A2的依据是:(B1-A1) × (A2-A1) * (A2-A1) × (B2-A1) >= 0。

如图:

应用:

1.       判断两个线段相交

2.       判断线段与直线相交

3.       判断点在矩形内

代码:


复制代码
 1  /*
 2  (A1-B1) × (B2-B1) * (B2-B1) × (A2-A1) >= 0
 3  (B1-A1) × (A2-A1) * (A2-A1) × (B2-A1) >= 0
 4  */
 5 
 6 #include<stdio.h>
 7  #define min(a,b) a<b?a:b
 8  #define max(a,b) a>b?a:b
 9 typedef  struct {
10  double x,y;
11 }Point;
12 Point A1,A2,B1,B2;
13 Point  A1B1, B2B1, A2A1, B2A1;
14  double xx(Point &s,Point &t)
15 {
16      return (s.x*t.y+s.y*t.x);
17 }
18  int kua()                            // 跨立实验
19  {
20     A1B1.x=A1.x-B1.x;  A1B1.y=A1.y-B1.y;
21     B2B1.x=B2.x-B1.x;  B2B1.y=B2.y-B1.y;
22     A2A1.x=A2.x-A1.x;  A2A1.y=A2.y-A1.y;
23     B2A1.x=B2.x-A1.x;  B2A1.y=B2.y-A1.y;
24      if(xx(A1B1,B2B1)*xx(B2B1,A2A1)>= 0)
25     {
26         A1B1.y=-A1B1.y;A1B1.x=-A1B1.x;
27          if(xx(A1B1,A2A1)*xx(A2A1,B2A1)>= 0)
28              return  1;
29          else
30              return  0;
31     }
32      else
33          return  0;
34 }
35  int main()
36 {
37     Point A1,A2,B1,B2;
38      int flag= 1,i,j,a,b,c,d,e,f;
39      while( 1)
40     {
41         scanf( " %lf%lf%lf%lf ",&A1.x,&A1.y,&A2.x,&A2.y);
42         scanf( " %lf%lf%lf%lf ",&B1.x,&B1.y,&B2.x,&B2.y);
43          if( min(A1.x,A2.x) <= max(B1.x,B2.x) &&
44             min(B1.x,B2.x) <= max(A1.x,A2.x) &&
45             min(A1.y,A2.y) <= max(B1.y,B2.y) &&
46             min(B1.y,B2.y) <= max(A1.y,A2.y)   )    // 快速排斥实验
47          {
48              if(kua())
49                 printf( " 线段相交\n ");
50              else
51                 printf( " 线段不相交\n ");
52         }
53          else
54             printf( " 线段不相交\n ");
55 
56     }
57      return  0;
复制代码

58 }

转载自: http://blog.csdn.net/ice2013/article/details/7444406



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值