svg_path_editor#
Submodules#
Attributes#
Classes#
2D point with |
|
Control numerical precision for mixed symbolic/numeric operations. |
|
Planar bevel face containing an elliptical-arc boundary. |
|
Planar bevel face bounded by straight segments. |
|
Abstract image encoder. |
|
SVG fragments for shaded bevels. |
|
Base class for a single SVG path command and its numeric values. |
|
An SVG path as a sequence of |
Functions#
|
Return a new path where the origin of a (sub)path is moved. |
|
Construct bevel faces for an offset of a simple closed path. |
|
Offset a simple closed SVG path. |
|
Optimize the representation of an SVG path. |
|
Reverse the drawing direction of a path or sub-path. |
|
Lambertian diffuse intensity from a surface normal. |
|
Render a Lambert–shaded elliptical cone, return encoded bytes and base64 URI. |
|
Per-bevel Lambert shading for an SVG path. |
Package Contents#
- class svg_path_editor.Point(x, y)[source]#
2D point with
decimal.Decimalcoordinates.- x: decimal.Decimal#
- y: decimal.Decimal#
- __eq__(other)[source]#
Compare coordinates for exact equality.
- Returns:
Trueiffotheris aPointwith equalxandy.- Parameters:
other (Any)
- Return type:
bool
- property vec2: Vec2#
Exact conversion to
Vec2.Coordinates are converted to SymPy rationals via
dec_to_rat().- Return type:
- property length: decimal.Decimal#
Euclidean norm \(‖v‖_2 = \sqrt{x^2 + y^2}\).
- Return type:
decimal.Decimal
- property normalized: Point#
Unit vector \(v / ‖v‖_2\).
The zero vector is returned unchanged.
- Return type:
- class svg_path_editor.Precision[source]#
Control numerical precision for mixed symbolic/numeric operations.
baselinedefines the primary target precision, whileadditionalcan be used to carry extra guard digits during intermediate computations.- Variables:
baseline – Baseline number of significant digits.
additional – Additional guard digits to be used internally.
- baseline: int#
- additional: int#
- property full: int#
Full number of significant digits to use.
- Returns:
baseline + additional.- Return type:
int
- svg_path_editor.change_path_origin(svg, new_origin_index, subpath=None)[source]#
Return a new path where the origin of a (sub)path is moved.
The command at
new_origin_indexbecomes the first command of the affected subpath segment; all items of that subpath are rotated accordingly. IfsubpathisTrue, only the subpath containingnew_origin_indexis transformed; ifFalse/None, the whole path is treated as a single segment.- Parameters:
svg (SvgPath) – Original path to transform.
new_origin_index (int) – Index of the command that should become the new origin within its subpath.
subpath (bool | None) – If
True, restrict the change to the subpath containingnew_origin_index; ifFalseorNone, treat the full path segment as one subpath.
- Returns:
A new
SvgPathinstance with the origin moved and the path representation optimized.- Return type:
- class svg_path_editor.BevelArced[source]#
Bases:
NamedTuplePlanar bevel face containing an elliptical-arc boundary.
The path consists of two corresponding arc segments (original and offset) joined by straight segments.
- Variables:
path – Closed
SvgPathdescribing the bevel face.c – Center of the supporting ellipse.
r – Radii vector of the supporting ellipse.
phi – Rotation of the ellipse in degrees.
locally_convex –
Trueiff the bevel is convex w.r.t. the interior.
- phi: decimal.Decimal#
- locally_convex: bool#
- class svg_path_editor.BevelPolygon[source]#
Bases:
NamedTuplePlanar bevel face bounded by straight segments.
- Variables:
path – Closed
SvgPathdescribing the bevel polygon.outward_normal – Unit normal pointing out of the filled region.
- svg_path_editor.bevel_path(path, *, d, prec=None)[source]#
Construct bevel faces for an offset of a simple closed path.
Unlike
offset_path(), this yields only the auxiliary faces that fill the bevel region between the original path and its offset.- Parameters:
path (SvgPath) – Closed
SvgPathwith exactly one subpathM … Z, using only line and elliptical-arc segments.d (Number) – Offset distance. Positive values move edges towards the interior.
prec (Precision | Literal['auto', 'auto-intersections'] | None) – Same semantics as in
offset_path().
- Returns:
Closed paths covering the bevel surface between original and offset.
- Raises:
AssertionError – If
pathis not a single closed subpath of the expected form, or if an offset intersection cannot be computed.- Return type:
collections.abc.Iterable[BevelPolygon | BevelArced]
- svg_path_editor.offset_path(path, *, d, prec=None)[source]#
Offset a simple closed SVG path.
The input must be a single closed subpath
M … Zof straight lines and elliptical arcs. Every segment is offset by distanced(inwards ford > 0), and consecutive offset segments are intersected to form the output path.- Parameters:
path (SvgPath) – Closed
SvgPathwith exactly one subpathM … Z, using only line and elliptical-arc segments.d (Number) – Offset distance. Positive values move edges towards the interior.
prec (Precision | Literal['auto', 'auto-intersections'] | None) –
Intersection and offsetting precision:
"auto": decimal precision +additional_digitsfor both offset geometry and intersections."auto-intersections": same automatic precision for intersections only; offsets remain symbolic.Precision: use this precision everywhere.None: purely symbolic where supported.
- Returns:
The offset closed path.
- Raises:
AssertionError – If
pathis not a single closed subpath of the expected form, or if an offset intersection cannot be computed.- Return type:
- svg_path_editor.optimize_path(svg, *, remove_useless_commands=False, remove_orphan_dots=False, use_shorthands=False, use_horizontal_and_vertical_lines=False, use_relative_absolute=False, use_reverse=False, use_close_path=False)[source]#
Optimize the representation of an SVG path.
The function can apply several optional passes that can be enabled using the parameters.
- Parameters:
svg (SvgPath) – Input path.
remove_useless_commands (bool) – Remove redundant
M/Zcommands and degenerateL/H/Vsegments.remove_orphan_dots (bool) – Remove empty closed subpaths (
Mimmediately followed byZ).use_shorthands (bool) – Convert eligible
C/Qsegments toS/Twhere possible.use_horizontal_and_vertical_lines (bool) – Replace
LwithHorVwhere possible.use_relative_absolute (bool) – Choose between relative and absolute commands per segment to minimize size.
use_reverse (bool) – Reverse the path direction if that yields a shorter minified representation. This can affect stroked paths.
use_close_path (bool) – Convert final line segments that return to start into
Z. This can affect stroked paths.
- Returns:
A new, possibly shorter, but geometrically equivalent path.
- Return type:
- svg_path_editor.reverse_path(svg, subpath_of_item=None)[source]#
Reverse the drawing direction of a path or sub-path.
- Parameters:
svg (SvgPath) – Input path.
subpath_of_item (int | None) – Index of an item within the sub-path to reverse, or
Noneto reverse the entire path.
- Returns:
A new path with the selected segment reversed. Geometry is preserved, but command types and relative/absolute representation may change.
- Return type:
- svg_path_editor.PNG#
- svg_path_editor.WEBP#
- class svg_path_editor.ImageFormat[source]#
Bases:
ProtocolAbstract image encoder.
- Variables:
media_type – MIME type of the encoded image.
extension – File extension (without dot).
- media_type: ClassVar[str]#
- extension: ClassVar[str]#
- class svg_path_editor.PathShading[source]#
SVG fragments for shaded bevels.
- Variables:
defs_body – Elements for a document-wide
<defs>(e.g. shared<image>or<clipPath>definitions).body – Per-path drawing elements (e.g.
<path>,<g>,<use>) that referencedefs_body.
- defs_body: list[str]#
- body: list[str]#
- svg_path_editor.lambert_from_angle(normal)[source]#
Lambertian diffuse intensity from a surface normal.
The light direction is fixed to \((0, -1, 1)\) in world space. The result is
\[I = \max(0, \hat{\mathbf{n}}\cdot\hat{\mathbf{L}}),\]evaluated via the signed angle of
normalin the \(xy\)-plane.- Parameters:
normal (Point) – Surface normal.
- Returns:
Lambertian intensity in \([0, 1]\).
- Return type:
decimal.Decimal
- svg_path_editor.lambert_shading_base64(*, r, phi, locally_convex, resolution, t=0.25, format=WEBP, seed=None)[source]#
Render a Lambert–shaded elliptical cone, return encoded bytes and base64 URI.
The cone radii are \(r = (r_x, r_y)\) in image space. For a point \((x, y)\) on the grid
\[(x, y) \in \left[-\frac{1}{r_x}, \frac{1}{r_x}\right] \times \left[-\frac{1}{r_y}, \frac{1}{r_y}\right],\]the unnormalized normal is
\[\mathbf{n}(x, y) = \left(\frac{x}{r_x^2}, \frac{y}{r_y^2}, 1\right).\]The Lambert term is
\[I(x, y) = \max\left(0, \hat{\mathbf{n}}(x, y)\cdot\hat{\mathbf{L}}\right),\]where \(\hat{\mathbf{L}}\) is the unit vector from \((0, s, 1)\), with \(s = -1\) if
locally_convexelse \(+1\), rotated in the \(xy\)-plane by \(-\varphi\) degrees.Grayscale is binary (0 or 255) according to \(I > t\). Alpha is a symmetric remap of \(I\) around \(t\):
\[\begin{split}\alpha(I) = \begin{cases} \dfrac{I - t}{1 - t}, & I \geq t,\\ \dfrac{t - I}{t}, & I < t. \end{cases}\end{split}\]Before 8-bit quantization, uniform noise in \([0, 1]\) is added to alpha for dithering.
The final RGBA image is encoded with
formatand returned both as raw bytes and as adata:...;base64,...URI.- Parameters:
r (Point) – Ellipse radii in \(x\) and \(y\).
phi (decimal.Decimal) – Rotation in degrees of the light direction in image space (clockwise in screen coordinates).
locally_convex (bool) – If true, the base light direction is \((0, -1, 1)\), otherwise \((0, 1, 1)\).
resolution (float) – Pixels per SVG unit. Image size is \(\lceil 2 r_x \, \mathrm{resolution} \rceil \times \lceil 2 r_y \, \mathrm{resolution} \rceil\).
t (float) – Neutral Lambert intensity in \([0, 1]\) (threshold).
format (ImageFormat) – Image format to use.
seed (int | None) – RNG seed for alpha dithering;
Noneis non-deterministic.
- Returns:
(img_bytes, img_data_uri)withimg_data_urisuitable for SVGhref.- Return type:
tuple[bytes, str]
- svg_path_editor.shade_path(svg, *, d, threshold, resolution, max_opacity=1, format=WEBP, seed=None, prec=None)[source]#
Per-bevel Lambert shading for an SVG path.
The path is decomposed into bevel regions via
svg_path_editor.path_offset.bevel_path(). Flat bevel polygons are shaded analytically withlambert_from_angle(). Curved bevel arcs use a small Lambert RGBA texture fromlambert_shading_base64(), referenced by<image>/<use>and clipped to the arc geometry.For each bevel polygon:
One
<path>is emitted withfill="white"orfill="black"depending on whether the intensity is above or belowthreshold.Opacity is a symmetric remap of the intensity around
thresholdin \([0, 1]\), scaled bymax_opacity.
For each bevel arc:
A Lambert cone texture is generated (or reused from a cache) for
(r.x, r.y, phi, locally_convex).A base
<image>at the origin with size \(2 r_x \times 2 r_y\) is placed inPathShading.defs_bodyonce per unique key.For each occurrence, a
<clipPath>with the bevel geometry and a<use>of the base image are emitted intoPathShading.body, translated so the image origin matches the lower-left corner of the ellipse bounding box, and rotated byphiaround the ellipse center if non-zero.<use>carries opacitymax_opacitywhen it is less than 1.
To integrate into an SVG, place all
defs_bodyentries inside a single document-level<defs>and insertbodywhere the path should render.- Parameters:
svg (SvgPath) – Input path to bevel and shade.
d (Number) – Offset distance for
bevel_path().threshold (Number) – Neutral Lambert intensity in \([0, 1]\), shared between flat bevels and textures.
resolution (float) – Pixels per SVG unit for generated textures; image dimensions follow
lambert_shading_base64().max_opacity (Number) – Global opacity scale in \([0, 1]\).
format (ImageFormat) – Texture format, e.g.
WEBPorPNG.seed (int | None) – RNG seed for alpha dithering in
lambert_shading_base64();Nonefor non-deterministic.prec (Precision | Literal['auto', 'auto-intersections'] | None) – Precision/geometry mode passed to
bevel_path()."auto"and"auto-intersections"select automatic strategies;Noneuses the default.
- Return type:
- class svg_path_editor.SvgItem(values, relative)[source]#
Bases:
abc.ABCBase class for a single SVG path command and its numeric values.
- Parameters:
values (list[T])
relative (bool)
- _relative: bool#
- values: list[decimal.Decimal]#
- absolute_control_points: list[SvgControlPoint] = []#
- static make(raw_item)[source]#
Construct the appropriate subclass of
SvgItemfrom a parsed command and its parameter strings.- Parameters:
raw_item (list[str]) – List starting with the command letter followed by numeric parameters as strings (e.g.
["M", "0", "0"]).- Raises:
ValueError – If the item is empty or the command is invalid.
- Return type:
- static make_from(origin, previous, new_type)[source]#
Create a new
SvgItemof typenew_typefrom an existing item.The new item preserves the current target location and, where possible, the original control point geometry.
- refresh_absolute_points(origin, previous)[source]#
Recalculate absolute points from stored values and the previous item.
- property relative: bool#
Whether this command is stored in relative coordinates.
- Return type:
bool
- refresh_absolute_control_points(origin, previous_target)[source]#
Recalculate absolute control points.
The default implementation assumes there are no control points.
- reset_control_points(previous_target)[source]#
Reset control points to a default geometry between previous and target.
Subclasses for curve commands override this to compute reasonable defaults.
- Parameters:
previous_target (SvgItem) – Previous item in the path.
- Return type:
None
- clone()[source]#
Return a shallow clone of this item, retaining its subclass.
Values, relativity and
previous_pointare copied. Absolute points and control points need to be recomputed viarefresh(), as is done inSvgPath.clone().- Return type:
Self
- translate(x, y, force=False)[source]#
Translate in place.
Relative items are translated only if
forceis true; otherwise their stored deltas are left unchanged.
- translated(x, y, force=False)[source]#
Return a translated copy. See
translate()for details.
- rotate(ox, oy, degrees, force=False)[source]#
Rotate the item in place around
(ox, oy).For relative items, rotation is performed around
(0, 0)unlessforceis true.
- rotated(ox, oy, degrees, force=False)[source]#
Return a rotated copy around
(ox, oy). Seerotate()for details.
- set_target_location(pt)[source]#
Move the geometric target of this command to
pt.- Parameters:
pt (Point) – New target location in absolute coordinates.
- Return type:
None
- set_control_location(idx, pt)[source]#
Move control point
idxtopt.Only meaningful for commands storing Bézier handles.
- Parameters:
idx (int) – Index of the control point to move.
pt (Point) – New control point location in absolute coordinates.
- Return type:
None
- property control_locations: list[SvgControlPoint]#
Absolute control points associated with this item.
- Return type:
list[SvgControlPoint]
- get_type(ignore_is_relative=False)[source]#
Return the SVG command letter for this item (e.g.
"M"or"l").- Parameters:
ignore_is_relative (bool) – Always return the uppercase key regardless of
relative.- Return type:
str
- as_standalone_string()[source]#
Return a standalone path string for this command.
The result starts with an
Mto this command’sprevious_pointfollowed by the command itself.- Return type:
str
- as_string(decimals=None, minify=False, trailing_items=())[source]#
Serialize this command into an SVG path fragment.
Optionally additional same-typed
trailing_itemscan be appended in a compact form.- Parameters:
decimals (int | None) – Number of decimal places, or
Nonefor default.minify (bool) – Use a more compact numeric representation.
trailing_items (collections.abc.Iterable[SvgItem]) – Additional items of the same type to serialize in the same command group.
- Return type:
str
- __format__(format_spec)[source]#
Format this item using
as_string().The
format_speccan be used to control decimal places and minification:""(empty): useas_string()defaults".3":decimals=3"m":minify=True".3m"or"m.3":decimals=3,minify=True
Any other characters are currently ignored.
- Parameters:
format_spec (str) – Format specification string (e.g.
".3m").- Return type:
str
- __str__()[source]#
Return
as_string()with default options.- Return type:
str
- class svg_path_editor.SvgPath(path)[source]#
An SVG path as a sequence of
SvgItem.- Parameters:
path (str | list[SvgItem])
- clone()[source]#
Return a deep clone of this path.
All contained items are cloned as well, and absolute positions are recomputed.
- Return type:
- rotate(ox, oy, degrees)[source]#
Rotate in place around
(ox, oy).May also normalize horizontal/vertical segments after rotation.
- property relative: bool#
Indicate whether all items are stored as relative commands.
Mixed paths (some absolute, some relative) return
False.- Return type:
bool
- with_relative(new_relative)[source]#
Return a new path with all items converted to the requested representation.
- Parameters:
new_relative (bool) – Target representation (
Truefor relative).- Return type:
- remove(item)[source]#
Remove the given item.
- Parameters:
item (SvgItem) – Item to remove.
- Raises:
ValueError – If the item is not present.
- Return type:
None
- insert(index, item)[source]#
Insert
itembeforeindex.- Parameters:
index (int) – Index before which to insert.
item (SvgItem) – Item to insert.
- Return type:
None
- as_string(decimals=None, minify=False)[source]#
Serialize the entire path to an SVG path data string.
- Parameters:
decimals (int | None) – Number of decimal places, or
Nonefor default.minify (bool) – Use a compact representation.
- Return type:
str
- property target_locations: list[SvgPoint]#
Final absolute points for each item in the path.
- Return type:
list[SvgPoint]
- property control_locations: list[SvgControlPoint]#
Flattened list of all absolute control points for the path.
- Return type:
list[SvgControlPoint]
- set_location(pt_reference, to)[source]#
Move the given point to
to.The reference must come from a previously queried point list (e.g.
target_locationsorcontrol_locations).
- refresh_absolute_positions()[source]#
Recompute absolute positions for all items in the path.
This should be called after structural or coordinate changes.
- Return type:
None
- __format__(format_spec)[source]#
Format this path using
as_string().The
format_speccan be used to control decimal places and minification, following the same rules asSvgItem.__format__():""(empty): useas_string()defaults".3":decimals=3"m":minify=True".3m"or"m.3":decimals=3,minify=True
Any other characters are currently ignored.
- Parameters:
format_spec (str) – Format specification string (e.g.
".3m").- Return type:
str
- __str__()[source]#
Return
as_string()with default options.- Return type:
str