Equana

Back to Tutorials

VTK.js 3D Visualization

Volume rendering, isosurfaces, and FEM mesh visualization

Run AllReset

VTK.js (Visualization Toolkit for JavaScript) enables advanced 3D visualization capabilities including volume rendering, isosurface extraction, and finite element mesh visualization. All VTK functions are available under the vtk namespace.

Interactive Controls: Drag to rotate, scroll to zoom, and shift+drag to pan.

Getting Started

The simplest way to get started is with built-in primitives. VTK provides sphere, cone, cube, and cylinder shapes that you can customize with parameters.

Code [1]Run
# Create a simple sphere
vtk.sphere()

Customizing Primitives

You can customize primitives with radius, center position, and resolution parameters. Higher resolution creates smoother surfaces but renders slower.

Code [2]Run
# Create a sphere with custom radius, center, and resolution
# Parameters: radius, [centerX, centerY, centerZ], resolution
vtk.sphere(2, [1, 0, 0], 64)
Code [3]Run
# VTK provides several built-in geometric primitives
vtk.cone(2, 0.5)  # Cone with height 2, radius 0.5
title("Cone")
Code [4]Run
vtk.cube(1, 1.5, 2)  # Box with dimensions 1x1.5x2
title("Cube")
Code [5]Run
vtk.cylinder(2, 0.5, 32)  # Cylinder with height 2, radius 0.5
title("Cylinder")

Function Reference

Geometric Primitives

FunctionDescriptionExample
vtk.sphere(r, center, res)Create a spherevtk.sphere(1, [0, 0, 0], 32)
vtk.cone(h, r)Create a conevtk.cone(1, 0.5)
vtk.cube(x, y, z)Create a boxvtk.cube(1, 2, 1)
vtk.cylinder(h, r, res)Create a cylindervtk.cylinder(2, 0.5, 32)

Data Visualization

FunctionDescriptionExample
vtk.polydata(points, polys, scalars)Surface mesh from points and polygonsvtk.polydata(pts, polys)
vtk.volume(data, dims)Volume rendering of 3D scalar fieldvtk.volume(data, dims)
vtk.isosurface(data, dims, isovalue)Extract isosurface at constant valuevtk.isosurface(data, dims, 0.5)
vtk.femgrid(nodes, elements, types, scalars)FEM mesh visualizationvtk.femgrid(nodes, elems, types)

Visualization Options

FunctionDescriptionExample
vtk.colormap(name)Set colormap (viridis, rainbow, coolwarm, jet, grayscale)vtk.colormap("coolwarm")
vtk.opacity(value)Set opacity (0-1)vtk.opacity(0.5)
vtk.edges("on"/"off")Toggle mesh edge visibilityvtk.edges("on")
vtk.wireframe()Wireframe rendering modevtk.wireframe()
vtk.surface()Surface rendering mode (default)vtk.surface()
vtk.points()Points-only rendering modevtk.points()

PolyData Meshes

PolyData is VTK's format for surface meshes. You define vertices (points) and connectivity (which points form polygons). The polygon array uses the format: [n, p1, p2, ..., pn] where n is the number of vertices in the polygon.

Code [6]Run
# Define 3 vertices (flat array: x1,y1,z1, x2,y2,z2, ...)
points = [0, 0, 0, 1, 0, 0, 0.5, 1, 0]

# Define a triangle (3 = number of vertices, then indices 0, 1, 2)
polys = [3, 0, 1, 2]

vtk.polydata(points, polys)
title("Triangle")

Colored Meshes

Add scalar values to color the mesh based on data. Each point gets a scalar value that maps to the current colormap.

Code [7]Run
# Create a simple tetrahedron (4 points × 3 coords = 12 values)
points = [0, 0, 0, 1, 0, 0, 0.5, 1, 0, 0.5, 0.5, 0.8]

# Four triangular faces (each: 3, idx0, idx1, idx2)
polys = [3, 0, 1, 2, 3, 0, 1, 3, 3, 1, 2, 3, 3, 0, 2, 3]

