如何测量直线和矩形之间的重叠?

时间:2018-01-20 02:27:15

标签: python math

我正在尝试测量线段和矩形之间的重叠。例如,线段表示为2点:

!important

和一个4点的矩形:

line = [(x1, y1), (x2, y2)]

有没有一种有效的方法来衡量两者之间重叠的长度(如果有的话)?

这是一个简单的图表:

enter image description here

编辑:为了澄清,线段可能与矩形部分相交,甚至根本不相交。

5 个答案:

答案 0 :(得分:3)

从图片

![enter image description here

我们有

P := (x2,y2) - (x1,y1) = (x2-x1, y2-y1)
Q := (x4,y4) - (x3,y3) = (x4-x3, y4-y3)
cos(α) := dotProduct(P,Q)/norm(P)norm(Q)
h := dist((x4,y4),(x5,y5))

,其中

dotProduct((px,py),(qx,qy)) := px*qx + py*qy
norm(a,b) := sqrt(squared(a)+squared(b))
dist(A,B) = norm(B-A)

然后d可以计算为

d := h/sin(α) = h/(sqrt(1-squared(cos(α)))

答案 1 :(得分:2)

找到仿射变换以使矩形轴对齐。它只是按角度旋转

fi = -atan2(y4-y3, x4-x3)

使用此旋转矩阵

转换线段末端的坐标和一些矩形坐标
 x' = x * Cos(fi) - y * Sin(fi)
 y' = x * Sin(fi) + y * Cos(fi)

请注意,现在矩形只需要两个x坐标和两个y坐标(left=x3', right=x4', bottom=y3', top=y6'

应用任何l ine-clipping algorithm

enter image description here

我建议使用Liang-Barsky(description with code) 计算后,夹点或段末端之间的距离在矩形内 (无限线与矩形相交且结果参数t0和/或t1超出0..1范围的情况)

答案 2 :(得分:0)

我只是在数学部分,没有编码

找到交点(upperx,uppery)(lowerx,lowery)
找到从上点到右上角的距离
找到从下点到右上角的距离
A =减去一个与另一个的距离 B =找到直肠右上角和右下角的距离

你现在有A和B的公式a ^ 2 + b ^ 2 = c ^ 2

享受

答案 3 :(得分:0)

我将这个答案分解为三个部分:

  • 计算交点的坐标
  • 创建一个计算两点之间距离的函数
  • 将所有内容与矩形
  • 放在一起

我还将使用matplotlib来查看示例。

交叉口

wikipedia article给出了一个公式,用于计算坐标描述的两条直线之间交点的坐标:

formula

使用共同坐标

(x1, y1)(x2, y2)(x3, y3)(x4, y4)

如果他们相交,那么分母:

(x1-x2)*(y3-y4)-(y1-y2)*(x3-x4)

将是0

所以,使用这个公式,我们可以创建一个函数来返回两行之间的交点, False意味着它们不相交:

def intersection(x1, y1, x2, y2, x3, y3, x4, y4):
    d = (x1-x2)*(y3-y4)-(y1-y2)*(x3-x4)
    if not d:
        return False
    return (((x1*y2-y1*x2)*(x3-x4) - (x1-x2)*(x3*y4-y3*x4))/d,
            ((x1*y2-y1*x2)*(y3-y4) - (y1-y2)*(x3*y4-y3*x4))/d)
我们可以看到

可以使用两个测试:

>>> intersection(0, 0, 8, 8, 0, 8, 8, 0)
(4.0, 4.0)
>>> intersection(6, 0, 6, 8, 7, 0, 7, 8)
False

您可以使用matplotlib图表来显示这些:

lines

距离

我们还需要能够计算两点之间的距离。这可以使用毕达哥拉斯定理来确定三角形斜边的长度:

a^2 + b^2 = c^2

和以前一样,让我们​​把它放到辅助函数中:

def distance(x1, y1, x2, y2):
    return ((x2-x1)**2 + (y2-y1)**2) ** 0.5

我们可以测试:

>>> distance(0, 0, 3, 4)
5.0

主要功能

我们现在可以创建主函数,它将实现上面定义的两个函数。

这方面的步骤很简单:

  • 计算两边和线之间的交叉点(False,如果没有)
  • 删除没有交叉点的情况
  • 如果有两个交叉点:
    • 返回它们之间的距离
  • 否则:
    • return False - 表示该行与矩形相交

现在用Python实现这个:

#first 2 points describe the line, last 4 the rectangle
def length_inside(x1, y1, x2, y2, x3, y3, x4, y4, x5, y5, x6, y6):
    intersects = [intersection(x1, y1, x2, y2, x3, y3, x4, y4),
                  intersection(x1, y1, x2, y2, x4, y4, x5, y5),
                  intersection(x1, y1, x2, y2, x5, y5, x6, y6),
                  intersection(x1, y1, x2, y2, x6, y6, x3, y3)]
    intersects = [i for i in intersects if i]
    if len(intersects) == 2:
        return distance(*intersects[0], *intersects[1])
    return False

并测试它:

>>> length_inside(2, 6, 5, 0, 1, 3, 2, 1, 6, 3, 5, 5)
2.23606797749979
>>> length_inside(0, 1, 0, 5, 1, 3, 2, 1, 6, 3, 5, 5)
False

通过情节的帮助可以看出是正确的:

plot2

答案 4 :(得分:0)

您没有排除外部库,所以这里是shapely,专为此类任务而设计。用C语言写成,Numpy array interface

from shapely.geometry import LineString, Polygon

line_list = [(0, 0), (5, 5)] 
rect_list = [(1, 1), (1, 3), (3, 3), (3, 1)]

line_in_rect = Polygon(rect_list).intersection(LineString(line_list))

if line_in_rect:
    print(line_in_rect.length)
else:
    print("no intersection")
但是,如果是矩形,或者重叠只是部分,则不测试。