3D viewer

Requires the viz extra (pip install "longeron[viz]").

A small three.js mesh viewer for baked geometry (anywidget).

Renders the mesh dicts produced by longeron.analysis.geometry following the house widget pattern (longeron.widgets.replay): Python bakes the geometry once per configuration into a JSON-string traitlet; the inline vanilla-JS front-end only paints – it builds three.js buffer geometries on load and per-interaction work is a camera move plus one render. Rendering is on-demand (no free-running animation loop), so an idle viewer costs nothing.

Interaction: drag to orbit, shift-drag or right-drag to pan (the canvas swallows the context-menu event so JupyterLab’s menu stays out of the way), scroll to zoom, double-click to re-fit; a subtle overlay hint names the bindings. The canvas fills the available cell width (a ResizeObserver re-sizes the renderer and re-fits the camera on host resizes); width_px/height_px set the aspect ratio and the fallback width. An optional second mesh (mesh_b_json) renders side by side at true scale for A/B comparison, with captions from label/label_b. A mesh dict may carry labels{text, anchor} entries as produced by longeron.analysis.geometry.lineup() – rendered as billboard sprites above each configuration, so a grid lineup names its cells in-scene. Updating mesh_json from Python (e.g. observing another widget’s traitlet) re-bakes the scene in place.

Linked selection: highlight_json (a JSON array of part identity keys – each part’s key if tagged via longeron.analysis.geometry.tag_parts(), else its name) pops the matched meshes with an emissive accent (the JupyterLab selection blue, read live from --jp-brand-color2) and dims the rest; "[]" restores every material instantly. A plain click (no drag) raycasts the scene and reports the hit part’s key on picked_json ("[]" for a background click), so Python can select the corresponding diagram node – longeron.analysis.link.link_selection() wires both directions.

Offline tradeoff: the front-end imports three.js (~630 kB) from the jsDelivr CDN at view time – the one exception to the otherwise self-contained widget. Vendoring the library into the package would add those bytes to every install for a demo-grade viewer; on an offline front-end the widget degrades to a printed notice instead of a scene.

Requires the viz extra for anywidget: pip install "longeron[viz]".

longeron.widgets.viewer3d.mesh_viewer(mesh, mesh_b=None, *, label='', label_b='', width_px=760, height_px=430)[source]

View one baked mesh dict, or two side by side at true scale.

mesh/mesh_b come from longeron.analysis.geometry (or any producer of the same schema). The canvas fills the notebook cell’s width; width_px/height_px set its aspect ratio (and the fallback width when the host width cannot be measured). Drag to orbit, shift-drag or right-drag to pan, scroll to zoom, double-click to re-fit. Assign a new JSON string to the returned widget’s mesh_json to swap the scene in place – e.g. from an observe handler on another widget.

Linked selection: widget.highlight(keys) pops the parts whose identity key (the key stamped by longeron.analysis.geometry.tag_parts(), else the part name) is in keys and dims the rest; widget.highlight() clears. A plain click on a part reports its key on the picked_json traitlet. See longeron.analysis.link.link_selection() for wiring both to a diagram.

Return type:

AnyWidget