判断两线段是否相交-考研真题
2015-12-06 14:56
295 查看
之前在网上看到一篇利用向量内积来判断线段是否相交的例子,自己也曾尝试过去书写这样的算法,但是在书写过程中发现,由于该算法涉及的知识包括向量叉乘和点乘公式以及行列式计算等,导致算法的可读性不强,有些地方难于理解。故利用中学的几何知识重新书写判断线段相交的算法,新的算法运算快捷且简单易懂。下面便是详细介绍:
如题:书写算法判断线段p1p2与线段p3p4是否相交。
核心思想其实非常的简单:这里将判断两线段p1p2与线段p3p4相交分解为判断线段p1p2与直线p3p4是否相交和线段p3p4与直线p1p2是否相交。
如果是直线的话,就好办了。
1、先根据直线上的两点算出直线p1p2和直线p3p4的代数方程;
2、判断点p3和点p4是否分别在直线p1p2的两侧;
3、判断点p1和点p2是否分别在直线p3p4的两侧;
4、如果条件2和3均满足,则两线段相交,否则不想交,最后输出结果。
这里还需要指出的一点是判断点在直线的哪一侧,可以将该点的x坐标代入直线方程计算得到y1,如果点的y坐标大于y1则点在直线上方,否则点在直线的下方。
同理判断两点是否在直线的两侧时,只需判断两点是否一个在上侧,一个在下侧即可。
好了,下面就是完整的代码了。
如题:书写算法判断线段p1p2与线段p3p4是否相交。
核心思想其实非常的简单:这里将判断两线段p1p2与线段p3p4相交分解为判断线段p1p2与直线p3p4是否相交和线段p3p4与直线p1p2是否相交。
如果是直线的话,就好办了。
1、先根据直线上的两点算出直线p1p2和直线p3p4的代数方程;
2、判断点p3和点p4是否分别在直线p1p2的两侧;
3、判断点p1和点p2是否分别在直线p3p4的两侧;
4、如果条件2和3均满足,则两线段相交,否则不想交,最后输出结果。
这里还需要指出的一点是判断点在直线的哪一侧,可以将该点的x坐标代入直线方程计算得到y1,如果点的y坐标大于y1则点在直线上方,否则点在直线的下方。
同理判断两点是否在直线的两侧时,只需判断两点是否一个在上侧,一个在下侧即可。
好了,下面就是完整的代码了。
// 判断两条线段是否相交.cpp : 定义控制台应用程序的入口点。 // #include "stdafx.h" #include <iostream> using namespace std; struct Point { double x,y; Point(double x =0,double y=0):x(x),y(y){} }; class StraightLine { public: Point begin,end; double k;//斜率 double b;//截距 public: StraightLine(const Point begin,const Point end):begin(begin),end(end) { k = (begin.y-end.y)/(begin.x-end.x); b = begin.y-k*begin.x; } public: bool isUpper(Point p);//点在是否在直线上方,如果在直线上或上方均返回true,否则返回false bool isCross(Point p1,Point p2);//点p1,p2组成的线段是否穿过直线 }; bool StraightLine::isUpper(Point p) { double y1 = k * p.x + b; if(p.y>=y1) return true; else return false; } bool StraightLine::isCross(Point p1,Point p2) { if(p1.x==p2.x&&p1.y==p2.y)return false;//若p1与p2坐标相同则返回false if(isUpper(p1)) { //如果p1在直线上方,p2在直线下方则满足条件返回True,否则返回false if(!isUpper(p2)) return true; else return false; } else { //如果p1在直线下方,p2在直线上方则满足条件返回True,否则返回false if(isUpper(p2)) return true; else return false; } return false; } void isCross(Point p1,Point p2,Point p3,Point p4) { StraightLine Line1(p1,p2); StraightLine Line2(p3,p4); //若点p3,p4分别在直线p1p2的两侧,且点p3,p4分别在直线p1p2的两侧,则线段p1p2与线段p3p4相交 if(Line1.isCross(p3,p4)&&Line2.isCross(p1,p2)) { printf("Cross!\n"); } else { printf("Don't Cross!\n"); } } int _tmain(int argc, _TCHAR* argv[]) { Point p1(1,2),p2(5,3),p3(1,5),p4(5,1); isCross(p1,p2,p3,p4); Point a1(1,3),a2(5,2),a3(2,4),a4(4,9); isCross(a1,a2,a3,a4); getchar(); return 0; }
相关文章推荐
- 使用C++实现JNI接口需要注意的事项
- 关于指针的一些事情
- c++ primer 第五版 笔记前言
- share_ptr的几个注意点
- 动易2006序列号破解算法公布
- Ruby实现的矩阵连乘算法
- C#插入法排序算法实例分析
- Lua中调用C++函数示例
- Lua教程(一):在C++中嵌入Lua脚本
- Lua教程(二):C++和Lua相互传递数据示例
- 超大数据量存储常用数据库分表分库算法总结
- C#数据结构与算法揭秘二
- C#冒泡法排序算法实例分析
- 算法练习之从String.indexOf的模拟实现开始
- C#算法之关于大牛生小牛的问题
- C++联合体转换成C#结构的实现方法
- C#实现的算24点游戏算法实例分析
- C++编写简单的打靶游戏
- C++ 自定义控件的移植问题
- C++变位词问题分析