{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "#### **Title**: PolyDraw\n", "\n", "**Description**: A linked streams example demonstrating how to use the PolyDraw stream.\n", "\n", "**Dependencies**: Bokeh\n", "\n", "**Backends**: [Bokeh](./PolyDraw.ipynb)" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "import holoviews as hv\n", "from holoviews import opts, streams\n", "\n", "hv.extension('bokeh')" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The ``PolyDraw`` stream adds a bokeh tool to the source plot, which allows drawing, dragging and deleting polygons and making the drawn data available to Python. The tool supports the following actions:\n", "\n", "::::{tab-set}\n", ":::{tab-item} Actions with Bokeh 3.4 and later\n", "**Add patch/multi-line**\n", " \n", " Click and hold for 300 ms to add the first vertex, then use tap and hold to add each subsequent vertex, \n", " to finalize the draw action double tap to insert the final vertex or press the ESC key to stop drawing.\n", "\n", "**Move patch/multi-line**\n", "\n", " Tap and drag an existing patch/multi-line; the point will be dropped once you let go of the mouse button.\n", "\n", "**Delete patch/multi-line**\n", "\n", " Tap a patch/multi-line to select it then press BACKSPACE key while the mouse is within the plot area.\n", ":::\n", "\n", ":::{tab-item} Actions before Bokeh 3.4\n", "**Add patch/multi-line**\n", "\n", " Double tap to add the first vertex, then use tap to add each subsequent vertex, \n", " to finalize the draw action double tap to insert the final vertex or press the ESC key to stop drawing.\n", "\n", "**Move patch/multi-line**\n", "\n", " Tap and drag an existing patch/multi-line; the point will be dropped once you let go of the mouse button.\n", "\n", "**Delete patch/multi-line**\n", "\n", " Tap a patch/multi-line to select it then press BACKSPACE key while the mouse is within the plot area.\n", ":::\n", "::::\n", "\n", "\n", "\n", "### Properties\n", "\n", "* **``drag``** (boolean): Whether to enable dragging of paths and polygons\n", "* **``empty_value``**: Value to add to non-coordinate columns when adding new path or polygon\n", "* **``num_objects``** (int): Maximum number of paths or polygons to draw before deleting the oldest object\n", "* **``show_vertices``** (boolean): Whether to show the vertices of the paths or polygons\n", "* **``styles``** (dict): Dictionary of style properties (e.g. line_color, line_width etc.) to apply to each path and polygon. If values are lists the values will cycle over the values) \n", "* **``vertex_style``** (dict): Dictionary of style properties (e.g. fill_color, line_width etc.) to apply to vertices if ``show_vertices`` enabled" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "As a simple example we will create simple ``Path`` and ``Polygons`` elements and attach each to a ``PolyDraw`` stream. We will also enable the ``drag`` option on the stream to enable dragging of existing glyphs. Additionally we can enable the ``show_vertices`` option which shows the vertices of the drawn polygons/lines and adds the ability to snap to them. Finally the ``num_objects`` option limits the number of lines/polygons that can be drawn by dropping the first glyph when the limit is exceeded. " ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "path = hv.Path([[(1, 5), (9, 5)]])\n", "poly = hv.Polygons([[(2, 2), (5, 8), (8, 2)]])\n", "path_stream = streams.PolyDraw(source=path, drag=True, show_vertices=True)\n", "poly_stream = streams.PolyDraw(source=poly, drag=True, num_objects=4,\n", " show_vertices=True, styles={\n", " 'fill_color': ['red', 'green', 'blue']\n", " })\n", "\n", "(path * poly).opts(\n", " opts.Path(color='red', height=400, line_width=5, width=400),\n", " opts.Polygons(fill_alpha=0.3, active_tools=['poly_draw']))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "
" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Whenever the data source is edited the data is synced with Python, both in the notebook and when deployed on the bokeh server. The data is made available as a dictionary of columns:" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "path_stream.data" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Alternatively we can use the ``element`` property to get an Element containing the returned data:" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "path_stream.element * poly_stream.element" ] } ], "metadata": { "language_info": { "name": "python", "pygments_lexer": "ipython3" } }, "nbformat": 4, "nbformat_minor": 4 }