判断与求解平面内两线段的交点的算法与实现

原创 2017年01月03日 23:42:52

两条线段的位置关系可以大致归类为平行、相交和不平行且不相交,平行又可以分为重合,共线(不重合),部分重合,不平行且不相交的情况为线段所在直线相交,交点在线段外。

 

我们要判断线段的位置关系以及计算交点的位置关系,需要用到向量的相关知识,即定义两个向量p(x1, y1)和q(x2, y2),向量积系数k=p×q=x1·y2-x2·y1,若k=0则pq平行,若k>0,则p逆时针旋转到q(这里指旋转角小于180度的情况),若k<0,则p顺时针旋转到q(相关推导请参考游戏中两个常用的数学运算推导及算法推论 中关于向量积的推导和推论)。

 

如下图,现在有4个点A(x1, y1)、B(x2, y2)、C(x3,y3)、D(x4, y4),若线段AB和CD存在交点,则设其交点为E(x, y),向量AB记为p1(dx1,dy1),向量CD记为p2(dx2, dy2),向量AC记为p3(dx3, dy3),如下图所示:

【原创】判断与求解平面内两线段的交点的算法与实现 - 远行的风 - 风的驿站

 

我们根据向量积系数为0来判断向量是否平行,即由如下算法:

float k = x1·y2-x2·y1;

if (k == 0) {

      //平行

} else {

      //进一步判断是否相交

}

这里对于平行中包含的共线、重合等特殊情况就不做具体讨论了,我们集中精力来考虑交点的求解算法。

我们先不考虑线段相交的情况,先来考虑直线的相交问题(要判断线段有无交点,可以先求解直线的交点,然后判断交点是否在线段内部)。

 

根据前面的定义我们能够得到下面的关系:

dx1=x2-x1

dy1=y2-y1

dx2=x4-x3

dy2=y4-y3

dx3=x3-x1

dy3=y3-y1

 

为了方便计算结果的表示,再定义下面的两个量:

t1=dx2·dy1-dx1·dy2

t2=dx1·dy3-dx3·dy1

 

设直线AB的斜率为k1,直线CD的斜率为k2,则有k1=(y-y1)/(x-x1)=(y2-y1)/(x2-x1)=dy1/dx1,k2=(y-y3)/(x-x3)=(y4-y3)/(x4-x3)=dy2/dx2,联立求解得:

x=(dx1·dx2·dy3-dx1·dy2·x3+dx2·dy1·x1)/(dy1·dx2-dy2·dx1)

=(dx1·dx2·dy3-dx1·dy2·x3+dx2·dy1·x3-dx2·dy1·x3+dx2·dy1·x1)/(dy1·dx2-dy2·dx1)

=x3+(dx1·dx2·dy3-dx2·dx3·dy1)/(dy1·dx2-dy2·dx1)

=x3+dx2·(dx1·dy3-dx3·dy1)/(dy1·dx2-dy2·dx1)

=x3+dx2·t2/t1

y=y3+dy2·(x-x3)/dx2=y3+dy2·t2/t1

 

因此,我们得到下面的求解算法(忽略具体的编程语言,只是算法的主体思路):

Struct Point {

      floatx;

      floaty;

}

 

float calculateVectorProduct(PointP1, Point P2, Point P3, Point P4) { 

      return(P2.x-P1.x) * (P4.y-P3.y) - (P2.y-P1.y) * (P4.x-P3.x);

}

 

PointcalculateIntersectionPoint(Point A, Point B, Point C, Point D) {

float t1 =calculateVectorProduct(C, D, A, B);

      floatt2 = calculateVectorProduct(A, B, A, C);

float x = C.x +(D.x-C.x) * t2 / t1;

float y = C.y +(D.y-C.y) * t2 / t1;

return newPoint(x, y);

}

 

在得到了交点之后,我们来做进一步的判断,来确定交点是否在线段上。要确定点是否在线段上其实比较简单,因为我们求得的点一定在直线上,所以不需要去计算点是否满足直线方程,只需要判断点的横纵坐标是否在线段两个端点的横纵坐标之间即可。

 

