Skip to content

Commit

Permalink
Merge pull request #277 from larrybradley/bbox
Browse files Browse the repository at this point in the history
Add BoundingBox union and intersection
  • Loading branch information
cdeil committed Jun 12, 2019
2 parents d6520fb + cacd9ad commit 54aac61
Show file tree
Hide file tree
Showing 3 changed files with 98 additions and 1 deletion.
7 changes: 6 additions & 1 deletion CHANGES.rst
Original file line number Diff line number Diff line change
@@ -1,7 +1,12 @@
0.4 (Unreleased)
================

- No changes yet.
New Features
------------

- Added ``union`` and ``intersection`` methods to the ``BoundingBox``
class. [#277]


0.3 (2018-09-09)
================
Expand Down
64 changes: 64 additions & 0 deletions regions/core/bounding_box.py
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,12 @@ def __eq__(self, other):
(self.iymax == other.iymax)
)

def __or__(self, other):
return self.union(other)

def __and__(self, other):
return self.intersection(other)

def __repr__(self):
data = self.__dict__
data['name'] = self.__class__.__name__
Expand Down Expand Up @@ -255,3 +261,61 @@ def plot(self, origin=(0, 0), ax=None, **kwargs):

reg = self.to_region()
return reg.plot(origin=origin, ax=ax, **kwargs)

def union(self, other):
"""
Return a `BoundingBox` representing the union of this
`BoundingBox` with another `BoundingBox`.
Parameters
----------
other : `~photutils.BoundingBox`
The `BoundingBox` to join with this one.
Returns
-------
result : `~photutils.BoundingBox`
A `BoundingBox` representing the union of the input
`BoundingBox` with this one.
"""

if not isinstance(other, BoundingBox):
raise TypeError('BoundingBox can be joined only with another '
'BoundingBox.')

ixmin = min((self.ixmin, other.ixmin))
ixmax = max((self.ixmax, other.ixmax))
iymin = min((self.iymin, other.iymin))
iymax = max((self.iymax, other.iymax))

return BoundingBox(ixmin=ixmin, ixmax=ixmax, iymin=iymin, iymax=iymax)

def intersection(self, other):
"""
Return a `BoundingBox` representing the intersection of this
`BoundingBox` with another `BoundingBox`.
Parameters
----------
other : `~photutils.BoundingBox`
The `BoundingBox` to intersect with this one.
Returns
-------
result : `~photutils.BoundingBox`
A `BoundingBox` representing the intersection of the input
`BoundingBox` with this one.
"""

if not isinstance(other, BoundingBox):
raise TypeError('BoundingBox can be intersected only with '
'another BoundingBox.')

ixmin = max(self.ixmin, other.ixmin)
ixmax = min(self.ixmax, other.ixmax)
iymin = max(self.iymin, other.iymin)
iymax = min(self.iymax, other.iymax)
if ixmax < ixmin or iymax < iymin:
return None

return BoundingBox(ixmin=ixmin, ixmax=ixmax, iymin=iymin, iymax=iymax)
28 changes: 28 additions & 0 deletions regions/core/tests/test_bounding_box.py
Original file line number Diff line number Diff line change
Expand Up @@ -99,3 +99,31 @@ def test_bounding_box_as_artist():
assert_allclose(patch.get_xy(), (0.5, 1.5))
assert_allclose(patch.get_width(), 9)
assert_allclose(patch.get_height(), 18)

def test_bounding_box_union():
bbox1 = BoundingBox(1, 10, 2, 20)
bbox2 = BoundingBox(5, 21, 7, 32)
bbox_union_expected = BoundingBox(1, 21, 2, 32)
bbox_union1 = bbox1 | bbox2
bbox_union2 = bbox1.union(bbox2)

assert bbox_union1 == bbox_union_expected
assert bbox_union1 == bbox_union2

with pytest.raises(TypeError):
bbox1.union((5, 21, 7, 32))

def test_bounding_box_intersect():
bbox1 = BoundingBox(1, 10, 2, 20)
bbox2 = BoundingBox(5, 21, 7, 32)
bbox_intersect_expected = BoundingBox(5, 10, 7, 20)
bbox_intersect1 = bbox1 & bbox2
bbox_intersect2 = bbox1.intersection(bbox2)

assert bbox_intersect1 == bbox_intersect_expected
assert bbox_intersect1 == bbox_intersect2

with pytest.raises(TypeError):
bbox1.intersection((5, 21, 7, 32))

assert bbox1.intersection(BoundingBox(30, 40, 50, 60)) is None

0 comments on commit 54aac61

Please sign in to comment.