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

Fixed the Solid.makeSphere implementation and added CQ.sphere that mirro... #82

Merged
merged 1 commit into from
Apr 13, 2015
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
62 changes: 62 additions & 0 deletions cadquery/CQ.py
Original file line number Diff line number Diff line change
Expand Up @@ -2271,3 +2271,65 @@ def _makebox(pnt):
#combine everything
return self.union(boxes)

def sphere(self, radius, direct=(0, 0, 1), angle1=-90, angle2=90, angle3=360, centered=(True, True, True), combine=True):
"""
Returns a 3D sphere with the specified radius for each point on the stack

:param radius: The radius of the sphere
:type radius: float > 0
:param direct: The direction axis for the creation of the sphere
:type direct: A three-tuple
:param angle1: The first angle to sweep the sphere arc through
:type angle1: float > 0
:param angle2: The second angle to sweep the sphere arc through
:type angle2: float > 0
:param angle3: The third angle to sweep the sphere arc through
:type angle3: float > 0
:param centered: A three-tuple of booleans that determines whether the sphere is centered on each axis origin
:param combine: Whether the results should be combined with other solids on the stack (and each other)
:type combine: true to combine shapes, false otherwise
:return: A sphere object for each point on the stack

Centered is a tuple that describes whether the sphere should be centered on the x,y, and z axes. If true,
the sphere is centered on the respective axis relative to the workplane origin, if false, the workplane center
will represent the lower bound of the resulting sphere

One sphere is created for each item on the current stack. If no items are on the stack, one box using
the current workplane center is created.

If combine is true, the result will be a single object on the stack:
If a solid was found in the chain, the result is that solid with all spheres produced fused onto it
otherwise, the result is the combination of all the produced boxes

If combine is false, the result will be a list of the spheres produced
"""

# Convert the direction tuple to a vector, if needed
if isinstance(direct, tuple):
direct = Vector(direct)

def _makesphere(pnt):
"""
Inner function that is used to create a sphere for each point/object on the workplane
:param pnt: The center point for the sphere
:return: A CQ Solid object representing a sphere
"""
(xp, yp, zp) = pnt.toTuple()

if centered[0]:
xp = xp - radius
if centered[1]:
yp = yp - radius
if centered[2]:
zp = zp - radius

return Solid.makeSphere(radius, Vector(xp, yp, zp), direct, angle1, angle2, angle3)

# We want a sphere for each point on the workplane
spheres = self.eachpoint(_makesphere, True)

# If we don't need to combine everything, just return the created spheres
if not combine:
return spheres
else:
return self.union(spheres)
4 changes: 2 additions & 2 deletions cadquery/freecad_impl/shapes.py
Original file line number Diff line number Diff line change
Expand Up @@ -638,13 +638,13 @@ def makeWedge(cls, xmin, ymin, zmin, z2min, x2min, xmax, ymax, zmax, z2max, x2ma
FreeCADPart.makeWedge(xmin, ymin, zmin, z2min, x2min, xmax, ymax, zmax, z2max, x2max, pnt, dir))

@classmethod
def makeSphere(cls, radius, pnt=None, angleDegrees1=None, angleDegrees2=None, angleDegrees3=None):
def makeSphere(cls, radius, pnt=None, dir=None, angleDegrees1=None, angleDegrees2=None, angleDegrees3=None):
"""
'makeSphere(radius,[pnt, dir, angle1,angle2,angle3]) --
Make a sphere with a giv
en radius\nBy default pnt=Vector(0,0,0), dir=Vector(0,0,1), angle1=0, angle2=90 and angle3=360'
"""
return Solid(FreeCADPart.makeSphere(radius, pnt, angleDegrees1, angleDegrees2, angleDegrees3))
return Shape.cast(FreeCADPart.makeSphere(radius, pnt.wrapped, dir.wrapped, angleDegrees1, angleDegrees2, angleDegrees3))

@classmethod
def extrudeLinearWithRotation(cls, outerWire, innerWires, vecCenter, vecNormal, angleDegrees):
Expand Down
2 changes: 2 additions & 0 deletions changes.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,3 +34,5 @@ v0.1.8
v0.1.9 (Unreleased)
-----
* Added license badge in changes.md
* Fixed Solid.makeSphere implementation
* Added CQ.sphere operation that mirrors CQ.box
24 changes: 24 additions & 0 deletions tests/TestCadQuery.py
Original file line number Diff line number Diff line change
Expand Up @@ -750,6 +750,30 @@ def testBoxCombine(self):
self.assertEquals(1,s.solids().size()) # we should have one big solid
self.assertEquals(26,s.faces().size()) # should have 26 faces. 6 for the box, and 4x5 for the smaller cubes

def testSphereDefaults(self):
s = Workplane("XY").sphere(10)
self.saveModel(s)
self.assertEquals(1, s.solids().size())
self.assertEquals(1, s.faces().size())

def testSphereCustom(self):
s = Workplane("XY").sphere(10, angle1=0, angle2=90, angle3=360, centered=(False, False, False))
self.saveModel(s)
self.assertEquals(1, s.solids().size())
self.assertEquals(2, s.faces().size())

def testSpherePointList(self):
s = Workplane("XY").rect(4.0, 4.0, forConstruction=True).vertices().sphere(0.25, combine=False)
self.saveModel(s)
self.assertEquals(4, s.solids().size())
self.assertEquals(4, s.faces().size())

def testSphereCombine(self):
s = Workplane("XY").rect(4.0, 4.0, forConstruction=True).vertices().sphere(0.25, combine=True)
self.saveModel(s)
self.assertEquals(1, s.solids().size())
self.assertEquals(4, s.faces().size())

def testQuickStartXY(self):
s = Workplane(Plane.XY()).box(2,4,0.5).faces(">Z").workplane().rect(1.5,3.5,forConstruction=True)\
.vertices().cskHole(0.125, 0.25,82,depth=None)
Expand Down