Utilities#
- class pyvcad.MaterialDefs#
Class representing material definitions that translates between material names, colors, and ids.
- __init__(*args, **kwargs)#
Overloaded function.
__init__(self: pyvcad.pyvcad.MaterialDefs) -> None
Default constructor mapping void material to id 0.
__init__(self: pyvcad.pyvcad.MaterialDefs, arg0: str) -> None
Constructor that takes a string as the path to the material configuration file.
- color(*args, **kwargs)#
Overloaded function.
color(self: pyvcad.pyvcad.MaterialDefs, arg0: typing.SupportsInt) -> pyvcad.pyvcad.Vec4
Returns the color of the material given the id.
color(self: pyvcad.pyvcad.MaterialDefs, arg0: str) -> pyvcad.pyvcad.Vec4
Returns the color of the material given the name.
- contains(self: pyvcad.pyvcad.MaterialDefs, arg0: str) bool#
Returns true if the material exists given the name.
- id(*args, **kwargs)#
Overloaded function.
id(self: pyvcad.pyvcad.MaterialDefs, arg0: str) -> int
Returns the id of the material given the name.
id(self: pyvcad.pyvcad.MaterialDefs, arg0: pyvcad.pyvcad.Vec4) -> int
Returns the id of the material given the color.
- name(self: pyvcad.pyvcad.MaterialDefs, arg0: SupportsInt) str#
Returns the name of the material given the id.
- num_materials(self: pyvcad.pyvcad.MaterialDefs) int#
Returns the number of materials.
- palette(self: pyvcad.pyvcad.MaterialDefs) list[pyvcad.pyvcad.Vec4]#
Returns a list of colors that are in the floating point range [0, 1]. The list contains 4-component colors (RGBA).
- prescaled_color_list(self: pyvcad.pyvcad.MaterialDefs) list[pyvcad.pyvcad.Vec4]#
Returns a list of colors that are prescaled to the range [0, 255]. The list contains 4-component colors (RGBA).
- update_color(self: pyvcad.pyvcad.MaterialDefs, arg0: SupportsInt, arg1: pyvcad.pyvcad.Vec4) None#
Updates the color of the material given the id. The new color of the material is specified as a 4-component color (RGBA).
- class pyvcad.ColorMap#
- __init__(self: pyvcad.pyvcad.ColorMap) None#
- add_color(self: pyvcad.pyvcad.ColorMap, value: SupportsFloat, color: pyvcad.pyvcad.Vec3) None#
- static create_grayscale() pyvcad.pyvcad.ColorMap#
- static create_inferno() pyvcad.pyvcad.ColorMap#
- static create_plasma() pyvcad.pyvcad.ColorMap#
- static create_viridis() pyvcad.pyvcad.ColorMap#
- get_color(self: pyvcad.pyvcad.ColorMap, value: SupportsFloat) pyvcad.pyvcad.Vec3#
- class pyvcad.TreeSampler#
Utility for sampling a Node into voxel-based representations.
Changing root, voxel_size, or material_defs requires constructing a new TreeSampler. Call sample_dimensions() to query the grid shape.
- __init__(self: pyvcad.pyvcad.TreeSampler, root: pyvcad.pyvcad.Node, voxel_size: pyvcad.pyvcad.Vec3, material_defs: pyvcad.pyvcad.MaterialDefs = None) None#
Create a TreeSampler for a given root node and voxel size.
- Parameters:
root (Node) – Root node of the tree to sample.
voxel_size (vec3) – Size of a voxel in world units.
material_defs (MaterialDefs, optional) – Material definitions used for color mapping.
- as_float_array(self: pyvcad.pyvcad.TreeSampler, attribute: str, progress: object = None) numpy.typing.NDArray[numpy.float32]#
Sample an attribute into a Float voxel grid.
- Parameters:
attribute (str) – Attribute name to sample.
progress (callable, optional) – Progress callback taking an int 0-100.
- Returns:
numpy_array of float32.
- as_material_fraction_array(self: pyvcad.pyvcad.TreeSampler, attribute: str, progress: object = None) numpy.typing.NDArray[numpy.float32]#
Sample a volume-fraction attribute into a per-material fraction grid.
- Parameters:
attribute (str) – Volume-fraction attribute name to sample.
progress (callable, optional) – Progress callback taking an int 0-100.
- Returns:
numpy_array of shape (num_voxels, num_materials), dtype float32.
- as_rgba_array(self: pyvcad.pyvcad.TreeSampler, attribute: str, color_map: pyvcad.pyvcad.ColorMap, blend: bool = True, progress: object = None) numpy.ndarray#
Sample an attribute into an RGBA voxel grid.
- Parameters:
attribute (str) – Attribute name to sample.
color_map (ColorMap) – Color map used to convert attributes to RGBA.
blend (bool) – Whether to blend multi-material voxels.
progress (callable, optional) – Progress callback taking an int 0-100.
- Returns:
(nx, ny, nz, numpy_array) with numpy_array of shape (nx*ny*nz*4,) and dtype uint8.
- Return type:
tuple
- as_signed_distance_array(self: pyvcad.pyvcad.TreeSampler, progress: object = None) numpy.ndarray#
Sample the tree into a signed distance field.
- Parameters:
progress (callable, optional) – Progress callback taking an int 0-100.
- Returns:
(nx, ny, nz, numpy_array) with numpy_array of shape (nx*ny*nz,) and dtype float32.
- Return type:
tuple
- as_vec3_array(self: pyvcad.pyvcad.TreeSampler, attribute: str, progress: object = None) numpy.typing.NDArray[numpy.float32]#
Sample an attribute into a Vec3 voxel grid.
- Parameters:
attribute (str) – Attribute name to sample.
progress (callable, optional) – Progress callback taking an int 0-100.
- Returns:
numpy_array of float32.
- as_vec4_array(self: pyvcad.pyvcad.TreeSampler, attribute: str, progress: object = None) numpy.typing.NDArray[numpy.float32]#
Sample an attribute into a Vec4 voxel grid.
- Parameters:
attribute (str) – Attribute name to sample.
progress (callable, optional) – Progress callback taking an int 0-100.
- Returns:
numpy_array of float32.
- clear_double_attribute_range_override(self: pyvcad.pyvcad.TreeSampler) None#
Clear any explicit scalar normalization override and return to sampled min/max.
- evaluate_points(self: pyvcad.pyvcad.TreeSampler, points: collections.abc.Sequence[pyvcad.pyvcad.Vec3], progress: object = None) list[float | None]#
Evaluate the signed-distance field at arbitrary world-space points.
The points are evaluated in parallel, and results preserve the input order.
- Parameters:
points (list[vec3]) – Points to evaluate.
progress (callable, optional) – Progress callback taking an int 0-100.
- Returns:
One signed distance or None per input point.
- Return type:
list[float | None]
- get_double_attribute_min_max(self: pyvcad.pyvcad.TreeSampler) tuple[float, float]#
Get the min and max values of the last sampled double attribute.
- Returns:
(min, max) as floats.
- Return type:
pair
- sample_dimensions(self: pyvcad.pyvcad.TreeSampler) tuple[int, int, int]#
Return the sample grid dimensions as (nx, ny, nz).
- sample_line(self: pyvcad.pyvcad.TreeSampler, start: pyvcad.pyvcad.Vec3, end: pyvcad.pyvcad.Vec3, count: SupportsInt, progress: object = None) list[tuple[float | None, AttributeSamples | None]]#
Sample the tree at evenly spaced points along a straight line.
- Parameters:
- Returns:
One (signed_distance_or_None, AttributeSamples_or_None) per sample.
- Return type:
list[tuple]
- sample_points(self: pyvcad.pyvcad.TreeSampler, points: collections.abc.Sequence[pyvcad.pyvcad.Vec3], progress: object = None) list[tuple[float | None, AttributeSamples | None]]#
Sample signed distance and attributes at arbitrary world-space points.
The points are sampled in parallel, and results preserve the input order.
- Parameters:
points (list[vec3]) – Points to sample.
progress (callable, optional) – Progress callback taking an int 0-100.
- Returns:
One (signed_distance_or_None, AttributeSamples_or_None) per point.
- Return type:
list[tuple]
- sample_points_to_colors(self: pyvcad.pyvcad.TreeSampler, points: collections.abc.Sequence[pyvcad.pyvcad.Vec3], attribute: str, color_map: pyvcad.pyvcad.ColorMap, blend: bool = True, progress: object = None) list[pyvcad.pyvcad.Vec3]#
Sample colors at arbitrary points in space.
- Parameters:
- Returns:
RGB colors for each point.
- Return type:
list[vec3]
- sample_points_to_float_array(self: pyvcad.pyvcad.TreeSampler, points: collections.abc.Sequence[pyvcad.pyvcad.Vec3], attribute: str, progress: object = None) list[float]#
Sample float attributes at arbitrary points in space.
- Parameters:
points (list[vec3]) – Points to sample.
attribute (str) – Attribute name to sample.
progress (callable, optional) – Progress callback taking an int 0-100.
- Returns:
sampled values for each point.
- Return type:
list[float]
- sample_points_to_material_fraction_array(self: pyvcad.pyvcad.TreeSampler, points: collections.abc.Sequence[pyvcad.pyvcad.Vec3], attribute: str, progress: object = None) numpy.typing.NDArray[numpy.float32]#
Sample a volume-fraction attribute at arbitrary points into a per-material fraction array.
- Parameters:
points (list[vec3]) – Points to sample.
attribute (str) – Volume-fraction attribute name to sample.
progress (callable, optional) – Progress callback taking an int 0-100.
- Returns:
(num_points, num_materials) float32 array of per-material fractions.
- Return type:
numpy.ndarray
- sample_points_to_vec3_array(self: pyvcad.pyvcad.TreeSampler, points: collections.abc.Sequence[pyvcad.pyvcad.Vec3], attribute: str, progress: object = None) list[pyvcad.pyvcad.Vec3]#
Sample vec3 attributes at arbitrary points in space.
- sample_points_to_vec4_array(self: pyvcad.pyvcad.TreeSampler, points: collections.abc.Sequence[pyvcad.pyvcad.Vec3], attribute: str, progress: object = None) list[pyvcad.pyvcad.Vec4]#
Sample vec4 attributes at arbitrary points in space.
- save_openvdb_occupancy_grid(self: pyvcad.pyvcad.TreeSampler, file_path: str, progress: object = None) None#
Sample the tree into a boolean occupancy grid and save it to a VDB file.
The output file contains a single OpenVDB BoolGrid named ‘occupancy’. Voxels are occupied where the sampled signed distance is <= 0.
- Parameters:
file_path (str) – VDB file path to write.
progress (callable, optional) – Progress callback taking an int 0-100.
- set_double_attribute_range_override(self: pyvcad.pyvcad.TreeSampler, min_value: SupportsFloat, max_value: SupportsFloat) None#
Override scalar normalization min/max for double-valued attribute coloring.
- Parameters:
min_value (float) – Minimum scalar value.
max_value (float) – Maximum scalar value.
- set_undefined_attribute_pattern_enabled(self: pyvcad.pyvcad.TreeSampler, enabled: bool) None#
Enable or disable the undefined-attribute stripe pattern.
When enabled (default True), inside voxels/points missing the selected attribute are rendered with a subtle world-space stripe pattern instead of plain gray.
- Parameters:
enabled (bool) – True to show the pattern, False for plain gray.
Surface probing#
Interrogate a prepared tree for where its surface is and which way it faces, and
turn a normal into the angles a Rotate node wants. See the
examples/surface_probe scripts for the full workflow.
- class pyvcad.SurfaceProbeResult#
The result of probing a prepared tree for its surface. Carries the surface position, the outward unit normal at that position, and the residual signed distance left after the probe converged.
- property hit#
True when the probe converged onto the surface. The position and normal are only meaningful when this is True.
- Type:
bool
- property normal#
The outward unit surface normal at the position, pointing away from the solid.
- Type:
- property signed_distance#
The residual signed distance at the position. Near zero for a converged probe.
- Type:
float
- pyvcad.probe_point(node: pyvcad.pyvcad.Node, point: pyvcad.pyvcad.Vec3, tolerance: SupportsFloat = 0.0001, max_iterations: SupportsInt = 16) pyvcad.pyvcad.SurfaceProbeResult#
Projects a point onto the nearest surface of a prepared tree and reports the normal there.
The starting point may be inside, outside, or already on the surface; it is walked down the signed distance field until it lands on the surface. This is the query behind the renderer’s Probe tool: pick a point on screen, then ask what the surface is doing there.
- Parameters:
node (Node) – The prepared node to interrogate. Call prepare() first.
point (Vec3) – The starting point in world coordinates.
tolerance (float, optional) – The signed distance that counts as on the surface. Defaults to 1e-4.
max_iterations (int, optional) – The maximum number of steps to take. Defaults to 16.
- Returns:
The surface position, unit normal, and residual signed distance.
- Return type:
Example
>>> import pyvcad as pv >>> sphere = pv.Sphere(pv.Vec3(0, 0, 0), 10.0) >>> sphere.prepare(pv.Vec3(0.2, 0.2, 0.2), 1.0) >>> probe = pv.probe_point(sphere, pv.Vec3(8.0, 0.0, 0.0)) >>> print(probe.position.x, probe.normal.x) 10.0 1.0
- pyvcad.probe_ray(node: pyvcad.pyvcad.Node, origin: pyvcad.pyvcad.Vec3, direction: pyvcad.pyvcad.Vec3, step_size: SupportsFloat = 0.0, tolerance: SupportsFloat = 0.0001) pyvcad.pyvcad.SurfaceProbeResult#
Casts a ray at a prepared tree and reports the first surface it enters.
The ray is clipped to the node’s bounding box, marched until it crosses into the solid, and then refined onto the surface. This is the query a viewport pick maps onto, with the camera position as the origin and the unprojected click as the direction.
- Parameters:
node (Node) – The prepared node to interrogate. Call prepare() first.
origin (Vec3) – The ray origin in world coordinates.
direction (Vec3) – The ray direction. Need not be normalized, but must not be zero length.
step_size (float, optional) – The march step in mm. Pass 0 to derive one from the bounding box.
tolerance (float, optional) – The signed distance that counts as on the surface. Defaults to 1e-4.
- Returns:
The entry point, unit normal, and residual signed distance. hit is False when the ray misses the node.
- Return type:
Example
>>> import pyvcad as pv >>> sphere = pv.Sphere(pv.Vec3(0, 0, 0), 10.0) >>> sphere.prepare(pv.Vec3(0.2, 0.2, 0.2), 1.0) >>> probe = pv.probe_ray(sphere, pv.Vec3(50.0, 0.0, 0.0), pv.Vec3(-1.0, 0.0, 0.0)) >>> print(probe.hit, probe.position.x) True 10.0
- pyvcad.surface_normal(node: pyvcad.pyvcad.Node, point: pyvcad.pyvcad.Vec3) pyvcad.pyvcad.Vec3#
Returns the outward unit surface normal of a prepared tree at a point.
This is the normalized signed distance gradient. Away from the surface it is the direction of steepest increase of the field. Returns a zero vector when the gradient is degenerate.
- Parameters:
- Returns:
The outward unit normal.
- Return type:
Example
>>> import pyvcad as pv >>> sphere = pv.Sphere(pv.Vec3(0, 0, 0), 10.0) >>> sphere.prepare(pv.Vec3(0.2, 0.2, 0.2), 1.0) >>> normal = pv.surface_normal(sphere, pv.Vec3(0.0, 10.0, 0.0)) >>> print(normal.y) 1.0
- pyvcad.alignment_angles(forward: pyvcad.pyvcad.Vec3, up: pyvcad.pyvcad.Vec3 = <pyvcad.pyvcad.Vec3 object at 0x1123ac7f0>) pyvcad.pyvcad.Vec3#
Computes the Rotate angles that aim a child node’s local axes along a chosen frame.
The child’s local +Z is aimed along forward and its local +Y along up. up only has to be roughly right: it is orthogonalized against forward, and a world axis is substituted when the two are parallel.
The Text node extrudes along +Z, so passing a surface normal as forward stands text up off that surface. Text builds its glyphs on a flipped X axis, which puts their visual up along its own -Y, so pass the negated world up to get text that reads upright.
- Parameters:
- Returns:
Euler angles in degrees, packed as (pitch, yaw, roll) for the Rotate node.
- Return type:
Example
>>> import pyvcad as pv >>> probe = pv.probe_point(sphere, pv.Vec3(8.0, 0.0, 0.0)) >>> angles = pv.alignment_angles(probe.normal, pv.Vec3(0, 0, -1)) >>> facing_text = pv.Rotate(angles, text)