{ "cells": [ { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "%gui qt" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "\n# Picking Markers\n\nDemonstrates how to identify (pick) markers. Hover markers to change their\nsymbol and color.\n\nControls:\n* p - Toggle picking view - shows the colors encoding marker ID\n* r - Reset marker symbols and colors\n" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "import random\nimport time\nimport numpy as np\nfrom scipy.constants import golden as GOLDEN\n\nfrom vispy import app, scene\nfrom vispy.scene.visuals import Markers\nfrom vispy.visuals.filters import MarkerPickingFilter\n\ncanvas = scene.SceneCanvas(keys='interactive', bgcolor='black')\nview = canvas.central_widget.add_view(camera=\"panzoom\")\nview.camera.rect = (-1, -1, 2, 2)\n\n# floret pattern\nn = 10_000\nradius = np.linspace(0, 0.9, n)**0.6 # prevent extreme density at center\ntheta = np.arange(n) * GOLDEN\npos = np.column_stack([radius * np.cos(theta), radius * np.sin(theta)])\n\nCOLORS = [\n (1, 0, 0, 1), # red\n (1, 0.5, 0, 1), # orange\n (1, 1, 0, 1), # yellow\n (0, 1, 0, 1), # green\n (0, 0, 1, 1), # blue\n (0.29, 0, 0.51, 1), # indigo\n (0.93, 0.51, 0.93, 1), # violet\n]\n\ncolors = np.zeros((n, 4), dtype=np.float32)\ncolors[:, 0] = 1 # red\ncolors[:, -1] = 1 # alpha\n_colors = colors.copy()\n\nsymbols = list(Markers._symbol_shader_values.keys())\nsymbols_ring = dict(zip(symbols, symbols[1:]))\nsymbols_ring[symbols[-1]] = symbols[0]\n\nEDGE_COLOR = \"white\"\nMARKER_SIZE = 0.0125\nEDGE_WDITH = MARKER_SIZE / 10\n\nmarkers = Markers(\n pos=pos,\n edge_color=EDGE_COLOR,\n face_color=colors,\n size=MARKER_SIZE,\n edge_width=EDGE_WDITH,\n scaling=\"scene\",\n)\nmarkers.update_gl_state(depth_test=True)\nview.add(markers)\n\n# Use filters to affect the rendering of the mesh.\npicking_filter = MarkerPickingFilter()\nmarkers.attach(picking_filter)\n\n\n@view.events.connect\ndef on_viewbox_change(event):\n # workaround for vispy/#2501\n markers.update_gl_state(blend=not picking_filter.enabled)\n\n\nthrottle = time.monotonic()\n\n\n@canvas.events.mouse_move.connect\ndef on_mouse_move(event):\n global throttle\n # throttle mouse events to 50ms\n if time.monotonic() - throttle < 0.05:\n return\n throttle = time.monotonic()\n\n # adjust the event position for hidpi screens\n render_size = tuple(d * canvas.pixel_scale for d in canvas.size)\n x_pos = event.pos[0] * canvas.pixel_scale\n y_pos = render_size[1] - (event.pos[1] * canvas.pixel_scale)\n\n # render a small patch around the mouse cursor\n restore_state = not picking_filter.enabled\n picking_filter.enabled = True\n markers.update_gl_state(blend=False)\n picking_render = canvas.render(\n crop=(x_pos - 2, y_pos - 2, 5, 5),\n bgcolor=(0, 0, 0, 0),\n alpha=True,\n )\n if restore_state:\n picking_filter.enabled = False\n markers.update_gl_state(blend=not picking_filter.enabled)\n\n # unpack the face index from the color in the center pixel\n marker_idx = (picking_render.view(np.uint32) - 1)[2, 2, 0]\n\n if marker_idx >= 0 and marker_idx < len(pos):\n new_symbols = list(markers.symbol)\n new_symbol = symbols_ring[new_symbols[marker_idx]]\n new_symbols[marker_idx] = new_symbol\n\n colors[marker_idx] = random.choice(COLORS)\n markers.set_data(\n pos=pos,\n edge_color=EDGE_COLOR,\n face_color=colors,\n size=MARKER_SIZE,\n edge_width=EDGE_WDITH,\n symbol=new_symbols,\n )\n\n\n@canvas.events.key_press.connect\ndef on_key_press(event):\n global colors\n if event.key == 'p':\n # toggle face picking view\n picking_filter.enabled = not picking_filter.enabled\n markers.update_gl_state(blend=not picking_filter.enabled)\n markers.update()\n if event.key == 'r':\n # reset marker symbols\n colors = _colors.copy()\n markers.set_data(\n pos=pos,\n edge_color=EDGE_COLOR,\n face_color=colors,\n size=MARKER_SIZE,\n edge_width=EDGE_WDITH,\n )\n\n\ncanvas.show()\n\n\nif __name__ == \"__main__\":\n print(__doc__)\n app.run()" ] } ], "metadata": { "kernelspec": { "display_name": "Python 3", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.9.19" } }, "nbformat": 4, "nbformat_minor": 0 }