# Assign scalar values to each point for coloring
scalars = [0, 0.33, 0.66, 1]

vtk.colormap("viridis")
vtk.polydata(points, polys, scalars)
title("Colored Tetrahedron")

Volume Rendering

Volume rendering visualizes 3D scalar data as a translucent volume, revealing internal structures. Use meshgrid with three arguments to create 3D coordinate arrays.

Note: Volume rendering is GPU-intensive. Start with small dimensions (e.g., 20×20×20) and increase resolution as needed.

Code [8]Run
# Create a 3D Gaussian blob
n = 21
coords = linspace(-2, 2, n)
(X, Y, Z) = meshgrid(coords, coords, coords)
data = exp(-(X.^2 + Y.^2 + Z.^2))

# Render as volume
vtk.volume(data, [n, n, n])
title("3D Gaussian Volume")

Isosurface Extraction

Isosurfaces are 3D contours at a constant scalar value — useful for visualizing boundaries in volumetric data. VTK uses the Marching Cubes algorithm to extract these surfaces.

Code [9]Run
# Create an implicit sphere function
n = 41
coords = linspace(-2, 2, n)
(X, Y, Z) = meshgrid(coords, coords, coords)
sphere_field = X.^2 + Y.^2 + Z.^2

# Extract isosurface at radius 1 (where x^2+y^2+z^2 = 1)
vtk.isosurface(sphere_field, [n, n, n], 1.0)
title("Sphere Isosurface (r=1)")

Torus Example

Create complex shapes using implicit surface equations. A torus can be defined as: (x2+y2R)2+z2=r2(\sqrt{x^2 + y^2} - R)^2 + z^2 = r^2

where RR is the major radius (distance from center to tube center) and rr is the minor radius (tube radius).

Code [10]Run
# Torus parameters
R_major = 1.5  # Major radius (distance from center to tube center)
r_minor = 0.5  # Minor radius (tube radius)

# Use uniform grid
n = 51
coords = linspace(-2.5, 2.5, n)
(X, Y, Z) = meshgrid(coords, coords, coords)

# Torus implicit equation
torus_field = (sqrt(X.^2 + Y.^2) - R_major).^2 + Z.^2 - r_minor^2

# Isosurface at 0 gives the torus surface
vtk.colormap("rainbow")
vtk.isosurface(torus_field, [n, n, n], 0)
title("Torus (R=1.5, r=0.5)")

FEM Mesh Visualization

Finite Element Method meshes consist of nodes (vertices) and elements (cells) of various types. Use vtk.femgrid to visualize tetrahedral, hexahedral, and other element types.

VTK Cell Type Reference

CodeNameDescription
1VERTEXSingle point
3LINELine segment
5TRIANGLETriangle (3 nodes)
9QUADQuadrilateral (4 nodes)
10TETRATetrahedron (4 nodes)
12HEXAHEDRONHexahedron/brick (8 nodes)
13WEDGEWedge/prism (6 nodes)
14PYRAMIDPyramid (5 nodes)
Code [11]Run
# Define 4 nodes of a tetrahedron (flat: x1,y1,z1, x2,y2,z2, ...)
nodes = [0, 0, 0, 1, 0, 0, 0.5, 1, 0, 0.5, 0.5, 1]

# Define one tetrahedron element
# Format: [numPoints, node0, node1, node2, node3]
elements = [4, 0, 1, 2, 3]
types = [10]  # VTK_TETRA = 10

vtk.edges("on")
vtk.femgrid(nodes, elements, types)
title("Tetrahedral Element")

Hexahedral Elements and Stress Visualization

Pass scalar values (stress, temperature, etc.) to color the mesh based on field data.

