
.. DO NOT EDIT.
.. THIS FILE WAS AUTOMATICALLY GENERATED BY SPHINX-GALLERY.
.. TO MAKE CHANGES, EDIT THE SOURCE PYTHON FILE:
.. "gallery/event_handling/path_editor.py"
.. LINE NUMBERS ARE GIVEN BELOW.

.. only:: html

    .. meta::
        :keywords: codex

    .. note::
        :class: sphx-glr-download-link-note

        :ref:`Go to the end <sphx_glr_download_gallery_event_handling_path_editor.py>`
        to download the full example code.

.. rst-class:: sphx-glr-example-title

.. _sphx_glr_gallery_event_handling_path_editor.py:


===========
Path editor
===========

Sharing events across GUIs.

This example demonstrates a cross-GUI application using Matplotlib event
handling to interact with and modify objects on the canvas.

.. note::
    This example exercises the interactive capabilities of Matplotlib, and this
    will not appear in the static documentation. Please run this code on your
    machine to see the interactivity.

    You can copy and paste individual parts, or download the entire example
    using the link at the bottom of the page.

.. GENERATED FROM PYTHON SOURCE LINES 19-149



.. image-sg:: /gallery/event_handling/images/sphx_glr_path_editor_001.png
   :alt: drag vertices to update path
   :srcset: /gallery/event_handling/images/sphx_glr_path_editor_001.png, /gallery/event_handling/images/sphx_glr_path_editor_001_2_00x.png 2.00x
   :class: sphx-glr-single-img





.. code-block:: Python


    import matplotlib.pyplot as plt
    import numpy as np

    from matplotlib.backend_bases import MouseButton
    from matplotlib.patches import PathPatch
    from matplotlib.path import Path

    fig, ax = plt.subplots()

    pathdata = [
        (Path.MOVETO, (1.58, -2.57)),
        (Path.CURVE4, (0.35, -1.1)),
        (Path.CURVE4, (-1.75, 2.0)),
        (Path.CURVE4, (0.375, 2.0)),
        (Path.LINETO, (0.85, 1.15)),
        (Path.CURVE4, (2.2, 3.2)),
        (Path.CURVE4, (3, 0.05)),
        (Path.CURVE4, (2.0, -0.5)),
        (Path.CLOSEPOLY, (1.58, -2.57)),
    ]

    codes, verts = zip(*pathdata)
    path = Path(verts, codes)
    patch = PathPatch(
        path, facecolor='green', edgecolor='yellow', alpha=0.5)
    ax.add_patch(patch)


    class PathInteractor:
        """
        A path editor.

        Press 't' to toggle vertex markers on and off.  When vertex markers are on,
        they can be dragged with the mouse.
        """

        showverts = True
        epsilon = 5  # max pixel distance to count as a vertex hit

        def __init__(self, pathpatch):

            self.ax = pathpatch.axes
            canvas = self.ax.figure.canvas
            self.pathpatch = pathpatch
            self.pathpatch.set_animated(True)

            x, y = zip(*self.pathpatch.get_path().vertices)

            self.line, = ax.plot(
                x, y, marker='o', markerfacecolor='r', animated=True)

            self._ind = None  # the active vertex

            canvas.mpl_connect('draw_event', self.on_draw)
            canvas.mpl_connect('button_press_event', self.on_button_press)
            canvas.mpl_connect('key_press_event', self.on_key_press)
            canvas.mpl_connect('button_release_event', self.on_button_release)
            canvas.mpl_connect('motion_notify_event', self.on_mouse_move)
            self.canvas = canvas

        def get_ind_under_point(self, event):
            """
            Return the index of the point closest to the event position or *None*
            if no point is within ``self.epsilon`` to the event position.
            """
            xy = self.pathpatch.get_path().vertices
            xyt = self.pathpatch.get_transform().transform(xy)  # to display coords
            xt, yt = xyt[:, 0], xyt[:, 1]
            d = np.sqrt((xt - event.x)**2 + (yt - event.y)**2)
            ind = d.argmin()
            return ind if d[ind] < self.epsilon else None

        def on_draw(self, event):
            """Callback for draws."""
            self.background = self.canvas.copy_from_bbox(self.ax.bbox)
            self.ax.draw_artist(self.pathpatch)
            self.ax.draw_artist(self.line)

        def on_button_press(self, event):
            """Callback for mouse button presses."""
            if (event.inaxes is None
                    or event.button != MouseButton.LEFT
                    or not self.showverts):
                return
            self._ind = self.get_ind_under_point(event)

        def on_button_release(self, event):
            """Callback for mouse button releases."""
            if (event.button != MouseButton.LEFT
                    or not self.showverts):
                return
            self._ind = None

        def on_key_press(self, event):
            """Callback for key presses."""
            if not event.inaxes:
                return
            if event.key == 't':
                self.showverts = not self.showverts
                self.line.set_visible(self.showverts)
                if not self.showverts:
                    self._ind = None
            self.canvas.draw()

        def on_mouse_move(self, event):
            """Callback for mouse movements."""
            if (self._ind is None
                    or event.inaxes is None
                    or event.button != MouseButton.LEFT
                    or not self.showverts):
                return

            vertices = self.pathpatch.get_path().vertices

            vertices[self._ind] = event.xdata, event.ydata
            self.line.set_data(zip(*vertices))

            self.canvas.restore_region(self.background)
            self.ax.draw_artist(self.pathpatch)
            self.ax.draw_artist(self.line)
            self.canvas.blit(self.ax.bbox)


    interactor = PathInteractor(patch)
    ax.set_title('drag vertices to update path')
    ax.set_xlim(-3, 4)
    ax.set_ylim(-3, 4)

    plt.show()


.. _sphx_glr_download_gallery_event_handling_path_editor.py:

.. only:: html

  .. container:: sphx-glr-footer sphx-glr-footer-example

    .. container:: sphx-glr-download sphx-glr-download-jupyter

      :download:`Download Jupyter notebook: path_editor.ipynb <path_editor.ipynb>`

    .. container:: sphx-glr-download sphx-glr-download-python

      :download:`Download Python source code: path_editor.py <path_editor.py>`

    .. container:: sphx-glr-download sphx-glr-download-zip

      :download:`Download zipped: path_editor.zip <path_editor.zip>`


.. only:: html

 .. rst-class:: sphx-glr-signature

    `Gallery generated by Sphinx-Gallery <https://sphinx-gallery.github.io>`_
