Utilities#

class pyvcad.MaterialDefs#

Class representing material definitions that translates between material names, colors, and ids.

__init__(*args, **kwargs)#

Overloaded function.

  1. __init__(self: pyvcad.pyvcad.MaterialDefs) -> None

Default constructor mapping void material to id 0.

  1. __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.

  1. color(self: pyvcad.pyvcad.MaterialDefs, arg0: typing.SupportsInt) -> pyvcad.pyvcad.Vec4

Returns the color of the material given the id.

  1. 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.

  1. id(self: pyvcad.pyvcad.MaterialDefs, arg0: str) -> int

Returns the id of the material given the name.

  1. 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:
  • start (vec3) – World-space start of the line.

  • end (vec3) – World-space end of the line.

  • count (int) – Number of samples along the line (minimum 2).

  • progress (callable, optional) – Progress callback taking an int 0-100.

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:
  • points (list[vec3]) – Points to sample.

  • attribute (str) – Attribute name to sample.

  • color_map (ColorMap) – Color map for attributes.

  • blend (bool) – Whether to blend multi-material samples.

  • progress (callable, optional) – Progress callback taking an int 0-100.

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.

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[vec3]

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.

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[vec4]

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:

Vec3

property position#

The point on the surface, in world coordinates.

Type:

Vec3

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:

SurfaceProbeResult

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:

SurfaceProbeResult

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:
  • node (Node) – The prepared node to interrogate. Call prepare() first.

  • point (Vec3) – The point to evaluate, in world coordinates.

Returns:

The outward unit normal.

Return type:

Vec3

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:
  • forward (Vec3) – The world direction the child’s local +Z should point along.

  • up (Vec3, optional) – The world direction the child’s local +Y should point along. Defaults to world +Z.

Returns:

Euler angles in degrees, packed as (pitch, yaw, roll) for the Rotate node.

Return type:

Vec3

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)