计算几何:线段判交模板--ACM
2015-07-04 17:37
295 查看
线段判交--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)的两侧,
![](http://my.csdn.net/uploads/201204/10/1334026912_8315.png)
即(A1-B1) × (B2-B1) * (A2-B1) × (B2-B1)<0。
上式可改写成(A1-B1) × (B2-B1) * (B2-B1) × (A2-A1)>0。
应该判断两次,即两条线段都要为直线,判断另一直线的两端点是否在它两边,若是则两线段相交。
若积极满跨立实验是不行的,如下面的情况:
![](http://my.csdn.net/uploads/201204/10/1334026917_9972.png)
即两条线段在同一条直线上。所以我们要同时满足两次跨立和快速排斥实验。
总体分析:
当(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。
如图:
![](http://my.csdn.net/uploads/201204/10/1334026930_3073.png)
应用:
1. 判断两个线段相交
2. 判断线段与直线相交
3. 判断点在矩形内
代码:
![](http://common.cnblogs.com/images/copycode.gif)
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;
![](http://common.cnblogs.com/images/copycode.gif)
58 }
转载自: http://blog.csdn.net/ice2013/article/details/7444406
给定两个点:
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)的两侧,
![](http://my.csdn.net/uploads/201204/10/1334026912_8315.png)
即(A1-B1) × (B2-B1) * (A2-B1) × (B2-B1)<0。
上式可改写成(A1-B1) × (B2-B1) * (B2-B1) × (A2-A1)>0。
应该判断两次,即两条线段都要为直线,判断另一直线的两端点是否在它两边,若是则两线段相交。
若积极满跨立实验是不行的,如下面的情况:
![](http://my.csdn.net/uploads/201204/10/1334026917_9972.png)
即两条线段在同一条直线上。所以我们要同时满足两次跨立和快速排斥实验。
总体分析:
当(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。
如图:
![](http://my.csdn.net/uploads/201204/10/1334026930_3073.png)
应用:
1. 判断两个线段相交
2. 判断线段与直线相交
3. 判断点在矩形内
代码:
![](http://common.cnblogs.com/images/copycode.gif)
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;
![](http://common.cnblogs.com/images/copycode.gif)
58 }
转载自: http://blog.csdn.net/ice2013/article/details/7444406
相关文章推荐
- java web之Filter详解
- Swift开发教程--Swift的基本语法
- gcc 已知的问题及规避方案 https://gcc.gnu.org/bugs/#known
- error C2440: ‘static_cast’ : cannot convert from ‘HRESULT (__thiscall CtestpalView::* )(WPARAM,LPARA
- javascript prototype详解
- android 随着认识的去除率EditText(它配备了防抖效果)
- (转)Sublime Text 2 2.0.2 序列号
- 联系我们如何添加百度地图路线坐标
- 你所不知道的SQL Server数据库启动过程,以及启动不起来的各种问题的分析及解决技巧
- 音乐播放器之myeclipse项目
- Linux NFS 介绍
- Path Sum II
- [转载] C++ 程序员快过来围观:非常实用全面的 C++ 资源
- openjudge 大师兄,师傅被妖怪抓走啦
- 点击listview中的imageview实现拍照然后显示
- linux下google chrome浏览器字体修改
- Leetcode:Container With Most Water
- Maven jenkins +Jmeter自动化测试
- Android开发中 更新API的问题
- 1949后教授如何评职称