mirror of
https://github.com/gumyr/build123d.git
synced 2025-12-05 18:20:46 -08:00
add align parameter to import_svg
This commit is contained in:
parent
40cf1437ed
commit
8e4aa3370d
3 changed files with 51 additions and 6 deletions
|
|
@ -43,7 +43,7 @@ dependencies = [
|
|||
"ezdxf >= 1.1.0, < 2",
|
||||
"ipython >= 8.0.0, < 9",
|
||||
"py-lib3mf >= 2.3.1",
|
||||
"ocpsvg >= 0.4, < 0.5",
|
||||
"ocpsvg >= 0.5, < 0.6",
|
||||
"trianglesolver",
|
||||
]
|
||||
|
||||
|
|
|
|||
|
|
@ -70,7 +70,8 @@ from OCP.XCAFDoc import (
|
|||
from ocpsvg import ColorAndLabel, import_svg_document
|
||||
from svgpathtools import svg2paths
|
||||
|
||||
from build123d.geometry import Color, Location
|
||||
from build123d.build_enums import Align
|
||||
from build123d.geometry import Color, Location, Vector, to_align_offset
|
||||
from build123d.topology import (
|
||||
Compound,
|
||||
Edge,
|
||||
|
|
@ -337,6 +338,7 @@ def import_svg(
|
|||
svg_file: str | Path | TextIO,
|
||||
*,
|
||||
flip_y: bool = True,
|
||||
align: Align | tuple[Align, Align] | None = Align.MIN,
|
||||
ignore_visibility: bool = False,
|
||||
label_by: Literal["id", "class", "inkscape:label"] | str = "id",
|
||||
is_inkscape_label: bool | None = None, # TODO remove for `1.0` release
|
||||
|
|
@ -346,6 +348,8 @@ def import_svg(
|
|||
Args:
|
||||
svg_file (Union[str, Path, TextIO]): svg file
|
||||
flip_y (bool, optional): flip objects to compensate for svg orientation. Defaults to True.
|
||||
align (Align | tuple[Align, Align] | None, optional): alignment of the SVG's viewbox,
|
||||
if None, the viewbox's origin will be at `(0,0,0)`. Defaults to Align.MIN.
|
||||
ignore_visibility (bool, optional): Defaults to False.
|
||||
label_by (str, optional): XML attribute to use for imported shapes' `label` property.
|
||||
Defaults to "id".
|
||||
|
|
@ -368,12 +372,18 @@ def import_svg(
|
|||
label_by = re.sub(
|
||||
r"^inkscape:(.+)", r"{http://www.inkscape.org/namespaces/inkscape}\1", label_by
|
||||
)
|
||||
for face_or_wire, color_and_label in import_svg_document(
|
||||
imported = import_svg_document(
|
||||
svg_file,
|
||||
flip_y=flip_y,
|
||||
ignore_visibility=ignore_visibility,
|
||||
metadata=ColorAndLabel.Label_by(label_by),
|
||||
):
|
||||
)
|
||||
|
||||
doc_xy = Vector(imported.viewbox.x, imported.viewbox.y)
|
||||
doc_wh = Vector(imported.viewbox.width, imported.viewbox.height)
|
||||
offset = to_align_offset(doc_xy, doc_xy + doc_wh, align)
|
||||
|
||||
for face_or_wire, color_and_label in imported:
|
||||
if isinstance(face_or_wire, TopoDS_Wire):
|
||||
shape = Wire(face_or_wire)
|
||||
elif isinstance(face_or_wire, TopoDS_Face):
|
||||
|
|
@ -381,6 +391,9 @@ def import_svg(
|
|||
else: # should not happen
|
||||
raise ValueError(f"unexpected shape type: {type(face_or_wire).__name__}")
|
||||
|
||||
if offset.X != 0 or offset.Y != 0: # avoid copying if we don't need to
|
||||
shape = shape.translate(offset)
|
||||
|
||||
if shape.wrapped:
|
||||
shape.color = Color(*color_and_label.color_for(shape.wrapped))
|
||||
shape.label = color_and_label.label
|
||||
|
|
|
|||
|
|
@ -16,10 +16,10 @@ from build123d.importers import (
|
|||
import_step,
|
||||
import_stl,
|
||||
)
|
||||
from build123d.geometry import Pos
|
||||
from build123d.geometry import Pos, Vector
|
||||
from build123d.exporters import ExportSVG
|
||||
from build123d.exporters3d import export_brep, export_step
|
||||
from build123d.build_enums import GeomType
|
||||
from build123d.build_enums import Align, GeomType
|
||||
|
||||
|
||||
class ImportSVG(unittest.TestCase):
|
||||
|
|
@ -116,6 +116,38 @@ class ImportSVG(unittest.TestCase):
|
|||
self.assertEqual(str(svg[1].color), str(Color(1, 0, 0, 1)))
|
||||
self.assertEqual(str(svg[2].color), str(Color(0, 0, 0, 1)))
|
||||
|
||||
def test_import_svg_origin(self):
|
||||
svg_src = (
|
||||
'<svg xmlns="http://www.w3.org/2000/svg" viewBox="1 1 6 8" width="6" height="8">'
|
||||
'<circle r="1" cx="2" cy="3"/>'
|
||||
"</svg>"
|
||||
)
|
||||
|
||||
svg = import_svg(StringIO(svg_src), align=None, flip_y=False)
|
||||
self.assertAlmostEqual(svg[0].bounding_box().center(), Vector(2.0, +3.0))
|
||||
|
||||
svg = import_svg(StringIO(svg_src), align=None, flip_y=True)
|
||||
self.assertAlmostEqual(svg[0].bounding_box().center(), Vector(2.0, -3.0))
|
||||
|
||||
def test_import_svg_align(self):
|
||||
svg_src = (
|
||||
'<svg xmlns="http://www.w3.org/2000/svg" viewBox="1 1 6 8" width="6" height="8">'
|
||||
'<rect x="1" y="1" width="6" height="8"/>'
|
||||
"</svg>"
|
||||
)
|
||||
|
||||
svg = import_svg(StringIO(svg_src), align=Align.MIN, flip_y=False)
|
||||
self.assertAlmostEqual(svg[0].bounding_box().min, Vector(0.0, 0.0))
|
||||
|
||||
svg = import_svg(StringIO(svg_src), align=Align.MIN, flip_y=True)
|
||||
self.assertAlmostEqual(svg[0].bounding_box().min, Vector(0, 0))
|
||||
|
||||
svg = import_svg(StringIO(svg_src), align=Align.MAX, flip_y=False)
|
||||
self.assertAlmostEqual(svg[0].bounding_box().max, Vector(0.0, 0.0))
|
||||
|
||||
svg = import_svg(StringIO(svg_src), align=Align.MAX, flip_y=True)
|
||||
self.assertAlmostEqual(svg[0].bounding_box().max, Vector(0, 0))
|
||||
|
||||
|
||||
class ImportBREP(unittest.TestCase):
|
||||
def test_bad_filename(self):
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue