feat(plotly): opstool-style contour, loads, supports, ghost and animation

Bring the Plotly canvas in line with opstool's visualisation recipes.

Camera / interaction:
- frame the camera in plotly's normalized scene units, using the model
  bounds (grid excluded); a data-unit eye rendered the model as a speck
- use turntable dragmode so Z stays up and the horizon stays level
- align mouse bindings with the PyVista/VTK backend and document them in
  Help → Mouse Controls

Visualisation:
- colour deformed / modal shapes by response with a shared colourbar
- scale load arrows by |F|, tint per load pattern, hover the magnitude,
  and fix cones rendering as oversized fins (sizemode scaled, not absolute)
- draw DOF-accurate support glyphs (ported from opstool; see NOTICE)
- add an undeformed-reference overlay on both canvas backends
- play mode shapes with plotly frame animation in-page

Tests: builder unit tests plus GUI regression tests for gestures, the
deformed push, the undeformed reference and animation payloads.
This commit is contained in:
smillmorel 2026-09-16 23:10:22 -04:00
commit d3878f23b3
26 changed files with 1687 additions and 153 deletions

View file

@ -66,7 +66,9 @@ correctly.
periods, frequencies, and participation factors per mode.
4. **Display → Animate Mode Shape** to view each mode. Use the mode
selector and the animation controls, and **Export…** if you want a
video of the mode shape.
video of the mode shape. On the Plotly backend the **Play** button runs
the animation inside the viewport (plotly frames); on PyVista it is
driven from Python.
5. Modal results also feed the response-spectrum case: define a response
spectrum, then run the SRSS or CQC combination and open
**Display → Show Response Spectrum**.
@ -77,12 +79,20 @@ After a run, the results/report panel shows a summary for the active case
(static reactions and forces, modal periods, and so on). Use the display
actions to inspect the model visually:
- **Display → Show Deformed Shape** — with a scale slider.
- **Display → Show Deformed Shape** — with a scale slider. The deformed
shape is coloured by displacement magnitude with a colourbar, and
**Display → Show Undeformed Reference** overlays the original shape for
comparison.
- **Display → Show Force Diagram…** — axial (P), shear (V2/V3), moment
(M2/M3) diagrams.
- **Display → Show Pushover Curve**, **Show Time-History**, **Show
Hysteresis** as applicable.
Nodal and distributed loads are drawn as arrows whose length scales with the
load magnitude; each load pattern gets its own colour and hovering an arrow
shows its value. Support symbols show which translation directions are
restrained.
To hand the analysis to someone else, or to archive exactly what was run,
export a script:
@ -122,6 +132,23 @@ wrapped in a single macro, so one undo removes the whole step. File
loads, analysis runs, and display-only changes are not model mutations and
are not undoable.
## 6. Navigating the 3D view
Both canvas backends (**Options → Canvas Backend**) use the same VTK-style mouse
bindings, and **Help → Mouse Controls** lists them in the app:
- **Rotate** — left-drag.
- **Pan** — Shift + left-drag, or middle-drag.
- **Zoom** — right-drag, or the mouse wheel.
- **Spin (roll)** — Ctrl + left-drag.
- **Select** — left-click a node or element; Ctrl+click or Shift+click adds
to the selection. A drag moves the view; only a click without movement
changes the selection.
View presets: **Ctrl+1** isometric, **Ctrl+2** top (XY), **Ctrl+3** front
(XZ), **Ctrl+4** right (YZ), **Ctrl+E** zoom extents. The camera keeps Z up,
so the horizon stays level while you orbit.
## Where to go next
- [`architecture.md`](architecture.md) — MVVM layering and command order.