Skip to content
This repository has been archived by the owner on Feb 9, 2021. It is now read-only.

Commit

Permalink
Merge pull request #251 from jpmlt/multi-sweep-branch
Browse files Browse the repository at this point in the history
Update sweep function in cq.py add test case and example
  • Loading branch information
jmwright committed Apr 10, 2018
2 parents 980ca90 + d40d8f4 commit 213624b
Show file tree
Hide file tree
Showing 3 changed files with 118 additions and 5 deletions.
28 changes: 23 additions & 5 deletions cadquery/cq.py
Original file line number Diff line number Diff line change
Expand Up @@ -2073,17 +2073,20 @@ def revolve(self, angleDegrees=360.0, axisStart=None, axisEnd=None, combine=True
if clean: newS = newS.clean()
return newS

def sweep(self, path, makeSolid=True, isFrenet=False, combine=True, clean=True):
def sweep(self, path, sweepAlongWires=False, makeSolid=True, isFrenet=False, combine=True, clean=True):
"""
Use all un-extruded wires in the parent chain to create a swept solid.
:param path: A wire along which the pending wires will be swept
:param boolean sweepAlongWires:
False to create mutliple swept from wires on the chain along path
True to create only one solid swept along path with shape following the list of wires on the chain
:param boolean combine: True to combine the resulting solid with parent solids if found.
:param boolean clean: call :py:meth:`clean` afterwards to have a clean shape
:return: a CQ object with the resulting solid selected.
"""

r = self._sweep(path.wire(), makeSolid, isFrenet) # returns a Solid (or a compound if there were multiple)
r = self._sweep(path.wire(), sweepAlongWires, makeSolid, isFrenet) # returns a Solid (or a compound if there were multiple)
if combine:
newS = self._combineWithBase(r)
else:
Expand Down Expand Up @@ -2397,11 +2400,14 @@ def _revolve(self, angleDegrees, axisStart, axisEnd):

return Compound.makeCompound(toFuse)

def _sweep(self, path, makeSolid=True, isFrenet=False):
def _sweep(self, path, sweepAlongWires=False, makeSolid=True, isFrenet=False):
"""
Makes a swept solid from an existing set of pending wires.
:param path: A wire along which the pending wires will be swept
:param boolean sweepAlongWires:
False to create mutliple swept from wires on the chain along path
True to create only one solid swept along path with shape following the list of wires on the chain
:return:a FreeCAD solid, suitable for boolean operations
"""

Expand All @@ -2413,8 +2419,20 @@ def _sweep(self, path, makeSolid=True, isFrenet=False):
self.ctx.pendingWires = [] # now all of the wires have been used to create an extrusion

toFuse = []
for ws in wireSets:
thisObj = Solid.sweep(ws[0], ws[1:], path.val(), makeSolid, isFrenet)
if not sweepAlongWires:
for ws in wireSets:
thisObj = Solid.sweep(ws[0], ws[1:], path.val(), makeSolid, isFrenet)
toFuse.append(thisObj)
else:
section = []
for ws in wireSets:
for i in range(0, len(ws)):
section.append(ws[i])

# implementation
outW = Wire(section[0].wrapped)
inW = section[1:]
thisObj = Solid.sweep(outW, inW, path.val(), makeSolid, isFrenet)
toFuse.append(thisObj)

return Compound.makeCompound(toFuse)
Expand Down
47 changes: 47 additions & 0 deletions examples/FreeCAD/Ex034_Sweep_Along_List_Of_Wires.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
import cadquery as cq

# X axis line length 20.0
path = cq.Workplane("XZ").moveTo(-10, 0).lineTo(10, 0)

# Sweep a circle from diameter 2.0 to diameter 1.0 to diameter 2.0 along X axis length 10.0 + 10.0
defaultSweep = cq.Workplane("YZ").workplane(offset=-10.0).circle(2.0). \
workplane(offset=10.0).circle(1.0). \
workplane(offset=10.0).circle(2.0).sweep(path, sweepAlongWires=True)

# We can sweep thrue different shapes
recttocircleSweep = cq.Workplane("YZ").workplane(offset=-10.0).rect(2.0, 2.0). \
workplane(offset=8.0).circle(1.0).workplane(offset=4.0).circle(1.0). \
workplane(offset=8.0).rect(2.0, 2.0).sweep(path, sweepAlongWires=True)

circletorectSweep = cq.Workplane("YZ").workplane(offset=-10.0).circle(1.0). \
workplane(offset=7.0).rect(2.0, 2.0).workplane(offset=6.0).rect(2.0, 2.0). \
workplane(offset=7.0).circle(1.0).sweep(path, sweepAlongWires=True)


# Placement of the Shape is important otherwise could produce unexpected shape
specialSweep = cq.Workplane("YZ").circle(1.0).workplane(offset=10.0).rect(2.0, 2.0). \
sweep(path, sweepAlongWires=True)

# Switch to an arc for the path : line l=5.0 then half circle r=4.0 then line l=5.0
path = cq.Workplane("XZ").moveTo(-5, 4).lineTo(0, 4). \
threePointArc((4, 0), (0, -4)).lineTo(-5, -4)

# Placement of different shapes should follow the path
# cylinder r=1.5 along first line
# then sweep allong arc from r=1.5 to r=1.0
# then cylinder r=1.0 along last line
arcSweep = cq.Workplane("YZ").workplane(offset=-5).moveTo(0, 4).circle(1.5). \
workplane(offset=5).circle(1.5). \
moveTo(0, -8).circle(1.0). \
workplane(offset=-5).circle(1.0). \
sweep(path, sweepAlongWires=True)


# Translate the resulting solids so that they do not overlap and display them left to right
show_object(defaultSweep)
show_object(circletorectSweep.translate((0, 5, 0)))
show_object(recttocircleSweep.translate((0, 10, 0)))
show_object(specialSweep.translate((0, 15, 0)))
show_object(arcSweep.translate((0, -5, 0)))


48 changes: 48 additions & 0 deletions tests/TestCadQuery.py
Original file line number Diff line number Diff line change
Expand Up @@ -445,6 +445,54 @@ def testSweep(self):
self.assertEqual(3, result.faces().size())
self.assertEqual(3, result.edges().size())

def testSweepAlongListOfWires(self):
"""
Tests the operation of sweeping along a list of wire(s) along a path
"""

# X axis line length 20.0
path = Workplane("XZ").moveTo(-10, 0).lineTo(10, 0)

# Sweep a circle from diameter 2.0 to diameter 1.0 to diameter 2.0 along X axis length 10.0 + 10.0
defaultSweep = Workplane("YZ").workplane(offset=-10.0).circle(2.0). \
workplane(offset=10.0).circle(1.0). \
workplane(offset=10.0).circle(2.0).sweep(path, sweepAlongWires=True)

# We can sweep thrue different shapes
recttocircleSweep = Workplane("YZ").workplane(offset=-10.0).rect(2.0, 2.0). \
workplane(offset=8.0).circle(1.0).workplane(offset=4.0).circle(1.0). \
workplane(offset=8.0).rect(2.0, 2.0).sweep(path, sweepAlongWires=True)

circletorectSweep = Workplane("YZ").workplane(offset=-10.0).circle(1.0). \
workplane(offset=7.0).rect(2.0, 2.0).workplane(offset=6.0).rect(2.0, 2.0). \
workplane(offset=7.0).circle(1.0).sweep(path, sweepAlongWires=True)

# Placement of the Shape is important otherwise could produce unexpected shape
specialSweep = Workplane("YZ").circle(1.0).workplane(offset=10.0).rect(2.0, 2.0). \
sweep(path, sweepAlongWires=True)

# Switch to an arc for the path : line l=5.0 then half circle r=4.0 then line l=5.0
path = Workplane("XZ").moveTo(-5, 4).lineTo(0, 4). \
threePointArc((4, 0), (0, -4)).lineTo(-5, -4)

# Placement of different shapes should follow the path
# cylinder r=1.5 along first line
# then sweep allong arc from r=1.5 to r=1.0
# then cylinder r=1.0 along last line
arcSweep = Workplane("YZ").workplane(offset=-5).moveTo(0, 4).circle(1.5). \
workplane(offset=5).circle(1.5). \
moveTo(0, -8).circle(1.0). \
workplane(offset=-5).circle(1.0). \
sweep(path, sweepAlongWires=True)

# Test and saveModel
self.assertEqual(1, defaultSweep.solids().size())
self.assertEqual(1, circletorectSweep.solids().size())
self.assertEqual(1, recttocircleSweep.solids().size())
self.assertEqual(1, specialSweep.solids().size())
self.assertEqual(1, arcSweep.solids().size())
self.saveModel(defaultSweep)

def testTwistExtrude(self):
"""
Tests extrusion while twisting through an angle.
Expand Down

0 comments on commit 213624b

Please sign in to comment.