Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add format_svg_path, deprecate format_svg #33

Merged
merged 1 commit into from
Jan 9, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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)])
Loading