Source code for pyvcad_metamaterials.stochastic

"""Thin builders for native aperiodic Delaunay and Voronoi lattices."""

# OpenVCAD
import pyvcad as pv

# Local
from .fields import _coerce_attribute
from .points import StochasticPointSet


_DELAUNAY_GRAPH_MODES = {
    "mesh_edges": pv.StochasticGraphExtraction.DELAUNAY_EDGES,
    "vertex_centroid": pv.StochasticGraphExtraction.DELAUNAY_FACET_VERTEX_CENTROID,
    "dual": pv.StochasticGraphExtraction.DELAUNAY_BARYCENTRIC_DUAL,
}

_BOUNDARY_MODES = {
    "open": pv.StochasticBoundaryMode.OPEN_CLIP,
    "closed": pv.StochasticBoundaryMode.CLOSED_CONFINE,
}


def _points(value):
    return list(value.points if isinstance(value, StochasticPointSet) else value)


def _boundary(value):
    if isinstance(value, pv.StochasticBoundaryMode):
        return value
    try:
        return _BOUNDARY_MODES[value]
    except (KeyError, TypeError):
        raise ValueError("boundary must be 'open', 'closed', or StochasticBoundaryMode") from None


[docs] def stochastic_graph_lattice( host, points, extraction, beam_thickness=1.0, node_radius=None, boundary="open", field_tolerance=0.05, boundary_tolerance=0.1, member_blend_radius=0.0, prune_loose=False, allow_outside_seeds=False, ): """Build a native host-confined graph lattice from explicit seed points. ``prune_loose=True`` drops strut pieces that the host cuts off at both ends (chords through a corner or a concave part of the host), which would otherwise print as loose fragments. ``allow_outside_seeds=True`` accepts seeds outside the host, for example a layer that bounds the Voronoi cells at the host surface; the host still clips the geometry. """ beam_radius = _coerce_attribute(beam_thickness) * 0.5 joint_field = None if node_radius is None else _coerce_attribute(node_radius) return pv.StochasticGraphLattice( host, _points(points), extraction, beam_radius, node_radius=joint_field, boundary_mode=_boundary(boundary), field_tolerance=float(field_tolerance), boundary_tolerance=float(boundary_tolerance), member_blend_radius=float(member_blend_radius), prune_loose_fragments=bool(prune_loose), allow_outside_seeds=bool(allow_outside_seeds), )
[docs] def delaunay_graph_lattice( host, points, beam_thickness=1.0, node_radius=None, mode="mesh_edges", boundary="open", field_tolerance=0.05, boundary_tolerance=0.1, member_blend_radius=0.0, prune_loose=False, allow_outside_seeds=False, ): """Build Delaunay beams using mesh-edge, vertex-centroid, or dual extraction.""" try: extraction = _DELAUNAY_GRAPH_MODES[mode] except KeyError: names = ", ".join(sorted(_DELAUNAY_GRAPH_MODES)) raise ValueError(f"mode must be one of: {names}") from None return stochastic_graph_lattice( host, points, extraction, beam_thickness, node_radius, boundary, field_tolerance, boundary_tolerance, member_blend_radius, prune_loose, allow_outside_seeds, )
[docs] def voronoi_graph_lattice( host, points, beam_thickness=1.0, node_radius=None, boundary="open", field_tolerance=0.05, boundary_tolerance=0.1, member_blend_radius=0.0, prune_loose=False, allow_outside_seeds=False, ): """Build beams along bounded Voronoi-cell edges. See :func:`stochastic_graph_lattice` for ``prune_loose`` and ``allow_outside_seeds``. """ return stochastic_graph_lattice( host, points, pv.StochasticGraphExtraction.VORONOI_EDGES, beam_thickness, node_radius, boundary, field_tolerance, boundary_tolerance, member_blend_radius, prune_loose, allow_outside_seeds, )
[docs] def stochastic_plate_lattice( host, points, extraction, wall_thickness=1.0, boundary="open", surface_tolerance=0.05, boundary_tolerance=0.1, member_blend_radius=0.0, ): """Build a native host-confined plate lattice from explicit seed points. Args: host (pv.Node): Solid that confines the lattice. points (list[pv.Vec3] | StochasticPointSet): Unique world-space seed points inside the host. extraction (pv.StochasticFaceExtraction): ``DELAUNAY_FACETS`` or ``VORONOI_FACES``. wall_thickness (float | pv.FloatAttribute | callable): Full plate thickness in mm, default ``1.0``. boundary (str | pv.StochasticBoundaryMode): ``"open"`` (default, ``OPEN_CLIP``) cuts plates at the host surface and leaves them open; ``"closed"`` (``CLOSED_CONFINE``) confines them and closes them against the host surface with contact patches and seams. surface_tolerance (float): Largest thickness interpolation error in mm, default ``0.05``. boundary_tolerance (float): Host-boundary tolerance in mm, default ``0.1``. member_blend_radius (float): Smooth-union radius between plates in mm, default ``0.0`` (sharp). Returns: pv.StochasticFaceLattice: The plate lattice node. Raises: ValueError: If ``boundary`` is not ``"open"``, ``"closed"`` or a ``pv.StochasticBoundaryMode``. """ return pv.StochasticFaceLattice( host, _points(points), extraction, _coerce_attribute(wall_thickness), boundary_mode=_boundary(boundary), surface_tolerance=float(surface_tolerance), boundary_tolerance=float(boundary_tolerance), member_blend_radius=float(member_blend_radius), )
[docs] def delaunay_plate_lattice( host, points, wall_thickness=1.0, boundary="open", surface_tolerance=0.05, boundary_tolerance=0.1, member_blend_radius=0.0, ): """Build symmetric plates around Delaunay tetrahedron facets. See :func:`stochastic_plate_lattice` for the arguments. """ return stochastic_plate_lattice( host, points, pv.StochasticFaceExtraction.DELAUNAY_FACETS, wall_thickness, boundary, surface_tolerance, boundary_tolerance, member_blend_radius, )
[docs] def voronoi_plate_lattice( host, points, wall_thickness=1.0, boundary="open", surface_tolerance=0.05, boundary_tolerance=0.1, member_blend_radius=0.0, ): """Build symmetric plates around bounded Voronoi-cell faces. See :func:`stochastic_plate_lattice` for the arguments. """ return stochastic_plate_lattice( host, points, pv.StochasticFaceExtraction.VORONOI_FACES, wall_thickness, boundary, surface_tolerance, boundary_tolerance, member_blend_radius, )