Code [12]Run
# Simple beam mesh (3 hex elements)
# 16 nodes × 3 coords = 48 values
beam_nodes = [
    0, 0, 0, 1, 0, 0, 2, 0, 0, 3, 0, 0,
    0, 1, 0, 1, 1, 0, 2, 1, 0, 3, 1, 0,
    0, 0, 1, 1, 0, 1, 2, 0, 1, 3, 0, 1,
    0, 1, 1, 1, 1, 1, 2, 1, 1, 3, 1, 1
]

# Three hexahedra forming a beam
# Each: [8, n0, n1, n2, n3, n4, n5, n6, n7]
beam_elements = [
    8, 0, 1, 5, 4, 8, 9, 13, 12,
    8, 1, 2, 6, 5, 9, 10, 14, 13,
    8, 2, 3, 7, 6, 10, 11, 15, 14
]
beam_types = [12, 12, 12]

# Von Mises stress (higher at fixed end)
stress = [100, 90, 80, 70, 100, 90, 80, 70, 100, 90, 80, 70, 100, 90, 80, 70]

vtk.colormap("coolwarm")
vtk.edges("on")
vtk.femgrid(beam_nodes, beam_elements, beam_types, stress)
title("Beam with Stress Visualization")

Visualization Options

Customize the appearance of your visualizations with colormaps, opacity, edge visibility, and rendering modes.

Code [13]Run
# Show edges for better mesh visibility
vtk.edges("on")

# Set partial transparency (0=invisible, 1=opaque)
vtk.opacity(0.8)

# Create a sphere
vtk.sphere(1, [0, 0, 0], 16)
title("Semi-transparent Sphere with Edges")
Code [14]Run
# Wireframe mode shows only the mesh lines
vtk.wireframe()
vtk.sphere(1, [0, 0, 0], 16)
title("Wireframe Sphere")

Advanced Examples

Heat Distribution

Visualize a 3D temperature field using volume rendering with a thermal colormap.

Code [15]Run
# Simulate heat distribution in a block
n = 11
coords = linspace(0, 1, n)
(X, Y, Z) = meshgrid(coords, coords, coords)

# Heat source at center, cooling at boundaries
T = exp(-10 * ((X - 0.5).^2 + (Y - 0.5).^2 + (Z - 0.5).^2))

vtk.colormap("coolwarm")
vtk.volume(T, [n, n, n])
title("Heat Distribution (Hot Center)")

Molecular Surface

Create molecular visualizations by blending electron density fields from multiple atomic centers.

Code [16]Run
# Implicit surface for a simple diatomic molecule
nx = 61
ny = 41
nz = 41
(X, Y, Z) = meshgrid(linspace(-3, 3, nx), linspace(-2, 2, ny), linspace(-2, 2, nz))

# Two atomic centers (spherical electron density)
r1 = sqrt(X.^2 + Y.^2 + Z.^2)
r2 = sqrt((X - 1.5).^2 + Y.^2 + Z.^2)

# Blend the two electron densities
molecule_field = exp(-r1) + exp(-r2) - 0.3

vtk.colormap("viridis")
vtk.isosurface(molecule_field, [nx, ny, nz], 0)
title("Diatomic Molecule Surface")

Summary

We've covered the main VTK.js visualization capabilities:

Key Concepts

  1. Primitives - Built-in shapes (sphere, cone, cube, cylinder) with customizable parameters
  2. PolyData - Custom surface meshes defined by points and polygon connectivity
  3. Volume Rendering - Visualize 3D scalar fields as translucent volumes
  4. Isosurfaces - Extract constant-value surfaces from volumetric data using Marching Cubes
  5. FEM Grids - Visualize finite element meshes with various cell types and scalar fields
  6. Options - Customize colormaps, opacity, edges, and rendering modes

Tips

  • 3D Meshgrid: Use (X, Y, Z) = meshgrid(x, y, z) to create 3D coordinate arrays
  • Performance: Start with coarse grids during development; volume rendering is GPU-intensive
  • Colormaps: Call vtk.colormap() before creating the visualization

Further Reading

Workbench

Clear
No variables in workbench

Next Steps