mre
mre

Reputation: 1873

Intersecting rectangles with Python

Given two rectangles r1 and r2 I try to test if the two intersect. Why don't the following two functions produce the same output?

Function 1:

def separate_helper(r1, r2):
  r1_left, r1_top, r1_right, r1_bottom = r1
  r2_left, r2_top, r2_right, r2_bottom = r2

  if r1_right < r2_left:
    separate = True
  elif    r1_left > r2_right:
    separate = True
  elif r1_top > r2_bottom:
    separate = True
  elif r1_bottom < r2_top:
    separate = True
  elif contains(r1, r2):
    separate = False
  else:
    separate = False
  return separate

Function 2:

def separate_helper2(r1, r2):
  r1_left, r1_top, r1_right, r1_bottom = r1
  r2_left, r2_top, r2_right, r2_bottom = r2

  separate = r1_right < r2_left or \
    r1_left > r2_right or \
    r1_top > r2_bottom or \
    r1_bottom < r2_top or \
    not contains(r1, r2)
  return separate

Function to check if rectangle 1 contains rectangle 2:

def contains(r1, r2):
  r1_left, r1_top, r1_right, r1_bottom = r1
  r2_left, r2_top, r2_right, r2_bottom = r2
  return r1_right >= r2_right and  r1_left <= r2_left and  r1_top <= r2_top and  r1_bottom >= r2_bottom

Here's a test case that fails:

assert separate_helper([29, 35, 53, 90], [23, 47, 90, 86]) == separate_helper2([29, 35, 53, 90], [23, 47, 90, 86])

It only fails when rectangle 1 contains rectangle 2, but I can't wrap my head around why.

Edit:

I'm using quickcheck for Python and nose to test the function. Here's the test code I'm using:

from qc import forall, lists, integers
from intersect import separate_helper, separate_helper2

@forall(tries=100, r1=lists(items=integers(), size=(4, 4)), r2=lists(items=integers(), size=(4, 4)))
def test_separate(r1, r2):
  assert separate_helper(r1, r2) == separate_helper2(r1, r2)

Upvotes: 2

Views: 2897

Answers (1)

abarnert
abarnert

Reputation: 365737

Look at your first version:

elif contains(r1, r2):
  separate = False
else:
  separate = False

Assuming you get through all of the proper-intersection cases, this will return False whether r1 contains r2 or not.

But in your second version:

... or \
not contains(r1, r2)

This will return False is r1 does not contain r2, but True otherwise.

So, they're doing different things in precisely the case "when rectangle 1 contains rectangle 2".

As a side question: why should r1 containing r2 return a different result from r2 containing r1?

Upvotes: 3

Related Questions