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.FloatAttribute giving 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 within mm. 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) unless signed=False. It is accurate within bandwidth of the body’s bounding box; farther away a monotone lower bound is returned, so choose bandwidth at 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 at end and clamped to [0, 1] beyond them, so the endpoints may be given in either order. smooth=True applies a smoothstep so the ramp starts and ends with zero slope; smooth=False keeps it linear. easing picks any curve of FloatAttribute.ease instead ("linear", "smoothstep", "smootherstep", "power", "sine" or "exponential", with shape for the exponent of power or the rate of exponential) and overrides smooth. Equal endpoints raise ValueError: 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 is pv.FloatAttribute.between(start, end): 0 on and inside the first body, 1 on and inside the second, graded by the distances to both; voxel_size and bandwidth prepare the bodies (choose a bandwidth at least as large as the gap).

coordinates may be a scalar attribute for scalar endpoints, a Vec3Attribute (or a pv.CellMap, meaning its logical_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 returns outside (default 0) instead of raising. Pass outside=None to 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 a pv.CellMap) measures distances in another space, for example logical cell units; where those coordinates are undefined the weight is outside (None raises).

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 i dominates near points[i]. Where custom coordinates are undefined (outside a CellMap domain) every partial weight is outside; 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.

inside is kept within region grown by half_width; outside is kept outside region shrunk by half_width. In the 2 * half_width band 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. region can 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] fills regions[i] (minus earlier regions) and the last node fills the rest, so len(nodes) must be len(regions) + 1. mode chooses how neighbours meet: "sharp" cuts at the region surface, "mix" blends distance fields across a 2 * half_width band (compatible families only, see mix()), and "overlap" keeps both structures in the band (see overlap()). 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 spacing or density is 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 to density ** (-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. relaxation applies 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=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.

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() for prune_loose and allow_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_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:

The plate lattice node.

Return type:

pv.StochasticFaceLattice

Raises:

ValueError – If boundary is not "open", "closed" or a pv.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).

spacing is a positive number, FloatAttribute or scalar callable (mm). Two seeds are accepted together when their distance is at least the mean of their local spacings, the same rule as sample_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 given seed but differ from sample_points_in_host(). Returns a StochasticPointSet.

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 with pv.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_spacings and a triangle_ids list giving the triangle each seed lies on.

Return type:

StochasticPointSet

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, with seed_pairs, triangle_ids and each seed’s cell_areas. Computed per triangle, exactly, so scanned meshes work.

Parameters:
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 within simplify_tolerance of 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. 0 keeps 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 / 2 of the body’s surface (inside pv.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 example mm.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 as method, seed or random_points as keywords) and a Voronoi graph lattice from them. Where regularity is 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 precomputed seeds no 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 region to 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_width band around the region surface and lets them intersect (see pyvcad_metamaterials.overlap()). The foam is built by voronoi_transition() on host grown into the band, with loose strut pieces pruned against exactly that boundary, so the band edge leaves no loose fragments. regularity (0 = random foam) and kind/cell_size/cell_map set the foam’s seeds; use the TPMS’s own cell_map so the foam cells match the TPMS cell size. beam_thickness and the TPMS wall thickness may be fields, for example ramps that thin each structure as it crosses the band. Extra options go to voronoi_transition().

Choose half_width between a quarter and a half of the cell size: narrower bands give few contacts, much wider ones double the material. With check_voxel_size the result is checked with pyvcad_metamaterials.require_connected() (raises ValueError when it is not one piece). Returns the joined node, clipped to host.

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() with spacing (mm; a number, FloatAttribute or scalar callable), so a spacing field grades the cell size, for example smaller cells near a head with mm.ramp(0, 15, coordinates=mm.distance_field(head)). Seeds are also placed in a ghost_layer just outside the host (default: the typical local spacing) so the cells at the surface are closed, and prune_loose drops 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, including mm.domain(cell_map) for a conformal liner volume. Returns voronoi_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, FloatAttribute or callable) is 0 where the foam should be random and 1 where it should be the regular lattice; ramps from ramp() 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 with cell_size (and optional lattice origin) or, with cell_map, placed through the map (see cell_map_sites()). Only sites inside the prepared host are 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 are random_points (for example a graded sample_points_in_host() result) or, by default, a Poisson-disk sample whose density matches the sites (random_spacing overrides 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 and minimum_separation (default 0.3 x) removes seeds that would make sliver cells. site_margin (cells) extends CellMap sites past the map boundary (see cell_map_sites()). Returns TransitionSeeds.

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.

bounds is a (minimum, maximum) pair; cell_size is a number or three numbers in mm; origin is a lattice corner (defaults to minimum). Sites within margin of the box are included. To line the sites up with a rectangular map’s graph lattice, use the map’s minimum corner as origin and its cell size.

pyvcad_metamaterials.cell_map_sites(cell_map, kind, margin=0.0)[source]#

Return kind sites 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 a pv.CellMapCollection contributes 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 (see voronoi_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 kind sites.

"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 to pyvcad_metamaterials.graph_lattice() with the same CellMap used for cell_map_sites(). It is periodic_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 kind sites.

cell_size is 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 of pv.Vec3) in parallel, and solid voxels are joined through face, edge and corner neighbours (connectivity=26) or faces only (6).

Resolution matters: choose voxel_size at 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 deciding connected; the default None ignores pieces of fewer than 8 voxels. Pass 0 to count every piece.

cull_far_cells=True decides 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 default False for 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 ValueError unless check_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_volume that 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.