Partitions: planar cuts & interlocking splits

Pure-Python port of BOSL2’s partitions.scad – slice an object with a plane, or partition a large object into two interlocking pieces for printing. The cut operators are methods on Bosl2Solid via the Partitionable mixin; the 2-D cut-path generators return Path objects and the mask builders return Bosl2Solids.

Planar half-cuts

left_half / right_half / front_half / back_half / top_half / bottom_half keep one side of an axis-aligned plane, and half_of(v, cp) cuts at any plane. Each intersects the solid with a half-space mask auto-sized from the object’s own bounding box, so BOSL2’s s= mask-size argument is optional:

cuboid([40, 30, 20]).left_half()          # keep the -X half
cuboid([40, 30, 20]).bottom_half(z=5)      # cut at Z=5, keep below
sphere(radius=20).half_of([0, 1, 1])            # cut on an arbitrary plane through the centre

Passing cut_path= (a 2-D partition_path()) makes the cut face follow an interlocking profile instead of a flat plane; cut_angle spins that face about the normal and offset grows the mask.

Interlocking partitions

.partition() cuts a solid into two mating pieces along a joint (jigsaw, dovetail, hammerhead, …) and spreads them apart, returning [back_piece, front_piece]:

back, front = cuboid([60, 40, 20]).partition(spread=12, cutpath="dovetail")

partition_path() builds the joint profile from a list of segment descriptors, and partition_mask() / partition_cut_mask() give the raw masks if you want to cut manually. Every partition_path output is pinned to the real BOSL2 in tests/test_bosl2_reorient.py.

Coverage of BOSL2 partitions.scad

BOSL2 function

Status

Notes

half_of

ported

half_of() – any plane; cut_path / cut_angle / offset supported. Auto-sizes the mask; the 2-D planar form is not ported (Bosl2Solid is 3-D).

left_half / right_half / front_half / back_half / top_half / bottom_half

ported

the six axis half-cuts, as methods.

partition

ported

partition() – returns the two interlocking pieces (spread/cutsize/cutpath/gap/spin/slop).

partition_mask / partition_cut_mask

ported

partition_mask() / partition_cut_mask().

partition_path

ported

partition_path() – the full segment grammar, including the xflip/yflip/addflip/wave/Nx/WxH/skew:/pinch: modifiers and the altpath redirect.

show_frameref

not ported

a preview-only frame-reference arrow (no geometry payload).

Examples

A box split into two dovetail-jointed pieces, spread apart:

back, front = s3.cuboid([60, 40, 20]).partition(spread=14, cutpath="dovetail")
(back | front).show()

⬇ Download STL mesh

A jigsaw cut face on one half of a long bar:

cut = partition_path([50, "jigsaw", 50], _fn=20)
s3.cuboid([100, 40, 16]).back_half(cut_path=cut).show()

⬇ Download STL mesh

API reference

bosl2.partitions.partition_path(pathdesc, repeat=1, y=None, altpath=None, seglen=25, segwidth=25, fn=None, fa=None, fs=None)[source]

Build a 2-D interlocking cut path from a list of segment descriptors (BOSL2 partition_path()).

Each item of pathdesc is a numeric length (a flat section), a 2-D path (used as-is), or a named section pattern – "flat", "sawtooth", "square", "triangle", "halfsine", "semicircle", "sinewave", "comb", "finger", "dovetail", "hammerhead", "jigsaw" – optionally suffixed with space-separated modifiers ("3x" repeat, "30x20" resize, "xflip"/"yflip"/"addflip"/"wave", "skew:15", "pinch:33" / "pinch:20deg"). Modifiers apply left to right.

Parameters:
  • pathdesc – list of segment descriptors

  • repeat (int) – repeat the whole pathdesc this many times (default 1)

  • y – if given, close the path at this Y (for a polygon); its sign orients the result

  • altpath – optional base path the pattern is redirected along

  • seglen (float) – default length for named sections (default 25)

  • segwidth (float) – default width for named sections (default 25)

  • fn (int | None)

  • fa (float | None)

  • fs (float | None)

Returns:

A Path (closed when y is given).

Return type:

Path

Examples

A wall profile mixing jigsaw and hammerhead joints, stroked into a divider:

wall = partition_path([40, "jigsaw", 10, "jigsaw yflip", 40], fn=24)
wall.stroke(width=3).linear_extrude(height=30).show()

⬇ Download STL mesh

bosl2.partitions.partition_mask(length=100, w=100, height=100, cutsize=10, cutpath='jigsaw', gap=0, cutpath_centered=True, inverse=False, slop=0.0, fn=None, fa=None, fs=None)[source]

