Skip to content

Commit

Permalink
add format_svg_path, deprecate format_svg (#33)
Browse files Browse the repository at this point in the history
  • Loading branch information
snoyer authored Jan 9, 2025
1 parent 2cda329 commit 0a2a8e3
Show file tree
Hide file tree
Showing 3 changed files with 49 additions and 11 deletions.
11 changes: 5 additions & 6 deletions ocpsvg/hlr.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@
from OCP.TopoDS import TopoDS, TopoDS_Edge, TopoDS_Shape

from .ocp import bounding_box, topoDS_iterator
from .svg import edge_to_svg_path, format_svg
from .svg import edge_to_svg_path, float_formatter, format_svg_path

HlrEdgeTypeName = Literal["undefined", "isoline", "sewn", "smooth", "sharp", "outline"]

Expand Down Expand Up @@ -170,7 +170,7 @@ def to_svg(
css_style: Optional[CssStyle] = None,
background: Optional[bool] = None,
tolerance: float = 1e-6,
float_format: str = "g",
decimals: Optional[int] = None,
) -> ET.ElementTree:
(x0, y0, x1, y1), scale, (W, H) = _viewbox_and_scale(
self.bounds(),
Expand All @@ -180,8 +180,7 @@ def to_svg(
)
ty = -(y1 + y0) / scale

def fmt(v: float):
return v.__format__(float_format)
fmt = float_formatter(decimals)

svg = ET.Element("svg", xmlns="http://www.w3.org/2000/svg")
svg.attrib["viewBox"] = f"{fmt(x0)} {fmt(y0)} {fmt(x1-x0)} {fmt(y1-y0)}"
Expand Down Expand Up @@ -224,9 +223,9 @@ def fmt(v: float):

attrs = {
"id": f"e{i}",
"d": format_svg(
"d": format_svg_path(
edge_to_svg_path(edge.projected_edge, tolerance=tolerance),
float_format=float_format,
decimals=decimals,
),
"class": " ".join(classnames),
}
Expand Down
27 changes: 25 additions & 2 deletions ocpsvg/svg.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import logging
import pathlib
import warnings
from itertools import chain
from math import degrees, pi
from typing import (
Expand Down Expand Up @@ -58,7 +59,7 @@
"edge_to_svg_path",
"curve_to_svg_path",
"SvgPathCommand",
"format_svg",
"format_svg_path",
]


Expand All @@ -78,7 +79,29 @@
]


class float_formatter:
"""float formatter with given precision and no trailing zeroes."""

def __init__(self, decimals: Optional[int] = None):
self.format_spec = f".{decimals or 12}f"

def __call__(self, v: float):
return v.__format__(self.format_spec).rstrip("0").rstrip(".")


def format_svg_path(
path: Iterable[SvgPathCommand], *, decimals: Optional[int] = None
) -> str:
ff = float_formatter(decimals)
return " ".join(f"{cmd[0]}{','.join(map(ff, cmd[1:]))}" for cmd in path)


def format_svg(path: Iterable[SvgPathCommand], float_format: str = "f") -> str:
warnings.warn(
"`format_svg` is deprecated, use `format_svg_path` instead.",
FutureWarning,
stacklevel=2,
)
return " ".join(
f"{cmd[0]}{','.join(arg.__format__(float_format) for arg in cmd[1:])}"
for cmd in path
Expand Down Expand Up @@ -808,7 +831,7 @@ def _path_from_SvgPathLike(path: SvgPathLike) -> svgelements.Path:
return path

if not isinstance(path, str):
path = format_svg(path)
path = format_svg_path(path)

try:
return svgelements.Path(str(path))
Expand Down
22 changes: 19 additions & 3 deletions tests/test_svg.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,14 +31,15 @@
from ocpsvg.svg import (
ColorAndLabel,
SvgPathCommand,
_SegmentInPath,
_SegmentInPath, # type: ignore private usage
bezier_to_svg_path,
edge_to_svg_path,
edges_from_svg_path,
face_to_svg_path,
faces_from_svg_path,
find_shapes_svg_in_document,
format_svg,
format_svg_path,
import_svg_document,
polyline_to_svg_path,
svg_element_to_path,
Expand All @@ -52,7 +53,7 @@

class SvgPath(list[SvgPathCommand]):
def __str__(self) -> str:
return format_svg(self)
return format_svg_path(self)


def wire_from_curves(*curves: Geom_Curve):
Expand Down Expand Up @@ -821,7 +822,7 @@ def test_fix_closing_lines_doc():
for e, _ in find_shapes_svg_in_document(StringIO(svg_src)):
path = svg_element_to_path(e)
assert path
for segment in path:
for segment in path: # type: ignore
assert not isinstance(segment, svgelements.Line)


Expand Down Expand Up @@ -985,3 +986,18 @@ def split_floats(text: str):
yield end

return list(split_floats(str(path)))


def test_format_svg_path():
assert format_svg_path([("M", 1, 2), ("L", 3.45, 6.78)]) == "M1,2 L3.45,6.78"


def test_format_svg_path_number_format():
path: list[SvgPathCommand] = [("M", 1.0, 2.0), ("L", 3e-8, 4.56789123456789)]
assert format_svg_path(path, decimals=2) == "M1,2 L0,4.57"
assert format_svg_path(path, decimals=8) == "M1,2 L0.00000003,4.56789123"


def test_format_svg_deprecated():
with pytest.warns(FutureWarning):
format_svg([("M", 1, 2), ("L", 3.45, 6.78)])

0 comments on commit 0a2a8e3

Please sign in to comment.