Geometry#

2D and 3D geometry types used internally by OpenVCAD. You may not need to use these directly, but they are useful for creating custom geometry.

class pyvcad.Point2#
__init__(*args, **kwargs)#

Overloaded function.

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

Default constructor creating a point at origin (0,0)

Example

>>> p = Point2()
>>> print(f'({p.x()}, {p.y()})')
(0.0, 0.0)
  1. __init__(self: pyvcad.pyvcad.Point2, arg0: typing.SupportsFloat, arg1: typing.SupportsFloat) -> None

Create a 2D point with given x and y coordinates

Parameters:
  • x (float) – X coordinate

  • y (float) – Y coordinate

Example

>>> p = Point2(1.0, 2.0)
>>> print(f'({p.x()}, {p.y()})')
(1.0, 2.0)
x(self: pyvcad.pyvcad.Point2) float#

Get the x coordinate of the point

Returns:

X coordinate

Return type:

float

y(self: pyvcad.pyvcad.Point2) float#

Get the y coordinate of the point

Returns:

Y coordinate

Return type:

float

class pyvcad.Segment2#
__init__(self: pyvcad.pyvcad.Segment2, arg0: pyvcad.pyvcad.Point2, arg1: pyvcad.pyvcad.Point2) None#

Create a 2D line segment between two points

Parameters:
  • p1 (Point2) – The first point of the segment

  • p2 (Point2) – The second point of the segment

Example

>>> p1 = Point2(0.0, 0.0)
>>> p2 = Point2(1.0, 1.0)
>>> segment = Segment2(p1, p2)
>>> source = segment.source()
>>> target = segment.target()
>>> print(f'From ({source.x()}, {source.y()}) to ({target.x()}, {target.y()})')
From (0.0, 0.0) to (1.0, 1.0)
source(self: pyvcad.pyvcad.Segment2) pyvcad.pyvcad.Point2#

Returns the source point of the segment

Returns:

The starting point of the segment

Return type:

Point2

target(self: pyvcad.pyvcad.Segment2) pyvcad.pyvcad.Point2#

Returns the target point of the segment

Returns:

The ending point of the segment

Return type:

Point2

class pyvcad.Vec2#
__init__(*args, **kwargs)#

Overloaded function.

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

Default constructor creating a zero vector (0,0)

Example

>>> v = Vec2()
>>> print(f'({v.x}, {v.y})')
(0.0, 0.0)
  1. __init__(self: pyvcad.pyvcad.Vec2, arg0: typing.SupportsFloat, arg1: typing.SupportsFloat) -> None

Create a 2D vector with given x and y components

Parameters:
  • x (float) – X component

  • y (float) – Y component

Example

>>> v = Vec2(1.0, 2.0)
>>> print(f'({v.x}, {v.y})')
(1.0, 2.0)
property x#

X component of the vector

property y#

Y component of the vector

class pyvcad.Vec3#
__init__(*args, **kwargs)#

Overloaded function.

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

Default constructor creating a zero vector (0,0,0)

Example

>>> v = Vec3()
>>> print(f'({v.x}, {v.y}, {v.z})')
(0.0, 0.0, 0.0)
  1. __init__(self: pyvcad.pyvcad.Vec3, arg0: typing.SupportsFloat, arg1: typing.SupportsFloat, arg2: typing.SupportsFloat) -> None

Create a 3D vector with given x, y, and z components

Parameters:
  • x (float) – X component

  • y (float) – Y component

  • z (float) – Z component

Example

>>> v = Vec3(1.0, 2.0, 3.0)
>>> print(f'({v.x}, {v.y}, {v.z})')
(1.0, 2.0, 3.0)
  1. __init__(self: pyvcad.pyvcad.Vec3, arg0: collections.abc.Sequence[typing.SupportsFloat]) -> None

Create a 3D vector from a list or tuple of 3 floats

Example

>>> v = Vec3([1.0, 2.0, 3.0])
>>> print(f'({v.x}, {v.y}, {v.z})')
(1.0, 2.0, 3.0)
property x#

X component of the vector

property y#

Y component of the vector

property z#

Z component of the vector

class pyvcad.Vec4#
__init__(*args, **kwargs)#

Overloaded function.

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

Default constructor creating a zero vector (0,0,0,0)

Example

>>> v = Vec4()
>>> print(f'({v.r}, {v.g}, {v.b}, {v.a})')
(0.0, 0.0, 0.0, 0.0)
  1. __init__(self: pyvcad.pyvcad.Vec4, arg0: typing.SupportsFloat, arg1: typing.SupportsFloat, arg2: typing.SupportsFloat, arg3: typing.SupportsFloat) -> None

Create a 4D vector with given r, g, b, and a components

Parameters:
  • r (float) – Red component

  • g (float) – Green component

  • b (float) – Blue component

  • a (float) – Alpha component

Example

>>> v = Vec4(1.0, 0.0, 0.0, 1.0)  # Red color with full opacity
>>> print(f'({v.r}, {v.g}, {v.b}, {v.a})')
(1.0, 0.0, 0.0, 1.0)
property a#

Alpha component of the vector

property b#

Blue component of the vector

property g#

Green component of the vector

property r#

Red component of the vector