A mask to remove half of an object, leaving an interlocking edge (BOSL2 partition_mask()).

Intersect it with (or subtract it from) a solid to keep the half within w of the cut plane. Pair a plain mask with an inverse=True one to split a part into two mating pieces.

Parameters:
  • length (float) – length of the cut axis

  • w – width of the kept part, back from the cut plane

  • height (float) – height of the part

  • cutsize – cut-pattern width (scalar, or [length, width])

  • cutpath – named cut pattern or an explicit 2-D path

  • gap (float) – empty gaps between pattern iterations

  • cutpath_centered (bool) – keep the pattern centered (default True)

  • inverse (bool) – build the mating (inverted) mask

  • slop (float) – shrink the mask by this much for a printer-fit clearance

  • fn (int | None)

  • fa (float | None)

  • fs (float | None)

Return type:

Bosl2Solid

bosl2.partitions.partition_cut_mask(length=100, height=100, cutsize=10, cutpath='jigsaw', gap=0, cutpath_centered=True, slop=0.1, fn=None, fa=None, fs=None)[source]

A thin mask to cut an object into two mating pieces (BOSL2 partition_cut_mask()).

Subtract it from a solid to split it along the cut path with a slop-wide kerf.

Parameters:
  • length (float)

  • height (float)

  • gap (float)

  • cutpath_centered (bool)

  • slop (float)

  • fn (int | None)

  • fa (float | None)

  • fs (float | None)

Return type:

Bosl2Solid

class bosl2.partitions.Partitionable[source]

Bases: ABC

Mixin adding the partitions.scad planar cuts and the partition() split as methods.

Inherited by Bosl2Solid. A half-cut intersects the solid with a half-space mask whose size defaults to the object’s own bounding box (so BOSL2’s s= argument is optional). cut_path= follows a 2-D partition_path() to make an interlocking cut face instead of a flat plane.

half_of(v=[0, 0, 1], center=None, s=None, cut_path=None, cut_angle=0, offset=0)[source]

Keep the half of this solid on the side the normal v points to (BOSL2 half_of()).

center is a point on the cut plane, or a scalar distance to shift the plane along v. s (the mask size) defaults to twice the object’s bounding-box reach, so it rarely needs setting. cut_path follows a 2-D partition_path() for an interlocking cut face; cut_angle spins that face about v; offset grows the mask.

Parameters:
  • center (bool | list[float] | None)

  • cut_angle (float)

left_half(x=0, s=None, cut_path=None, cut_angle=0, offset=0)[source]

Keep the left (-X) half, cut at X=x (BOSL2 left_half()).

Parameters:

cut_angle (float)

right_half(x=0, s=None, cut_path=None, cut_angle=0, offset=0)[source]

Keep the right (+X) half, cut at X=x (BOSL2 right_half()).

Parameters:

cut_angle (float)

front_half(y=0, s=None, cut_path=None, cut_angle=0, offset=0)[source]

Keep the front (-Y) half, cut at Y=y (BOSL2 front_half()).

Parameters:

cut_angle (float)

back_half(y=0, s=None, cut_path=None, cut_angle=0, offset=0)[source]

Keep the back (+Y) half, cut at Y=y (BOSL2 back_half()).

Parameters:

cut_angle (float)

bottom_half(z=0, s=None, cut_path=None, cut_angle=0, offset=0)[source]

Keep the bottom (-Z) half, cut at Z=z (BOSL2 bottom_half()).

Parameters:

cut_angle (float)

top_half(z=0, s=None, cut_path=None, cut_angle=0, offset=0)[source]

Keep the top (+Z) half, cut at Z=z (BOSL2 top_half()).

Parameters:

cut_angle (float)

partition(spread=10, cutsize=10, cutpath='jigsaw', gap=0, cutpath_centered=True, spin=0, slop=0.0, fn=None, fa=None, fs=None)[source]

Cut this solid into two interlocking pieces, spread apart (BOSL2 partition()).

Returns [back_piece, front_piece] – the two halves with matched joining edges, moved spread apart along the (spun) Y axis so they print separately and snap back together. The joint follows cutpath ("jigsaw", "dovetail", "hammerhead", …); spin rotates the cut direction; slop leaves a printer-fit clearance.

Parameters:
  • spread (float)

  • gap (float)

  • cutpath_centered (bool)

  • slop (float)

  • fn (int | None)

  • fa (float | None)

  • fs (float | None)