{ "cells": [ { "cell_type": "markdown", "id": "pick-intro", "metadata": {}, "source": [ "# Picking\n", "\n", "`ngsolve_webgpu` ships pick handlers that decode click events on rendered scenes back into mesh entities (elements, regions) or OCC geometry features (vertex/edge/face).\n", "\n", "The pick handlers run **inside the live Jupyter session** — they need a Python kernel to receive the click events and react.\n", "\n", "## How it works\n", "\n", "1. Register a click handler on `scene.input_handler` that calls `scene.select(x, y)`.\n", "2. The scene reads the GPU selection buffer at that pixel, identifies the renderer, and calls its `on_select` callback.\n", "3. Use `MeshPickResult` or `GeoPickResult` to decode the raw event into meaningful data." ] }, { "cell_type": "markdown", "id": "pick-mesh-md", "metadata": {}, "source": [ "## Mesh picking\n", "\n", "Click on a surface element to print its element number and region name." ] }, { "cell_type": "code", "execution_count": null, "id": "pick-mesh", "metadata": {}, "outputs": [], "source": [ "from ngsolve import *\n", "from ngsolve_webgpu.mesh import MeshData, MeshElements2d, MeshWireframe2d\n", "from ngsolve_webgpu.pick import MeshPickResult\n", "import webgpu.jupyter as wj\n", "\n", "mesh = Mesh(unit_cube.GenerateMesh(maxh=0.3))\n", "mesh_data = MeshData(mesh)\n", "\n", "surface = MeshElements2d(mesh_data)\n", "wireframe = MeshWireframe2d(mesh_data)\n", "\n", "def on_pick(ev):\n", " pick = MeshPickResult(ev, mesh, scene.options, kind='surface')\n", " print(pick)\n", "\n", "surface.on_select(on_pick)\n", "\n", "scene = wj.Draw([surface, wireframe])\n", "scene.input_handler.on_click(lambda ev: scene.select(ev['canvasX'], ev['canvasY']))" ] }, { "cell_type": "markdown", "id": "pick-geo-md", "metadata": {}, "source": [ "## Geometry picking — OCC shapes\n", "\n", "Click on a face or edge of the OCC box to identify it." ] }, { "cell_type": "code", "execution_count": null, "id": "pick-geo", "metadata": {}, "outputs": [], "source": [ "from netgen.occ import Box, Pnt, OCCGeometry\n", "from ngsolve_webgpu.geometry import GeometryRenderer\n", "from ngsolve_webgpu.pick import GeoPickResult\n", "import webgpu.jupyter as wj\n", "\n", "geo = OCCGeometry(Box(Pnt(0, 0, 0), Pnt(1, 1, 1)))\n", "renderer = GeometryRenderer(geo)\n", "\n", "def on_pick(ev):\n", " pick = GeoPickResult(ev, geo, scene2.options)\n", " print(f'Picked {pick.kind_label} #{pick.index} name={pick.name!r}')\n", "\n", "renderer.faces.on_select(on_pick)\n", "renderer.edges.on_select(on_pick)\n", "\n", "scene2 = wj.Draw([renderer])\n", "scene2.input_handler.on_click(lambda ev: scene2.select(ev['canvasX'], ev['canvasY']))" ] }, { "cell_type": "code", "execution_count": null, "id": "c6fc06a4-d865-4c77-b91b-1127d27e672f", "metadata": {}, "outputs": [], "source": [] } ], "metadata": { "kernelspec": { "display_name": "Python 3 (ipykernel)", "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.14.5" } }, "nbformat": 4, "nbformat_minor": 5 }