Architecture Overview
This package bridges Plant MTGs with meshes and high‑performance visualization.
OPF/OPS files ──► read_opf/read_ops ──► MTG (MultiScaleTreeGraph)
│
▼
Reference Meshes (RefMesh)
│
▼
Geometry (ref_mesh + transform)
│
(lazy) refmesh_to_mesh per node
│
▼
Merge all meshes into a single Meshes.SimpleMesh geometry
│
▼
plantviz (Makie recipe) ──► Makie Figure/Axis- Core types:
RefMeshstores template geometry;Geometryattaches aref_mesh, a transform (Translate,Rotate,Scale,Affine, orSequentialTransform), and an optional cached mesh to an MTG node attribute:geometry. - IO:
read_opf/read_opspopulate MTG nodes and scene transforms;write_opf/write_opsserialize meshes and transforms back to disk. - Computation: meshes are computed lazily; call
refmesh_to_meshto materialize. Matrix generation usesget_transformation_matrix. At render time, node meshes are merged to a singleSimpleMesh. - Visualization:
plantvizbuilds on Makie’s ComputeGraph. It maps colors from attributes or user dictionaries viaget_mtg_color/get_color/get_colormap, wires them as compute nodes withmap!, and renders the merged mesh once.
Minimal example
using PlantGeom
opf = read_opf("test/files/simple_plant.opf")
fig, ax, plt = plantviz(opf) # visualizeColor Mapping & Caching
User input to plantviz(color=..., colormap=..., colorrange=...)
│
▼
get_mtg_color / get_ref_meshes_color get_colormap
│ │
▼ ▼
get_color_range ◄──────────── optional user colorrange
│
▼
Per-node color values (or per-refmesh/per-vertex inputs)
│ ┌─────────────────────────────────────────┐
├────────────►│ Cache: UUIDs-based attribute on MTG │
│ │ (e.g., :_cache_<hash>) holds Observables│
▼ └─────────────────────────────────────────┘
Makie plot attributes (colormap, colorrange, color per vertex)
│
▼
plantviz recipe renders via Meshes/Makie- Inputs: single color,
Dict("RefMeshName" => color), attribute symbol (e.g.,:z_max), or per-vertex arrays. A vector of colors/symbols per node is also supported; it expands to per-face colors using theface2nodemapping of the merged mesh. - Mapping:
get_colormapresolves aColorScheme;get_color_rangederives or validates ranges;get_colormaps values to colors. - Caching:
- Per-node color caches (UUID-derived Observables) for interactive updates when plotting per-node geometry.
- Scene cache on the root (
:_scene_cache) as a single-entry NamedTuple(hash, mesh, face2node). Thehashencodes the scene version and relevant options (filters). Invalidate withbump_scene_version!(mtg).
Rendering Model (Merged by Default)
- Build: traverses selected nodes, transforms ref meshes, materializes node meshes if needed, and merges them into one
SimpleMeshfor rendering. The merge is performed in a single pass for performance. - Colors: computes a single per-vertex color array and passes it to Makie. Attribute colors honor
colormapandcolorrange; dictionary inputs by refmesh are supported; per-vertex dictionaries pass through directly. - Mapping:
face2nodeis stored alongside the merged mesh in:_scene_cacheto map triangles back to node IDs. This enables expanding per-node color vectors to per-face arrays. - Use:
plantviz(opf, color=:z_max); invalidate cache after geometry/attribute changes viabump_scene_version!(opf). The merged mesh andface2nodeare reused across color updates.
Key Components
build_merged_mesh_with_map(mtg; ...): collects selected node meshes and returns(merged::SimpleMesh, face2node::Vector{Int}). Theface2nodearray maps each element of the merged mesh back to its originating node id.- Scene cache helpers:
scene_version,bump_scene_version!: version the scene to invalidate cache.scene_cache_key: builds a stable key for the current selection/options.get_cached_scene,set_cached_scene!: retrieve/store a single cached scene(hash, mesh, face2node)on the MTG root.
- PlantViz recipe (Makie): defines attributes (
color,colormap,colorrange, etc.) and derives compute nodes withmap!(:colorant,:colormap_resolved,:colorrange_resolved,:index_resolved). The plot calls into a helper that computes or retrieves the merged scene and computes vertex colors as needed.
Performance Notes
- Merging: performed in one pass; avoid repeated pairwise merges. Connectivity indices are reindexed with a running vertex offset.
- face2node: built with a single preallocated vector, filling by contiguous slices per node to minimize allocations.
- Colors: computed once per render and are not cached in the scene cache; only the merged mesh and face2node are cached to reduce invalidation churn.