Skip to content

Commit

Permalink
Support rotation of Ellipse,RectanglePixelRegion MPL selectors
Browse files Browse the repository at this point in the history
  • Loading branch information
dhomeier committed Jul 29, 2021
1 parent 5055128 commit 142f080
Show file tree
Hide file tree
Showing 2 changed files with 55 additions and 30 deletions.
42 changes: 27 additions & 15 deletions regions/shapes/ellipse.py
Original file line number Diff line number Diff line change
Expand Up @@ -209,13 +209,22 @@ def as_artist(self, origin=(0, 0), **kwargs):
**mpl_kwargs)

def _update_from_mpl_selector(self, *args, **kwargs):
xmin, xmax, ymin, ymax = self._mpl_selector.extents
self.center = PixCoord(x=0.5 * (xmin + xmax),
y=0.5 * (ymin + ymax))
self.width = (xmax - xmin)
self.height = (ymax - ymin)
self.angle = 0. * u.deg
if self._mpl_selector_callback is not None:
# _rect_properties replace _rect_bbox in matplotlib#19864
# "Note that if rotation != 0, ``xmin, ymin`` are interpreted as the
# lower corner, and ``xmax, ymax`` are calculated using only width and
# height assuming no rotation."

self.center = PixCoord(*self._mpl_selector.center)
if hasattr(self._mpl_selector, '_rotation'):
x0, y0, self.width, self.height, rotation = self._mpl_selector._rect_properties
else:
xmin, xmax, ymin, ymax = self._mpl_selector.extents
self.width = 2 * (self.center.x - xmin)
self.height = 2 * (self.center.y - ymin)
rotation = 0
self.angle = rotation * u.radian

if getattr(self, '_mpl_selector_callback', None) is not None:
self._mpl_selector_callback(self)

def as_mpl_selector(self, ax, active=True, sync=True, callback=None,
Expand Down Expand Up @@ -262,10 +271,6 @@ def as_mpl_selector(self, ax, active=True, sync=True, callback=None,
raise Exception('Cannot attach more than one selector to a '
'region.')

if self.angle.value != 0:
raise NotImplementedError('Cannot create matplotlib selector for '
'rotated ellipse.')

if sync:
sync_callback = self._update_from_mpl_selector
else:
Expand All @@ -279,10 +284,17 @@ def sync_callback(*args, **kwargs):
'linewidth': self.visual.get('linewidth', 1),
'linestyle': self.visual.get('linestyle', 'solid')})

self._mpl_selector.extents = (self.center.x - self.width / 2,
self.center.x + self.width / 2,
self.center.y - self.height / 2,
self.center.y + self.height / 2)
xy0 = [self.center.x - self.width / 2, self.center.y - self.height / 2]
self._mpl_selector.extents = (xy0[0], self.center.x + self.width / 2,
xy0[1], self.center.y + self.height / 2)

if self.angle.value != 0:
if hasattr(self._mpl_selector, '_rotation'):
self._mpl_selector._set_corner_width_rotation(xy0, self.width, self.height,
self.angle.to_value('radian'))
else:
raise NotImplementedError('Cannot create matplotlib selector for rotated ellipse.')

self._mpl_selector.set_active(active)
self._mpl_selector_callback = callback

Expand Down
43 changes: 28 additions & 15 deletions regions/shapes/rectangle.py
Original file line number Diff line number Diff line change
Expand Up @@ -202,13 +202,22 @@ def as_artist(self, origin=(0, 0), **kwargs):
angle=angle, **mpl_kwargs)

def _update_from_mpl_selector(self, *args, **kwargs):
xmin, xmax, ymin, ymax = self._mpl_selector.extents
self.center = PixCoord(x=0.5 * (xmin + xmax),
y=0.5 * (ymin + ymax))
self.width = (xmax - xmin)
self.height = (ymax - ymin)
self.angle = 0. * u.deg
if self._mpl_selector_callback is not None:
# _rect_properties replace _rect_bbox in matplotlib#19864
# "Note that if rotation != 0, ``xmin, ymin`` are interpreted as the
# lower corner, and ``xmax, ymax`` are calculated using only width and
# height assuming no rotation."

self.center = PixCoord(*self._mpl_selector.center)
if hasattr(self._mpl_selector, '_rotation'):
x0, y0, self.width, self.height, rotation = self._mpl_selector._rect_properties
else:
xmin, xmax, ymin, ymax = self._mpl_selector.extents
self.width = 2 * (self.center.x - xmin)
self.height = 2 * (self.center.y - ymin)
rotation = 0
self.angle = rotation * u.radian

if getattr(self, '_mpl_selector_callback', None) is not None:
self._mpl_selector_callback(self)

def as_mpl_selector(self, ax, active=True, sync=True, callback=None,
Expand Down Expand Up @@ -255,10 +264,6 @@ def as_mpl_selector(self, ax, active=True, sync=True, callback=None,
raise Exception('Cannot attach more than one selector to a '
'region.')

if self.angle.value != 0:
raise NotImplementedError('Cannot create matplotlib selector for '
'rotated rectangle.')

if sync:
sync_callback = self._update_from_mpl_selector
else:
Expand All @@ -272,10 +277,18 @@ def sync_callback(*args, **kwargs):
'linewidth': self.visual.get('linewidth', 1),
'linestyle': self.visual.get('linestyle', 'solid')})

self._mpl_selector.extents = (self.center.x - self.width / 2,
self.center.x + self.width / 2,
self.center.y - self.height / 2,
self.center.y + self.height / 2)
xy0 = [self.center.x - self.width / 2, self.center.y - self.height / 2]
self._mpl_selector.extents = (xy0[0], self.center.x + self.width / 2,
xy0[1], self.center.y + self.height / 2)

if self.angle.value != 0:
if hasattr(self._mpl_selector, '_rotation'):
self._mpl_selector._set_corner_width_rotation(xy0, self.width, self.height,
self.angle.to_value('radian'))
else:
raise NotImplementedError('Cannot create matplotlib selector for rotated '
'rectangle.')

self._mpl_selector.set_active(active)
self._mpl_selector_callback = callback

Expand Down

0 comments on commit 142f080

Please sign in to comment.