class pyvcad.Polygon2#
static Clip(arg0: collections.abc.Sequence[pyvcad.pyvcad.Polygon2], arg1: collections.abc.Sequence[Polyline2]) tuple[list[pyvcad.pyvcad.Polygon2], list[Polyline2]]#
static Difference(arg0: collections.abc.Sequence[pyvcad.pyvcad.Polygon2], arg1: collections.abc.Sequence[pyvcad.pyvcad.Polygon2]) list[pyvcad.pyvcad.Polygon2]#
static Intersection(arg0: collections.abc.Sequence[pyvcad.pyvcad.Polygon2], arg1: collections.abc.Sequence[pyvcad.pyvcad.Polygon2]) list[pyvcad.pyvcad.Polygon2]#
static Offset(arg0: collections.abc.Sequence[pyvcad.pyvcad.Polygon2], arg1: SupportsFloat) list[pyvcad.pyvcad.Polygon2]#
static Union(arg0: collections.abc.Sequence[pyvcad.pyvcad.Polygon2], arg1: collections.abc.Sequence[pyvcad.pyvcad.Polygon2]) list[pyvcad.pyvcad.Polygon2]#
__init__(*args, **kwargs)#

Overloaded function.

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

  2. __init__(self: pyvcad.pyvcad.Polygon2, arg0: collections.abc.Sequence[pyvcad.pyvcad.Point2]) -> None

  3. __init__(self: pyvcad.pyvcad.Polygon2, arg0: collections.abc.Sequence[pyvcad.pyvcad.Vec2]) -> None

bounding_box(self: pyvcad.pyvcad.Polygon2) tuple[pyvcad.pyvcad.Point2, pyvcad.pyvcad.Point2]#
diff(self: pyvcad.pyvcad.Polygon2, arg0: pyvcad.pyvcad.Polygon2) list[pyvcad.pyvcad.Polygon2]#
do_clip(self: pyvcad.pyvcad.Polygon2, arg0: collections.abc.Sequence[Polyline2]) tuple[list[pyvcad.pyvcad.Polygon2], list[Polyline2]]#
do_union(*args, **kwargs)#

Overloaded function.

  1. do_union(self: pyvcad.pyvcad.Polygon2, arg0: pyvcad.pyvcad.Polygon2) -> list[pyvcad.pyvcad.Polygon2]

  2. do_union(self: pyvcad.pyvcad.Polygon2, arg0: collections.abc.Sequence[pyvcad.pyvcad.Polygon2]) -> list[pyvcad.pyvcad.Polygon2]

double_area(self: pyvcad.pyvcad.Polygon2) float#
draw(self: pyvcad.pyvcad.Polygon2) None#
holes(self: pyvcad.pyvcad.Polygon2) list[pyvcad.pyvcad.Polygon2]#
inside(self: pyvcad.pyvcad.Polygon2, arg0: pyvcad.pyvcad.Point2) bool#
intersect(*args, **kwargs)#

Overloaded function.

  1. intersect(self: pyvcad.pyvcad.Polygon2, arg0: pyvcad.pyvcad.Polygon2) -> list[pyvcad.pyvcad.Polygon2]

  2. intersect(self: pyvcad.pyvcad.Polygon2, arg0: collections.abc.Sequence[pyvcad.pyvcad.Polygon2]) -> list[pyvcad.pyvcad.Polygon2]

is_ccw(self: pyvcad.pyvcad.Polygon2) bool#
offset(self: pyvcad.pyvcad.Polygon2, arg0: SupportsFloat) list[pyvcad.pyvcad.Polygon2]#
on_boundary(self: pyvcad.pyvcad.Polygon2, arg0: pyvcad.pyvcad.Point2) bool#
reverse(self: pyvcad.pyvcad.Polygon2) None#
set_holes(self: pyvcad.pyvcad.Polygon2, arg0: collections.abc.Sequence[pyvcad.pyvcad.Polygon2]) None#
simplify(self: pyvcad.pyvcad.Polygon2, tolerance: SupportsFloat = 0.001) None#
to_polyline(self: pyvcad.pyvcad.Polygon2) Polyline2#
class pyvcad.Polyline2#
__init__(*args, **kwargs)#

Overloaded function.

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

  2. __init__(self: pyvcad.pyvcad.Polyline2, arg0: collections.abc.Sequence[pyvcad.pyvcad.Point2]) -> None

  3. __init__(self: pyvcad.pyvcad.Polyline2, arg0: collections.abc.Sequence[pyvcad.pyvcad.Vec2]) -> None

append(self: pyvcad.pyvcad.Polyline2, arg0: pyvcad.pyvcad.Polyline2) None#
length(self: pyvcad.pyvcad.Polyline2) float#
points(self: pyvcad.pyvcad.Polyline2) list[pyvcad.pyvcad.Point2]#
prepend(self: pyvcad.pyvcad.Polyline2, arg0: pyvcad.pyvcad.Polyline2) None#
reverse(self: pyvcad.pyvcad.Polyline2) None#
segments(self: pyvcad.pyvcad.Polyline2) list[pyvcad.pyvcad.Segment2]#
simplify(self: pyvcad.pyvcad.Polyline2, tolerance: SupportsFloat = 0.001) None#
translate(self: pyvcad.pyvcad.Polyline2, arg0: pyvcad.pyvcad.Point2) None#
class pyvcad.Arrangement2#

A class representing a 2D arrangement of polygons and polylines. When polygons and polylines are inserted into the arrangement, they are split by each other and the resulting faces are stored in the arrangement.

__init__(self: pyvcad.pyvcad.Arrangement2) None#

Default constructor. Creates an Arrangement2 object.

getBoundedFaces(self: pyvcad.pyvcad.Arrangement2) list[pyvcad.pyvcad.Polygon2]#

Returns a list of all bounded faces in the arrangement.

getUnboundedFaces(self: pyvcad.pyvcad.Arrangement2) list[pyvcad.pyvcad.Polygon2]#

Returns a list of all unbounded faces in the arrangement.

insert(*args, **kwargs)#

