Skip to content

Commit f3b0b09

Browse files
greyltcadam-urbanczyklorenzncode
authored
allow specification of dxf layer names to import. for issue #1051 (#1061)
* allow specification of dxf layer names to import. for issue #1051 * black, version 19.10b0 reformat * change dxf import/export defaults from None to [] * Change type annotations * Black fix * Add tests, update error message, use set. Co-authored-by: AU <[email protected]> Co-authored-by: Lorenz Neureuter <[email protected]>
1 parent f1b8763 commit f3b0b09

File tree

5 files changed

+66
-14
lines changed

5 files changed

+66
-14
lines changed

cadquery/occ_impl/importers/__init__.py

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -67,15 +67,19 @@ def importStep(fileName):
6767
return cq.Workplane("XY").newObject(solids)
6868

6969

70-
def importDXF(filename, tol=1e-6, exclude=[]):
70+
def importDXF(filename, tol=1e-6, exclude=[], include=[]):
7171
"""
72-
Loads a DXF file into a cadquery Workplane.
72+
Loads a DXF file into a Workplane.
73+
74+
All layers are imported by default. Provide a layer include or exclude list
75+
to select layers. Layer names are handled as case-insensitive.
7376
7477
:param fileName: The path and name of the DXF file to be imported
75-
:param tol: The tolerance used for merging edges into wires (default: 1e-6)
76-
:param exclude: a list of layer names not to import (default: [])
78+
:param tol: The tolerance used for merging edges into wires
79+
:param exclude: a list of layer names not to import
80+
:param include: a list of layer names to import
7781
"""
7882

79-
faces = _importDXF(filename, tol, exclude)
83+
faces = _importDXF(filename, tol, exclude, include)
8084

8185
return cq.Workplane("XY").newObject(faces)

cadquery/occ_impl/importers/dxf.py

Lines changed: 26 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -157,24 +157,42 @@ def _dxf_convert(elements, tol):
157157
return rv
158158

159159

160-
def _importDXF(filename: str, tol: float = 1e-6, exclude: List[str] = []) -> List[Face]:
160+
def _importDXF(
161+
filename: str, tol: float = 1e-6, exclude: List[str] = [], include: List[str] = [],
162+
) -> List[Face]:
161163
"""
162164
Loads a DXF file into a list of faces.
163165
164166
:param fileName: The path and name of the DXF file to be imported
165-
:param tol: The tolerance used for merging edges into wires (default: 1e-6)
166-
:param exclude: a list of layer names not to import (default: [])
167+
:param tol: The tolerance used for merging edges into wires
168+
:param exclude: a list of layer names not to import
169+
:param include: a list of layer names to import
167170
"""
168171

169-
# normalize layer names to conform the DXF spec
170-
exclude_lwr = [ex.lower() for ex in exclude]
172+
if exclude and include:
173+
raise ValueError("you may specify either 'include' or 'exclude' but not both")
171174

172175
dxf = ezdxf.readfile(filename)
173176
faces = []
174177

175-
for name, layer in dxf.modelspace().groupby(dxfattrib="layer").items():
176-
res = _dxf_convert(layer, tol) if name.lower() not in exclude_lwr else None
177-
if res:
178+
layers = dxf.modelspace().groupby(dxfattrib="layer")
179+
180+
# normalize layer names to conform the DXF spec
181+
names = set([name.lower() for name in layers.keys()])
182+
183+
if include:
184+
selected = names & set([name.lower() for name in include])
185+
elif exclude:
186+
selected = names - set([name.lower() for name in exclude])
187+
else:
188+
selected = names
189+
190+
if not selected:
191+
raise ValueError("no DXF layers selected")
192+
193+
for name, layer in layers.items():
194+
if name.lower() in selected:
195+
res = _dxf_convert(layers[name], tol)
178196
wire_sets = sortWiresByBuildOrder(res)
179197
for wire_set in wire_sets:
180198
faces.append(Face.makeFromWires(wire_set[0], wire_set[1:]))

cadquery/sketch.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -170,6 +170,7 @@ def importDXF(
170170
filename: str,
171171
tol: float = 1e-6,
172172
exclude: List[str] = [],
173+
include: List[str] = [],
173174
angle: Real = 0,
174175
mode: Modes = "a",
175176
tag: Optional[str] = None,
@@ -178,7 +179,7 @@ def importDXF(
178179
Import a DXF file and construct face(s)
179180
"""
180181

181-
res = Compound.makeCompound(_importDXF(filename, tol, exclude))
182+
res = Compound.makeCompound(_importDXF(filename, tol, exclude, include))
182183

183184
return self.face(res, angle, mode, tag)
184185

tests/test_importers.py

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77

88
from cadquery import importers, Workplane
99
from tests import BaseTest
10+
from pytest import approx, raises
1011

1112
# where unit test output will be saved
1213
OUTDIR = tempfile.gettempdir()
@@ -138,6 +139,26 @@ def testImportDXF(self):
138139
self.assertEqual(obj.faces().size(), 2)
139140
self.assertEqual(obj.wires().size(), 2)
140141

142+
obj = importers.importDXF(filename, include=["Layer2"])
143+
assert obj.vertices("<XY").val().toTuple() == approx(
144+
(104.2871791623584, 0.0038725018551133, 0.0)
145+
)
146+
147+
obj = importers.importDXF(filename, include=["Layer2", "Layer3"])
148+
assert obj.vertices("<XY").val().toTuple() == approx(
149+
(104.2871791623584, 0.0038725018551133, 0.0)
150+
)
151+
assert obj.vertices(">XY").val().toTuple() == approx(
152+
(257.6544359816229, 93.62447646419444, 0.0)
153+
)
154+
155+
with raises(ValueError):
156+
importers.importDXF(filename, include=["Layer1"], exclude=["Layer3"])
157+
158+
with raises(ValueError):
159+
# Layer4 does not exist
160+
importers.importDXF(filename, include=["Layer4"])
161+
141162
# test dxf extrusion into the third dimension
142163
extrusion_value = 15.0
143164
tmp = obj.wires()

tests/test_sketch.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -717,3 +717,11 @@ def test_dxf_import():
717717
s3 = Sketch().circle(20).importDXF(filename, tol=1e-3, mode="s")
718718

719719
assert s3._faces.isValid()
720+
721+
s4 = Sketch().importDXF(filename, tol=1e-3, include=["0"])
722+
723+
assert s4._faces.isValid()
724+
725+
s5 = Sketch().importDXF(filename, tol=1e-3, exclude=["1"])
726+
727+
assert s5._faces.isValid()

0 commit comments

Comments
 (0)