Svg¶
Load SVG drawings into a Region of outlines
Load SVG drawings into a Region of outlines.
-
pybosl2.svg.svg_outlines(file, fn=
None, fa=None, fs=2.0, flip_y=True)[source]¶ Return an SVG’s outlines as plain
[[x, y], ...]point rings.Every subpath of every shape becomes one closed ring. Curves (cubic/quadratic béziers and arcs) are flattened to sampled points; the number of samples is controlled by fn, fa and fs (the same
$fn/$fa/$fstriplet OpenSCAD uses). Straight segments keep their endpoints.The raw rings, with no nesting applied – see
region_from_svg()to get aRegionwith holes resolved.- Parameters:¶
- file : str¶
Path to the SVG.
- fn : int | None¶
Minimum fragment count per curved segment. When set (
>= 3) it gives an absolute point count; otherwise points are derived from fs. Omitted, the ambientuse_defaults(fn=...)value applies;fn=0opts back out to fa/fs.- fa : float | None¶
Minimum angle in degrees between fragments (accepted for API parity; only relevant for circular arcs). Omitted, the ambient
use_defaults(fa=...)value applies.- fs : float¶
Minimum fragment size in SVG user units. Each curved segment gets
max(3, ceil(length / fs))points. Omitted, the ambientuse_defaults(fs=...)value applies.- flip_y : bool¶
Negate Y. SVG’s Y axis points DOWN and OpenSCAD’s points UP, so without this every imported drawing comes out mirrored.
- Returns:¶
One list of
[x, y]points per ring, in the SVG’s own USER UNITS. The renderer’s importer instead converts px to mm at 72 dpi (a factor of 25.4/72); nothing here guesses at a physical size, so resize the result to whatever the part needs.- Raises:¶
ImportError – If
svgelementsis not installed.- Return type:¶
list[list[list[float]]]
-
pybosl2.svg.region_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.The alternative to handing the file to the renderer’s importer: that returns an opaque handle you can only transform, while this returns real outlines you can measure, offset, round, tessellate or use as a lid pattern – and it needs no renderer, so SVG-derived shapes become testable without one.
Nesting is resolved with the EVEN-ODD rule (
even_odd()) among shapes of the SAME colour – what a traced drawing means by a hole: an outline inside one solid cuts it, an outline inside that hole is solid again. Shapes of DIFFERENT colours are composited in SVG paint order instead, each covering whatever was drawn before it, so the returned pieces never overlap.- 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; see
svg_outlines()). Omitted, the ambientuse_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 (e.g.
"#ff0000"). PassNone(the default) to use the SVG’s own colours.- strokes : str¶
"polygon"(default) converts stroked paths into 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
viewBoxif one is declared, so shapes that paint outside the intended canvas are trimmed away.
- Returns:¶
A
Regionof the drawing.- Raises:¶
ImportError – If
svgelementsis not installed.- Return type:¶
Examples
An imported drawing, inset and extruded into a plate:
import os, tempfile tmp = tempfile.NamedTemporaryFile(suffix=".svg", mode="w", delete=False) tmp.write('<svg xmlns="http://www.w3.org/2000/svg"><path d="M10,10H90V90H10Z"/></svg>') tmp.close() from pybosl2 import Region result = Region.from_svg(tmp.name).offset(delta=-0.5).geometry().linear_extrude(height=2) result.show() os.unlink(tmp.name)
-
pybosl2.svg.svg_rings_with_colors(file, fn=
None, fa=None, fs=2.0, flip_y=True, color=None, strokes='polygon', clip_to_viewbox=True)[source]¶ Every closed ring in an SVG, flattened, with the fill colour of each.
The element each ring came from is NOT preserved – use
svg_element_groups()when that matters (it does for compositing: nesting means “hole” only WITHIN one element).- Parameters:¶
- file : str¶
Path to the SVG file to read.
- fn : int | None¶
Fixed fragment count for curved surfaces. 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¶
Minimum fragment size in millimetres. Omitted, the ambient
use_defaults(fs=...)value applies.- flip_y : bool¶
Flip the Y axis, since SVG counts Y downwards and this library counts it up.
- color : str | None¶
Colour to use for rings the file does not give one.
- strokes : str¶
How to treat stroked-but-unfilled paths.
- clip_to_viewbox : bool¶
Drop anything outside the document’s viewBox.
- Return type:¶
tuple[list[‘Path2D’], list[str | None]]
-
pybosl2.svg.svg_element_groups(file, fn=
None, fa=None, fs=2.0, flip_y=True, color=None, strokes='polygon', clip_to_viewbox=True)[source]¶ Return an SVG’s shapes, IN PAINT ORDER, each with its own rings kept together.
This grouping is the thing compositing needs and flattening destroys: a ring nested inside another means “hole” only when both came from the SAME element (that is what
fill-ruledecides). Two separate elements that happen to nest – a flag’s green field drawn on top of its red one – are not a solid and a hole, they are two shapes, the later one painted over the earlier.Every subpath of every shape becomes one closed
Path2D; the colour list gives the hex fill colour of the shape each ring came from (orNonefor shapes with no fill / pattern fills). The rings themselves are identical to those returned bysvg_outlines()but as typed objects.The return value can be unpacked directly:
paths, colors = svg_rings_with_colors("drawing.svg")- 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; see
svg_outlines()). Omitted, the ambientuse_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.
- color : str | None¶
When set, every returned ring gets this colour instead of the SVG’s own fill colours. Pass
None(the default) to use the colours from the SVG.- strokes : str¶
How to handle stroked paths.
"polygon"(default) converts each stroked path to a filled polygon via shapely buffering so strokes appear as solid coloured pieces."ignore"skips shapes that have a stroke but no fill colour.- clip_to_viewbox : bool¶
When True (the default), clip shapes to the SVG’s
viewBoxif one is declared.
- Returns:¶
[(colour, [Path2D, ...]), ...]in document (paint) order – one entry per filled shape, plus one per stroked shape (a stroke paints over its own fill).- Raises:¶
ImportError – If
svgelementsis not installed.- Return type:¶
list[tuple[str | None, list[Path2D]]]
-
pybosl2.svg.regions_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 list of
Regionobjects, coloured.Shapes with the same fill colour are grouped into one
Region; shapes with no fill colour (or pattern/gradient fills) are grouped into an uncoloured Region. The result is a list of Regions that can each be offset, extruded or rendered independently, each carrying the SVG’s colour through to the output.- 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; see
svg_outlines()). Omitted, the ambientuse_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.
- color : str | None¶
When set, overrides every shape’s fill colour with this hex string (e.g.
"#ff0000"). PassNone(the default) to use the SVG’s own colours.- strokes : str¶
"polygon"(default) converts stroked paths into filled polygons."ignore"skips shapes that have only a stroke and no fill.- clip_to_viewbox : bool¶
When True (the default), clip shapes to the SVG’s
viewBoxif one is declared.
- Returns:¶
A list of
Regionobjects, one per distinct fill colour found in the SVG. Each Region has its colour set viaRegion.color().- Raises:¶
ImportError – If
svgelementsis not installed.- Return type:¶
list[‘Region’]
Examples
An imported drawing with two colours, extruded and shown side by side:
import os, tempfile tmp = tempfile.NamedTemporaryFile(suffix=".svg", mode="w", delete=False) tmp.write('<svg xmlns="http://www.w3.org/2000/svg">' '<path d="M10,10H40V40H10Z" fill="#ff0000"/>' '<path d="M50,10H80V40H50Z" fill="#0000ff"/>' '</svg>') tmp.close() from pybosl2.svg import regions_from_svg parts = regions_from_svg(tmp.name) import pythonscad as ps for region in parts: region.geometry().linear_extrude(height=3) ps.show() os.unlink(tmp.name)