Overloaded function.

  1. insert(self: pyvcad.pyvcad.Arrangement2, polygon: pyvcad.pyvcad.Polygon2) -> None

Inserts a Polygon2 into the arrangement.

Parameters:

polygon (Polygon2) – The polygon to insert.

  1. insert(self: pyvcad.pyvcad.Arrangement2, polyline: pyvcad.pyvcad.Polyline2) -> None

Inserts a Polyline2 into the arrangement.

Parameters:

polyline (Polyline2) – The polyline to insert.

class pyvcad.HexahedralMesh#

Structured geometric hexahedral mesh.

__init__(self: pyvcad.pyvcad.HexahedralMesh) None#
bounding_box(self: pyvcad.pyvcad.HexahedralMesh) tuple[pyvcad.pyvcad.Vec3, pyvcad.pyvcad.Vec3]#

Returns the mesh bounding box.

property cell_centroids#

Centroid of each element.

property elements#

Hexahedral element connectivity.

static from_tree(root: pyvcad.pyvcad.Node, settings: pyvcad.pyvcad.HexahedralMeshSettings) pyvcad.pyvcad.HexahedralMesh#

Build a structured hexahedral mesh from a tree.

property nodes#

Mesh node coordinates.

number_of_elements(self: pyvcad.pyvcad.HexahedralMesh) int#

Returns the number of elements.

number_of_nodes(self: pyvcad.pyvcad.HexahedralMesh) int#

Returns the number of nodes.

voxel_size(self: pyvcad.pyvcad.HexahedralMesh) pyvcad.pyvcad.Vec3#

Returns the voxel size used to build the mesh.

class pyvcad.CADModel#

A topology-preserving CAD model shared by selected faces and implicit CAD nodes.

__init__(*args, **kwargs)#
face(self: pyvcad.pyvcad.CADModel, index: SupportsInt) pyvcad.pyvcad.CADFace#

Return one face by stable index.

Parameters:

index (int) – Zero-based face index.

Example

>>> face = model.face(0)
property faces#

All faces in stable model order.

static from_brep(path: str) pyvcad.pyvcad.CADModel#

Load an ASCII BREP model.

Parameters:

path (str) – BREP file path.

Example

>>> model = pv.CADModel.from_brep('part.brep')
static from_brep_bytes(data: bytes) pyvcad.pyvcad.CADModel#

Load in-memory ASCII BREP bytes.

Parameters:

data (bytes) – ASCII BREP stream contents.

Example

>>> model = pv.CADModel.from_brep_bytes(data)
static from_cadquery(value: object) pyvcad.pyvcad.CADModel#

Convert a CadQuery workplane, shape, or shape selection into a topology-preserving CAD model.

CadQuery is optional. Install OpenVCAD[cad] before calling this method.

Parameters:

value (object) – CadQuery workplane, shape, or iterable of shapes to retain.

Example

>>> import cadquery as cq
>>> model = pv.CADModel.from_cadquery(cq.Workplane('XY').box(10, 10, 10))
static from_iges(path: str) pyvcad.pyvcad.CADModel#

Load an IGES model.

Parameters:

path (str) – IGES or IGS file path.

Example

>>> model = pv.CADModel.from_iges('part.iges')
static from_step(path: str) pyvcad.pyvcad.CADModel#

Load a STEP model.

Parameters:

path (str) – STEP or STP file path.

Example

>>> model = pv.CADModel.from_step('part.step')
select_faces(self: pyvcad.pyvcad.CADModel, indices: collections.abc.Sequence[SupportsInt] = [], surface_type: object = None, normal: object = None, min_dot: SupportsFloat = -1.0, area_range: object = None, bounding_box_intersection: object = None) list[pyvcad.pyvcad.CADFace]#

Select imported CAD faces using stable geometric filters.

Parameters:
  • indices (list[int]) – Optional stable indices.

  • surface_type (str | None) – Canonical surface type.

  • normal (Vec3 | None) – Requested representative direction.

  • min_dot (float) – Minimum normal-direction dot product.

  • area_range (tuple[float, float] | None) – Inclusive area limits.

  • bounding_box_intersection (tuple[Vec3, Vec3] | None) – Required box overlap.

Example

>>> upward = model.select_faces(normal=pv.Vec3(0, 0, 1), min_dot=0.8)
to_node(self: pyvcad.pyvcad.CADModel, use_fast_mode: bool = False) CAD#

Convert the retained CAD model into an implicit CAD node without reparsing.

Parameters:

use_fast_mode (bool) – Build a discretized accelerated SDF during prepare.

Example

>>> node = model.to_node(use_fast_mode=False)
class pyvcad.CADFace#

A stable topology-preserving face selected from a CADModel.

__init__(*args, **kwargs)#
property area#

Face area in square millimetres.

property boundary_loop_count#

Number of trimming boundary loops.

property bounding_box#

World-coordinate face bounding box.

property centroid#

Area centroid in world coordinates.

property index#

Stable zero-based face index within the parent model.

property is_trimmed#

Whether the face has nontrivial trimming.

property normal#

Representative oriented unit normal.

property outward_orientation_validated#

Whether this face normal was validated against the owning CAD solid.

property surface_type#

Canonical CAD surface type name.

class pyvcad.ParametricSurface#

Abstract surface evaluated on a rectangular UV domain, shared by CADFace and TriangleMeshSurface so either can drive a CellMap.

property bounding_box#

World-space bounding box of the selected surface.

contains(self: pyvcad.pyvcad.ParametricSurface, u: SupportsFloat, v: SupportsFloat, tolerance: SupportsFloat = 1e-07) bool#

Test whether native UV coordinates lie on the surface.

