python-rectangles icon indicating copy to clipboard operation
python-rectangles copied to clipboard

Incorrect distance_to_rect

Open Jip-Hop opened this issue 8 years ago • 0 comments

I've made another implementation of distance_to_rect based on a few StackOverflow answers and our outcomes coincide sometimes, but not always. This image below is made from these two rectangles:

(8.908981945487593, 31.168620023667902, 9.96352669616626, 4.934035502617441)
(13.395327701789306, 7.479377139686417, 1.2312990956716174, 7.478459519903835)
schermafbeelding 2017-05-22 om 12 12 58 The distance between them is 16.21 as you can see in the image. This is also the result of my distance function, but yours outputs 18.76.
Discrepancy
(8.908981945487593, 31.168620023667902, 9.96352669616626, 4.934035502617441)
(13.395327701789306, 7.479377139686417, 1.2312990956716174, 7.478459519903835)
('myDist', 16.21078336407765)
('yourDist', 18.755207381364034)

You said in #2 you never managed to find a list of pre-computed distances. Perhaps you could use this test script I've made to check against and find an error in your code. Having our implementations checked would benefit me too :)

# https://codereview.stackexchange.com/questions/31352/overlapping-rectangles
# http://stackoverflow.com/questions/10347085/distance-between-two-rectangles
# http://stackoverflow.com/questions/40523022/manhatten-distance-between-rectangles

import random
from geometry import *

class MyRect:
    def __init__(self,x,y,width,height):
        self.x = x
        self.y = y
        self.width = width
        self.height = height

def overlap(r1, r2):
    #Overlapping rectangles overlap both horizontally & vertically
    return range_overlap(r1.x, r1.x + r1.width, r2.x, r2.x + r2.width) and range_overlap(r1.y + r1.height, r1.y, r2.y + r2.height, r2.y)

def range_overlap(a_min, a_max, b_min, b_max):
    #Neither range is completely greater than the other
    return (a_min <= b_max) and (b_min <= a_max)

def distance_between_rectangles(rect1, rect2):
    if (overlap(rect1, rect2)):
        return 0
    
    mostLeft =  rect1 if rect1.x < rect2.x else rect2
    mostRight = rect1 if rect2.x < rect1.x else rect2

    xDifference = 0 if mostLeft.x == mostRight.x else mostRight.x - (mostLeft.x + mostLeft.width)
    xDifference = max(0, xDifference)

    upper = rect1 if rect1.y < rect2.y else rect2
    lower = rect1 if rect2.y < rect1.y else rect2

    yDifference = 0 if upper.y == lower.y else lower.y - (upper.y + upper.height)
    yDifference = max(0, yDifference)

    return sqrt(xDifference**2 + yDifference**2)

Ax = random.uniform(0, 100)
Ay = random.uniform(0, 100)
Aw = random.uniform(0, 10)
Ah = random.uniform(0, 10)

Bx = random.uniform(0, 100)
By = random.uniform(0, 100)
Bw = random.uniform(0, 10)
Bh = random.uniform(0, 10)

myDist = distance_between_rectangles(MyRect(Ax, Ay, Aw, Ah), MyRect(Bx, By, Bw, Bh))
yourDist = Rect(Ax, Ay, Aw, Ah).distance_to_rect(Rect(Bx, By, Bw, Ah))

if(myDist != yourDist):
    print("Discrepancy")
else:
    print("Same")

print(Ax, Ay, Aw, Ah)
print(Bx, By, Bw, Bh)
print("myDist", myDist)
print("yourDist", yourDist)

Jip-Hop avatar May 22 '17 10:05 Jip-Hop