Distributors: copiers & reflected copies

Pure-Python port of BOSL2’s distributors.scad – the “copiers” that duplicate a shape into a line, grid, ring, arc, sphere, or path pattern, plus the reflected-copy helpers. Each copier is a module-level function returning a list of 4x4 transformation matrices (BOSL2’s function form), and a matching method on every geometry object via the distributors mixin.

What a copier returns depends on the object it is called on:

  • shapes3d – the union of the transformed geometry copies (a new solid), matching BOSL2’s module form:

    cuboid([10, 10, 10]).grid_copies(num_copies=[3, 3], spacing=30)   # 9 cubes, unioned
    cuboid([6, 6, 6]).zrot_copies(rots=6, radius=30)                 # a ring of 6 cubes
    part.right(20).xflip_copy()                              # part + its mirror image
    
  • paths / path3d – a plain list of the transformed path copies (BOSL2’s function form). A 2-D Path only supports the in-plane copiers; one that would lift it out of the XY plane (zcopies, xrot_copies, sphere_copies, …) raises, directing you to Path3D.

Every copier’s matrices are pinned to the real BOSL2 output in tests/test_pybosl2_reorient.py.

Coverage of BOSL2 distributors.scad

BOSL2 function

Status

Notes

move_copies

ported

distributors() – a copy at each given offset.

xcopies / ycopies / zcopies

ported

spacing/n/l/sp and the explicit-position-list form.

line_copies

ported

distributors() – along a line by spacing, length, or p1/p2.

grid_copies

ported

square and staggered (hex) grids, size/n/spacing, axes=, and an inside= polygon mask (grid2d is the deprecated alias, not ported).

rot_copies

ported

rotated copies about any axis, with cp/sa/delta/subrot.

xrot_copies / yrot_copies / zrot_copies

ported

rings about the X/Y/Z axes (r/d, sa, subrot).

arc_copies

ported

along a circular or elliptical arc in the XY plane (arc_of alias not ported).

sphere_copies

ported

golden-spiral spread over a sphere/ellipsoid (ovoid_spread alias not ported).

path_copies

ported

distributors() – along a 2-D/3-D path, oriented to it (path_spread alias not ported).

mirror_copy / xflip_copy / yflip_copy / zflip_copy

ported

the original plus one reflected copy.

distribute / xdistribute / ydistribute / zdistribute

ported

distributors() – lay a list of distinct solids out so they don’t overlap (sizes taken from each child’s bounding box if not given).

$pos / $idx / $ang / $row / $col side-effect variables

not ported

OpenSCAD special variables for per-copy customization have no Python equivalent; build the variants yourself and use move_copies with explicit matrices.

Examples

A grid of rounded pillars, unioned into one solid:

from functools import reduce
from pybosl2 import shapes3d as s3

reduce(lambda a, b: a | b, s3.cyl(height=12, radius=4, rounding=1).grid_copies(num_copies=[4, 3], spacing=14)).show()
Loading 3-D preview…

⬇ Download STL mesh

A ring of wedges facing the centre:

from functools import reduce
from pybosl2 import shapes3d as s3

reduce(lambda a, b: a | b, s3.prismoid([6, 10], [2, 10], height=12).zrot_copies(rots=8, radius=24)).show()
Loading 3-D preview…

⬇ Download STL mesh

Copies of a 2-D outline along an arc, extruded together:

from functools import reduce
from pybosl2 import Path2D

tile = Path2D([[-3, -3], [3, -3], [3, 3], [-3, 3]])
reduce(lambda a, b: a | b, (c.polygon() for c in tile.arc_copies(radius=30, ea=180, num_copies=10))) \
    .linear_extrude(height=3).show()
Loading 3-D preview…

⬇ Download STL mesh

API reference

Return Distributors: line/grid/ring/arc/sphere/path copiers and reflected copies.

pybosl2.distributors.xdistribute(children, spacing=None, sizes=None, length=None)[source]

Distribute distinct children along the X axis.

Examples

from pybosl2.solid import cuboid
from pybosl2.distributors import xdistribute

xdistribute(spacing=15, children=[cuboid([5, 5, 20]) for _ in range(5)]).show()
Loading 3-D preview…

⬇ Download STL mesh

Parameters:
children : list[BaseShape]

spacing : float | None

sizes : list[float] | None

length : float | None

Return type:

BaseShape

pybosl2.distributors.ydistribute(children, spacing=None, sizes=None, length=None)[source]