Parameters:
  • u (float) – Native U coordinate.

  • v (float) – Native V coordinate.

  • tolerance (float) – Parametric tolerance for near-boundary coordinates.

Example

>>> inside = surface.contains(0.5, 0.5)
normal_at(self: pyvcad.pyvcad.ParametricSurface, u: SupportsFloat, v: SupportsFloat) pyvcad.pyvcad.Vec3#

Evaluate the oriented unit normal at native UV coordinates.

Parameters:
  • u (float) – Native U coordinate.

  • v (float) – Native V coordinate.

Example

>>> direction = surface.normal_at(0.5, 0.5)
property outward_orientation_validated#

Whether positive normal orientation was validated against a source solid.

point(self: pyvcad.pyvcad.ParametricSurface, u: SupportsFloat, v: SupportsFloat) pyvcad.pyvcad.Vec3#

Evaluate the surface position at native UV coordinates.

Parameters:
  • u (float) – Native U coordinate.

  • v (float) – Native V coordinate.

Example

>>> position = surface.point(0.5, 0.5)
property u_periodic#

Whether the native U direction wraps through a seam.

property uv_bounds#

Native parameter rectangle as (minimum, maximum) UV corners.

property v_periodic#

Whether the native V direction wraps through a seam.

class pyvcad.TriangleMeshSurface#

An immutable triangle-mesh disk patch flattened into a UV chart so it can drive a CellMap like a CAD face. The flattening method is selectable: ‘lscm’ (default, free-boundary near-conformal), ‘arap’ (free-boundary as-rigid-as-possible), or ‘authalic’ (circular-border iterative area-preserving). Free-boundary charts keep the patch’s natural outline inside their UV bounding rectangle; contains() reports the real boundary so CellMap trimming stops the lattice at the patch edge. If the requested map folds, a guaranteed-injective convex-border mean-value parameterization is used instead.

__init__(*args, **kwargs)#

Overloaded function.

  1. __init__(self: pyvcad.pyvcad.TriangleMeshSurface, surface_mesh: pyvcad.pyvcad.SurfaceMesh, u_axis_hint: pyvcad.pyvcad.Vec3 | None = None, method: str = ‘lscm’) -> None

Parameterize an existing SurfaceMesh disk patch.

Parameters:
  • surface_mesh (SurfaceMesh) – Source disk patch; its data is copied.

  • u_axis_hint (Vec3, optional) – World-space direction the chart’s u-axis should follow across the patch.

  • method (str) – Flattening method: ‘lscm’, ‘arap’, or ‘authalic’.

Example

>>> surface = pv.TriangleMeshSurface(mesh, method='arap')
  1. __init__(self: pyvcad.pyvcad.TriangleMeshSurface, path: str, u_axis_hint: pyvcad.pyvcad.Vec3 | None = None, method: str = ‘lscm’) -> None

Load and parameterize a disk patch from a mesh file.

Parameters:
  • path (str) – Mesh file path. The closed-mesh check is bypassed, then stricter disk validation is applied.

  • u_axis_hint (Vec3, optional) – World-space direction the chart’s u-axis should follow across the patch.

  • method (str) – Flattening method: ‘lscm’, ‘arap’, or ‘authalic’.

Example

>>> surface = pv.TriangleMeshSurface('patch.obj')
  1. __init__(self: pyvcad.pyvcad.TriangleMeshSurface, vertices: collections.abc.Sequence[pyvcad.pyvcad.Vec3], triangles: collections.abc.Sequence[typing.Annotated[collections.abc.Sequence[typing.SupportsInt], “FixedSize(3)”]], u_axis_hint: pyvcad.pyvcad.Vec3 | None = None, method: str = ‘lscm’) -> None

Parameterize a disk patch from raw vertices and indexed triangles.

Parameters:
  • vertices (list[Vec3]) – Patch vertices.

  • triangles (list[tuple[int, int, int]]) – Consistently wound triangles.

  • u_axis_hint (Vec3, optional) – World-space direction the chart’s u-axis should follow across the patch.

  • method (str) – Flattening method: ‘lscm’, ‘arap’, or ‘authalic’.

Example

>>> surface = pv.TriangleMeshSurface(vertices, triangles)
property bounding_box#

World-space bounding box of the patch.

static from_selection(source_mesh: pyvcad.pyvcad.SurfaceMesh, triangle_ids: collections.abc.Sequence[SupportsInt], u_axis_hint: pyvcad.pyvcad.Vec3 | None = None) pyvcad.pyvcad.TriangleMeshSurface#

Extract and parameterize an explicitly selected open disk patch from a closed outward-oriented source mesh. Source triangle winding is preserved.

Parameters:
  • source_mesh (SurfaceMesh) – Watertight source mesh retained unchanged.

  • triangle_ids (list[int]) – Stable source triangle indices.

  • u_axis_hint (Vec3, optional) – World-space chart U direction.

mesh(self: pyvcad.pyvcad.TriangleMeshSurface) pyvcad.pyvcad.SurfaceMesh#

Return an immutable copy of the patch as a SurfaceMesh.

Example

>>> patch_mesh = surface.mesh()
property parameterization_method#

‘free_boundary_lscm’, ‘free_boundary_arap’, or ‘convex_border_iterative_authalic’ for the requested primary map, or ‘convex_border_mean_value’ when the guaranteed-injective fallback was used.

property source_triangle_ids#

Selected source triangle IDs, or an empty list for a standalone patch.

property triangle_count#

Number of patch triangles.

property uv_coordinates#

Per-vertex chart coordinates inside the reported UV bounds.

property vertex_count#

Number of patch vertices.

property vertex_normals#

Per-vertex angle-weighted unit normals.

property vertices#

Patch vertices.

