判断平面上两直线相交
2016-02-29 20:51
645 查看
直线相交
首先引出计算几何学中一个最基本的问题:如何判断向量
在
的顺时针方向还是逆时针方向?
把p0定为原点,p1的坐标是(x1,y1),p2的坐标是(x2,y2)。向量的叉积(cross product)实际上就是矩阵的行列式:
当叉积为正时,说明
在
的顺时针方向上;叉积为0说明两向量共线(同向或反向)。
当同时满足:
(1)
和
在
的两侧(即一个顺时针方向上,一个在逆时针方向上)
(2)
和
在
的两侧
时可肯定
和
相交。
图1
图1是线段相交的一般情形。
图2只满足第(1)条,不满足第(2)条所以不能证明
和
相交。
图2
图3和图4是一种特殊情况,它不满足第(2)条,因为
和
重合,即
和
的叉积为0。
可见当叉积为0时要分情况讨论,当p3在线段p1p2上时两线段相交;当p3在线段p1p2的延长线上时两线段不相交。
[cpp] view
plaincopy
double direction(pair<double,double> p1,pair<double,double> p2,pair<double,double> p3){
pair<double,double> d1=make_pair(p3.first-p1.first,p3.second-p1.second);
pair<double,double> d2=make_pair(p2.first-p1.first,p2.second-p1.second);
return d1.first*d2.second-d1.second*d2.first;
}
direction函数用于计算
和
的叉积。
[cpp] view
plaincopy
bool OnSegment(pair<double,double> p1,pair<double,double> p2,pair<double,double> p3){
double x_min,x_max,y_min,y_max;
if(p1.first<p2.first){
x_min=p1.first;
x_max=p2.first;
}else{
x_min=p2.first;
x_max=p1.first;
}
if(p1.second<p2.second){
y_min=p1.second;
y_max=p2.second;
}else{
y_min=p2.second;
y_max=p1.second;
}
if(p3.first<x_min || p3.first>x_max || p3.second<y_min || p3.second>y_max)
return false;
else
return true;
}
当p3在直线p1p2上时,OnSegment函数用于确认p3在
上,还是在
的延长线上。
下面是用于判断两线段是否相交的主函数。
[cpp] view
plaincopy
bool SegmentIntersect(pair<double,double> p1,pair<double,double> p2,pair<double,double> p3,pair<double,double> p4){
double d1=direction(p3,p4,p1);
double d2=direction(p3,p4,p2);
double d3=direction(p1,p2,p3);
double d4=direction(p1,p2,p4);
if(d1*d2<0 && d3*d4<0)
return true;
else if(d1==0 && OnSegment(p3,p4,p1))
return true;
else if(d2==0 && OnSegment(p3,p4,p2))
return true;
else if(d3==0 && OnSegment(p1,p2,p3))
return true;
else if(d4==0 && OnSegment(p1,p2,p4))
return true;
else
return false;
}
测试函数:
[cpp] view
plaincopy
int main(){
double x1,y1,x2,y2,x3,y3,x4,y4;
cout<<"Please input x1,y1,x2,y2,x3,y3,x4,y4 by order"<<endl;
cin>>x1>>y1>>x2>>y2>>x3>>y3>>x4>>y4;
pair<double,double> p1=make_pair(x1,y1);
pair<double,double> p2=make_pair(x2,y2);
pair<double,double> p3=make_pair(x3,y3);
pair<double,double> p4=make_pair(x4,y4);
if(SegmentIntersect(p1,p2,p3,p4))
cout<<"YES"<<endl;
else
cout<<"NO"<<endl;
return 0;
}
首先引出计算几何学中一个最基本的问题:如何判断向量
在
的顺时针方向还是逆时针方向?
把p0定为原点,p1的坐标是(x1,y1),p2的坐标是(x2,y2)。向量的叉积(cross product)实际上就是矩阵的行列式:
当叉积为正时,说明
在
的顺时针方向上;叉积为0说明两向量共线(同向或反向)。
当同时满足:
(1)
和
在
的两侧(即一个顺时针方向上,一个在逆时针方向上)
(2)
和
在
的两侧
时可肯定
和
相交。
图1
图1是线段相交的一般情形。
图2只满足第(1)条,不满足第(2)条所以不能证明
和
相交。
图2
图3和图4是一种特殊情况,它不满足第(2)条,因为
和
重合,即
和
的叉积为0。
可见当叉积为0时要分情况讨论,当p3在线段p1p2上时两线段相交;当p3在线段p1p2的延长线上时两线段不相交。
[cpp] view
plaincopy
double direction(pair<double,double> p1,pair<double,double> p2,pair<double,double> p3){
pair<double,double> d1=make_pair(p3.first-p1.first,p3.second-p1.second);
pair<double,double> d2=make_pair(p2.first-p1.first,p2.second-p1.second);
return d1.first*d2.second-d1.second*d2.first;
}
direction函数用于计算
和
的叉积。
[cpp] view
plaincopy
bool OnSegment(pair<double,double> p1,pair<double,double> p2,pair<double,double> p3){
double x_min,x_max,y_min,y_max;
if(p1.first<p2.first){
x_min=p1.first;
x_max=p2.first;
}else{
x_min=p2.first;
x_max=p1.first;
}
if(p1.second<p2.second){
y_min=p1.second;
y_max=p2.second;
}else{
y_min=p2.second;
y_max=p1.second;
}
if(p3.first<x_min || p3.first>x_max || p3.second<y_min || p3.second>y_max)
return false;
else
return true;
}
当p3在直线p1p2上时,OnSegment函数用于确认p3在
上,还是在
的延长线上。
下面是用于判断两线段是否相交的主函数。
[cpp] view
plaincopy
bool SegmentIntersect(pair<double,double> p1,pair<double,double> p2,pair<double,double> p3,pair<double,double> p4){
double d1=direction(p3,p4,p1);
double d2=direction(p3,p4,p2);
double d3=direction(p1,p2,p3);
double d4=direction(p1,p2,p4);
if(d1*d2<0 && d3*d4<0)
return true;
else if(d1==0 && OnSegment(p3,p4,p1))
return true;
else if(d2==0 && OnSegment(p3,p4,p2))
return true;
else if(d3==0 && OnSegment(p1,p2,p3))
return true;
else if(d4==0 && OnSegment(p1,p2,p4))
return true;
else
return false;
}
测试函数:
[cpp] view
plaincopy
int main(){
double x1,y1,x2,y2,x3,y3,x4,y4;
cout<<"Please input x1,y1,x2,y2,x3,y3,x4,y4 by order"<<endl;
cin>>x1>>y1>>x2>>y2>>x3>>y3>>x4>>y4;
pair<double,double> p1=make_pair(x1,y1);
pair<double,double> p2=make_pair(x2,y2);
pair<double,double> p3=make_pair(x3,y3);
pair<double,double> p4=make_pair(x4,y4);
if(SegmentIntersect(p1,p2,p3,p4))
cout<<"YES"<<endl;
else
cout<<"NO"<<endl;
return 0;
}
相关文章推荐
- 如何组织构建多文件 C 语言程序(二)
- 如何写好 C main 函数
- Lua和C语言的交互详解
- 关于C语言中参数的传值问题
- 简要对比C语言中三个用于退出进程的函数
- 深入C++中API的问题详解
- 基于C语言string函数的详解
- C语言中fchdir()函数和rewinddir()函数的使用详解
- C语言内存对齐实例详解
- C语言编程中统计输入的行数以及单词个数的方法
- C语言自动生成enum值和名字映射代码
- 使用C语言判断英文字符大小写的方法
- c语言实现的带通配符匹配算法
- C语言实现顺序表基本操作汇总
- C语言中计算正弦的相关函数总结
- 使用C语言详解霍夫曼树数据结构
- 探讨C语言的那些小秘密之断言
- C语言实现BMP转换JPG的方法
- 深入探讨C语言中局部变量与全局变量在内存中的存放位置
- C语言查找数组里数字重复次数的方法