矩形之间的曼哈顿距离

时间:2016-11-10 08:30:02

标签: python distance rectangles

我有一组矩形,我需要计算它们之间的manhatten距离。我已经尝试过实现它,但代码爆炸并且效果不佳。

也许有人可以帮助我使用一些智能(和高效)公式来计算两个矩形之间的距离?

示例:

enter image description here

AB之间的距离是行1的长度。 AC之间的距离是行2的长度。等

我使用python来实现一切。如果已经存在一个函数(例如scipy)并且有人知道它,那么这也很棒。

谢谢

2 个答案:

答案 0 :(得分:3)

我建议你使用矩形和矩形宽度的中心点来计算距离。您主要必须弄清楚用于计算的矩形的哪些角(边)。其他一切都很简单。一个简单的例子:

class Rect:
    def __init__(self,cpt,w,h):
        self.x = cpt[0]
        self.y = cpt[1]
        self.w = w
        self.h = h

    def dist(self,other):
        #overlaps in x or y:
        if abs(self.x - other.x) <= (self.w + other.w):
            dx = 0;
        else:
            dx = abs(self.x - other.x) - (self.w + other.w)
        #
        if abs(self.y - other.y) <= (self.h + other.h):
            dy = 0;
        else:
            dy = abs(self.y - other.y) - (self.h + other.h)
        return dx + dy

#example:
A = Rect((0,0),2,1)
B = Rect((4,5),1,2)
C = Rect((-1,-5),1,1)

print(A.dist(C))
print(A.dist(B))
print(B.dist(C))

答案 1 :(得分:0)

@LynxLike的解决方案似乎无效,因此我发布了另一个解决方案。本文结尾处的测试用例是简化的分段距离,每种情况的答案都很明显,而先前的解决方案却有些失败。

通常,虽然问题看起来很复杂,但是您可以通过将问题分为x段和y段并通过对两个轴使用相同的算法分别进行计算来简化问题。解决方案应同时适用于矩形和线段。

对于dx,您计算右矩形(或线段)的x坐标是否大于左矩形的x坐标和宽度之和。如果是肯定的,那就意味着有一段距离。否则,它要么是触摸,重叠(沿x轴),要么是rect的相对位置被翻转。基本上,除非矩形距离一定,否则您将得到0或负值结果,您可以使用max函数轻松将其裁剪为0。您无需检查哪一面是哪一面。您可以再次使用max()来同时检查这两种情况。

# assuming other is on the right
d_case1 = max(other.x - (self.x+self.w), 0)
# assuming self is on the right
d_case2 = max(self.x - (other.x+other.w), 0)
# checking if any distance has positive
dx = max(d_case1, d_case2)

这是一个完整的解决方案。我使用@LynxLike的Rect类,因为它很简洁!谢谢!

class Rect:
    def __init__(self, cpt, w, h):
        self.x = cpt[0]
        self.y = cpt[1]
        self.w = w
        self.h = h

    def dist(self, other):
        dx = max(max(other.x - (self.x+self.w), 0),
                 max(self.x - (other.x+other.w), 0))
        dy = max(max(other.y - (self.y+self.h), 0),
                 max(self.y - (other.y+other.h), 0))
        return dx + dy

# Case1: 1 distance apart
A = Rect((1,0),3,0)  #| ---
B = Rect((5,0),3,0)  #|     ---
assert A.dist(B) == 1
assert B.dist(A) == 1

# Case2: touching
A = Rect((1,0),4,0)  #| ----
B = Rect((5,0),3,0)  #|     ---
assert A.dist(B) == 0
assert B.dist(A) == 0

# Case3: intersects
A = Rect((1,0),5,0)  #| -----
B = Rect((5,0),3,0)  #|     ---
assert A.dist(B) == 0
assert B.dist(A) == 0

# Case4: 1 distance apart in negative domain
A = Rect((-1,0),3,0)  #      -|-- 
B = Rect((-5,0),3,0)  #  ---
assert A.dist(B) == 1
assert B.dist(A) == 1