Distribute distinct children along the Y axis.

Parameters:
children : list[BaseShape]

spacing : float | None

sizes : list[float] | None

length : float | None

Return type:

BaseShape

pybosl2.distributors.zdistribute(children, spacing=None, sizes=None, length=None)[source]

Distribute distinct children along the Z axis.

Parameters:
children : list[BaseShape]

spacing : float | None

sizes : list[float] | None

length : float | None

Return type:

BaseShape

class pybosl2.distributors.DistributableMatrix[source]

Bases: object

Return Matrix-generating copiers – each returns list[np.ndarray] (4x4 matrices).

static line_copies(spacing=None, length=None, p1=None, p2=None, num_copies=None)

Return translation matrices evenly spread along a line.

Parameters:
spacing : float | ndarray | None

length : float | ndarray | None

p1 : Point | None

p2 : Point | None

num_copies : int | None

Return type:

list[ndarray]

static xcopies(spacing=None, length=None, start_pos=None, num_copies=None)

Return copies spread along the X axis.

Parameters:
spacing : float | None

length : float | None

start_pos : float | Point | None

num_copies : int | None

Return type:

list[ndarray]

static ycopies(spacing=None, length=None, start_pos=None, num_copies=None)

Return copies spread along the Y axis.

Parameters:
spacing : float | None

length : float | None

start_pos : float | Point | None

num_copies : int | None

Return type:

list[ndarray]

static zcopies(spacing=None, length=None, start_pos=None, num_copies=None)

Return copies spread along the Z axis.

Parameters:
spacing : float | None

length : float | None

start_pos : float | Point | None

num_copies : int | None

Return type:

list[ndarray]

static grid_copies(spacing=None, size=None, stagger=False, inside=None, nonzero=None, axes='xy', num_copies=None)

Return copies laid out in a square or staggered (hex) grid.

Parameters:
spacing : float | Sequence[float] | ndarray | None

size : float | Sequence[float] | ndarray | None

stagger : bool | StaggerMode

inside : Sequence[Sequence[float]] | ndarray | None

nonzero : bool | None

axes : str

num_copies : int | Sequence[int] | ndarray | None

Return type:

list[ndarray]

static rot_copies(rots=None, v=None, center=(0, 0, 0), sa=0, offset=0, delta=(0, 0, 0), subrot=True, num_copies=None)

Return rotated copies about an axis, optionally offset into a ring.

Parameters:
rots : Sequence[float] | None

v : Point | None

center : bool | Sequence[float]

sa : float

offset : float

delta : Sequence[float]

subrot : bool

num_copies : int | None

Return type:

list[ndarray]

static xrot_copies(rots=None, center=(0, 0, 0), sa=0, radius=None, diameter=None, subrot=True, num_copies=None)

Return rotated copies around the X axis, optionally into a ring of radius radius.

Parameters:
rots : Sequence[float] | None

center : bool | Sequence[float]

sa : float

radius : float | None

diameter : float | None

subrot : bool

num_copies : int | None

Return type:

list[ndarray]

static yrot_copies(rots=None, center=(0, 0, 0), sa=0, radius=None, diameter=None, subrot=True, num_copies=None)

Return rotated copies around the Y axis, optionally into a ring of radius radius.

Parameters:
rots : Sequence[float] | None

center : bool | Sequence[float]

sa : float

radius : float | None

diameter : float | None

subrot : bool

num_copies : int | None

Return type:

list[ndarray]

static zrot_copies(rots=None, center=(0, 0, 0), sa=0, radius=None, diameter=None, subrot=True, num_copies=None)

Return rotated copies around the Z axis, optionally into a ring of radius radius.

Parameters:
rots : Sequence[float] | None

center : bool | Sequence[float]

sa : float

radius : float | None

diameter : float | None

subrot : bool

num_copies : int | None

Return type:

list[ndarray]

static arc_copies(radius=None, radius_x=None, radius_y=None, diameter=None, diameter_x=None, diameter_y=None, sa=0, ea=360, rot=True, num_copies=6)

Return copies spread along an (elliptical) arc in the XY plane.

Parameters:
radius : float | None

radius_x : float | None

radius_y : float | None

diameter : float | None

diameter_x : float | None

diameter_y : float | None

sa : float

ea : float

rot : bool

num_copies : int

Return type:

list[ndarray]

static sphere_copies(num_copies=100, radius=None, diameter=None, cone_ang=90, scale=(1, 1, 1), perp=True)

