visualdynamics.viz.geometry¶
geometry
¶
PyVista scene construction for Geometry.
Coordinates are converted from stored SI to the display unit system at scene build time — switching unit systems rebuilds the scene, never the data.
Tracelines and line elements are drawn with direct colors, grouped by color index, except when the scene is colored by value (see docs/colormap.md). An older note here warned that macOS VTK silently drops scalar-mapped line cells; that was measured against pyvista 0.48.4 / VTK 9.6.2 and does not reproduce — see the same doc for the numbers.
Functions:
| Name | Description |
|---|---|
axis_unit_text |
What the labelled axes say. A geometry whose units are undefined |
display_points |
(coordinates to draw, axis unit text) for a geometry. |
geometry_scene |
Build (or add to) a PyVista plotter showing the geometry. |
annotate_scene |
Scene annotations, each independently switchable. |
shared_points |
A vtkPoints every mesh can share, plus a writable numpy view of it. |
dof_axis |
0/1/2 for a DOF direction's axis — 'RZ-' is a Z, so blue. |
dof_arrow_length |
One length for every arrow on a plot: 12% of the geometry's |
add_dof_arrows |
Labelled arrows marking DOFs on the geometry. |
add_coordinate_system |
One coordinate system: three directions, named, with angles curved. |
shared_scalars |
A VTK point-data array every mesh can share, and a numpy view of it. |
label_choices |
|
labels_fit |
Would captioning this kind stay under |
label_spots |
(positions, texts) captioning one kind of entity with its id. |
add_geometry |
Add one geometry's meshes to an existing plotter. |
plot_geometry |
Show the geometry interactively, or render to |
plot_dofs |
The geometry with labelled arrows at every DOF |
Classes¶
Functions:¶
axis_unit_text
¶
axis_unit_text(
geometry: Geometry, unit_system: UnitSystem
) -> str
What the labelled axes say. A geometry whose units are undefined says so rather than naming one.
Source code in src/visualdynamics/viz/geometry.py
display_points
¶
display_points(
geometry: Geometry, unit_system: UnitSystem
) -> tuple[ndarray, str]
(coordinates to draw, axis unit text) for a geometry.
A geometry whose units are undefined is drawn with the file's raw coordinates — converting them would silently scale unknown values — and its axes say so rather than naming a unit.
Source code in src/visualdynamics/viz/geometry.py
geometry_scene
¶
geometry_scene(
geometry: Geometry,
unit_system: UnitSystem | None = None,
plotter: Any = None,
node_size: float = 8.0,
line_width: float = 2.0,
show_edges: bool = True,
opacity: float = 1.0,
labels: Sequence[str] | None = None,
off_screen: bool = False,
theme: Any = None,
components: Sequence[str] | None = None,
) -> Any
Build (or add to) a PyVista plotter showing the geometry.
theme is 'light', 'dark', or a colors dict; it sets the scene
background and annotation color. components limits what is drawn to a
subset of {'nodes', 'tracelines', 'elements'} — selecting one in the
project tree shows just that part. Returns the plotter; call .show() on
it (or .screenshot() if off_screen).
Source code in src/visualdynamics/viz/geometry.py
annotate_scene
¶
annotate_scene(
plotter: Any,
axis_unit: str,
colors: Mapping[str, str],
bounds: bool = True,
orientation: bool = True,
) -> None
Scene annotations, each independently switchable.
bounds is the labelled box drawn around the geometry; orientation is
the small triad in the corner. The 3D view toolbar toggles them
separately.
Source code in src/visualdynamics/viz/geometry.py
shared_points
¶
A vtkPoints every mesh can share, plus a writable numpy view of it.
Writing through the view and calling Modified() moves every mesh at once — the difference between one upload per frame and one per mesh.
Source code in src/visualdynamics/viz/geometry.py
dof_axis
¶
0/1/2 for a DOF direction's axis — 'RZ-' is a Z, so blue.
dof_arrow_length
¶
One length for every arrow on a plot: 12% of the geometry's extent, shrunk to the closest spacing of the arrowed nodes so a dense set of arrows never overlaps its neighbours.
Source code in src/visualdynamics/viz/geometry.py
add_dof_arrows
¶
add_dof_arrows(
plotter: Any,
geometry: Geometry,
dofs: Sequence[str],
unit_system: UnitSystem | None = None,
incoming: bool = False,
name: str | None = None,
) -> int
Labelled arrows marking DOFs on the geometry.
One arrow per DOF, colored by the axis it points along — X red,
Y green, Z blue, the orientation marker's own convention. Response
style starts at the node and points outward, label at the tip;
incoming (forces) ends on the node instead, label at the base.
All arrows share one length: 12% of the geometry's extent, shrunk
to the closest node spacing so dense sets never overlap. DOFs at
nodes the geometry does not have are skipped. Returns how many
were drawn.
Source code in src/visualdynamics/viz/geometry.py
add_coordinate_system
¶
add_coordinate_system(
plotter: Any,
origin: ArrayLike,
matrix: ArrayLike,
cs_type: int,
length: float,
text_color: str = "#000000",
label: str | None = None,
name: str | None = None,
) -> None
One coordinate system: three directions, named, with angles curved.
label (the system's id) is written at the origin. Direction names come
from the type — X/Y/Z, R/theta/Z, or R/theta/phi — and each is written
at the tip of its own arrow, so a cylindrical system is tellable from a
cartesian one at a glance rather than by consulting the table.
Given a name, every actor is named from it, so drawing again replaces
the drawing instead of piling another one on top — which is what lets a
frame be turned live without rebuilding the scene around it.
Source code in src/visualdynamics/viz/geometry.py
shared_scalars
¶
A VTK point-data array every mesh can share, and a numpy view of it.
The colour twin of shared_points: one array, written once per frame,
recolours every mesh in the scene at once.
Source code in src/visualdynamics/viz/geometry.py
label_choices
¶
label_choices(
labels: Sequence[str]
| Mapping[str, Sequence[int] | None]
| None,
) -> dict[str, Sequence[int] | None]
labels in one shape: {kind: the ids to caption, or None}.
Both spellings read naturally where they are used. A script says
labels=['nodes'] and means the nodes that are drawn; the window,
which knows exactly what the user picked, says
labels={'blocks': [3]}. None means "whatever this kind draws",
which is the right answer for both.
Source code in src/visualdynamics/viz/geometry.py
labels_fit
¶
labels_fit(
geometry: Geometry,
kind: str,
chosen: Sequence[int] | None = None,
) -> bool
Would captioning this kind stay under ENTITY_LABEL_LIMIT?
Asked by the window before it turns labels on, so a selection too large to caption says so in the status bar rather than drawing nothing and leaving the user to wonder.
Source code in src/visualdynamics/viz/geometry.py
label_spots
¶
label_spots(
geometry: Geometry,
points: ndarray,
kind: str,
chosen: Sequence[int] | None = None,
) -> tuple[ndarray, list[str]]
(positions, texts) captioning one kind of entity with its id.
points is the geometry's nodes as drawn, so a caption lands in the
same units and the same frame as the thing it names. Everything but
a node is captioned at the centroid of its own nodes: the middle
of a traceline's run, of an element's corners, of a block's
elements. That is where a reader looks for the name of a shape, and
it keeps the number off the vertices, which are already carrying
node ids whenever both are shown.
A traceline id can name several runs — a UNV dataset-82 line that lifts the pen arrives as several polylines under one id — and each run is captioned where it is. One centroid for the id would land between them, in empty space, naming nothing.
chosen is the ids (nodes, coordinate systems, blocks) or indices
(tracelines, elements) to caption; None captions every one of the
kind. Returns nothing past ENTITY_LABEL_LIMIT; see labels_fit.
Source code in src/visualdynamics/viz/geometry.py
add_geometry
¶
add_geometry(
plotter: Any,
geometry: Geometry,
unit_system: UnitSystem | None = None,
node_size: float = 8.0,
line_width: float = 2.0,
show_edges: bool = True,
opacity: float = 1.0,
labels: Sequence[str]
| Mapping[str, Sequence[int] | None]
| None = None,
components: Sequence[str] | None = None,
color_override: Any = None,
text_color: str = "#000000",
entities: Mapping[str, Sequence[int]] | None = None,
points_source: Any = None,
meshes: list[Any] | None = None,
scalars: Any = None,
clim: tuple[float, float] | None = None,
) -> str
Add one geometry's meshes to an existing plotter.
color_override paints the whole geometry one color, which is how
several geometries overlaid in one scene stay tellable apart.
entities restricts drawing to specific items, as a dict with any of
'nodes' (node ids), 'coordinate_systems' (ids), 'tracelines' (indices)
and 'elements' (indices) — that is how a single node or traceline picked
in the tree gets highlighted.
labels names the kinds to caption with their ids — any of 'nodes',
'coordinate_systems', 'tracelines', 'elements', 'blocks'. Captions
follow entities when it restricts the drawing, so labelling a
picked traceline names that one and not all of them, and a kind with
more than ENTITY_LABEL_LIMIT of them is left uncaptioned (see
labels_fit).
scalars is a VTK point-data array shared by every mesh, colouring the
whole geometry by value instead of by the geometry's own colour indices;
clim fixes what the ends of the colour map mean. One array serves all
the meshes, so a frame writes it once. Returns the axis unit text.
Source code in src/visualdynamics/viz/geometry.py
527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 | |
plot_geometry
¶
plot_geometry(
geometry: Geometry,
unit_system: UnitSystem | None = None,
screenshot: str | None = None,
theme: Any = None,
show: bool = True,
**kwargs: Any,
) -> Any
Show the geometry interactively, or render to screenshot headlessly.
Shown, it comes up in the app's own 3-D pane — the labelled axes and
the orientation triad are toggles on the bar over it, exactly as in
the window. Returns the pane (its .plotter is the PyVista one), or
the image array when rendering to a file.
Source code in src/visualdynamics/viz/geometry.py
plot_dofs
¶
plot_dofs(
geometry: Geometry,
source: Any,
quantity: str,
unit_system: UnitSystem | None = None,
screenshot: str | None = None,
theme: Any = None,
show: bool = True,
**kwargs: Any,
) -> Any
The geometry with labelled arrows at every DOF source measures
as quantity — the GUI's DOF-arrows toggle, from a script.
Forces end on their node with the label at the base, responses
leave it with the label at the tip, exactly as the desktop draws
them. source is a data object (or several).