Grading, mixing, stochastic lattices, and transitions#
Material grading#
- pyvcad_metamaterials.skin_core_tpms(cell_map, skin_material, core_material, kind='gyroid', wall_thickness=2.0, skin_ratio=0.35, transition=0.15)[source]#
Build a mapped TPMS with material graded through each wall’s depth.
- pyvcad_metamaterials.per_strut_material(cell_map, unit_cell, selector, beam_radius=0.8, node_radius=None)[source]#
Assign native material tags to unit-cell edges selected by orientation or position.
- pyvcad_metamaterials.distance_field(body, voxel_size=0.5, bandwidth=10.0, signed=True)[source]#
Return a fast native
pv.FloatAttributegiving the distance in mm to a body node.This is
pv.FloatAttribute.distance_to(body, ...), the core spelling, kept here so lattice scripts can stay withinmm. Use it to grade lattices by distance from another part, for example strut radius or wall thickness falling off with distance from a head form:radius = mm.distance_field(head, bandwidth=30.0).map_range(0.0, 30.0, 1.2, 0.5).clamp(0.5, 1.2)
The body (any node, including meshes and CAD) is cloned and prepared with
voxel_size; your node is not modified. The value is signed (negative inside) unlesssigned=False. It is accurate withinbandwidthof the body’s bounding box; farther away a monotone lower bound is returned, so choosebandwidthat least as large as the distances you grade over.
Mixing structures#
- pyvcad_metamaterials.ramp(start, end, axis='x', smooth=True, coordinates=None, outside=0.0, easing=None, shape=None, voxel_size=0.5, bandwidth=10.0)[source]#
Return a composed, clamped scalar attribute along an axis, between points or between bodies.
The result is 0 at
start, 1 atendand clamped to [0, 1] beyond them, so the endpoints may be given in either order.smooth=Trueapplies a smoothstep so the ramp starts and ends with zero slope;smooth=Falsekeeps it linear.easingpicks any curve ofFloatAttribute.easeinstead ("linear","smoothstep","smootherstep","power","sine"or"exponential", withshapefor the exponent of power or the rate of exponential) and overridessmooth. Equal endpoints raiseValueError: use a sharp region (pv.Intersection/pv.Difference) for a step instead of a zero-width band.The endpoints may be numbers (positions along
axis), points, or two nodes. Between two nodes the ramp ispv.FloatAttribute.between(start, end): 0 on and inside the first body, 1 on and inside the second, graded by the distances to both;voxel_sizeandbandwidthprepare the bodies (choose a bandwidth at least as large as the gap).coordinatesmay be a scalar attribute for scalar endpoints, a Vec3Attribute (or apv.CellMap, meaning itslogical_position) for axis ramps along u/v/w, or a Vec3Attribute for point endpoints. It defaults to ordinary Cartesian consumer coordinates. Custom coordinates such as a CellMap’s logical position are undefined outside the map’s domain; there the ramp returnsoutside(default 0) instead of raising. Passoutside=Noneto keep the strict behaviour.
- pyvcad_metamaterials.idw_weight(points, index, exponent=2.0, coordinates=None, outside=0.0)[source]#
Return one seed’s normalized inverse-distance weight as a scalar attribute.
The weight is 1 at its own seed, 0 at the other seeds, and the weights of all seeds sum to 1 everywhere. Seeds must be distinct.
coordinates(a Vec3Attribute or apv.CellMap) measures distances in another space, for example logical cell units; where those coordinates are undefined the weight isoutside(Noneraises).
- pyvcad_metamaterials.mix(left, right, weight=None, *, region=None, half_width=None)[source]#
Mix two nodes with a scalar attribute or native region-distance ramp.
- pyvcad_metamaterials.mix_many(nodes, points, exponent=2.0, coordinates=None, outside=0.0)[source]#
Fold N nodes into one binary Mix tree using partial IDW weights.
Node
idominates nearpoints[i]. Where customcoordinatesare undefined (outside a CellMap domain) every partial weight isoutside; the default 0 keeps the first node there.
- pyvcad_metamaterials.overlap(inside, outside, region, half_width)[source]#
Join two structures by keeping both in a band around a region surface.
insideis kept withinregiongrown byhalf_width;outsideis kept outsideregionshrunk byhalf_width. In the2 * half_widthband both are present and their physical intersections form the join. This is the robust choice for unlike families (TPMS to graph, Voronoi to TPMS) where blending the two distance fields can pinch apart.regioncan be any closed node, for example a box, sphere, or CAD body.
- pyvcad_metamaterials.zones(nodes, regions, mode='sharp', half_width=None)[source]#
Assign one structure per region with N-way priority.
nodes[i]fillsregions[i](minus earlier regions) and the last node fills the rest, solen(nodes)must belen(regions) + 1.modechooses how neighbours meet:"sharp"cuts at the region surface,"mix"blends distance fields across a2 * half_widthband (compatible families only, seemix()), and"overlap"keeps both structures in the band (seeoverlap()). Build every structure on the same CellMap so cells line up across zones.
Stochastic lattices#
Delaunay and Voronoi lattices built from seed points inside a host. The graph builders make struts; the plate builders make walls.
- pyvcad_metamaterials.sample_points_in_host(host, spacing=None, density=None, seed=0, max_count=None, relaxation=0, boundary_clearance=0.0, attempts_per_point=80)[source]#
Sample deterministic, variably spaced world-space points in a prepared host.
Exactly one of
spacingordensityis required. Each may be a positive number,FloatAttribute, or scalar callable accepted by OpenVCAD. Density is interpreted as target points per cubic world unit and converted locally todensity ** (-1/3)spacing. Two samples are accepted when their separation is at least the mean of their local spacings.The host must already have been prepared. A point is inside when its host SDF is at most
-boundary_clearance. Rejection sampling therefore remains correct for disconnected and non-convex hosts, but a loose bounding box can be expensive.relaxationapplies deterministic separation-preserving jitter passes.
- class pyvcad_metamaterials.StochasticPointSet(points, local_spacings, seed, candidate_count, rejected_count)[source]#
Inspectable output from
sample_points_in_host().- candidate_count#
Number of random candidates drawn before relaxation.
- local_spacings#
Local target spacing in mm at each accepted point.
- points#
Accepted points as a list of
pv.Vec3.
- rejected_count#
Candidates that were not kept (
candidate_count - len(points)).
- seed#
Random seed the points were drawn with.
- pyvcad_metamaterials.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)[source]#
Build a native host-confined graph lattice from explicit seed points.
prune_loose=Truedrops 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=Trueaccepts seeds outside the host, for example a layer that bounds the Voronoi cells at the host surface; the host still clips the geometry.
- pyvcad_metamaterials.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)[source]#
Build Delaunay beams using mesh-edge, vertex-centroid, or dual extraction.
- pyvcad_metamaterials.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)[source]#
Build beams along bounded Voronoi-cell edges.
See
stochastic_graph_lattice()forprune_looseandallow_outside_seeds.
- pyvcad_metamaterials.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)[source]#
Build a native host-confined plate lattice from explicit seed points.
- Parameters:
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_FACETSorVORONOI_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:
The plate lattice node.
- Return type:
pv.StochasticFaceLattice
- Raises:
ValueError – If
boundaryis not"open","closed"or apv.StochasticBoundaryMode.
- pyvcad_metamaterials.delaunay_plate_lattice(host, points, wall_thickness=1.0, boundary='open', surface_tolerance=0.05, boundary_tolerance=0.1, member_blend_radius=0.0)[source]#
Build symmetric plates around Delaunay tetrahedron facets.
See
stochastic_plate_lattice()for the arguments.
- pyvcad_metamaterials.voronoi_plate_lattice(host, points, wall_thickness=1.0, boundary='open', surface_tolerance=0.05, boundary_tolerance=0.1, member_blend_radius=0.0)[source]#
Build symmetric plates around bounded Voronoi-cell faces.
See
stochastic_plate_lattice()for the arguments.
- pyvcad_metamaterials.random_seeds(host, spacing, seed=0, max_count=None, boundary_clearance=0.0, attempts_per_point=30)[source]#
Sample Poisson-disk seeds in a prepared host quickly (native, ~10^5 points).
spacingis a positive number,FloatAttributeor scalar callable (mm). Two seeds are accepted together when their distance is at least the mean of their local spacings, the same rule assample_points_in_host(), but the native sampler grows the point set front by front instead of testing every pair, so it suits large hosts. Results are deterministic for a givenseedbut differ fromsample_points_in_host(). Returns aStochasticPointSet.
Voronoi ribs on a surface#
Seeds spread over a triangle surface own the parts of it closest to them; the boundaries between those cells become ribs or walls.
- pyvcad_metamaterials.surface_seeds(mesh, spacing, seed=0, max_count=None, attempts_per_point=30)[source]#
Sample variable-spacing Poisson-disk seeds on a triangle surface.
Darts land uniformly by area and are kept when their straight-line distance to every kept seed is at least the mean of the two local spacings, until a long run of darts finds no room. Each dart needs only its own triangle, so open, non-manifold and noisy scanned meshes work. Keep the spacing below the thickness of thin walls: distances are straight-line, so seeds on the two sides of a thin wall would see each other.
- Parameters:
mesh (pv.SurfaceMesh) – The surface. Build one from a node with
pv.SurfaceMesh(node, voxel_size)or load a file withpv.SurfaceMesh(path).spacing (float | pv.FloatAttribute | callable) – Local spacing in mm, positive. A field is sampled on the surface (with
d = 0), so it can grade the cell size.seed (int) – Random seed, default
0.max_count (int | None) – Largest number of seeds;
None(default) fills the surface.attempts_per_point (int) – Rejected darts allowed per kept seed before sampling stops.
- Returns:
The seeds, with
local_spacingsand atriangle_idslist giving the triangle each seed lies on.- Return type:
Example
>>> mesh = pv.SurfaceMesh(pv.Sphere(pv.Vec3(0, 0, 0), 20.0), 0.5) >>> seeds = mm.surface_seeds(mesh, spacing=6.0, seed=1)
- pyvcad_metamaterials.surface_voronoi(mesh, seeds)[source]#
Return the Voronoi diagram of seeds restricted to a triangle surface.
Each seed owns the part of the surface closer to it (in a straight line) than to any other seed. The result’s
segments(an(N, 2, 3)array) are the boundaries between those cells, one straight piece per triangle crossed, withseed_pairs,triangle_idsand each seed’scell_areas. Computed per triangle, exactly, so scanned meshes work.- Parameters:
mesh (pv.SurfaceMesh) – The surface.
seeds (StochasticPointSet | list | numpy.ndarray) – Seed points, usually from
surface_seeds().
- Returns:
The restricted diagram.
- Return type:
pv.SurfaceVoronoi
Example
>>> diagram = mm.surface_voronoi(mesh, seeds) >>> diagram.segments.shape
- pyvcad_metamaterials.surface_voronoi_ribs(mesh, seeds, beam_thickness=1.0, node_radius=None, simplify_tolerance=0.05)[source]#
Build round ribs along the Voronoi cell boundaries of seeds on a surface.
The ribs follow the restricted Voronoi diagram (
surface_voronoi()): the struts are centred on the surface, so half of each rib stands proud of it and half sinks in. Union them with the part to stiffen its skin, or use them alone as a surface net. Chains of short pieces are merged into longer straight struts that stay withinsimplify_toleranceof the exact boundary.- Parameters:
mesh (pv.SurfaceMesh) – The surface.
seeds (StochasticPointSet | list | numpy.ndarray) – Seed points, usually from
surface_seeds().beam_thickness (float | pv.FloatAttribute | callable) – Rib diameter in mm. A field is sampled at both ends of every strut (with
d = 0), so the thickness can vary along the surface.node_radius (float | pv.FloatAttribute | callable | None) – Radius in mm of a ball at every junction of three or more ribs;
None(default) adds none.simplify_tolerance (float) – Largest distance in mm a merged strut may leave the exact boundary, default
0.05.0keeps one strut per triangle crossed.
- Returns:
The ribs (new geometry; its distance is exact outside the struts and a bound inside, like any union of struts).
- Return type:
pv.BeamLattice
Example
>>> seeds = mm.surface_seeds(mesh, spacing=6.0) >>> ribs = mm.surface_voronoi_ribs(mesh, seeds, beam_thickness=1.2)
- pyvcad_metamaterials.surface_voronoi_plates(body, seeds, rib_height, wall_thickness=1.0, member_blend_radius=0.0, surface_tolerance=0.05)[source]#
Build walls along the Voronoi cell boundaries of seeds on the surface of a body.
The walls are the faces of the seeds’ 3D Voronoi cells, kept within
rib_height / 2of the body’s surface (insidepv.Thicken(rib_height, body)). For seeds on the surface those faces cut it exactly along the restricted Voronoi diagram, so every wall is centred on a cell boundary and stands across the surface. Use the body’s mesh for the seeds, for examplemm.surface_seeds(pv.SurfaceMesh(body, 0.5), 6.0).- Parameters:
body (pv.Node) – A closed body; its surface carries the walls.
seeds (StochasticPointSet | list | numpy.ndarray) – Seeds on the body’s surface.
rib_height (float | pv.FloatAttribute | pv.ScalarParameter | callable) – Total wall height in mm across the surface (half outside, half inside).
wall_thickness (float | pv.FloatAttribute | callable) – Wall thickness in mm; a field may vary it along the surface.
member_blend_radius (float) – Fillet radius in mm where walls meet, default
0.surface_tolerance (float) – Largest thickness interpolation error in mm.
- Returns:
The walls.
- Return type:
pv.StochasticFaceLattice
Example
>>> walls = mm.surface_voronoi_plates(body, seeds, rib_height=3.0, wall_thickness=0.8)
Random-to-regular transitions#
- pyvcad_metamaterials.SITE_KINDS#
Built-in immutable sequence.
If no argument is given, the constructor returns an empty tuple. If iterable is specified the tuple is initialized from iterable’s items.
If the argument is a tuple, the return value is the same object.
Regular point sets accepted by the transition helpers:
sc,bcc,fcc.
- pyvcad_metamaterials.voronoi_transition(host, regularity, kind='bcc', cell_size=None, cell_map=None, beam_thickness=1.0, node_radius=None, seeds=None, ghost_layer=None, boundary='open', member_blend_radius=0.0, field_tolerance=0.05, boundary_tolerance=0.1, prune_loose=True, **seed_options)[source]#
One call: a Voronoi strut lattice that turns from random foam into a regular lattice.
Builds
transition_seeds()(pass seed options such asmethod,seedorrandom_pointsas keywords) and a Voronoi graph lattice from them. Whereregularityis 1 the struts are the edges of cubes ("sc"), Kelvin cells ("bcc") or rhombic dodecahedra ("fcc"). Both regions belong to one Voronoi graph, so they share nodes and the transition itself cannot pinch apart.ghost_layer(mm, default one site spacing) also places seeds in a layer just outside the host; the host still clips the geometry. Without that layer the outermost Voronoi cells are unbounded, so regular cells at the surface lose the struts that lie on it.prune_loose=True(default) 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. With precomputedseedsno ghost layer is added unless requested.The host must be prepared. Check the result with
pyvcad_metamaterials.check_connectivity(); a very thin host can still split.
- pyvcad_metamaterials.voronoi_tpms_transition(host, region, tpms, half_width, regularity=0.0, kind='bcc', cell_size=None, cell_map=None, beam_thickness=1.0, check_voxel_size=None, **options)[source]#
Join a Voronoi foam inside
regionto a TPMS outside it through an overlap band.A TPMS sheet and a strut foam have nothing in common to blend, so this keeps both structures in a
2 * half_widthband around the region surface and lets them intersect (seepyvcad_metamaterials.overlap()). The foam is built byvoronoi_transition()onhostgrown into the band, with loose strut pieces pruned against exactly that boundary, so the band edge leaves no loose fragments.regularity(0 = random foam) andkind/cell_size/cell_mapset the foam’s seeds; use the TPMS’s owncell_mapso the foam cells match the TPMS cell size.beam_thicknessand the TPMS wall thickness may be fields, for example ramps that thin each structure as it crosses the band. Extraoptionsgo tovoronoi_transition().Choose
half_widthbetween a quarter and a half of the cell size: narrower bands give few contacts, much wider ones double the material. Withcheck_voxel_sizethe result is checked withpyvcad_metamaterials.require_connected()(raisesValueErrorwhen it is not one piece). Returns the joined node, clipped tohost.
- pyvcad_metamaterials.voronoi_foam(host, spacing, seed=0, beam_thickness=1.0, node_radius=None, ghost_layer=None, prune_loose=True, member_blend_radius=0.0, boundary='open', field_tolerance=0.05, boundary_tolerance=0.1)[source]#
One call: a random Voronoi strut foam that fills a prepared host in one piece.
Seeds come from
random_seeds()withspacing(mm; a number,FloatAttributeor scalar callable), so a spacing field grades the cell size, for example smaller cells near a head withmm.ramp(0, 15, coordinates=mm.distance_field(head)). Seeds are also placed in aghost_layerjust outside the host (default: the typical local spacing) so the cells at the surface are closed, andprune_loosedrops strut pieces the host cuts off at both ends. A spacing field must therefore be defined a little outside the host as well. The host can be any prepared node, includingmm.domain(cell_map)for a conformal liner volume. Returnsvoronoi_graph_lattice(host, ...).
- pyvcad_metamaterials.transition_seeds(host, regularity, kind='bcc', cell_size=None, cell_map=None, origin=None, method='match', random_points=None, random_spacing=None, jitter=0.5, match_radius=None, minimum_separation=None, seed=0, boundary_clearance=0.0, site_margin=0.0)[source]#
Build Voronoi seeds that change from random to a regular lattice.
regularity(number,FloatAttributeor callable) is 0 where the foam should be random and 1 where it should be the regular lattice; ramps fromramp()work well. Where it cannot be evaluated (for example outside a CellMap domain) it counts as 0.The regular sites are
kind("sc","bcc"or"fcc") sites either on an axis-aligned grid withcell_size(and optional latticeorigin) or, withcell_map, placed through the map (seecell_map_sites()). Only sites inside the preparedhostare used.method="match"(default) pairs each site with a nearby random seed and slides the seed onto the site by the local regularity, so the seed count and cell size stay continuous. The random seeds arerandom_points(for example a gradedsample_points_in_host()result) or, by default, a Poisson-disk sample whose density matches the sites (random_spacingoverrides it).method="jitter"instead displaces every site by up to(1 - regularity) * jitter * nearest_neighbour(a perturbed lattice), which needs no random set.match_radius(default 0.75 x the site nearest-neighbour distance) limits pairing andminimum_separation(default 0.3 x) removes seeds that would make sliver cells.site_margin(cells) extends CellMap sites past the map boundary (seecell_map_sites()). ReturnsTransitionSeeds.
- class pyvcad_metamaterials.TransitionSeeds(result, sites, random_points, nearest_neighbor, method)[source]#
Seeds from
transition_seeds()with provenance for inspection.- points#
Seeds to pass to a Voronoi lattice.
- Type:
list[pv.Vec3]
- regularity#
Regularity weight that placed each seed.
- Type:
list[float]
- sites#
Regular sites inside the host.
- Type:
list[pv.Vec3]
- random_points#
Random seeds used (empty for
method="jitter").- Type:
list[pv.Vec3]
- regular_index, random_index
Source site / random seed of each point or -1.
- Type:
list[int]
- matched_count#
Random seeds paired with a site (
method="match").- Type:
int
- dropped_count#
Seeds removed by the minimum-separation check.
- Type:
int
- nearest_neighbor#
Site nearest-neighbour distance in mm.
- Type:
float
- pyvcad_metamaterials.lattice_sites(kind, bounds, cell_size, origin=None, margin=0.0)[source]#
Return regular
"sc","bcc"or"fcc"sites inside an axis-aligned box.boundsis a(minimum, maximum)pair;cell_sizeis a number or three numbers in mm;originis a lattice corner (defaults tominimum). Sites withinmarginof the box are included. To line the sites up with a rectangular map’s graph lattice, use the map’s minimum corner asoriginand its cell size.
- pyvcad_metamaterials.cell_map_sites(cell_map, kind, margin=0.0)[source]#
Return
kindsites placed through a CellMap (“align to graph points”).Sites are generated in logical cell coordinates and mapped to world space, so the regular region of a transition follows the map, and its Voronoi cells line up with a graph lattice of
voronoi_unit_cell()on the same map. Sites in trimmed-away elements are skipped, periodic seams are not duplicated, and apv.CellMapCollectioncontributes the sites of every map.margin(in cells) also returns sites up to that far outside the map’s logical box on non-periodic axes, continuing the map linearly from its boundary. These outside sites bound the Voronoi cells at the map surface (seevoronoi_transition()).Voronoi cells are only similarity-invariant: the alignment is exact for cubic cells on a rectangular map and approximate where the map stretches or bends cells. Keep cells near cubic (similar size along U, V and W).
- pyvcad_metamaterials.voronoi_unit_cell(kind)[source]#
Return the graph unit cell whose tiling equals the Voronoi edges of
kindsites."sc"gives the cubic cell,"bcc"the Kelvin cell (truncated octahedra) and"fcc"the rhombic-dodecahedron cell. The edges are in the same origin-centred, normalized[-0.5, 0.5]convention as the built-in cells, so the result can be passed topyvcad_metamaterials.graph_lattice()with the same CellMap used forcell_map_sites(). It isperiodic_voronoi()of the sites, so other seed sets work the same way.
- pyvcad_metamaterials.matched_spacing(kind, cell_size)[source]#
Return the Poisson-disk spacing whose seed density equals
kindsites.cell_sizeis the cubic cell edge in mm (or three edges). Random seeds sampled with this spacing make Voronoi cells of the same average size as the regular lattice, so the cell size stays continuous across a transition.
Connectivity checks#
- pyvcad_metamaterials.check_connectivity(node, voxel_size, connectivity=26, bounds=None, min_island_volume=None, cull_far_cells=False)[source]#
Count the separate solid pieces of a node on a voxel grid.
A lattice transition that pinches apart, or clipping that leaves loose strut fragments, shows up as more than one component. The node is sampled at voxel centres over its bounding box (or
bounds, a(minimum, maximum)pair ofpv.Vec3) in parallel, and solid voxels are joined through face, edge and corner neighbours (connectivity=26) or faces only (6).Resolution matters: choose
voxel_sizeat most about half the thinnest strut radius or wall thickness. Thinner necks may be reported as breaks, and gaps narrower than one voxel may be bridged. Where a member leaves the part at a grazing angle the grid can also catch a sliver as a separate one- or two-voxel speck that shrinks with finer voxels.min_island_volume(mm^3) ignores pieces smaller than that volume when decidingconnected; the defaultNoneignores pieces of fewer than 8 voxels. Pass0to count every piece.cull_far_cells=Truedecides whole 8x8x8 voxel blocks from one probe when the field there is far from zero, which skips empty space around a curved part (about twice as fast on a dome liner). It is exact for true distances, such as stochastic strut lattices, primitives and their booleans, but TPMS fields can change faster than distance, so keep the defaultFalsefor designs that contain them.Returns a
ConnectivityReport;bool(report)is True for one piece.
- pyvcad_metamaterials.require_connected(node, voxel_size, connectivity=26, bounds=None, min_island_volume=None)[source]#
Raise
ValueErrorunlesscheck_connectivity()finds exactly one piece.The message lists where the extra pieces are so the transition band, beam thickness or seed settings can be adjusted. Returns the report when the node is connected.
- class pyvcad_metamaterials.ConnectivityReport(report, min_island_volume)[source]#
Readable result of
check_connectivity().- component_count#
Number of separate solid pieces.
- Type:
int
- connected#
True when the solid is one piece (or empty pieces were ignored).
- Type:
bool
- volumes#
Component volumes in mm^3, largest first.
- Type:
list[float]
- sample_points#
One solid point inside each component (x, y, z) in mm.
- Type:
list[tuple]
- bounds#
(minimum, maximum)sample box of each component.- Type:
list[tuple]
- voxel_size#
Sampling pitch in mm.
- Type:
float
- ignored_count#
Components smaller than
min_island_volumethat were ignored.- Type:
int
- property islands#
Every component except the largest, as
(volume, sample_point)pairs.
- property largest_fraction#
Fraction of the kept solid volume in the largest component.