Visualization¶
PaNTr ships with a visualization module (pantr.viz) built on
PyVista that renders B-spline and Bezier geometries
using native VTK higher-order Bezier cell types. Rather than baking the geometry
into a fixed triangle mesh up front, each cell carries the exact polynomial map.
To display it, a viewer still tessellates the cell into triangles – but at a
subdivision level you choose, so you trade resolution for cost and can refine as
far as you like; the geometry stored in a file stays exact no matter how it is later
tessellated.
Installation¶
pantr.viz ships with every PaNTr install but needs the third-party
PyVista library to do anything; PyVista is not pulled in by
a default pip install pantr. Make it available in either equivalent way:
pip install "pantr[viz]" # let pantr pull in pyvista automatically
pip install pyvista # or install pyvista directly
The viz extra simply enforces that pyvista gets installed alongside
pantr; if pyvista is already present (or installed later), pantr.viz
works without the extra.
Quick start¶
The simplest way to visualize a geometry is the plot() convenience method
available on both Bspline and Bezier objects:
import numpy as np
from pantr.bspline import Bspline, BsplineSpace, BsplineSpace1D
# Build a quadratic B-spline curve
space = BsplineSpace([BsplineSpace1D([0, 0, 0, 1, 2, 3, 3, 3], 2)])
cp = np.array([
[0.0, 0.0, 0.0],
[0.5, 1.0, 0.0],
[1.0, 0.5, 0.5],
[1.5, 1.0, 0.0],
[2.0, 0.0, 0.0],
])
curve = Bspline(space, cp)
# Interactive visualization
curve.plot(show_control_polygon=True, show_knot_lines=True)
For multiple geometries or finer control, use pantr.viz directly:
from pantr.viz import plot
plot(curve, surface, show_control_polygon=True)
Scene composition¶
The Scene class lets you combine multiple geometries with individual
rendering options:
from pantr.viz import Scene
scene = Scene()
scene.add(surface, color="lightblue", show_knot_lines=True)
scene.add(curve, color="red", show_control_polygon=True)
scene.add(boundary_curve, color="black")
scene.show()
Method chaining is supported:
(
Scene()
.add(surface, color="lightblue", opacity=0.8)
.add(curve, color="red")
.show()
)
Per-geometry options¶
Option |
Type |
Default |
Description |
|---|---|---|---|
|
|
|
Surface color (uses colormap for scalar fields if |
|
|
|
Surface opacity |
|
|
|
Render control polygon (points and wireframe) |
|
|
|
Render knot lines (B-splines only) |
|
|
|
Color of control point spheres |
|
|
|
Size of control point spheres |
|
|
|
Color of control polygon wireframe |
|
|
|
Color of knot lines |
|
|
|
Width of knot lines |
|
|
|
Show color bar for scalar fields |
|
|
|
Use scalar value as z-coordinate (see below) |
Scalar fields¶
When a B-spline or Bezier has rank == 1 (a scalar field), the visualization
depends on the parametric dimension:
dim=1: line plot – the parametric coordinate is on the x-axis and the scalar value on the y-axis.
dim=2: by default, a color map on the parametric domain
(u, v, 0). Setelevation=Trueto use the scalar as the z-coordinate:(u, v, f(u,v)).dim=3: color map on the parametric domain
(u, v, w).
from pantr.bezier import Bezier
# A bilinear scalar field on a quad
cp = np.array([[[0.0], [1.0]], [[2.0], [3.0]]])
scalar_field = Bezier(cp)
# Flat color map (default)
scalar_field.plot()
# Elevation surface
scalar_field.plot(elevation=True)
Control polygon¶
The control polygon shows both the control points (as small spheres) and the wireframe connecting adjacent control points along each parametric direction:
Curves: a single polyline through all control points.
Surfaces: a grid of lines along both parametric directions.
Volumes: edges of the 3D control point lattice.
For rational (NURBS) geometries, the projected Euclidean coordinates are used (i.e. divided by the homogeneous weight).
curve.plot(show_control_polygon=True)
Knot lines¶
Knot lines are the images of iso-parametric lines at interior knot values. They are only available for B-splines (not Bezier objects, which have a single element).
Curves (dim=1): knot points rendered as dots on the curve.
Surfaces (dim=2): iso-parametric curves at each interior knot in each direction, rendered as wireframe lines.
Volumes (dim=3): iso-parametric surfaces at each interior knot.
surface_bspline.plot(show_knot_lines=True)
Working with pyvista directly¶
For advanced use cases, convert geometries to pyvista objects and use the full pyvista API:
from pantr.viz import to_pyvista, control_polygon_mesh
# Get an UnstructuredGrid with VTK Bezier cells
grid = to_pyvista(surface)
# Manipulate with pyvista
grid.plot(show_edges=True, cmap="viridis")
# Get the control polygon as pyvista PolyData (points + wireframe)
poly_mesh = control_polygon_mesh(surface)
Rational geometries include a "RationalWeights" point data array on the
grid. Scalar fields include the scalar values as point data (named "scalar"
by default, configurable via scalar_name).
Exporting to VTK files¶
Export geometries to VTK files for visualization in ParaView (5.10+ supports Bézier cells natively). ParaView tessellates each cell at its Nonlinear Subdivision Level – raise that level for a closer fit to the curved geometry; the data stored in the file is exact regardless:
from pantr.viz import save
# XML UnstructuredGrid format (recommended)
save(surface, "surface.vtu")
# Legacy VTK format
save(surface, "surface.vtk")
The file format is inferred from the extension.
Supported geometries¶
Parametric dim |
Rank |
VTK cell type |
Description |
|---|---|---|---|
1 |
2–3 |
Bezier curve |
2D/3D curve |
1 |
1 |
Bezier curve |
Scalar line plot |
2 |
2–3 |
Bezier quadrilateral |
2D/3D surface |
2 |
1 |
Bezier quadrilateral |
Scalar color map / elevation |
3 |
3 |
Bezier hexahedron |
3D volume |
3 |
1 |
Bezier hexahedron |
Scalar color map on volume |
Both non-rational and rational (NURBS) geometries are supported. Periodic and unclamped B-splines are automatically converted to open form before visualization.