class pyvcad.ImageHeightField#

Mip-filtered grayscale/luminance PNG height map. Image values map to [0, amplitude_mm], and normalized (u, v) = (0, 0) is the lower-left image corner.

__init__(self: pyvcad.pyvcad.ImageHeightField, path: str, amplitude_mm: SupportsFloat, channel: str = 'luminance', mapping: str = 'fit', repeats: Annotated[collections.abc.Sequence[SupportsInt], 'FixedSize(2)'] = [1, 1]) None#
property amplitude_mm#
property channel#
property height#
property mapping#
property mip_level_count#
property path#
property repeats#
sample(self: pyvcad.pyvcad.ImageHeightField, u: SupportsFloat, v: SupportsFloat, millimeters_per_u: SupportsFloat = 1.0, millimeters_per_v: SupportsFloat = 1.0, voxel_size: pyvcad.pyvcad.Vec3 = <pyvcad.pyvcad.Vec3 object at 0x107568f70>) float#

Sample the filtered physical height at normalized UV coordinates.

property width#
class pyvcad.FunctionalHeightField#

Height source backed by a FloatAttribute sampled at normalized UV coordinates (x=u, y=v, z=0, d=0). The result is clamped to [0, 1] then scaled by amplitude_mm.

__init__(self: pyvcad.pyvcad.FunctionalHeightField, function: FloatAttribute, amplitude_mm: SupportsFloat) None#
property amplitude_mm#
sample(self: pyvcad.pyvcad.FunctionalHeightField, u: SupportsFloat, v: SupportsFloat, millimeters_per_u: SupportsFloat = 1.0, millimeters_per_v: SupportsFloat = 1.0, voxel_size: pyvcad.pyvcad.Vec3 = <pyvcad.pyvcad.Vec3 object at 0x107568830>) float#

Sample the clamped physical height at normalized UV coordinates.

class pyvcad.TrimMode#

Strategy for restricting a surface-built cell map to the surface’s true domain.

Members:

none : Keep the full rectangular logical domain; nothing is removed.

cells : Deactivate whole logical elements outside the surface domain (blocky).

boundary : Clip smoothly at the surface’s true boundary curve (default).

boundary = <TrimMode.boundary: 2>#
cells = <TrimMode.cells: 1>#
TrimMode.name -> str
none = <TrimMode.none: 0>#
property value#
class pyvcad.CellMap#

An immutable structured curvilinear coordinate map.

__init__(*args, **kwargs)#
static between_cad_faces(first: pyvcad.pyvcad.CADFace, second: pyvcad.pyvcad.CADFace, cells: typing.Annotated[collections.abc.Sequence[typing.SupportsInt], "FixedSize(3)"], linear: bool = False, trim: pyvcad.pyvcad.TrimMode = <TrimMode.boundary: 2>, auto_align: bool = True, flip_u: bool = False, flip_v: bool = False, exchange_uv: bool = False, first_origin: typing.Annotated[collections.abc.Sequence[typing.SupportsFloat], "FixedSize(2)"] | None = None, second_origin: typing.Annotated[collections.abc.Sequence[typing.SupportsFloat], "FixedSize(2)"] | None = None) pyvcad.pyvcad.CellMap#

Construct a curvilinear volume between two CAD faces.

Parameters:
  • first (CADFace) – First boundary face.

  • second (CADFace) – Second boundary face.

  • cells (tuple[int, int, int]) – Positive U/V/W counts.

  • linear (bool) – Use linear rather than midpoint-sampled curved cells.

  • trim (TrimMode) – How to restrict the map to the faces’ common true domain.

  • auto_align (bool) – Search compatible UV symmetries.

  • flip_u (bool) – Flip the second U direction in advanced mode.

  • flip_v (bool) – Flip the second V direction in advanced mode.

  • exchange_uv (bool) – Exchange second-face U and V in advanced mode.

  • first_origin (tuple[float, float] | None) – Normalized periodic UV origin shift.

  • second_origin (tuple[float, float] | None) – Normalized periodic UV origin shift.

Example

>>> cell_map = pv.CellMap.between_cad_faces(first, second, (12, 8, 3))
static between_surfaces(first: pyvcad.pyvcad.ParametricSurface, second: pyvcad.pyvcad.ParametricSurface, cells: typing.Annotated[collections.abc.Sequence[typing.SupportsInt], "FixedSize(3)"], linear: bool = False, trim: pyvcad.pyvcad.TrimMode = <TrimMode.boundary: 2>, auto_align: bool = True, flip_u: bool = False, flip_v: bool = False, exchange_uv: bool = False, first_origin: typing.Annotated[collections.abc.Sequence[typing.SupportsFloat], "FixedSize(2)"] | None = None, second_origin: typing.Annotated[collections.abc.Sequence[typing.SupportsFloat], "FixedSize(2)"] | None = None) pyvcad.pyvcad.CellMap#

Construct a curvilinear volume between two parametric surfaces of any type.

Parameters:
  • first (ParametricSurface) – First boundary surface.

  • second (ParametricSurface) – Second boundary surface.

  • cells (tuple[int, int, int]) – Positive U/V/W counts.

  • linear (bool) – Use linear rather than midpoint-sampled curved cells.

  • trim (TrimMode) – How to restrict the map to the surfaces’ common true domain.

  • auto_align (bool) – Search compatible UV symmetries.

  • flip_u (bool) – Flip the second U direction in advanced mode.

  • flip_v (bool) – Flip the second V direction in advanced mode.

  • exchange_uv (bool) – Exchange second-surface U and V in advanced mode.

  • first_origin (tuple[float, float] | None) – Normalized periodic UV origin shift.

  • second_origin (tuple[float, float] | None) – Normalized periodic UV origin shift.

