如何在2D中测试线段是否与轴对齐的矩形相交?

时间:2020-03-06 14:24:35  来源:igfitidea点击:

如何在2D中测试线段是否与轴对齐的矩形相交?段的两端定义为:p1,p2. 矩形由左上角和右下角定义。

解决方案

使用Cohen-Sutherland算法。

它用于剪辑,但可以略微调整此任务。它将2D空间划分为一个井字游戏板,矩形作为"中心正方形"。
然后它会检查线的两个点分别在九个区域中的哪个区域。

  • 如果两个点都在左,右,上或者下,我们将微不足道。
  • 如果其中任一点在里面,我们都会微不足道地接受。
  • 在极少数情况下,我们可以根据矩形所在的区域进行数学运算,以使其与矩形的任意可能相交。

快速的Google搜索弹出带有C ++代码的页面,用于测试路口。

基本上,它测试线与每个边界或者矩形之间的交点。

矩形和直线相交代码

由于矩形已对齐,因此Liang-Barsky可能是一个很好的解决方案。如果此处的速度显着,则它比科恩-萨瑟兰(Cohen-Sutherland)快。

信号图说明
另一个很好的描述
当然,维基百科

我做了一点餐巾纸溶液。

接下来找到m和c,因此等式y = mx + c

y = (Point2.Y - Point1.Y) / (Point2.X - Point1.X)

替换P1坐标以查找c

现在,对于矩形顶点,将X值放入线方程中,获取Y值,然后查看Y值是否位于下面所示的矩形边界内

(我们可以找到矩形的常量值X1,X2,Y1,Y2,这样)

X1 <= x <= X2 & 
Y1 <= y <= Y2

如果Y值满足上述条件并且位于(Point1.Y,Point2.Y)之间,则我们有一个交点。
如果该顶点无法切入,请尝试每个顶点。

编写了非常简单有效的解决方案:

bool SegmentIntersectRectangle(double a_rectangleMinX,
                                 double a_rectangleMinY,
                                 double a_rectangleMaxX,
                                 double a_rectangleMaxY,
                                 double a_p1x,
                                 double a_p1y,
                                 double a_p2x,
                                 double a_p2y)
  {
    // Find min and max X for the segment

    double minX = a_p1x;
    double maxX = a_p2x;

    if(a_p1x > a_p2x)
    {
      minX = a_p2x;
      maxX = a_p1x;
    }

    // Find the intersection of the segment's and rectangle's x-projections

    if(maxX > a_rectangleMaxX)
    {
      maxX = a_rectangleMaxX;
    }

    if(minX < a_rectangleMinX)
    {
      minX = a_rectangleMinX;
    }

    if(minX > maxX) // If their projections do not intersect return false
    {
      return false;
    }

    // Find corresponding min and max Y for min and max X we found before

    double minY = a_p1y;
    double maxY = a_p2y;

    double dx = a_p2x - a_p1x;

    if(Math::Abs(dx) > 0.0000001)
    {
      double a = (a_p2y - a_p1y) / dx;
      double b = a_p1y - a * a_p1x;
      minY = a * minX + b;
      maxY = a * maxX + b;
    }

    if(minY > maxY)
    {
      double tmp = maxY;
      maxY = minY;
      minY = tmp;
    }

    // Find the intersection of the segment's and rectangle's y-projections

    if(maxY > a_rectangleMaxY)
    {
      maxY = a_rectangleMaxY;
    }

    if(minY < a_rectangleMinY)
    {
      minY = a_rectangleMinY;
    }

    if(minY > maxY) // If Y-projections do not intersect return false
    {
      return false;
    }

    return true;
  }

原始海报想要检测线段和多边形之间的交点。如果有交叉点,则无需定位。如果这就是意思,那么我们可以做的工作比Liang-Barsky或者Cohen-Sutherland少:

令段端点为p1 =(x1 y1)和p2 =(x2 y2)。
令矩形的角为(xBL yBL)和(xTR yTR)。

那你要做的就是

A.检查矩形的所有四个角是否在直线的同一侧。
通过p1和p2的直线的隐式方程为:

F(x y)=(y2-y1)* x +(x1-x2)* y +(x2 * y1-x1 * y2)

如果F(x y)= 0,则(x y)为ON。
如果F(x y)> 0,则(x y)在该行上方。
如果F(x y)<0,则(x y)在该行"下方"。

将所有四个角代入F(x y)。如果它们全部为负或者全部为正,则没有交集。如果有些是肯定的而有些是消极的,请转到步骤B。

B.将端点投影到x轴上,并检查线段的阴影是否与多边形的阴影相交。在y轴上重复:

如果(x1> xTR和x2> xTR),则没有交点(直线在矩形的右边)。
如果(x1 <xBL并且x2 <xBL),则没有交点(直线在矩形的左侧)。
如果(y1> yTR且y2> yTR),则无交集(直线在矩形上方)。
如果(y1 <yBL并且y2 <yBL),则没有交点(直线在矩形下方)。
否则,有一个交叉点。回答科恩·萨瑟兰(Cohen-Sutherland)或者其他答案中提到的任何代码。

我们当然可以先做B,然后再做A。

阿列霍