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

Python 如何测量直线和矩形之间的重叠?,python,math,Python,Math,我试图测量线段和矩形之间的重叠。例如,线段表示为2个点: 行=[x1,y1,x2,y2] 和一个矩形作为4个点: rect=[x3,y3,x4,y4,x5,y5,x6,y6] 是否有一种有效的方法来测量两者之间的重叠长度(如果有) 下面是一个简单的图表: 编辑:只是澄清一下,线段可能部分与矩形相交,甚至根本不相交 我只复习了数学部分,没有编码 找到交点upperx,uppery lowerx,lowery 找到从上点到右上角的距离 找到从下点到右上角的距离 A=从一个减去另一个的距离 B=找到从

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

行=[x1,y1,x2,y2]

和一个矩形作为4个点:

rect=[x3,y3,x4,y4,x5,y5,x6,y6]

是否有一种有效的方法来测量两者之间的重叠长度(如果有)

下面是一个简单的图表:


编辑:只是澄清一下,线段可能部分与矩形相交,甚至根本不相交

我只复习了数学部分,没有编码

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

现在公式A^2+B^2=c^2有了A和B


享受

我只复习了数学部分,没有编码

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

现在公式A^2+B^2=c^2有了A和B

欣赏图片中的

我们有

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))
在哪里

那么d可以计算为

d := h/sin(α) = h/(sqrt(1-squared(cos(α)))
从照片上看

我们有

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))
在哪里

那么d可以计算为

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

查找仿射变换以使矩形轴对齐。这只是角度的旋转

fi = -atan2(y4-y3, x4-x3)
使用此旋转矩阵变换线段端点坐标和一些矩形坐标

 x' = x * Cos(fi) - y * Sin(fi)
 y' = x * Sin(fi) + y * Cos(fi)
请注意,现在只需要两个x坐标和两个y坐标来表示左=x3',右=x4',下=y3',上=y6'

应用任何l

我推荐梁巴斯基一号。 计算后,得到剪辑点之间的距离或矩形内的线段端点之间的距离
当无限直线与矩形相交且结果参数t0和/或t1超出0..1范围时,查找仿射变换以使矩形轴对齐。这只是角度的旋转

fi = -atan2(y4-y3, x4-x3)
使用此旋转矩阵变换线段端点坐标和一些矩形坐标

 x' = x * Cos(fi) - y * Sin(fi)
 y' = x * Sin(fi) + y * Cos(fi)
请注意,现在只需要两个x坐标和两个y坐标来表示左=x3',右=x4',下=y3',上=y6'

应用任何l

我推荐梁巴斯基一号。 计算后,得到剪辑点之间的距离或矩形内的线段端点之间的距离
当无限直线与矩形相交且结果参数t0和/或t1超出0..1范围时,我将此答案分为三部分:

计算交点的坐标 创建函数以计算两点之间的距离 把它和矩形放在一起 我还将使用可视化的例子

十字路口 这为我们提供了一个公式,用于计算由坐标描述的两条直线之间交点的坐标:

坐标为:x1,y1,x2,y2,x3,y3和x4,y4

如果它们不相交,则分母:

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

因此,使用这个公式,我们可以创建一个函数,它将返回两条直线之间的交点,或者错误地表示它们不相交:

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绘图将其可视化:

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

a^2 + b^2 = c^2
与前面一样,让我们将其放入一个helper函数中:

def distance(x1, y1, x2, y2):
    return ((x2-x1)**2 + (y2-y1)**2) ** 0.5
我们可以测试:

>>> distance(0, 0, 3, 4)
5.0
主要功能 现在我们可以创建main函数,它将实现上面定义的两个函数

这方面的步骤很简单:

如果每条边和直线之间没有交点,则计算交点为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
通过绘图可以看出这是正确的:


我把这个答案分为三个部分:

计算交点的坐标 创建函数以计算两点之间的距离 把它和矩形放在一起 我还将使用可视化的例子

十字路口 这为我们提供了一个公式,用于计算由坐标描述的两条直线之间交点的坐标:

坐标为:x1,y1,x2,y2,x3,y3和x4,y4

如果它们不相交,则分母:

将是0

因此,使用这个公式,我们可以创建一个函数,它将返回两条直线之间的交点,或者错误地表示它们不相交:

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绘图将其可视化:

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

a^2 + b^2 = c^2
与前面一样,让我们将其放入一个helper函数中:

def distance(x1, y1, x2, y2):
    return ((x2-x1)**2 + (y2-y1)**2) ** 0.5
我们可以测试:

>>> distance(0, 0, 3, 4)
5.0
主要功能 现在我们可以创建main函数,它将实现上面定义的两个函数

这方面的步骤很简单:

如果每条边和直线之间没有交点,则计算交点为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
通过绘图可以看出这是正确的:


您没有排除外部库,因此这里是为此类任务设计的。用C写的,有一个


但是,不测试它是否是矩形,或者重叠是否只是部分重叠

您没有排除外部库,因此这里是为此类任务设计的。用C写的,有一个



但是,不测试它是否是矩形,或者重叠是否只是部分重叠

sqrtsquareda,squaredb看起来有点奇怪。sqrt是R→ R或C→ Python的标准数学/cmath库中的C。@9000谢谢!我已经修正了打字错误。使用毕达哥拉斯定理定义dist也很好。@9000当然。为了完整性,我也添加了dotProduct的定义。有一些交叉情况-您只考虑了一个。sqrtsquareda,squaredb看起来有点奇怪。sqrt是R→ R或C→ Python的标准数学/cmath库中的C。@9000谢谢!我已经修正了打字错误。使用毕达哥拉斯定理定义dist也很好。@9000当然。为了完整性,我也添加了dotProduct的定义。有一些交叉点的情况-你只考虑了一个。我会扩展一点。寻找直线和矩形每边之间的交点与直线相交,拾取位于线段内的点。您可以得到0、1或2个不同的点;对于2,毕达哥拉斯公式给出了距离。通过使用上面的公式,我只使用了一个直角三角形。由于90度角,我把毕达哥拉斯公式简化为a^2+b^2=c^2。否则,就不必担心角度了。我会延伸一点。寻找直线和矩形每边之间的交点与直线相交,拾取位于线段内的点。您可以得到0、1或2个不同的点;对于2,毕达哥拉斯公式给出了距离。通过使用上面的公式,我只使用了一个直角三角形。由于90度角,我把毕达哥拉斯公式简化为a^2+b^2=c^2。否则,就不必担心角度了。@usr2564301不,不能保证交叉点的存在。@KlausD。我目前的方法是推导直线段和矩形的方程并求解它们。但它在计算上相当昂贵,我的直觉是应该有更好的方法。@usr2564301谢谢。我希望通过“如果有的话”可以说明交叉口是没有保证的。我现在已经说得很清楚了。@usr2564301不,不能保证交叉口的存在。@KlausD。我目前的方法是推导直线段和矩形的方程并求解它们。但它在计算上相当昂贵,我的直觉是应该有更好的方法。@usr2564301谢谢。我希望通过“如果有的话”可以说明交叉口是没有保证的。我现在已经说得很清楚了。我不认为线裁剪允许部分重叠/相交。@当然,线裁剪允许部分重叠-经典用法是在矩形窗口内绘制线段的一部分。我对答案进行了一点扩展。我不认为线裁剪允许部分重叠/交叉。@Kar当然,线裁剪允许部分重叠-经典用法是在矩形窗口内绘制线段的一部分。我把答案扩大了一点。