Return copies spread over a sphere/ellipsoid by the golden-spiral method.

Parameters:
num_copies : int

radius : float | None

diameter : float | None

cone_ang : float

scale : Sequence[float]

perp : bool

Return type:

list[ndarray]

static path_copies(path, spacing=None, start_pos=None, dist=None, rotate_children=True, closed=None, num_copies=None)

Return copies placed along path, oriented to it.

Parameters:
path : Sequence[Sequence[float]]

spacing : float | None

start_pos : float | None

dist : Sequence[float] | None

rotate_children : bool

closed : bool | None

num_copies : int | None

Return type:

list[ndarray]

static mirror_copy(v=(0, 0, 1), offset=0, center=None)

Return the original plus a mirrored copy across the plane with normal v.

Parameters:
v : Sequence[float]

offset : float

center : bool | list[float] | None

Return type:

list[ndarray]

static xflip_copy(offset=0, x=0)

Return the original plus a copy mirrored across the X=*x* plane.

Parameters:
offset : float

x : float

Return type:

list[ndarray]

static yflip_copy(offset=0, y=0)

Return the original plus a copy mirrored across the Y=*y* plane.

Parameters:
offset : float

y : float

Return type:

list[ndarray]

static zflip_copy(offset=0, z=0)

Return the original plus a copy mirrored across the Z=*z* plane.

Parameters:
offset : float

z : float

Return type:

list[ndarray]

class pybosl2.distributors.Distributable[source]

Bases: ABC

Return Mixin adding the distributors.scad copiers as methods.

Inherited by Bosl2Solid, Path2D, and Path3D. Each copier returns a list of positioned copies; callers union, hull, or combine them as needed.

move_and_copy(vectors=None)[source]

Copy to each offset in vectors (BOSL2 move_copies).

Parameters:
vectors : list[Point] | None

A list of Point offsets, or None for a single copy at the origin.

Returns:

The union (or list for paths) of copies at each offset.

Return type:

list[__SPHINX_IMMATERIAL_TYPE_VAR__V__CopyType]

line_copies(spacing=None, length=None, p1=None, p2=None, num_copies=None)[source]

Return copies spread along a line.

Parameters:
spacing : float | None

length : float | None

p1 : Point | None

p2 : Point | None

num_copies : int | None

Return type:

list[__SPHINX_IMMATERIAL_TYPE_VAR__V__CopyType]

xcopies(spacing=None, length=None, start_pos=None, num_copies=None)[source]

Return copies spread along the X axis.

Parameters:
spacing : float | None

length : float | None

start_pos : float | Point | None

num_copies : int | None

Return type:

list[__SPHINX_IMMATERIAL_TYPE_VAR__V__CopyType]

ycopies(spacing=None, length=None, start_pos=None, num_copies=None)[source]

Return copies spread along the Y axis.

Parameters:
spacing : float | None

length : float | None

start_pos : float | Point | None

num_copies : int | None

Return type:

list[__SPHINX_IMMATERIAL_TYPE_VAR__V__CopyType]

zcopies(spacing=None, length=None, start_pos=None, num_copies=None)[source]

Return copies spread along the Z axis.

Parameters:
spacing : float | None

length : float | None

start_pos : float | Point | None

num_copies : int | None

Return type:

list[__SPHINX_IMMATERIAL_TYPE_VAR__V__CopyType]

grid_copies(spacing=None, size=None, stagger=False, inside=None, nonzero=None, axes='xy', num_copies=None)[source]

Return copies in a square or staggered (hex) grid.

Parameters:
spacing : float | Sequence[float] | ndarray | None

size : float | Sequence[float] | ndarray | None

stagger : bool | StaggerMode

inside : Sequence[Sequence[float]] | ndarray | None

nonzero : bool | None

axes : str

num_copies : int | Sequence[int] | ndarray | None

Return type:

list[__SPHINX_IMMATERIAL_TYPE_VAR__V__CopyType]

rot_copies(rots=None, v=None, center=(0, 0, 0), sa=0, offset=0, delta=(0, 0, 0), subrot=True, num_copies=None)[source]

Rotated copies about an axis (optionally into a ring via delta).

Parameters:
rots : Sequence[float] | None

v : Point | None

center : bool | Sequence[float]

sa : float

offset : float

delta : Sequence[float]

subrot : bool

num_copies : int | None

Return type:

list[__SPHINX_IMMATERIAL_TYPE_VAR__V__CopyType]

