Regions¶
Object API for 2-D paths and regions.
Path2D and Region: object wrappers over the 2-D point maths in paths.py/rounding.py/ transforms.py, so a polygon can be built once and then chained (Path2D(pts).offset(radius=-2).round_corners(radius=1).polygon()) instead of threading raw point lists through free functions.
-
class pybosl2.regions.Region(paths=
())[source]¶ Bases:
objectA 2-D region backed by
shapely(not OpenSCAD/PythonSCAD).Stores
MultiPolygoninternally and derivesPath2Doutlines only when requested. All Boolean operations (union, intersection, difference, symmetric difference) use shapely directly. Operator overloads (|,&,-,^) are provided.Create a region from a single outline (no holes):
Region([[0, 0], [80, 0], [80, 60], [0, 60]])Create a region with holes (outline first, then hole paths):
Region([ [[0, 0], [80, 0], [80, 60], [0, 60]], # outer outline [[20, 20], [60, 20], [60, 40], [20, 40]], # hole 1 ])Or use the shorthand
with_holes()for a more readable call.For native-geometry output (e.g. extrusion), call
geometry()which converts paths toBosl2Shape2D.- Parameters:¶
- paths : Any¶
The outlines; each is coerced to a
Path2D. A single flat point list is treated as one outline. Ashapely.Polygonorshapely.MultiPolygonis also accepted.
Examples
A rectangular plate with a rectangular hole (outline + one hole), extruded into a solid:
from pybosl2 import Region region = Region([ [[0, 0], [80, 0], [80, 60], [0, 60]], [[20, 20], [60, 20], [60, 40], [20, 40]], ]) region.geometry().linear_extrude(height=5).show()Loading 3-D preview…- simplify(tolerance)[source]¶
Return a copy with each polygon simplified, keeping its colour.
Douglas-Peucker, topology-preserving, applied per polygon so the per-piece colours survive –
shapely’s ownsimplifyon the whole geometry would return bare polygons and drop them.Worth doing on traced or imported artwork, where the point count reflects the drawing tool rather than anything the output can show: Wikipedia’s Flag of Portugal carries 33150 points, and a tolerance of 0.25 (0.02mm once that flag is 60mm wide) takes it to 11315 with the area unchanged to five figures.
- color_all(c)[source]¶
Return a simplified copy with every polygon set to the same colour.
All polygons are unioned together (same-colour overlaps merge into one shape) and the per-polygon colour list is collapsed to a single entry. The result has
_polygon_colorscleared since every piece is the same colour, and_colorset to c.
- property paths : list[Path2D]¶
The list of
Path2Dobjects derived from the geometry.Extracted on-demand from the underlying shapely
PolygonorMultiPolygon.- Returns:¶
A list of
Path2Dobjects.
- property geom : MultiPolygon¶
The underlying shapely geometry.
- to_shapely()[source]¶
Return the shapely geometry for this region.
Equivalent to the
geomproperty; provided for explicit usage.
-
classmethod from_svg(file, fn=
None, fa=None, fs=2.0, flip_y=True, color=None, strokes='polygon', clip_to_viewbox=True)[source]¶ Load an SVG drawing as a Region of outlines (see
pybosl2.svg.region_from_svg()).Real path data rather than the renderer’s opaque imported handle, so the drawing can be measured, offset, rounded or tessellated like anything else – and needs no renderer.
- Parameters:¶
- file : str¶
Path to the SVG.
- fn : int | None¶
Minimum fragment count per curved segment (
>= 3→ absolute point count). Omitted, the ambientuse_defaults(fn=...)value applies;fn=0opts back out to fa/fs.- fa : float | None¶
Minimum angle in degrees (accepted for API parity). Omitted, the ambient
use_defaults(fa=...)value applies.- fs : float¶
Minimum fragment size in SVG user units (default
2.0). Omitted, the ambientuse_defaults(fs=...)value applies.- flip_y : bool¶
Negate Y so the drawing is not mirrored (SVG’s Y axis points down).
- color : str | None¶
When set, overrides every shape’s fill colour with this hex string. Pass
None(the default) to use the SVG’s own colours.- strokes : str¶
"polygon"(default) converts stroked paths to filled polygons."ignore"skips shapes that have only a stroke and no fill.- clip_to_viewbox : bool¶
When True (the default), clip the drawing to the SVG’s
viewBox. Pass False for a drawing whose content already sits inside its viewBox, which is the usual case for a CAD-style silhouette, to skip the work.
- Returns:¶
A
Regionof the drawing, nested by the even-odd rule.- Return type:¶
- classmethod even_odd(paths)[source]¶
Create a region from outlines nested by the EVEN-ODD rule.
Colours are read from each
Path2Dobject (viacolor()). Same-colour solids are unioned together; different-colour solids are kept as separate non-overlapping polygons inside the region – the first colour in order wins any overlap sogeometry()andlinear_extrude()render each in its own colour. Uncoloured paths are transparent: they do not participate in overlap resolution.The default constructor is outer-plus-holes: outline 0 bounds the region and every other outline is a hole in it. Even-odd instead decides each outline by how many others CONTAIN it, which is the rule SVG and OpenSCAD’s multi-path
polygon()use.- Parameters:¶
- paths : Sequence[Path2D]¶
The outlines, each a
Path2D(SPEC C-7a). ColouredPath2Dobjects carry their colour through to the result.
- Returns:¶
A
Regionwhose solid area is the even-odd interpretation of paths. The_polygon_colorslist tracks which polygon has which colour.- Return type:¶
Examples
Two disjoint squares, each with a hole – four outlines, two solids:
Region.even_odd([outer_a, hole_a, outer_b, hole_b])Overlapping red and blue squares – first colour wins the overlap:
from pybosl2 import Path2D, Region from pybosl2.color import Color red = Path2D([[0,0],[30,0],[30,20],[0,20]]).color(Color("#ff0000")) blue = Path2D([[20,0],[50,0],[50,20],[20,20]]).color(Color("#0000ff")) Region.even_odd([red, blue]).geometry().linear_extrude(height=3).show()
- classmethod with_holes(outline, *holes)[source]¶
Create a region from an outline plus hole outlines.
Convenience constructor. Equivalent to
Region([outline, \\*holes]). See__init__()for the full constructor.
- property outline : Path2D¶
The outer path.
- Returns:¶
The first
Path2Din the region, which is the outer outline.
- property holes : list[Path2D]¶
The hole paths.
- Returns:¶
All
Path2Dobjects after the first, which are the interior holes.
-
offset(radius=
None, delta=None, chamfer=False, fn=None, fa=None, fs=None)[source]¶ Offset every path in the region.
- Parameters:¶
- radius : float | None¶
The corner-rounding radius for the offset.
- delta : float | None¶
The absolute offset distance.
- chamfer : bool¶
Whether to chamfer corners instead of rounding them.
- fn : int | None¶
Fixed number of fragments for the rounded corners; ambient default when omitted. Omitted, the ambient
use_defaults(fn=...)value applies;fn=0opts back out to fa/fs.- fa : float | None¶
Minimum fragment angle for the rounded corners. Omitted, the ambient
use_defaults(fa=...)value applies.- fs : float | None¶
Minimum fragment size for the rounded corners. Omitted, the ambient
use_defaults(fs=...)value applies.
- Returns:¶
A new
Regionwith every path offset by the given parameters.- Return type:¶
-
round_corners(radius=
None, method=RoundingMethod.CIRCLE, cut=None, joint=None, width=None, curvature=None, closed=None, fn=None, fa=None, fs=None)[source]¶ Round the corners of every path in the region.
- Parameters:¶
- radius : float | list[float] | None¶
The rounding radius. A single float applies to all corners; a list applies per-corner radii.
- method : RoundingMethod¶
The rounding method (
"circle","smooth", etc.).- cut : float | None¶
Cut depth for chamfers.
- joint : float | None¶
Joint distance for rounding.
- width : float | None¶
Width for rounding.
- curvature : float | None¶
Curvature value for rounding.
- closed : bool | None¶
Override whether paths are treated as closed.
- fn : int | None¶
Fixed number of fragments per full circle; ambient default when omitted. Omitted, the ambient
use_defaults(fn=...)value applies;fn=0opts back out to fa/fs.- fa : float | None¶
Minimum fragment angle in degrees. Omitted, the ambient
use_defaults(fa=...)value applies.- fs : float | None¶
Minimum fragment size in millimetres. Omitted, the ambient
use_defaults(fs=...)value applies.
- Returns:¶
A new
Regionwith rounded corners on every path.- Return type:¶
- bounds()[source]¶
Return the axis-aligned bounding box over every path in the region (SPEC S-2b).
- Returns:¶
The
Bounds2Dbox – the same type every otherbounds()in the library answers, rather than the bare NumPy[[min], [max]]array this used to hand back.- Raises:¶
Bosl2ValueError – If the region holds no paths.
- Return type:¶
Examples
from pybosl2 import Path2D, Region region = Region([Path2D([[0, 0], [30, 0], [30, 20], [0, 20]], closed=True)]) print(region.bounds().size) # (30.0, 20.0) region.geometry().linear_extrude(height=4).show()Loading 3-D preview…
- geometry()[source]¶
2-D geometry: every polygon in the region, each with its holes subtracted.
When
_polygon_colorsis populated each polygon is coloured individually before being unioned into the final shape. Otherwise the region’s single_coloris applied to every piece.
- fill()[source]¶
Return this region as 2-D geometry with its holes filled in.
Equivalent to just the outline (OpenSCAD
fill()).
- classmethod hull(*others)[source]¶
Return the 2-D convex hull of all the given regions and paths.
Uses shapely
convex_hull()on the union of all input geometries. Accepts a flat list or multiple arguments:Region.convex_hull(rect, circle) Region.convex_hull([rect, circle])
-
linear_extrude(height, center=
False, twist=0.0, scale=1.0, slices=None, fn=None, fa=None, fs=None, color_heights=None)[source]¶ Extrude this region along +Z into a 3-D solid with holes included.
When the region contains multiple colour groups (via
_polygon_colors), each group is extruded separately and the results are unioned – so different-colour parts of an SVG drawing become different-colour solids without manual splitting.The result depends on the active backend: a
Bosl2Solidunder the default CSG backend, or aPyShapeunderuse_backend("sdf"). Seepybosl2.paths.Path2D.linear_extrude()for per-backend options.The SDF backend’s prism is the union of the outlines’ fields, so it can only express a region of DISJOINT islands; a region with holes raises
UnsupportedByBackendErrorthere.- Parameters:¶
- height : float¶
The extrusion height along +Z.
- center : bool¶
Extrude symmetrically along Z if True (default False).
- twist : float¶
Twist angle in degrees over the full height (default 0).
- scale : float¶
Scale factor for the top cross-section (default 1.0).
- slices : int | None¶
Number of intermediate layers for twist/scale (auto if None).
- fn : int | None¶
Smoothness override for the angular resolution. Omitted, the ambient
use_defaults(fn=...)value applies;fn=0opts back out to fa/fs.- fa : float | None¶
Smoothness override for the minimum angle. Omitted, the ambient
use_defaults(fa=...)value applies.- fs : float | None¶
Smoothness override for the minimum segment length. Omitted, the ambient
use_defaults(fs=...)value applies.- color_heights : dict[str | Color, float] | None¶
Optional dict mapping colour names (
"#ff0000","red", orColorobjects) to a specific extrusion height. Coloured pieces that match a key are extruded by that height; pieces whose colour is not in the mapping use the default height.
- Returns:¶
A
Bosl2Solid(CSG) orPyShape(SDF).- Return type:¶
Example:
red = Path2D.square(20).color("red") blue = Path2D.square(20).color("blue") region = Region.even_odd([red, blue.translate([25, 0])]) solid = region.linear_extrude( height=5, color_heights={"red": 10, "blue": 3}, ) solid.show() # The red square is 10 mm tall, the blue square is 3 mm tall.
-
rotate_extrude(angle=
360.0, fn=None, fa=None, fs=None)[source]¶ Revolve this region about the Y axis into a 3-D solid.
- Parameters:¶
- angle : float¶
The rotation angle in degrees.
- fn : int | None¶
Number of polygon segments for curved geometry. Omitted, the ambient
use_defaults(fn=...)value applies;fn=0opts back out to fa/fs.- fa : float | None¶
Minimum angle for polygon segments. Omitted, the ambient
use_defaults(fa=...)value applies.- fs : float | None¶
Minimum size for polygon segments. Omitted, the ambient
use_defaults(fs=...)value applies.
- Returns:¶
A
Solidfrom the active backend (SPEC A-10). Revolving is CSG-only, so the SDF backend refuses rather than approximating (SPEC B-4).- Return type:¶
-
stroke(width=
1, closed=None, endcap1=CapType.ROUND, endcap2=CapType.ROUND, joints=CapType.ROUND)[source]¶ Stroke every path in the region (closed) and return the union as a Region.
- Parameters:¶
- width : float¶
Stroke width.
- closed : bool | None¶
Accepted for signature parity; a region’s paths are always stroked closed.
- endcap1 : CapType | CapSpec¶
Cap style for the start of each path.
- endcap2 : CapType | CapSpec¶
Cap style for the end of each path.
- joints : CapType | CapSpec¶
Cap style where segments meet.
- Returns:¶
A
Regionof the stroked outlines.- Return type:¶
-
dashed_stroke(dashpat=
None, closed=None, fit=True, mindash=0.5)[source]¶ Break every path in the region into dashed polygon outlines.
Returns a
Regionof all dash polygons.
-
debug_region(size=
1, vertices=True)[source]¶ Visualize this region with vertex labels for debugging.
Produces the filled region as a thin flat solid with every path’s vertices labelled in red – path
agets labelsa0, a1, ..., pathbb0, b1, ...(BOSL2debug_region()). A single-path region defers todebug_polygon().
- intersection(other)[source]¶
Return the 2-D intersection of this region with other (the area they share).
Uses shapely for exact polygon coordinates. The result inherits self’s colour.
Examples
Two overlapping squares share a rectangular strip:
from pybosl2 import Region a = Region([[0, 0], [40, 0], [40, 30], [0, 30]]) b = Region([[20, 0], [60, 0], [60, 30], [20, 30]]) a.intersection(b).geometry().linear_extrude(height=3).show()Loading 3-D preview…
- union(other)[source]¶
Return the 2-D union of this region and other (all area covered by either).
Uses shapely for exact polygon coordinates. When self and other carry different colours, the union inherits self’s colour – the first path in the set wins the overlap.
Examples
Two adjacent squares merge into an L-shape:
from pybosl2 import Region a = Region([[0, 0], [30, 0], [30, 30], [0, 30]]) b = Region([[20, 0], [50, 0], [50, 30], [20, 30]]) a.union(b).geometry().linear_extrude(height=3).show()Loading 3-D preview…
- difference(other)[source]¶
Return the 2-D difference: self with the area of other subtracted.
Uses shapely for exact polygon coordinates. The result inherits self’s colour.
Examples
Punch a rectangular notch out of a square:
from pybosl2 import Region plate = Region([[0, 0], [60, 0], [60, 40], [0, 40]]) notch = Region([[20, 10], [40, 10], [40, 30], [20, 30]]) plate.difference(notch).geometry().linear_extrude(height=4).show()Loading 3-D preview…
Path and Path3D are re-exported here for convenience but documented on the
Paths page.