Volumes#
Volume adapters connect discrete 3D grids (simulation output, CT/MRI, or other VDB-backed data) to OpenVCAD’s continuous sampling model. Instead of baking data into dense meshes, you keep a sparse OpenVDB grid and query it at any world-space point. Sampling uses trilinear interpolation between voxel centers, so fields stay smooth for rendering, slicing, and compilers.
Typical uses include mapping Hounsfield units or bone density to material properties, reusing FEA or fluid fields on printable geometry, and importing artist-authored VDBs from external tools.
Interface you use in Python
Typed volumes —
FloatVolume,Vec2sVolume,Vec3sVolume, andVec4sVolumewrap scalar or vector VDB grids. Callsample(x, y, z)for a value,bounding_box()for world-space bounds, andclone()when you need a thread-safe copy for concurrent evaluation.VDB files — Use
pyvcad.vdb_loader(load_float_volume,load_vec3s_volume,load_vec4s_volume) to open a named grid from a.vdbfile, optionally centered on the origin.DICOM stacks —
DICOMLoaderreads a directory of slices, applies real-world spacing and rescale metadata where available, and builds a scalarFloatVolume(commonly HU). Callas_volume()when you are ready to sample.Attributes — A
FloatVolumeis a continuous field; pass it toFloatAttribute(volume)(orset_volumeon an existingFloatAttribute) and attach that attribute to geometry withset_attribute, same as expression-driven fields. Evaluation runs where your solid exists, using the volume’s values inside the part.
Examples#
The patterns below mirror the getting-started discussion of sampled scalar fields: load data, wrap in FloatAttribute, attach to a primitive or mesh.
VDB scalar grid
import pyvcad as pv
vol = pv.vdb_loader.load_float_volume("model.vdb", "density")
bbox_min, bbox_max = vol.bounding_box()
solid = pv.RectPrism.FromMinAndMax(bbox_min, bbox_max)
solid.set_attribute(pv.DefaultAttributes.DENSITY, pv.FloatAttribute(vol))
DICOM series → float volume
import pyvcad as pv
loader = pv.DICOMLoader("path/to/dicom_series")
vol = loader.as_volume()
solid = pv.RectPrism.FromMinAndMax(*vol.bounding_box())
solid.set_attribute(pv.DefaultAttributes.HU, pv.FloatAttribute(vol))
Volume types#
- class pyvcad.FloatVolume#
A VDB volume storing scalar float values.
- __init__(*args, **kwargs)#
Overloaded function.
__init__(self: pyvcad.pyvcad.FloatVolume) -> None
Constructor. Creates an empty FloatVDBVolume.
__init__(self: pyvcad.pyvcad.FloatVolume, grid: openvdb::v13_0::Grid<openvdb::v13_0::tree::Tree<openvdb::v13_0::tree::RootNode<openvdb::v13_0::tree::InternalNode<openvdb::v13_0::tree::InternalNode<openvdb::v13_0::tree::LeafNode<float, 3u>, 4u>, 5u>>>>, center: bool = False) -> None
Constructor. Creates a FloatVDBVolume from an existing grid.
- Parameters:
grid (FloatGrid) – The OpenVDB grid to use.
center (bool) – If True, centers the volume about the origin. Defaults to False.
- bounding_box(self: pyvcad.pyvcad.FloatVolume) tuple[pyvcad.pyvcad.Vec3, pyvcad.pyvcad.Vec3]#
Get the world space bounding box of the volume.
- clone(self: pyvcad.pyvcad.FloatVolume) pyvcad.pyvcad.FloatVolume#
Create a thread-safe clone of this volume.
- Returns:
A cloned volume instance.
- Return type:
- grid_type(self: pyvcad.pyvcad.FloatVolume) str#
Get the grid type name.
- Returns:
The grid type name.
- Return type:
str
- sample(self: pyvcad.pyvcad.FloatVolume, x: SupportsFloat, y: SupportsFloat, z: SupportsFloat) float#
Sample the volume at the given coordinates.
- Parameters:
x (float) – X coordinate.
y (float) – Y coordinate.
z (float) – Z coordinate.
- Returns:
The sampled value.
- Return type:
float
- class pyvcad.Vec2sVolume#
A VDB volume storing 2D vector values with single precision.
- __init__(self: pyvcad.pyvcad.Vec2sVolume) None#
Constructor. Creates an empty Vec2sVDBVolume.
- bounding_box(self: pyvcad.pyvcad.Vec2sVolume) tuple[pyvcad.pyvcad.Vec3, pyvcad.pyvcad.Vec3]#
Get the world space bounding box of the volume.
- clone(self: pyvcad.pyvcad.Vec2sVolume) pyvcad.pyvcad.Vec2sVolume#
Create a thread-safe clone of this volume.
- Returns:
A cloned volume instance.
- Return type:
- grid_type(self: pyvcad.pyvcad.Vec2sVolume) str#
Get the grid type name.
- Returns:
The grid type name.
- Return type:
str
- sample(self: pyvcad.pyvcad.Vec2sVolume, x: SupportsFloat, y: SupportsFloat, z: SupportsFloat) pyvcad.pyvcad.Vec2#
Sample the volume at the given coordinates.
- Parameters:
x (float) – X coordinate.
y (float) – Y coordinate.
z (float) – Z coordinate.
- Returns:
The sampled 2D vector value.
- Return type:
- class pyvcad.Vec3sVolume#
A VDB volume storing 3D vector values with single precision.
- __init__(*args, **kwargs)#
Overloaded function.
__init__(self: pyvcad.pyvcad.Vec3sVolume) -> None
Constructor. Creates an empty Vec3sVDBVolume.
__init__(self: pyvcad.pyvcad.Vec3sVolume, grid: openvdb::v13_0::Grid<openvdb::v13_0::tree::Tree<openvdb::v13_0::tree::RootNode<openvdb::v13_0::tree::InternalNode<openvdb::v13_0::tree::InternalNode<openvdb::v13_0::tree::LeafNode<openvdb::v13_0::math::Vec3<float>, 3u>, 4u>, 5u>>>>, center: bool = False) -> None
Constructor. Creates a Vec3sVDBVolume from an existing grid.
- Parameters:
grid (Vec3SGrid) – The OpenVDB grid to use.
center (bool) – If True, centers the volume about the origin. Defaults to False.
- bounding_box(self: pyvcad.pyvcad.Vec3sVolume) tuple[pyvcad.pyvcad.Vec3, pyvcad.pyvcad.Vec3]#
Get the world space bounding box of the volume.
- clone(self: pyvcad.pyvcad.Vec3sVolume) pyvcad.pyvcad.Vec3sVolume#
Create a thread-safe clone of this volume.
- Returns:
A cloned volume instance.
- Return type:
- grid_type(self: pyvcad.pyvcad.Vec3sVolume) str#
Get the grid type name.
- Returns:
The grid type name.
- Return type:
str
- sample(self: pyvcad.pyvcad.Vec3sVolume, x: SupportsFloat, y: SupportsFloat, z: SupportsFloat) pyvcad.pyvcad.Vec3#
Sample the volume at the given coordinates.
- Parameters:
x (float) – X coordinate.
y (float) – Y coordinate.
z (float) – Z coordinate.
- Returns:
The sampled 3D vector value.
- Return type:
- class pyvcad.Vec4sVolume#
A VDB volume storing 4D vector values with single precision.
- __init__(self: pyvcad.pyvcad.Vec4sVolume) None#
Constructor. Creates an empty Vec4sVDBVolume.
- bounding_box(self: pyvcad.pyvcad.Vec4sVolume) tuple[pyvcad.pyvcad.Vec3, pyvcad.pyvcad.Vec3]#
Get the world space bounding box of the volume.
- clone(self: pyvcad.pyvcad.Vec4sVolume) pyvcad.pyvcad.Vec4sVolume#
Create a thread-safe clone of this volume.
- Returns:
A cloned volume instance.
- Return type:
- grid_type(self: pyvcad.pyvcad.Vec4sVolume) str#
Get the grid type name.
- Returns:
The grid type name.
- Return type:
str
- sample(self: pyvcad.pyvcad.Vec4sVolume, x: SupportsFloat, y: SupportsFloat, z: SupportsFloat) pyvcad.pyvcad.Vec4#
Sample the volume at the given coordinates.
- Parameters:
x (float) – X coordinate.
y (float) – Y coordinate.
z (float) – Z coordinate.
- Returns:
The sampled 4D vector value.
- Return type:
Loaders#
- class pyvcad.DICOMLoader#
A loader for DICOM image stacks that converts them to VDB volumes.
- __init__(self: pyvcad.pyvcad.DICOMLoader, directory: str, center: bool = False, rescale_slope: SupportsFloat = -inf, rescale_intercept: SupportsFloat = -inf, slice_thickness: SupportsFloat = -inf, x_pixel_spacing: SupportsFloat = -inf, y_pixel_spacing: SupportsFloat = -inf) None#
Constructor. Creates a DICOMLoader for loading DICOM image stacks.
- Parameters:
directory (str) – The directory containing the DICOM stack.
center (bool, optional) – Whether to center the volume at the origin. Default is false.
rescale_slope (double, optional) – The rescale slope to apply to pixel values.
rescale_intercept (double, optional) – The rescale intercept to apply to pixel values.
slice_thickness (double, optional) – The slice thickness in mm.
x_pixel_spacing (double, optional) – The pixel spacing in x direction in mm.
y_pixel_spacing (double, optional) – The pixel spacing in y direction in mm.
- as_volume(self: pyvcad.pyvcad.DICOMLoader) pyvcad.pyvcad.FloatVolume#
Convert the loaded DICOM stack to a VDB volume.
- Returns:
The resulting VDB volume.
- Return type:
FloatVDBVolume
- get_bounding_box(self: pyvcad.pyvcad.DICOMLoader) tuple[pyvcad.pyvcad.Vec3, pyvcad.pyvcad.Vec3]#
Get the axis-aligned bounding box of the loaded DICOM volume in mm.
- Returns:
A tuple containing two glm.vec3 vectors representing the minimum and maximum corners of the bounding box ((min_x, min_y, min_z), (max_x, max_y, max_z)).
- Return type:
tuple
- get_dimensions(self: pyvcad.pyvcad.DICOMLoader) pyvcad.pyvcad.Vec3#
Get the physical dimensions of the loaded DICOM volume in mm.
- Returns:
A vector containing the dimensions in x, y, and z directions (x_dim, y_dim, z_dim).
- Return type:
glm.vec3
- get_min_max_hu(self: pyvcad.pyvcad.DICOMLoader) tuple[float, float]#
Get the minimum and maximum Hounsfield Unit (HU) values in the loaded DICOM volume.
- Returns:
A tuple containing the minimum and maximum HU values (min_hu, max_hu).
- Return type:
tuple
- get_rescale_intercept(self: pyvcad.pyvcad.DICOMLoader) float#
Get the rescale intercept used for converting pixel values to Hounsfield Units (HU).
- Returns:
The rescale intercept.
- Return type:
double
- get_rescale_slope(self: pyvcad.pyvcad.DICOMLoader) float#
Get the rescale slope used for converting pixel values to Hounsfield Units (HU).
- Returns:
The rescale slope.
- Return type:
double
- get_voxel_size(self: pyvcad.pyvcad.DICOMLoader) pyvcad.pyvcad.Vec3#
Get the voxel size of the loaded DICOM volume in mm.
- Returns:
A vector containing the voxel size in x, y, and z directions (x_size, y_size, z_size).
- Return type:
glm.vec3
pyvcad.vdb_loader#
VDB file loading utilities