Rounding: round_corners & smooth_path¶
Pure-Python port of the path-rounding core of BOSL2’s rounding.scad:
round_corners() rounds every corner of a path, and
smooth_path() fits a continuous-curvature curve through a path. Both work on
2-D and 3-D paths and are methods on paths and path3d:
Path([[0, 0], [40, 0], [40, 30], [0, 30]]).round_corners(radius=5)
Path([[0, 0], [40, 0], [40, 30], [0, 30]]).round_corners(method="smooth", joint=8)
Path([[0, 0], [10, 30], [30, -10], [50, 20]], closed=False).smooth_path(relsize=0.4)
round_corners supports three corner styles – "circle" (a constant-radius arc), "smooth"
(a continuous-curvature bezier, so no curvature discontinuity where the round meets the edge), and
"chamfer" (a straight bevel) – sized by exactly one of radius/r (circle only), cut
(depth toward the corner), joint (distance back along each edge), or width (chamfer only).
k (smooth only) tunes the curvature match. Both functions are pinned point-for-point to the
real BOSL2 output in tests/test_pybosl2_reorient.py; the circle case is bit-identical to the
toolkit’s original round_corners.
Coverage of BOSL2 rounding.scad¶
BOSL2 function |
Status |
Notes |
|---|---|---|
|
ported |
|
|
ported ( |
|
|
not ported |
join paths end-to-end with rounded joints – a follow-up. |
|
not ported |
variable-width strokes and rounded-edge extrusions – a large follow-up. |
|
not ported |
the continuous-curvature 3-D prism generators (thousands of lines) – a large follow-up. |
Examples¶
A square rounded three ways (circle, smooth, chamfer), extruded:
from pybosl2 import Path2D
sq = [[0, 0], [40, 0], [40, 30], [0, 30]]
a = Path2D(sq).round_corners(method="circle", radius=6).polygon().linear_extrude(height=4)
b = Path2D(sq).round_corners(method="smooth", joint=10).polygon().linear_extrude(height=4).right(50)
c = Path2D(sq).round_corners(method="chamfer", joint=8).polygon().linear_extrude(height=4).right(100)
(a | b | c).show()
A wiggly path smoothed into a flowing ribbon:
from pybosl2 import Path2D
pts = [[0, 0], [10, 30], [30, -10], [50, 20], [70, 0]]
Path2D(pts).smooth_path(relsize=0.4).stroke(width=2).linear_extrude(height=3).show()
API reference¶
Path-rounding core: round_corners and smooth_path (BOSL2 rounding.scad).
- class pybosl2.rounding.Roundable[source]¶
Bases:
objectMixin adding the rounding.scad path operators as methods on
Path2Dand.Path3D.-
round_corners(radius=
None, method=RoundingMethod.CIRCLE, cut=None, joint=None, width=None, curvature=None, closed=None, fn=None, fa=None, fs=None, k=None)[source]¶ Round every corner of this path (BOSL2 round_corners()).
method is
"circle"(a constant-radius arc),"smooth"(a continuous-curvature bezier), or"chamfer"(a straight bevel). Size the roundover with exactly one of radius (circle only), cut (depth toward the corner), joint (distance back from the corner along each edge), or width (chamfer only) – each a scalar or a per-corner list. curvature (smooth only, 0..1) tunes how tight the curvature match is. Works on 2-D and 3-D paths.Examples
A rounded, smoothed and chamfered square (three copies):
from pybosl2 import Path2D, Path3D from pybosl2.enums import RoundingMethod sq = [[0, 0], [40, 0], [40, 40], [0, 40]] Path2D(sq).round_corners(method=RoundingMethod.SMOOTH, joint=10).polygon().linear_extrude( height=4 ).show()Loading 3-D preview…A 2-D path with circle-rounded corners:
from pybosl2 import Path2D, Path3D from pybosl2.enums import RoundingMethod path = Path2D([[0, 0], [20, 0], [20, 10], [10, 15], [0, 10]]) path.round_corners(method=RoundingMethod.CIRCLE, radius=3).polygon().linear_extrude(height=5).show()Loading 3-D preview…
-
smooth_path(tangents=
None, size=None, relsize=None, splinesteps=10, uniform=False, closed=None)[source]¶ Fit a smooth continuous-curvature curve through this path (BOSL2 smooth_path(), method=”edges”).
Runs a cubic bezier through every point, matching the path’s tangents, and samples it with splinesteps points per segment. size / relsize bound how far the curve may bow away from the straight path (relsize is a fraction of each segment, default 0.1). The BOSL2
method="corners"variant is not ported.Examples
A wiggly control path smoothed into a flowing curve:
from pybosl2 import Path2D, Path3D pts = [[0, 0], [10, 30], [30, -10], [50, 20], [70, 0]] Path2D(pts).smooth_path(relsize=0.4).stroke(width=2).linear_extrude(height=3).show()Loading 3-D preview…A sawtooth path smoothed with explicit size and relsize:
from pybosl2 import Path2D, Path3D path = Path2D([[0, 0], [10, 5], [20, 0], [30, 10]]) path.smooth_path(relsize=0.1).stroke(width=1).linear_extrude(height=3).show()Loading 3-D preview…
-
offset_stroke(width=
1.0, closed=None, endcap=CapType.ROUND, joint=CapType.ROUND)[source]¶ Offset this 2-D path to create a thickened outline Region (BOSL2 offset_stroke()).
-
offset_sweep(height, bottom=
None, top=None, steps=16, caps=CapType.BUTT, style=VNFStyle.MIN_EDGE)[source]¶ Offset sweep/extrusion of this 2-D shape (BOSL2 offset_sweep()).
-
convex_offset_extrude(height, bottom=
None, top=None, steps=16, caps=CapType.BUTT, style=VNFStyle.MIN_EDGE)[source]¶ Offset sweep/extrusion of this 2-D shape (BOSL2 convex_offset_extrude()).
-
rounded_prism(top=
None, height=None, joint_top=None, joint_bottom=None, joint_sides=None, curvature_sides=None, steps=16, caps=CapType.BUTT, style=VNFStyle.MIN_EDGE, joint_bot=None, k_sides=None)[source]¶ Return the rounded prism between this path and a top path (BOSL2 rounded_prism()).
- Parameters:¶
- top : Sequence[Sequence[float]] | None¶
- height : float | None¶
- joint_top : float | dict[str, object] | None¶
- joint_bottom : float | dict[str, object] | None¶
- joint_sides : float | list[float] | None¶
- curvature_sides : float | list[float] | None¶
- steps : int¶
- caps : CapsSpec¶
- style : VNFStyle¶
- joint_bot : float | dict[str, object] | None¶
- k_sides : float | list[float] | None¶
- Return type:¶
object
-
join_prism(height, fillet=
0.0, steps=16, caps=CapType.BUTT, style=VNFStyle.MIN_EDGE)[source]¶ Join this prism to a base plane with a filleted transition (BOSL2 join_prism()).
-
prism_connector(length, fillet=
0.0, fillet1=None, fillet2=None, steps=16, caps=CapType.BUTT, style=VNFStyle.MIN_EDGE)[source]¶ Construct a filleted prism connecting two objects (BOSL2 prism_connector()).
-
attach_prism(length, fillet=
0.0, rounding=0.0, steps=16, caps=CapType.BUTT, style=VNFStyle.MIN_EDGE)[source]¶ Attach a filleted prism with optional rounded end (BOSL2 attach_prism()).
-
bent_cutout_mask(radius, thickness, style=
VNFStyle.MIN_EDGE)[source]¶ Create a mask to generate a round-edged cutout in a cylindrical shell (BOSL2 bent_cutout_mask()).
-
round_corners(radius=