Changing import_svg to use ocpsvg

This commit is contained in:
gumyr 2023-10-21 11:22:11 -04:00
parent 8baf47549b
commit dd4f923f6c
5 changed files with 149 additions and 57 deletions

View file

@ -108,7 +108,8 @@ A procedure for avoiding this issue is to install in a conda environment, which
conda install -c cadquery -c conda-forge cadquery=master conda install -c cadquery -c conda-forge cadquery=master
pip install svgwrite svgpathtools anytree scipy ipython \ pip install svgwrite svgpathtools anytree scipy ipython \
ocp_tessellate webcolors==1.12 numpy numpy-quaternion cachetools==5.2.0 \ ocp_tessellate webcolors==1.12 numpy numpy-quaternion cachetools==5.2.0 \
ocp_vscode requests orjson urllib3 certifi numpy-stl git+https://github.com/jdegenstein/py-lib3mf ocp_vscode requests orjson urllib3 certifi numpy-stl git+https://github.com/jdegenstein/py-lib3mf \
git+https://github.com/snoyer/ocpsvg
pip install --no-deps git+https://github.com/gumyr/build123d pip install --no-deps git+https://github.com/gumyr/build123d
`You can track the issue here <https://github.com/CadQuery/ocp-build-system/issues/11#issuecomment-1407769681>`_ `You can track the issue here <https://github.com/CadQuery/ocp-build-system/issues/11#issuecomment-1407769681>`_

View file

@ -47,6 +47,7 @@ dependencies = [
"numpy-stl >= 3.0.0, <4", "numpy-stl >= 3.0.0, <4",
"ipython >= 8.0.0, <9", "ipython >= 8.0.0, <9",
"py_lib3mf @ git+https://github.com/jdegenstein/py-lib3mf", "py_lib3mf @ git+https://github.com/jdegenstein/py-lib3mf",
"ocpsvg @ git+https://github.com/snoyer/ocpsvg",
] ]
[project.urls] [project.urls]

View file

@ -30,35 +30,19 @@ license:
import os import os
from math import degrees from math import degrees
from typing import Union from pathlib import Path
from stl.mesh import Mesh from typing import TextIO, Union
from svgpathtools import svg2paths
from OCP.TopoDS import TopoDS_Face, TopoDS_Shape import OCP.IFSelect
from build123d.geometry import Color
from build123d.topology import Compound, Face, Shape, ShapeList, Wire
from OCP.BRep import BRep_Builder from OCP.BRep import BRep_Builder
from OCP.BRepTools import BRepTools from OCP.BRepTools import BRepTools
from OCP.STEPControl import STEPControl_Reader
import OCP.IFSelect
from OCP.RWStl import RWStl from OCP.RWStl import RWStl
from OCP.BRepBuilderAPI import ( from OCP.STEPControl import STEPControl_Reader
BRepBuilderAPI_MakeEdge, from OCP.TopoDS import TopoDS_Face, TopoDS_Shape, TopoDS_Wire
BRepBuilderAPI_MakeFace, from ocpsvg import ColorAndLabel, import_svg_document
BRepBuilderAPI_MakeSolid, from svgpathtools import svg2paths
BRepBuilderAPI_MakeVertex,
BRepBuilderAPI_MakeWire,
BRepBuilderAPI_Sewing,
)
from OCP.gp import gp_Pnt
from build123d.topology import (
Compound,
Edge,
Face,
Shape,
ShapeList,
Shell,
Solid,
downcast,
)
def import_brep(file_name: str) -> Shape: def import_brep(file_name: str) -> Shape:
@ -219,23 +203,49 @@ def import_svg_as_buildline_code(file_name: str) -> tuple[str, str]:
return ("\n".join(buildline_code), builder_name) return ("\n".join(buildline_code), builder_name)
def import_svg(file_name: str) -> ShapeList[Edge]: def import_svg(
svg_file: Union[str, Path, TextIO],
*,
flip_y: bool = True,
ignore_visibility: bool = False,
label_by: str = "id",
is_inkscape_label: bool = False,
) -> ShapeList[Union[Wire, Face]]:
"""import_svg """import_svg
Get a ShapeList of Edge from the paths in the provided svg file.
Args: Args:
filepath (str): svg file svg_file (Union[str, Path, TextIO]): svg file
flip_y (bool, optional): flip objects to compensate for svg orientation. Defaults to True.
ignore_visibility (bool, optional): Defaults to False.
label_by (str, optional): xml attribute. Defaults to "id".
Raises: Raises:
ValueError: File not found ValueError: unexpected shape type
Returns: Returns:
ShapeList[Edge]: Edges in svg file ShapeList[Union[Wire, Face]]: objects contained in svg
""" """
if not os.path.exists(file_name): shapes = []
raise ValueError(f"{file_name} not found") label_by = (
svg_code, builder_name = import_svg_as_buildline_code(file_name) "{http://www.inkscape.org/namespaces/inkscape}" + label_by
ex_locals = {} if is_inkscape_label
exec(svg_code, None, ex_locals) else label_by
return ex_locals[builder_name].edges() )
for face_or_wire, color_and_label in import_svg_document(
svg_file,
flip_y=flip_y,
ignore_visibility=ignore_visibility,
metadata=ColorAndLabel.Label_by(label_by),
):
if isinstance(face_or_wire, TopoDS_Wire):
shape = Wire(face_or_wire)
elif isinstance(face_or_wire, TopoDS_Face):
shape = Face(face_or_wire)
else: # should not happen
raise ValueError(f"unexpected shape type: {type(face_or_wire).__name__}")
shape.color = Color(*color_and_label.color)
shape.label = color_and_label.label
shapes.append(shape)
return ShapeList(shapes)