xrot_copies(rots=None, center=(0, 0, 0), sa=0, radius=None, diameter=None, subrot=True, num_copies=None)[source]

Rotated copies around the X axis.

Parameters:
rots : Sequence[float] | None

center : bool | Sequence[float]

sa : float

radius : float | None

diameter : float | None

subrot : bool

num_copies : int | None

Return type:

list[__SPHINX_IMMATERIAL_TYPE_VAR__V__CopyType]

yrot_copies(rots=None, center=(0, 0, 0), sa=0, radius=None, diameter=None, subrot=True, num_copies=None)[source]

Rotated copies around the Y axis.

Parameters:
rots : Sequence[float] | None

center : bool | Sequence[float]

sa : float

radius : float | None

diameter : float | None

subrot : bool

num_copies : int | None

Return type:

list[__SPHINX_IMMATERIAL_TYPE_VAR__V__CopyType]

zrot_copies(rots=None, center=(0, 0, 0), sa=0, radius=None, diameter=None, subrot=True, num_copies=None)[source]

Rotated copies around the Z axis.

Parameters:
rots : Sequence[float] | None

center : bool | Sequence[float]

sa : float

radius : float | None

diameter : float | None

subrot : bool

num_copies : int | None

Return type:

list[__SPHINX_IMMATERIAL_TYPE_VAR__V__CopyType]

arc_copies(radius=None, radius_x=None, radius_y=None, diameter=None, diameter_x=None, diameter_y=None, sa=0, ea=360, rot=True, num_copies=6)[source]

Return copies spread along an (elliptical) arc in the XY plane.

Parameters:
radius : float | None

radius_x : float | None

radius_y : float | None

diameter : float | None

diameter_x : float | None

diameter_y : float | None

sa : float

ea : float

rot : bool

num_copies : int

Return type:

list[__SPHINX_IMMATERIAL_TYPE_VAR__V__CopyType]

sphere_copies(num_copies=100, radius=None, diameter=None, cone_ang=90, scale=(1, 1, 1), perp=True)[source]

Return copies spread over a sphere/ellipsoid surface.

Parameters:
num_copies : int

radius : float | None

diameter : float | None

cone_ang : float

scale : Sequence[float]

perp : bool

Return type:

list[__SPHINX_IMMATERIAL_TYPE_VAR__V__CopyType]

path_copies(path, spacing=None, start_pos=None, dist=None, rotate_children=True, closed=None, num_copies=None)[source]

Return copies placed along path, oriented to it.

Parameters:
path : Sequence[Sequence[float]]

spacing : float | None

start_pos : float | None

dist : Sequence[float] | None

rotate_children : bool

closed : bool | None

num_copies : int | None

Return type:

list[__SPHINX_IMMATERIAL_TYPE_VAR__V__CopyType]

mirror_copy(v=(0, 0, 1), offset=0, center=None)[source]

Return this object plus a copy mirrored across the plane with normal v.

Parameters:
v : Sequence[float]

offset : float

center : bool | list[float] | None

Return type:

list[__SPHINX_IMMATERIAL_TYPE_VAR__V__CopyType]

xflip_copy(offset=0, x=0)[source]

Return This object plus a copy mirrored across the X=*x* plane.

Parameters:
offset : float

x : float

Return type:

list[__SPHINX_IMMATERIAL_TYPE_VAR__V__CopyType]

yflip_copy(offset=0, y=0)[source]

Return This object plus a copy mirrored across the Y=*y* plane.

Parameters:
offset : float

y : float

Return type:

list[__SPHINX_IMMATERIAL_TYPE_VAR__V__CopyType]

zflip_copy(offset=0, z=0)[source]

Return This object plus a copy mirrored across the Z=*z* plane.

Parameters:
offset : float

z : float

Return type:

list[__SPHINX_IMMATERIAL_TYPE_VAR__V__CopyType]

static distribute(children, spacing=None, sizes=None, dir=Anchor.RIGHT, length=None)[source]

Space a list of distinct objects along dir so they don’t overlap.

Unlike the copiers, this lays out several different children. sizes gives each child’s extent along dir; auto-computed from bounding boxes if omitted.

Parameters:
children : list[BaseShape]

Objects with translate(), bounds(), and CSG operators.

spacing : float | None

Gap between adjacent children.

sizes : list[float] | None

Per-child extent along dir.

dir : Anchor | Point

Direction vector (default +X).

length : float | None

Total length to fill.

Returns:

The union of all positioned children.

Return type:

BaseShape