算法实现比较简单:

float min(float Num1, float Num2) {

      returnNum1 > Num2 ? Num2 : Num1;

}

 

float max(float Num1, float Num2) {

      returnNum1 > Num2 ? Num1 : Num2;

}

 

float isBetween(float Num, floatNum1, float Num2) {

      floatdeviation =0.1;      //   由于浮点数的精度问题,因此引入误差防止误判

      return(Num >= min(Num1, Num2)-deviation && Num <= max(Num1,Num2)+deviation;

}

 

bool isPointInSegment(Point P1,Point LineStart, Point LineEnd) {

      return(isBetween(P1.x, LineStart.x,LineEnd.x)  &&  isBetween(P1.y, LineStart.y,LineEnd.y));

}

当然这里isPointInSegment这个方法是基于P1在LineStart和LineEnd确定的直线上的,也就是基于P1是前面算法中求得的直线交点。要判断点是否在直线上,需要根据y=kx+t来求解出直线方程,然后验证点坐标是否满足直线方程即可。

 

算法如下:

bool checkIsPointOnLine(Point P1,Point LineStart, Point LineEnd) {

      if(isBetween(LineStart.x-LineEnd.x, 0, 0)) {

           returnisBetween(P1.x-LineStart.x, 0, 0);

      }else {

           floatk = (LineEnd.y-LineStart.y)/(LineEnd.x-LineStart.x);

           floatcalculatedY = k * (P1.x-LineEnd.x) + LineEnd.y;

           returnisBetween(P1.y-calculatedY, 0, 0);

      }

}

 

据此我们可以对任意给出的4个点做判断:

Point A = Point(1, 1);

Point B = Point(4, 3);

Point C = Point(2, 1);

Point D = Point(4, 5);

Point E =calculateIntersectionPoint(A, B, C, D);

bool isOnSegment = isPointInSegment(E, A, B) & isPointInSegment(E, C, D);

 

这个算法对于模拟游戏中需要求解线段之间的交点,射线之间的交点是非常有帮助的。如果有疑问,欢迎留言~

版权声明:本文为博主原创文章,未经博主允许不得转载。

相关文章推荐

线段求交算法demo

线段求交算法demo                        ...

线段求交算法对比研究

线段求交算法对比研究 -----by wangsh  一.介绍 线段求交算法在计算几何,地理信息系统算法等相关应用中占有重要的位置,本文简单给出算法说明。 Bentley & Ottmann于...

计算几何之线段性质(二):求线段交点

求线段的交点即求线段交点的坐标。若已确定两线段相交,可以通过解析几何中的直线方程来求解交点,这里介绍另外的一种方法。叉积multi(p1,p2,p0)可以看做是由点P1,P2,P0和P1+P2,这四个...

判断两条线段是否相交(三种算法)

算法1:///----------alg 1------------ struct Point { double x, y; }; bool between(double a, d...

求线段交点"的几种算法(js实现,完整版)

“求线段交点”是一种非常基础的几何计算, 在很多游戏中都会被使用到. 下面我就现学现卖的把最近才学会的一些”求线段交点”的算法说一说, 希望对大家有所帮助. 本文讲的内容都很初级, 主要是面向...

平面内两条线段的位置关系(相交)判定与交点求解

本文转自博客园:原文地址 概念 平面内两条线段位置关系的判定在很多领域都有着广泛的应用,比如游戏、CAD、图形处理等,而两线段交点的求解又是该算法中重要的一环。本文将尽可能用通俗的语言...

平面内两条线段的位置关系(相交)判定与交点求解

http://www.cnblogs.com/devymex/archive/2010/08/19/1803885.html   概念 平面内两条线段位置关系的判定在很多领域都有着广泛的应用,比...

平面内两条线段的位置关系(相交)判定与交点求解

http://www.cnblogs.com/devymex/archive/2010/08/19/1803885.html 概念 平面内两条线段位置关系的判定在很多领域都有着广泛...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:深度学习:神经网络中的前向传播和反向传播算法推导
举报原因:
原因补充:

(最多只允许输入30个字)