Cell maps#
A cell map is an immutable coordinate layout: a box, a cylinder, a spherical
band, or a curvilinear volume on top of a surface. Every structure builder
takes one. The returned objects are pyvcad.CellMap or
pyvcad.CellMapCollection instances.
Analytic maps#
- pyvcad_metamaterials.rectangular_cell_map(bounds, cell_size=None, cells=None, linear=True)[source]#
Create an axis-aligned finite cell map.
Exactly one of
cell_sizeandcellsis required. Requested cell sizes are converted to integer counts with ceiling so the supplied bounds remain exact and opposite boundaries never drift.
- pyvcad_metamaterials.cylindrical_cell_map(center, inner_radius, outer_radius, height, cells=None, axis=<pyvcad.pyvcad.Vec3 object>, reference_direction=<pyvcad.pyvcad.Vec3 object>, start_angle_degrees=0.0, sweep_degrees=360.0, linear=False, arc_count=None, axial_cell_size=None, radial_cell_size=None)[source]#
Create an analytic annular-cylinder cell map.
Provide either explicit
cells=(circumferential, axial, radial)or the complete sizing grouparc_count,axial_cell_size, andradial_cell_size. Target sizes are rounded up to counts so the requested radii and height remain exact.
- pyvcad_metamaterials.spherical_cell_map(center, inner_radius, outer_radius, latitude_bounds_degrees, cells=None, north_axis=<pyvcad.pyvcad.Vec3 object>, reference_direction=<pyvcad.pyvcad.Vec3 object>, start_longitude_degrees=0.0, longitude_sweep_degrees=360.0, linear=False, longitude_count=None, latitude_count=None, radial_cell_size=None)[source]#
Create an analytic spherical-shell band cell map.
Provide either explicit
cells=(longitude, latitude, radial)or the complete sizing grouplongitude_count,latitude_count, andradial_cell_size. Radial target size is rounded up to a count so the requested radii remain exact.
Surface maps#
- pyvcad_metamaterials.cell_map_from_surface(surface_or_surfaces, cells, height, linear=False, trim=<TrimMode.boundary: 2>, standoff=0.0)[source]#
Create one signed-height map per parametric surface.
Accepts a single
ParametricSurface(a CADFace or TriangleMeshSurface), or a non-empty iterable that mixes any surface types. A single surface returns apv.CellMap; an iterable returns apv.CellMapCollectionwith per-surface cell counts broadcast fromcells.heightis the signed thickness of the map in mm along the surface normal. It may be:a number, for a constant height (the original behaviour);
a
pv.FloatAttribute(or a numba callable), sampled once per cell-map column at the column’s base point on the surface, for a variable height;a per-vertex array (list or NumPy array with one value per vertex) for a
pv.TriangleMeshSurface, interpolated across the patch.surface_gapcomputes one by ray casting to a target such as the inside of a shell, so the cells end on it.
A variable height must stay finite, non-zero, and of one sign over the whole map. With several surfaces,
heightis either broadcast to all of them or given as a list with one entry per surface.trimselects how the map is restricted to the surface’s true domain: apv.TrimModeor one of the strings"none","cells","boundary".standoffis a signed stand-off distance along the surface normal at which the map begins, so it spans[standoff, standoff + height]off the surface.
- pyvcad_metamaterials.cell_map_from_cad_face(face_or_faces, cells, height, linear=False, trim=<TrimMode.boundary: 2>, standoff=0.0)[source]#
Create one native-UV signed-height map per CAD face.
- pyvcad_metamaterials.cell_map_between_surfaces(first_surface, second_surface, cells, linear=False, trim=<TrimMode.boundary: 2>, auto_align=True, first_origin=None, flip_first=False, second_origin=None, flip_second=False, standoff=0.0)[source]#
Create a curvilinear volume between two parametric surfaces of any type.
first_surfaceandsecond_surfacemay be any mix of CADFace and TriangleMeshSurface. In advanced mode,flip_firstandflip_secondrequest opposing UV orientation changes. Origins are normalized(u, v)seam shifts and non-zero values are valid only for periodic directions.standoffshifts the first surface along its oriented normal (in mm) before the two surfaces are interpolated, so the volume starts a clearance away from it. Zero (the default) leaves the map unchanged; the second surface never moves.
- pyvcad_metamaterials.cell_map_between_cad_faces(first_face, second_face, cells, linear=False, trim=<TrimMode.boundary: 2>, auto_align=True, first_origin=None, flip_first=False, second_origin=None, flip_second=False, standoff=0.0)[source]#
Create a curvilinear volume between two compatible CAD faces.
In advanced mode,
flip_firstandflip_secondrequest opposing UV orientation changes. Origins are normalized(u, v)seam shifts and non-zero values are valid only for periodic CAD directions.standoffshifts the first face along its oriented normal before interpolating.
Map tools#
- pyvcad_metamaterials.warp_cell_map(cell_map, u_scale=0.0, v_scale=0.0, w_scale=0.0, lock_u_bounds=True, lock_v_bounds=True, lock_w_bounds=True)[source]#
Warp relative U/V/W spacing with bounded positive exponential weights.
Each cell’s share of the map along an axis is weighted by
exp(clamp(scale, -4, 4)), sampled on the unwarped base map. A scale of0keeps the original spacing; larger values give that region more room. The base map is not modified.- Parameters:
cell_map (pv.CellMap | pv.CellMapCollection) – Base map or maps.
u_scale (float | pv.FloatAttribute | callable) – Relative spacing controls per axis, default
0.0. These are weights, not cell sizes in mm.cell_map.logical_positionis a convenient input.v_scale (float | pv.FloatAttribute | callable) – Relative spacing controls per axis, default
0.0. These are weights, not cell sizes in mm.cell_map.logical_positionis a convenient input.w_scale (float | pv.FloatAttribute | callable) – Relative spacing controls per axis, default
0.0. These are weights, not cell sizes in mm.cell_map.logical_positionis a convenient input.lock_u_bounds (bool) – Keep the two outer faces on that axis fixed and redistribute the cells between them (default
True).lock_v_bounds (bool) – Keep the two outer faces on that axis fixed and redistribute the cells between them (default
True).lock_w_bounds (bool) – Keep the two outer faces on that axis fixed and redistribute the cells between them (default
True).
- Returns:
The warped map, same kind as the input.
- Return type:
pv.CellMap | pv.CellMapCollection
- Raises:
RuntimeError – If a map was built with
TrimMode.boundary(rebuild it withtrim="none"before warping), or if the warp would fold the domain.
Example
>>> warped = mm.warp_cell_map(cell_map, u_scale=cell_map.logical_position.x * 0.2)
- pyvcad_metamaterials.rim(cell_map, width=1.0)[source]#
Build a solid rim along the edges of each surface map.
The rim is a signed distance field from the map’s edge wall (the surface’s cropped boundary swept through the map height for boundary-trimmed maps, and the exposed lateral cell faces otherwise). It extends
widthinward from the edge, so unioning it with a lattice built on the same map seals the lattice’s open edge cells.widthmay be a constant or apv.FloatAttributesampled through the map.
- pyvcad_metamaterials.surface_gap(surface, target, max_distance, offset=0.0, missing='raise', tolerance=0.001, voxel_size=0.25)[source]#
Measure the gap from every vertex of a mesh patch along its normal to a target.
This is the head-to-shell gap that drives an exact-fit variable-height map: with
gap = mm.surface_gap(head, shell, 60.0),mm.cell_map_from_surface(head, cells, height=gap)grows cells from the head patch that end on the shell.- Parameters:
surface (pv.TriangleMeshSurface) – Patch whose vertices and vertex normals cast the rays.
target – What the rays hit. A
pv.TriangleMeshSurfaceorpv.SurfaceMeshis hit by exact ray-triangle intersection, so open or non-watertight meshes (a shell’s inner surface exported from CAD) work. Any otherpyvcadnode is sphere-traced against its signed distance field (a private clone is prepared withvoxel_size).max_distance (float) – Longest ray in mm.
offset (float) – Subtracted from every distance, for example a stand-off or a clearance.
missing – What to do for rays that hit nothing within
max_distance:"raise"(default) raisesValueError,"nearest"copies the value of the nearest vertex that did hit, and a number is used as is.tolerance (float) – Hit tolerance in mm for sphere tracing.
voxel_size (float) – Voxel size in mm used to prepare a node target.
- Returns:
One distance in mm per surface vertex, minus
offset.- Return type:
numpy.ndarray
- pyvcad_metamaterials.domain(cell_map)[source]#
Return the active volume of a cell map as a solid node (
pv.CellMapDomain).The node’s field is the map’s signed domain distance in mm: negative inside the active, trimmed map volume and positive outside, including trimmed margins and holes. Use it to clip another node to a liner volume (
pv.Intersection), as a keep-out (pv.Difference), or as the host of a stochastic lattice. Apv.CellMapCollectionreturns the union of its maps’ domains.
- pyvcad_metamaterials.map_node(cell_map, node, space='physical', scale=None, clip_to_domain=True)[source]#
Wrap any node through a cell map so geometry designed flat follows the map.
The node is authored in a flat child box and evaluated at the map’s logical coordinates scaled to child units. With
space="physical"(default) the scale is the map’s average millimetres per cell along U, V, and W, so the child boxpv.MappedNode.child_boundscovers the whole map in approximate millimetres;space="logical"uses cell units, andscale(apv.Vec3or 3-tuple) sets explicit child units per cell. Typical uses are pads, bosses, labels, or cut-outs placed on a curved liner. Distances are first-order Jacobian estimates: accurate near the surface (safe for meshing) but approximate far from it.By default the wrapped node ends where the map ends (its field is clipped with the map’s domain distance). Pass
clip_to_domain=Falsewhen the node marks a zone of the map, for example a region forzones()oroverlap(): inside the domain it then keeps its own depth, so growing or shrinking the region by a band width works as expected.
Raw OCP shapes#
CadQuery shapes are converted with pyvcad.CADModel.from_cadquery. Raw
OCP shapes use the optional pyvcad_metamaterials.occ adapters, which need
the cad extra (pip install "pyvcad-metamaterials[cad]").