Esempio n. 1
0
class LassoSelection(PolygonToolBase):

    def __init__(self, ax, on_move=None, on_release=None, on_enter=None,
                     useblit=True, line_props=None):
        super(LassoSelection, self).__init__(ax, on_move=on_move,
                                            on_release=on_release,
                                                on_enter=on_enter,
                                                useblit=useblit,
                                                line_props=line_props)
        self.shape = 'lasso'
        self.mode = 'lasso'
        self._prev_angle = 1e6
        self._indicator = Rectangle((0, 0), 0, 0)
        self._indicator.set_visible(False)
        ax.add_patch(self._indicator)
        self._artists.append(self._indicator)

    def on_move(self, event):
        if self.verts is None or not self._busy:
            return
        if self.mode == 'polygon':
            self.verts[-1] = (event.xdata, event.ydata)
        else:
            # see if we are moving in the same direction
            point2 = (event.xdata, event.ydata)
            point1 = np.asarray(self.verts[-1], dtype=float)
            point2 = np.asarray(point2, dtype=float)
            dx, dy = point2 - point1
            theta = np.arctan2(dy, dx)
            if theta == self._prev_angle:
                self.verts[-1] = (event.xdata, event.ydata)
            else:
                self.verts.append((event.xdata, event.ydata))
            self._prev_angle = theta
        try:
            self._show_indicator()
        except TypeError:
            pass
        self.update()

    def on_mouse_release(self, event):
        self.mode = 'polygon'

    def on_mouse_press(self, event):
        if self._indicator.get_visible() or event.dblclick:
            self.verts = self.verts[:-1]
            self.finalize()
            return
        if not self._busy:
            self.start(event)
        self.mode = 'lasso'
        self.verts.append((event.xdata, event.ydata))
        self.update()

    def start(self, event):
        super(LassoSelection, self).start(event)
        self._prev_angle = 1e6

    def finalize(self):
        self.verts.append(self.verts[0])
        self._indicator.set_visible(False)
        super(LassoSelection, self).finalize()

    def _show_indicator(self):
        if not self.verts:
            return
        bounds = self.ax.dataLim.bounds
        wid = float(bounds[2] - bounds[0])
        hgt = float(bounds[3] - bounds[1])
        orig = self.verts[0]
        curr = self.verts[-1]
        # see if we are within 2% in x and y
        if (abs(curr[0] - orig[0]) / wid < 0.02 and
            abs(curr[1] - orig[1]) / hgt < 0.02):
                wid /= 100.
                hgt /= 100.
                self._indicator.set_xy((orig[0] - wid / 2.,
                                              orig[1] - hgt / 2.))
                self._indicator.set_width(wid * 2)
                self._indicator.set_height(hgt * 2)
                if not self._indicator.get_visible():
                    self._indicator.set_visible(True)
                    self.redraw()
        elif self._indicator.get_visible():
            self._indicator.set_visible(False)
            self.redraw()

    @property
    def geometry(self):
        return self.verts

    @geometry.setter
    def geometry(self, verts):
        self.verts = verts
        self.update()