我有一组矩形,我需要计算它们之间的manhatten距离。我已经尝试过实现它,但代码爆炸并且效果不佳。
也许有人可以帮助我使用一些智能(和高效)公式来计算两个矩形之间的距离?
示例:
A
和B
之间的距离是行1
的长度。 A
和C
之间的距离是行2
的长度。等
我使用python来实现一切。如果已经存在一个函数(例如scipy)并且有人知道它,那么这也很棒。
谢谢
答案 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