Skip to content

Commit

Permalink
Added forConstruction option to Workplane.offset2D
Browse files Browse the repository at this point in the history
  • Loading branch information
marcus7070 committed Feb 13, 2021
1 parent 0d96f63 commit 5e3fb9e
Show file tree
Hide file tree
Showing 2 changed files with 57 additions and 15 deletions.
51 changes: 36 additions & 15 deletions cadquery/cq.py
Original file line number Diff line number Diff line change
Expand Up @@ -2042,16 +2042,20 @@ def _addPendingWire(self, wire: Wire) -> None:
"""
self.ctx.pendingWires.append(wire)

def _consolidateWires(self) -> List[Wire]:
def _consolidateWires(self, forConstruction: bool = False) -> List[Wire]:

wires = cast(
List[Union[Edge, Wire]],
[el for el in chain(self.ctx.pendingEdges, self.ctx.pendingWires)],
)
if not wires:
if forConstruction:
inputs = [obj for obj in self.objects if isinstance(obj, (Wire, Edge))]
else:
inputs = [
cast(Union[Edge, Wire], x)
for x in chain(self.ctx.pendingEdges, self.ctx.pendingWires)
]

if not inputs:
return []

return Wire.combine(wires)
return Wire.combine(inputs)

def consolidateWires(self) -> "Workplane":
"""
Expand Down Expand Up @@ -3742,22 +3746,39 @@ def toPending(self) -> "Workplane":
return self

def offset2D(
self, d: float, kind: Literal["arc", "intersection", "tangent"] = "arc"
self,
d: float,
kind: Literal["arc", "intersection", "tangent"] = "arc",
forConstruction: bool = False,
) -> "Workplane":
"""
Creates a 2D offset wire.
:param float d: thickness. Negative thickness denotes offset to inside.
:param kind: offset kind. Use "arc" for rounded and "intersection" for sharp edges (default: "arc")
:param d: thickness. Negative thickness denotes offset to inside.
:param kind: offset kind. Use "arc" for rounded and "intersection" for sharp
edges (default: "arc")
:param forConstruction: True if the result will be used to make a solid, False if
it is just for reference.
Pops pending wires and edges from the modelling context, consolidates them,
offsets them and then returns the result to pending wires.
However, if forConstruction is True, does not touch pending wires and edges and
instead consolidates wires and edges from self.objects, offsets them and returns
the result in a new workplane.
:raises RuntimeError: if there are no wires to offset.
:return: CQ object with resulting wire(s).
"""

ws = self._consolidateWires()
ws = self._consolidateWires(forConstruction=forConstruction)
if not ws:
raise RuntimeError("No wires to offset")
rv = list(chain.from_iterable(w.offset2D(d, kind) for w in ws))

self.ctx.pendingEdges = []
self.ctx.pendingWires = rv
if not forConstruction:
self.ctx.pendingEdges = []
self.ctx.pendingWires = rv

return self.newObject(rv)

Expand Down
21 changes: 21 additions & 0 deletions tests/test_cadquery.py
Original file line number Diff line number Diff line change
Expand Up @@ -3887,6 +3887,27 @@ def testOffset2D(self):
)
self.assertEqual(s.solids().size(), 4)

# test forConstruction
# forConstruction=True should place results in objects, not ctx.pendingWires
w6 = (
Workplane()
.rect(1, 1, forConstruction=True)
.offset2D(0.5, forConstruction=True)
)
self.assertEqual(len(w6.ctx.pendingWires), 0)
self.assertEqual(w6.size(), 1)

# forConstruction=True should not use pending wires/edges, unlike forConstruction=False
w7 = Workplane().box(1, 1, 1).faces(">Z").edges().toPending().wire().end(3)
# there should be a wire in pendingWires, and no wires in w7.objects
self.assertEqual(len(w7.ctx.pendingWires), 1)
self.assertEqual(any(isinstance(x, Wire) for x in w7.vals()), False)
# so forConstruction=False should work
w7.offset2D(0.5)
# and forConstruction=True should fail
with self.assertRaises(RuntimeError):
w7.offset2D(0.5, forConstruction=True)

def testConsolidateWires(self):

w1 = Workplane().lineTo(0, 1).lineTo(1, 1).consolidateWires()
Expand Down

0 comments on commit 5e3fb9e

Please sign in to comment.