Example

>>> cell_map = pv.CellMap.between_surfaces(first, second, (12, 8, 3))
property bounds#

World-coordinate bounding box.

property cell_index#

Deterministically owned integer cell index as a Vec3Attribute adapter.

property cells#

Positive logical U/V/W cell counts.

static cylindrical(center: pyvcad.pyvcad.Vec3, inner_radius: typing.SupportsFloat, outer_radius: typing.SupportsFloat, height: typing.SupportsFloat, cells: typing.Annotated[collections.abc.Sequence[typing.SupportsInt], "FixedSize(3)"], axis: pyvcad.pyvcad.Vec3 = <pyvcad.pyvcad.Vec3 object at 0x10757d7b0>, reference_direction: pyvcad.pyvcad.Vec3 = <pyvcad.pyvcad.Vec3 object at 0x10757d7f0>, start_angle_degrees: typing.SupportsFloat = 0.0, sweep_degrees: typing.SupportsFloat = 360.0, linear: bool = False) pyvcad.pyvcad.CellMap#

Construct an analytic annular-cylinder map.

U follows azimuth, V follows the cylinder axis from lower to upper, and W follows radius from the inner to the outer boundary.

Parameters:
  • center (Vec3) – Axial midpoint in millimetres.

  • inner_radius (float) – Positive inner radius in millimetres.

  • outer_radius (float) – Outer radius in millimetres.

  • height (float) – Positive total axial height in millimetres.

  • cells (tuple[int, int, int]) – Circumferential, axial, and radial counts.

  • axis (Vec3) – Cylinder axis and positive V direction.

  • reference_direction (Vec3) – Projected direction defining the zero-angle seam.

  • start_angle_degrees (float) – Angular position of U = 0.

  • sweep_degrees (float) – Positive angular sweep up to 360 degrees.

  • linear (bool) – Use linear rather than midpoint-refined curved cells.

Example

>>> cell_map = pv.CellMap.cylindrical(pv.Vec3(0, 0, 0), 16.0, 20.0, 30.0, (16, 6, 1))
domain_signed_distance(self: pyvcad.pyvcad.CellMap, world: pyvcad.pyvcad.Vec3) float#

Return signed distance to the finite active CellMap domain.

Parameters:

world (Vec3) – World-coordinate query point.

Example

>>> distance = cell_map.domain_signed_distance(world)
forward(self: pyvcad.pyvcad.CellMap, logical: pyvcad.pyvcad.Vec3) pyvcad.pyvcad.Vec3#

Map a logical point into world space.

Parameters:

logical (Vec3) – Logical U/V/W coordinate.

Example

>>> world = cell_map.forward(pv.Vec3(0.5, 0.5, 0.5))
static from_cad_face(face: pyvcad.pyvcad.CADFace, cells: typing.Annotated[collections.abc.Sequence[typing.SupportsInt], "FixedSize(3)"], height: typing.SupportsFloat, linear: bool = False, trim: pyvcad.pyvcad.TrimMode = <TrimMode.boundary: 2>, standoff: typing.SupportsFloat = 0.0) pyvcad.pyvcad.CellMap#

Construct a signed-height map from one CAD face.

Parameters:
  • face (CADFace) – Source CAD face.

  • cells (tuple[int, int, int]) – Positive U/V/W counts.

  • height (float) – Total signed normal height in millimetres.

  • linear (bool) – Use linear rather than midpoint-sampled curved cells.

  • trim (TrimMode) – How to restrict the map to the trimmed face’s true domain.

  • standoff (float) – Signed stand-off distance along the face normal at which the map begins.

Example

>>> cell_map = pv.CellMap.from_cad_face(face, (8, 8, 1), 2.0)
static from_surface(surface: pyvcad.pyvcad.ParametricSurface, cells: typing.Annotated[collections.abc.Sequence[typing.SupportsInt], "FixedSize(3)"], height: typing.SupportsFloat, linear: bool = False, trim: pyvcad.pyvcad.TrimMode = <TrimMode.boundary: 2>, standoff: typing.SupportsFloat = 0.0) pyvcad.pyvcad.CellMap#

Construct a signed-height map from any parametric surface.

Parameters:
  • surface (ParametricSurface) – Source CAD face or triangle-mesh patch.

  • cells (tuple[int, int, int]) – Positive U/V/W counts.

  • height (float) – Total signed normal height in millimetres.

  • linear (bool) – Use linear rather than midpoint-sampled curved cells.

  • trim (TrimMode) – How to restrict the map to the surface’s true domain.

  • standoff (float) – Signed stand-off distance along the surface normal at which the map begins, so it spans [standoff, standoff + height].

Example

>>> cell_map = pv.CellMap.from_surface(surface, (12, 12, 1), 2.0, standoff=4.0)
property has_boundary_trim#

Whether the map carries an implicit true-boundary clip.

in_coordinates(self: pyvcad.pyvcad.CellMap, attribute: Attribute, coordinates: str) Attribute#

Wrap an attribute so its x, y, and z inputs use this CellMap.

Parameters:
  • attribute (Attribute) – Attribute to sample in mapped coordinates.

  • coordinates (str) – ‘map’, ‘logical’, ‘cell_index’, or ‘cell’.

Example

>>> color = cell_map.in_coordinates(pv.Vec4Attribute('x', '1-x', 'z', '1'), 'cell')
inverse(self: pyvcad.pyvcad.CellMap, world: pyvcad.pyvcad.Vec3, tolerance: SupportsFloat = 1e-06, max_iterations: SupportsInt = 24) object#

Invert a world point into logical coordinates.

