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 #145 from dcowden/sweep
Browse files Browse the repository at this point in the history
Sweep -- awesome work!
  • Loading branch information
dcowden committed Apr 27, 2016
2 parents 7f29a14 + 02dd0f2 commit 37cf193
Show file tree
Hide file tree
Showing 4 changed files with 116 additions and 0 deletions.
40 changes: 40 additions & 0 deletions cadquery/cq.py
Original file line number Diff line number Diff line change
Expand Up @@ -2055,6 +2055,24 @@ 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):
"""
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 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)
if combine:
newS = self._combineWithBase(r)
else:
newS = self.newObject([r])
if clean: newS = newS.clean()
return newS

def _combineWithBase(self, obj):
"""
Combines the provided object with the base solid, if one can be found.
Expand Down Expand Up @@ -2318,6 +2336,28 @@ def _revolve(self, angleDegrees, axisStart, axisEnd):

return Compound.makeCompound(toFuse)

def _sweep(self, path, 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
:return:a FreeCAD solid, suitable for boolean operations
"""

# group wires together into faces based on which ones are inside the others
# result is a list of lists
s = time.time()
wireSets = sortWiresByBuildOrder(list(self.ctx.pendingWires), self.plane, [])
# print "sorted wires in %d sec" % ( time.time() - s )
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)
toFuse.append(thisObj)

return Compound.makeCompound(toFuse)

def box(self, length, width, height, centered=(True, True, True), combine=True, clean=True):
"""
Return a 3d box with specified dimensions for each object on the stack.
Expand Down
22 changes: 22 additions & 0 deletions cadquery/freecad_impl/shapes.py
Original file line number Diff line number Diff line change
Expand Up @@ -905,6 +905,28 @@ def revolve(cls, outerWire, innerWires, angleDegrees, axisStart, axisEnd):

return Shape.cast(result)

@classmethod
def sweep(cls, outerWire, innerWires, path, makeSolid=True, isFrenet=False):
"""
Attempt to sweep the list of wires into a prismatic solid along the provided path
:param outerWire: the outermost wire
:param innerWires: a list of inner wires
:param path: The wire to sweep the face resulting from the wires over
:return: a Solid object
"""

# FreeCAD allows this in one operation, but others might not
freeCADWires = [outerWire.wrapped]
for w in innerWires:
freeCADWires.append(w.wrapped)

# f = FreeCADPart.Face(freeCADWires)
wire = FreeCADPart.Wire([path.wrapped])
result = wire.makePipeShell(freeCADWires, makeSolid, isFrenet)

return Shape.cast(result)

def tessellate(self, tolerance):
return self.wrapped.tessellate(tolerance)

Expand Down
File renamed without changes
54 changes: 54 additions & 0 deletions tests/TestCadQuery.py
Original file line number Diff line number Diff line change
Expand Up @@ -349,6 +349,60 @@ def testRevolveCone(self):
self.assertEqual(2, result.vertices().size())
self.assertEqual(3, result.edges().size())

def testSweep(self):
"""
Tests the operation of sweeping a wire(s) along a path
"""
pts = [
(0, 1),
(1, 2),
(2, 4)
]

# Spline path
path = Workplane("XZ").spline(pts)

# Test defaults
result = Workplane("XY").circle(1.0).sweep(path)
self.assertEqual(3, result.faces().size())
self.assertEqual(3, result.edges().size())

# Test with makeSolid False
result = Workplane("XY").circle(1.0).sweep(path, makeSolid=False)
self.assertEqual(1, result.faces().size())
self.assertEqual(3, result.edges().size())

# Test with isFrenet True
result = Workplane("XY").circle(1.0).sweep(path, isFrenet=True)
self.assertEqual(3, result.faces().size())
self.assertEqual(3, result.edges().size())

# Test with makeSolid False and isFrenet True
result = Workplane("XY").circle(1.0).sweep(path, makeSolid=False, isFrenet=True)
self.assertEqual(1, result.faces().size())
self.assertEqual(3, result.edges().size())

# Test rectangle with defaults
result = Workplane("XY").rect(1.0, 1.0).sweep(path)
self.assertEqual(6, result.faces().size())
self.assertEqual(12, result.edges().size())

# Polyline path
path = Workplane("XZ").polyline(pts)

# Test defaults
result = Workplane("XY").circle(0.1).sweep(path)
self.assertEqual(5, result.faces().size())
self.assertEqual(7, result.edges().size())

# Arc path
path = Workplane("XZ").threePointArc((1.0, 1.5),(0.0, 1.0))

# Test defaults
result = Workplane("XY").circle(0.1).sweep(path)
self.assertEqual(3, result.faces().size())
self.assertEqual(3, result.edges().size())

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

0 comments on commit 37cf193

Please sign in to comment.