Merge pull request #82 from dcowden/sphere

Fixed the Solid.makeSphere implementation and added CQ.sphere that mirro...
This commit is contained in:
Jeremy Wright 2015-04-13 08:10:56 -04:00
commit cde33d8204
4 changed files with 90 additions and 2 deletions

View File

@ -2271,3 +2271,65 @@ class Workplane(CQ):
#combine everything #combine everything
return self.union(boxes) 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)

View File

@ -638,13 +638,13 @@ class Solid(Shape):
FreeCADPart.makeWedge(xmin, ymin, zmin, z2min, x2min, xmax, ymax, zmax, z2max, x2max, pnt, dir)) FreeCADPart.makeWedge(xmin, ymin, zmin, z2min, x2min, xmax, ymax, zmax, z2max, x2max, pnt, dir))
@classmethod @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]) -- 'makeSphere(radius,[pnt, dir, angle1,angle2,angle3]) --
Make a sphere with a giv 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' 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 @classmethod
def extrudeLinearWithRotation(cls, outerWire, innerWires, vecCenter, vecNormal, angleDegrees): def extrudeLinearWithRotation(cls, outerWire, innerWires, vecCenter, vecNormal, angleDegrees):

View File

@ -34,3 +34,5 @@ v0.1.8
v0.1.9 (Unreleased) v0.1.9 (Unreleased)
----- -----
* Added license badge in changes.md * Added license badge in changes.md
* Fixed Solid.makeSphere implementation
* Added CQ.sphere operation that mirrors CQ.box

View File

@ -750,6 +750,30 @@ class TestCadQuery(BaseTest):
self.assertEquals(1,s.solids().size()) # we should have one big solid 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 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): def testQuickStartXY(self):
s = Workplane(Plane.XY()).box(2,4,0.5).faces(">Z").workplane().rect(1.5,3.5,forConstruction=True)\ 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) .vertices().cskHole(0.125, 0.25,82,depth=None)