Parameters:
  • world (Vec3) – World-coordinate point.

  • tolerance (float) – Requested Newton convergence tolerance; a scale-aware numerical floor is applied.

  • max_iterations (int) – Maximum damped Newton iterations.

Example

>>> logical = cell_map.inverse(world)
jacobian(self: pyvcad.pyvcad.CellMap, logical: pyvcad.pyvcad.Vec3) Annotated[list[pyvcad.pyvcad.Vec3], 'FixedSize(3)']#

Return world derivatives with respect to U, V, and W.

Parameters:

logical (Vec3) – Logical U/V/W coordinate.

Example

>>> du, dv, dw = cell_map.jacobian(pv.Vec3(0.5, 0.5, 0.5))
jacobian_determinant(self: pyvcad.pyvcad.CellMap, logical: pyvcad.pyvcad.Vec3) float#

Evaluate the local map Jacobian determinant.

Parameters:

logical (Vec3) – Logical U/V/W coordinate.

Example

>>> determinant = cell_map.jacobian_determinant(pv.Vec3(0.5, 0.5, 0.5))
property jacobian_determinant_field#

Jacobian determinant as a world-sampled float attribute.

property logical_position#

Logical lattice position as an explicit Vec3Attribute adapter.

property maximum_principal_stretch_field#

Maximum principal stretch as a world-sampled float attribute.

property middle_principal_stretch_field#

Middle principal stretch as a world-sampled float attribute.

property minimum_principal_stretch_field#

Minimum principal stretch as a world-sampled float attribute.

property periodic_axes#

Periodic U/V/W connectivity flags.

principal_stretches(self: pyvcad.pyvcad.CellMap, logical: pyvcad.pyvcad.Vec3) pyvcad.pyvcad.Vec3#

Return ascending directional stretch estimates.

Parameters:

logical (Vec3) – Logical U/V/W coordinate.

Example

>>> stretches = cell_map.principal_stretches(pv.Vec3(0.5, 0.5, 0.5))
static rectangular(minimum: pyvcad.pyvcad.Vec3, maximum: pyvcad.pyvcad.Vec3, cells: Annotated[collections.abc.Sequence[SupportsInt], 'FixedSize(3)'], linear: bool = True) pyvcad.pyvcad.CellMap#

Construct a rectangular map.

Parameters:
  • minimum (Vec3) – Lower world bounds.

  • maximum (Vec3) – Upper world bounds.

  • cells (tuple[int, int, int]) – Positive U/V/W counts.

  • linear (bool) – Use one trilinear element per cell.

Example

>>> cell_map = pv.CellMap.rectangular(pv.Vec3(0, 0, 0), pv.Vec3(10, 10, 10), (2, 2, 2))
static spherical(center: pyvcad.pyvcad.Vec3, inner_radius: typing.SupportsFloat, outer_radius: typing.SupportsFloat, latitude_bounds_degrees: typing.Annotated[collections.abc.Sequence[typing.SupportsFloat], "FixedSize(2)"], cells: typing.Annotated[collections.abc.Sequence[typing.SupportsInt], "FixedSize(3)"], north_axis: pyvcad.pyvcad.Vec3 = <pyvcad.pyvcad.Vec3 object at 0x1074e7df0>, reference_direction: pyvcad.pyvcad.Vec3 = <pyvcad.pyvcad.Vec3 object at 0x10757db30>, start_longitude_degrees: typing.SupportsFloat = 0.0, longitude_sweep_degrees: typing.SupportsFloat = 360.0, linear: bool = False) pyvcad.pyvcad.CellMap#

Construct an analytic spherical-shell band map.

U follows longitude, V follows latitude from south to north, and W follows radius from the inner to the outer boundary.

Parameters:
  • center (Vec3) – Sphere center in millimetres.

  • inner_radius (float) – Positive inner radius in millimetres.

  • outer_radius (float) – Outer radius in millimetres.

  • latitude_bounds_degrees (tuple[float, float]) – South/north bounds inside (-90, 90).

  • cells (tuple[int, int, int]) – Longitude, latitude, and radial counts.

  • north_axis (Vec3) – North direction and positive V orientation.

  • reference_direction (Vec3) – Projected direction defining the zero-longitude seam.

  • start_longitude_degrees (float) – Longitude of U = 0.

  • longitude_sweep_degrees (float) – Positive longitude sweep up to 360 degrees.

  • linear (bool) – Use linear rather than midpoint-refined curved cells.

Example

>>> cell_map = pv.CellMap.spherical(pv.Vec3(0, 0, 0), 18.0, 22.0, (-60.0, 60.0), (16, 8, 1))
to_cell_frame(self: pyvcad.pyvcad.CellMap, vector: Vec3Attribute) Vec3Attribute#

Convert a raw Cartesian vector attribute through the inverse CellMap Jacobian.

Parameters:

vector (Vec3Attribute) – Raw direction or displacement in consuming coordinates.

Example

>>> local_direction = cell_map.to_cell_frame(direction)
to_map_direction(self: pyvcad.pyvcad.CellMap, vector: Vec3Attribute) Vec3Attribute#

Convert a world-space vector through the inverse CellMap Jacobian.

This is the direction-focused alias of to_cell_frame(). The result is not normalized.

to_world_direction(self: pyvcad.pyvcad.CellMap, vector: Vec3Attribute) Vec3Attribute#

Convert a vector expressed in logical map coordinates through the CellMap Jacobian.

The result is not normalized, so it can represent either a direction or a displacement.

Parameters:

vector (Vec3Attribute) – Direction or displacement in logical U/V/W coordinates.

Example

>>> world_direction = cell_map.to_world_direction(pv.Vec3Attribute(1, 0, 0)).normalized()
property trim_mode#

