Sweeps (skin)¶
Pure-Python port of the surface generators from BOSL2’s skin.scad — every one builds a
VNF you render with .polyhedron().
Coverage of BOSL2 skin.scad¶
BOSL2 function |
Status |
Notes |
|---|---|---|
|
ported |
|
|
ported |
|
|
ported |
|
|
ported |
|
|
ported |
|
|
ported |
|
|
ported |
|
|
ported |
|
|
ported |
|
|
not ported |
use |
|
not ported |
need the BOSL2 attachment/anchor system |
textures ( |
not ported |
the whole texturing engine |
rounded / chamfered “fancy” caps |
not ported |
use flat caps, or a native end treatment |
region shapes with holes |
not ported |
use a native |
|
not ported |
only needed by the un-ported matching methods |
API reference¶
- bosl2.skin.path3d(path)[source]¶
Pad a 2-D (or 3-D) point list to 3-D with z=0.
The coordinates are converted to plain Python floats, not left as whatever the input held: a numpy row in would otherwise leak
np.float64scalars out of an annotation that promisesfloat, and those raise SystemError/TypeError at the native FFI boundary (see the note in bosl2/paths.py).- Parameters:
path (Sequence[Sequence[float]])
- Return type:
list[list[float]]
- bosl2.skin.clockwise_polygon(poly)[source]¶
poly wound clockwise (reversed if its signed area is positive/CCW).
- Parameters:
poly (Sequence[Sequence[float]])
- Return type:
list[Sequence[float]]
- bosl2.skin.frame_map(x=None, y=None, z=None)[source]¶
The 4x4 rotation whose columns are the given orthonormal axes (BOSL2 frame_map()).
Give any two of x/y/z (as 3-vectors); the third is filled in by the cross product.
- Parameters:
x (Sequence[float] | None)
y (Sequence[float] | None)
z (Sequence[float] | None)
- Return type:
- bosl2.skin.CapsSpec = bool | typing.Sequence[bool] | None¶
one bool for both ends, a
[cap1, cap2]pair for each end separately, or None to take the call’s own default. Every sweep/skin entry point accepts all three spellings, exactly as BOSL2 does – see_norm_caps().- Type:
A BOSL2
caps=argument
- bosl2.skin.sweep(shape, transforms, closed=False, caps=None, style='min_edge')[source]¶
Apply each 4x4 transform to the 2-D shape and skin the resulting profiles into a VNF.
- Parameters:
shape (Sequence[Sequence[float]]) – a 2-D polygon (list of [x, y] points)
transforms (Sequence[Sequence[Sequence[float]]]) – list of 4x4 matrices, one per cross section along the path
closed (bool) – the sweep loops back on itself (no caps)
caps (bool | Sequence[bool] | None) – cap the open ends (default: True/True open, none closed); bool or [bool, bool]
style (str) – vnf_vertex_array quad-subdivision style
- Return type:
- bosl2.skin.path_sweep(shape, path, method='incremental', normal=None, closed=False, twist=0.0, twist_by_length=True, scale=(1.0, 1.0), scale_by_length=True, symmetry=1, last_normal=None, tangent=None, uniform=True, relaxed=False, caps=None, style='min_edge', transforms=False)[source]¶
Sweep the 2-D shape along the 2-D/3-D path, returning a VNF (or the transform list).
method orients the cross section: “incremental” (rotation-minimizing frame), “manual” (using normal as a per-point normal list), or “natural” (the path’s own normal). twist (degrees) and scale (scalar, 2-vector, per-point vector, or Nx2) are interpolated along the path. See BOSL2 path_sweep() for the full semantics.
Examples
Sweeping a small square profile along a helical path into a solid:
square = [[-3, -3], [3, -3], [3, 3], [-3, 3]] helix = [[10 * math.cos(t), 10 * math.sin(t), t * 3] for t in np.linspace(0, 3 * math.pi, 40)] path_sweep(square, helix).polyhedron().show()
- Parameters:
shape (Sequence[Sequence[float]])
path (Sequence[Sequence[float]])
method (str)
normal (Sequence[float] | Sequence[Sequence[float]] | None)
closed (bool)
twist (float)
twist_by_length (bool)
scale (tuple[float, float])
scale_by_length (bool)
symmetry (int)
last_normal (Sequence[float] | None)
tangent (Sequence[Sequence[float]] | None)
uniform (bool)
relaxed (bool)
caps (bool | Sequence[bool] | None)
style (str)
transforms (bool)
- bosl2.skin.slice_profiles(profiles, slices, closed=False)[source]¶
Interpolate slices extra profiles between each consecutive pair (BOSL2 slice_profiles()).
slices is a count (or a per-segment list). The profiles must all be equal-length point lists; the interpolation is vertex-by-vertex.
- Parameters:
profiles (Sequence[Sequence[float]])
slices (int)
closed (bool)
- Return type:
list[list[float]]
- bosl2.skin.skin(profiles, slices, refine=1.0, method='direct', sampling=None, caps=None, closed=False, style='min_edge', z=None)[source]¶
Blend a stack of 2-D/3-D profiles into a skinned surface, returning a VNF (BOSL2 skin()).
Consecutive profiles are connected vertex-to-vertex; slices extra interpolated profiles are inserted between each pair to smooth the transition. Profiles of differing point counts are resampled up to the largest (via
Path._subdivide_path()).- Parameters:
profiles (Sequence[Sequence[Sequence[float]]]) – list of >= 2 closed profiles (each a list of points). If 2-D, give matching z.
slices (int) – number of interpolated profiles inserted between each pair (int or per-gap list)
refine (float) – subdivide every profile by this factor before skinning (default 1)
method (str) – “direct” (connect vertex i to vertex i) or “reindex” (rotate each profile to best-align with the previous). The “distance”/”tangent” vertex-matching methods are not ported.
sampling (str | None) – “length” or “segment” resampling (default “length”)
caps (bool | Sequence[bool] | None) – cap the ends (default: True for open, False for closed); bool or [bool, bool]
closed (bool) – the stack loops back to the first profile (default False)
style (str) – vnf_vertex_array quad-subdivision style
z (Sequence[float] | None) – per-profile Z heights, required when the profiles are 2-D
- Return type:
Examples
Skinning a round profile up to a square one (a lofted transition):
circle = [[6 * math.cos(t), 6 * math.sin(t)] for t in np.linspace(0, 2 * math.pi, 24, endpoint=False)] square = [[-8, -8], [8, -8], [8, 8], [-8, 8]] skin([circle, square], slices=20, method="reindex", z=[0, 25]).polyhedron().show()
- bosl2.skin.linear_sweep(region, height=None, twist=0.0, scale=1, shift=(0.0, 0.0), slices=None, caps=None, style='default', center=None)[source]¶
Extrude a 2-D outline to height with optional twist / scale / shift (BOSL2 linear_sweep()).
A single closed outline (a Path or point list) is supported – for a region with holes use a native
linear_extrudeinstead. The bottom sits on Z=0 unless center is True.- Parameters:
region (Sequence[Sequence[float]]) – the 2-D outline to extrude (a closed path)
height (float | None) – extrusion height (aliases: height; default 1)
twist (float) – total twist over the height, in degrees (default 0)
scale – scale of the top relative to the bottom (scalar or [x, y]; default 1)
shift – [x, y] offset of the top relative to the bottom (default [0, 0])
slices (int | None) – number of intermediate layers (default: enough for ~5 deg of twist each)
caps (bool | Sequence[bool] | None) – cap the ends (default True); bool or [bool, bool]
center (bool | None) – center the extrusion on Z (default False -> base on Z=0)
style (str) – vnf_vertex_array quad-subdivision style
- Return type:
Examples
A twisting, tapering square column:
square = [[-10, -10], [10, -10], [10, 10], [-10, 10]] linear_sweep(square, height=40, twist=120, scale=0.4).polyhedron().show()
- bosl2.skin.rotate_sweep(shape, angle=360.0, caps=None, closed=None, style='min_edge', start=0.0)[source]¶
Revolve a 2-D shape (in the X+ half-plane, x=radius, y=height) around the Z axis (BOSL2 rotate_sweep()).
A closed shape profile makes a solid of revolution; an open path with caps is first closed to the axis. A full 360-degree revolution loops seamlessly; a partial angle end-caps the sweep.
- Parameters:
shape (Sequence[Sequence[float]]) – the 2-D profile to revolve (x >= 0)
angle (float) – revolution angle in degrees, 0 < angle <= 360 (default 360)
caps (bool | Sequence[bool] | None) – end-cap a partial revolution / close an open profile to the axis (default: angle < 360)
closed (bool | None) – legacy inverse of caps (give one or the other)
style (str) – vnf_vertex_array quad-subdivision style
start (float) – starting angle in degrees (default 0)
- Return type:
Examples
Revolving a rounded profile into a spool:
profile = [[4, -10], [12, -10], [12, -6], [7, -2], [7, 2], [12, 6], [12, 10], [4, 10]] rotate_sweep(profile, 360).polyhedron().show()
- bosl2.skin.spiral_sweep(poly, height, radius=None, turns=1.0, radius1=None, radius2=None, diameter=None, diameter1=None, diameter2=None, center=True, style='min_edge')[source]¶
Sweep a 2-D cross-section poly along a helix (BOSL2 spiral_sweep(), without lead-in tapers).
poly’s X is the radial offset from the helix radius and its Y is the vertical offset, so a small wire cross-section becomes a spring/thread. The lead-in taper options are not ported.
- Parameters:
poly (Sequence[Sequence[float]]) – the 2-D wire cross-section (closed path)
height (float) – total height of the spiral
radius/diameter – helix radius/diameter (or per-end radius1/radius2 / diameter1/diameter2 for a conical spiral)
turns (float) – number of turns (default 1)
center (bool) – center the spiral on Z (default True)
style (str) – vnf_vertex_array quad-subdivision style
radius (float | None)
radius1 (float | None)
radius2 (float | None)
diameter (float | None)
diameter1 (float | None)
diameter2 (float | None)
- Return type:
Examples
A rectangular-section coil spring:
section = [[-1.2, -1.2], [1.2, -1.2], [1.2, 1.2], [-1.2, 1.2]] spiral_sweep(section, height=40, radius=12, turns=5).polyhedron().show()
- bosl2.skin.subdivide_and_slice(profiles, slices, numpoints=None, method='length', closed=False)[source]¶
Resample every profile up to numpoints then interpolate slices between them (BOSL2 subdivide_and_slice()).
numpoints defaults to the largest profile’s length; “lcm” uses the least common multiple of the profile lengths. Returns the stacked list of (equal-length) profiles.
- Parameters:
profiles (Sequence[Sequence[float]])
slices (int)
method (str)
closed (bool)
- Return type:
list[list[float]]
- bosl2.skin.path_sweep2d(shape, path, closed=False, caps=None, quality=1, style='min_edge')[source]¶
Sweep a 2-D shape along a 2-D path, mapping the shape’s Y to Z (BOSL2 path_sweep2d()).
Both shape and path are 2-D
Pathobjects (coerced from point lists). Each shape point offsets the path by its X and lifts it to its Y, so a shape with a wide X range becomes a wall of varying width along the path. Unlikepath_sweep(), moderate local concavity is handled by the offset (mitre joins); an offset large enough to collapse a feature of the path will still fold, so keep the shape’s X extent below the path’s tightest radius.- Parameters:
shape (Sequence[Sequence[float]]) – the 2-D cross-section (a closed path); its X is the offset from the path, its Y the height
path (Sequence[Sequence[float]]) – the 2-D path to sweep along
closed (bool) – the path is a closed loop (default False)
caps (bool | Sequence[bool] | None) – cap the open ends (default: True for open, False for closed)
quality (int) – accepted for signature parity (unused – the mitre offset needs no quality knob)
style (str) – vnf_vertex_array quad-subdivision style
- Return type:
Examples
A rounded bar swept along a wavy 2-D path:
shape = [[-2, -2], [2, -2], [2, 2], [-2, 2]] path = [[t, 8 * math.sin(t / 12)] for t in range(0, 90, 3)] path_sweep2d(shape, path).polyhedron().show()
- bosl2.skin.rot_resample(rotlist, sides, twist=None, scale=None, smoothlen=1, long=False, turns=0, closed=False, method='length')[source]¶
Resample a list of 4x4 transforms to uniform screw-motion spacing (BOSL2 rot_resample()).
Interpolates between successive transforms along their screw motion (via
rot_decode()), optionally adding twist and scale (smoothed over smoothlen). Handy for regularizing the transform list frompath_sweep(..., transforms=True)before handing it tosweep().- Parameters:
rotlist (Sequence[Sequence[float]]) – list of 4x4 transform matrices
sides (int) – number of output samples (method=”length”) or samples per gap (method=”count”)
twist – extra twist in degrees (scalar or per-gap list)
scale – extra scale (scalar or per-gap list, multiplied cumulatively)
smoothlen (int) – odd window length for smoothing the twist/scale (default 1 = none)
long – take the >180-degree rotation at a gap (scalar or per-gap list)
turns (float) – extra full turns to add at a gap (scalar or per-gap list)
closed (bool) – the transform list forms a loop (default False)
method (str) – “length” (uniform screw-distance) or “count” (fixed samples per gap)
- Return type:
list