判断两线段是否相交-考研真题

来源:互联网 发布:大连开发区知润山房照 编辑:程序博客网 时间:2024/05/27 02:32

之前在网上看到一篇利用向量内积来判断线段是否相交的例子,自己也曾尝试过去书写这样的算法,但是在书写过程中发现,由于该算法涉及的知识包括向量叉乘和点乘公式以及行列式计算等,导致算法的可读性不强,有些地方难于理解。故利用中学的几何知识重新书写判断线段相交的算法,新的算法运算快捷且简单易懂。下面便是详细介绍:

如题:书写算法判断线段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,否则返回falsebool 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坐标相同则返回falseif(isUpper(p1)){//如果p1在直线上方,p2在直线下方则满足条件返回True,否则返回falseif(!isUpper(p2))return true;elsereturn false;}else{//如果p1在直线下方,p2在直线上方则满足条件返回True,否则返回falseif(isUpper(p2))return true;elsereturn 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;}


0 0
原创粉丝点击