The TrimMode the map was built with.

property u_field#

Logical U coordinate as a float attribute.

property unit_cell_phase#

Fractional unit-cell phase as an explicit Vec3Attribute adapter.

property v_field#

Logical V coordinate as a float attribute.

validate(self: pyvcad.pyvcad.CellMap) pyvcad.pyvcad.CellMapDiagnostics#

Validate Jacobians, inverse lookup, trim statistics, and aspect ratio.

Example

>>> diagnostics = cell_map.validate()
property w_field#

Logical W coordinate as a float attribute.

static warp(base: pyvcad.pyvcad.CellMap, u_scale: object = None, v_scale: object = None, w_scale: object = None, lock_u_bounds: bool = True, lock_v_bounds: bool = True, lock_w_bounds: bool = True) pyvcad.pyvcad.CellMap#

Warp relative cell spacing while retaining an immutable map.

Parameters:
  • base (CellMap) – Base map.

  • u_scale (FloatAttribute | float | None) – Relative U spacing weights.

  • v_scale (FloatAttribute | float | None) – Relative V spacing weights.

  • w_scale (FloatAttribute | float | None) – Relative W spacing weights.

  • lock_u_bounds (bool) – Preserve opposite U boundaries.

  • lock_v_bounds (bool) – Preserve opposite V boundaries.

  • lock_w_bounds (bool) – Preserve opposite W boundaries.

Example

>>> warped = pv.CellMap.warp(cell_map, u_scale, None, None)
class pyvcad.CellMapCollection#

A collection of independently parameterized CAD-face maps.

__init__(self: pyvcad.pyvcad.CellMapCollection, maps: collections.abc.Sequence[pyvcad.pyvcad.CellMap]) None#

Construct a map collection.

Parameters:

maps (list[CellMap]) – Independent cell maps.

Example

>>> collection = pv.CellMapCollection([first, second])
property maps#

Independent maps in collection order.

validate(self: pyvcad.pyvcad.CellMapCollection) list[pyvcad.pyvcad.CellMapDiagnostics]#

Validate every independent map.

Example

>>> diagnostics = collection.validate()
class pyvcad.CellMapDiagnostics#

Validation evidence for a structured curvilinear cell map.

property active_element_count#
property inverse_solver_failures#
property inverted_cell_count#
property maximum_aspect_ratio#
property maximum_jacobian_determinant#
property minimum_jacobian_determinant#
property non_neighbor_overlap_count#
property trimmed_element_count#
property valid#

Whether all mandatory validation checks passed.

class pyvcad.ImplicitUnitCell#

A custom periodic implicit unit cell in normalized coordinates.

__init__(self: pyvcad.pyvcad.ImplicitUnitCell, value: object, gradient: object = None, name: str = 'custom') None#

Construct a custom periodic implicit unit cell.

Parameters:
  • value (callable) – Scalar callback over normalized u, v, w; numba.cfunc is the native fast path.

  • gradient (callable | None) – Optional analytic Vec3 callback.

  • name (str) – Diagram and inspection name.

Example

>>> cell = pv.ImplicitUnitCell(lambda u, v, w: math.sin(2 * math.pi * u))
static mixed(first: pyvcad.pyvcad.ImplicitUnitCell, second: pyvcad.pyvcad.ImplicitUnitCell, weight: object) pyvcad.pyvcad.ImplicitUnitCell#

Mix two periodic implicit cells with a scalar attribute.

Parameters:

Example

>>> weight = pv.FloatAttribute(0.5)
>>> cell = pv.ImplicitUnitCell.mixed(first, second, weight)
property name#

Inspection name.

static standard(name: str) pyvcad.pyvcad.ImplicitUnitCell#

Return a standard TPMS unit cell by name.

Parameters:

name (str) – Standard TPMS name.

Example

>>> cell = pv.ImplicitUnitCell.standard('gyroid')
validate_periodicity(self: pyvcad.pyvcad.ImplicitUnitCell, tolerance: SupportsFloat = 1e-06) bool#

Compare opposite unit-cell boundaries.

Parameters:

tolerance (float) – Maximum scalar mismatch.

Example

>>> assert cell.validate_periodicity()
class pyvcad.GraphUnitCell#

A normalized indexed graph unit cell with optional tags.

__init__(self: pyvcad.pyvcad.GraphUnitCell, vertices: collections.abc.Sequence[pyvcad.pyvcad.Vec3], edges: collections.abc.Sequence[tuple[SupportsInt, SupportsInt]], vertex_tags: collections.abc.Sequence[SupportsInt] = [], edge_tags: collections.abc.Sequence[SupportsInt] = [], orientation_tags: collections.abc.Sequence[SupportsInt] = [], material_tags: collections.abc.Sequence[SupportsInt] = []) None#

Construct a normalized graph unit cell.

Parameters:
  • vertices (list[Vec3]) – Normalized vertices in [0, 1].

  • edges (list[tuple[int, int]]) – Indexed edges.

  • vertex_tags (list[int]) – Optional per-vertex tags.

  • edge_tags (list[int]) – Optional per-edge tags.

  • orientation_tags (list[int]) – Optional per-edge orientation tags.

  • material_tags (list[int]) – Optional per-edge material tags.

Example

>>> cell = pv.GraphUnitCell([pv.Vec3(0, 0, 0), pv.Vec3(1, 1, 1)], [(0, 1)])
property edge_tags#

Per-edge tags.

property edges#

Indexed edges.

property material_tags#

Per-edge material tags.

property orientation_tags#

Per-edge orientation tags.

property vertex_tags#

Per-vertex tags.

property vertices#

Normalized vertices.