84
tests/svg_import_test.svg Normal file
View file

@ -0,0 +1,84 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
width="210mm"
height="297mm"
viewBox="0 0 210 297"
version="1.1"
id="svg933"
inkscape:version="1.2.2 (732a01da63, 2022-12-09, custom)"
sodipodi:docname="svg_import_test.svg"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns="http://www.w3.org/2000/svg"
xmlns:svg="http://www.w3.org/2000/svg">
<sodipodi:namedview
id="namedview935"
pagecolor="#ffffff"
bordercolor="#000000"
borderopacity="0.25"
inkscape:showpageshadow="2"
inkscape:pageopacity="0.0"
inkscape:pagecheckerboard="0"
inkscape:deskcolor="#d1d1d1"
inkscape:document-units="mm"
showgrid="false"
inkscape:zoom="1.414741"
inkscape:cx="224.4227"
inkscape:cy="583.49903"
inkscape:window-width="2490"
inkscape:window-height="1536"
inkscape:window-x="0"
inkscape:window-y="0"
inkscape:window-maximized="1"
inkscape:current-layer="layer4" />
<defs
id="defs930" />
<g
inkscape:label="Base"
inkscape:groupmode="layer"
id="layer1">
<path
id="id_base"
style="display:inline;stroke-width:0.264583"
d="m 45.732092,105.28401 a 10.107891,10.107891 0 0 0 -10.10791,10.10791 v 58.42021 a 10.107891,10.107891 0 0 0 10.10791,10.10791 h 68.861948 a 10.107891,10.107891 0 0 0 10.10791,-10.10791 v -58.42021 a 10.107891,10.107891 0 0 0 -10.10791,-10.10791 z"
inkscape:label="label_base" />
</g>
<g
inkscape:groupmode="layer"
id="layer4"
inkscape:label="Wire">
<path
style="fill:none;stroke-width:0.264583;stroke:#000000;stroke-opacity:1"
d="M 54.771808,98.981222 H 123.4902 v 0"
id="id_wire"
inkscape:label="label_wire" />
</g>
<g
inkscape:groupmode="layer"
id="layer2"
inkscape:label="Hole1">
<circle
style="fill:#800000;stroke-width:0.264583"
id="id_red_hole"
cx="54.771809"
cy="126.52283"
r="11.419678"
inkscape:label="label_red_hole"
inkscape:highlight-color="#ee3b45" />
</g>
<g
inkscape:groupmode="layer"
id="layer3"
inkscape:label="Hole2">
<circle
style="fill:#000080;stroke-width:0.264583"
id="id_blue_hole"
cx="98.322319"
cy="160.14645"
r="18.159254"
inkscape:label="label_blue_hole"
inkscape:highlight-color="#3e62e3" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 2.5 KiB

View file

@ -6,7 +6,7 @@ from build123d import (
Bezier, Bezier,
RadiusArc, RadiusArc,
) )
from build123d.importers import import_svg_as_buildline_code, import_brep from build123d.importers import import_svg_as_buildline_code, import_brep, import_svg
from build123d.exporters import ExportSVG from build123d.exporters import ExportSVG
@ -57,25 +57,21 @@ class ImportSVG(unittest.TestCase):
self.assertEqual(builder_name, "builder") self.assertEqual(builder_name, "builder")
# def test_import_svg_as_buildline_code_ccw(self): def test_import_svg(self):
# # Create svg file for tag in ["id", "label"]:
# with BuildLine() as test_obj: # Import the svg object as a ShapeList
# l3 = RadiusArc((0, 1), (0, 0), 1.5) svg = import_svg(
# show(test_obj) "svg_import_test.svg", label_by=tag, is_inkscape_label=tag == "label"
# svg = ExportSVG() )
# svg.add_shape(test_obj.wires()[0], "")
# svg.write("test.svg")
# # Read the svg as code # Exact the shape of the plate & holes
# buildline_code, builder_name = import_svg_as_buildline_code("test.svg") base_faces = svg.filter_by(lambda f: "base" in f.label)
hole_faces = svg.filter_by(lambda f: "hole" in f.label)
test_wires = svg.filter_by(lambda f: "wire" in f.label)
# # Execute it and convert to Edges self.assertEqual(len(list(base_faces)), 1)
# ex_locals = {} self.assertEqual(len(list(hole_faces)), 2)
# exec(buildline_code, None, ex_locals) self.assertEqual(len(list(test_wires)), 1)
# test_obj: BuildLine = ex_locals[builder_name]
# os.remove("test.svg")
# self.assertEqual(test_obj.edges()[0].geom_type(), "ELLIPSE")
class ImportBREP(unittest.TestCase): class ImportBREP(unittest.TestCase):