Merge pull request #858 from martinbudden/cylinder
Added cylinder 3D primitive to Workplane.
This commit is contained in:
@ -3800,6 +3800,69 @@ class Workplane(object):
|
||||
else:
|
||||
return self.union(spheres, clean=clean)
|
||||
|
||||
def cylinder(
|
||||
self: T,
|
||||
height: float,
|
||||
radius: float,
|
||||
direct: Vector = Vector(0, 0, 1),
|
||||
angle: float = 360,
|
||||
centered: Union[bool, Tuple[bool, bool, bool]] = True,
|
||||
combine: bool = True,
|
||||
clean: bool = True,
|
||||
) -> T:
|
||||
"""
|
||||
Returns a cylinder with the specified radius and height for each point on the stack
|
||||
|
||||
:param height: The height of the cylinder
|
||||
:type height: float > 0
|
||||
:param radius: The radius of the cylinder
|
||||
:type radius: float > 0
|
||||
:param direct: The direction axis for the creation of the cylinder
|
||||
:type direct: A three-tuple
|
||||
:param angle: The angle to sweep the cylinder arc through
|
||||
:type angle: float > 0
|
||||
:param centered: If True, the cylinder will be centered around the reference point. If False,
|
||||
the corner of a bounding box around the cylinder will be on the reference point and it
|
||||
will extend in the positive x, y and z directions. Can also use a 3-tuple to specify
|
||||
centering along each axis.
|
||||
: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
|
||||
:param clean: call :py:meth:`clean` afterwards to have a clean shape
|
||||
:return: A cylinder object for each point on the stack
|
||||
|
||||
One cylinder is created for each item on the current stack. If no items are on the stack, one
|
||||
cylinder is created using the current workplane center.
|
||||
|
||||
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 cylinders produced fused onto it otherwise,
|
||||
the result is the combination of all the produced cylinders.
|
||||
|
||||
If combine is false, the result will be a list of the cylinders produced.
|
||||
"""
|
||||
|
||||
if isinstance(centered, bool):
|
||||
centered = (centered, centered, centered)
|
||||
|
||||
offset = Vector()
|
||||
if not centered[0]:
|
||||
offset += Vector(radius, 0, 0)
|
||||
if not centered[1]:
|
||||
offset += Vector(0, radius, 0)
|
||||
if centered[2]:
|
||||
offset += Vector(0, 0, -height / 2)
|
||||
|
||||
s = Solid.makeCylinder(radius, height, offset, direct, angle)
|
||||
|
||||
# We want a cylinder for each point on the workplane
|
||||
cylinders = self.eachpoint(lambda loc: s.moved(loc), True)
|
||||
|
||||
# If we don't need to combine everything, just return the created cylinders
|
||||
if not combine:
|
||||
return cylinders
|
||||
else:
|
||||
return self.union(cylinders, clean=clean)
|
||||
|
||||
def wedge(
|
||||
self: T,
|
||||
dx: float,
|
||||
|
@ -90,6 +90,7 @@ Some 3D operations also require an active 2D workplane, but some do not.
|
||||
Workplane.cutThruAll
|
||||
Workplane.box
|
||||
Workplane.sphere
|
||||
Workplane.cylinder
|
||||
Workplane.union
|
||||
Workplane.combine
|
||||
Workplane.intersect
|
||||
|
@ -81,7 +81,6 @@ rotation/transform that return a copy
|
||||
primitive creation
|
||||
Need primitive creation for:
|
||||
* cone
|
||||
* cylinder
|
||||
* torus
|
||||
* wedge
|
||||
|
||||
|
@ -2443,6 +2443,39 @@ class TestCadQuery(BaseTest):
|
||||
self.assertEqual(1, s.solids().size())
|
||||
self.assertEqual(4, s.faces().size())
|
||||
|
||||
def testCylinderDefaults(self):
|
||||
s = Workplane("XY").cylinder(20, 10)
|
||||
self.assertEqual(1, s.size())
|
||||
self.assertEqual(1, s.solids().size())
|
||||
self.assertEqual(3, s.faces().size())
|
||||
self.assertEqual(2, s.vertices().size())
|
||||
self.assertTupleAlmostEquals(s.val().Center().toTuple(), (0, 0, 0), 3)
|
||||
|
||||
def testCylinderCentering(self):
|
||||
radius = 10
|
||||
height = 40
|
||||
b = (True, False)
|
||||
expected_x = (0, radius)
|
||||
expected_y = (0, radius)
|
||||
expected_z = (0, height / 2)
|
||||
for (xopt, xval), (yopt, yval), (zopt, zval) in product(
|
||||
zip(b, expected_x), zip(b, expected_y), zip(b, expected_z)
|
||||
):
|
||||
s = Workplane("XY").cylinder(height, radius, centered=(xopt, yopt, zopt))
|
||||
self.assertEqual(1, s.size())
|
||||
self.assertTupleAlmostEquals(
|
||||
s.val().Center().toTuple(), (xval, yval, zval), 3
|
||||
)
|
||||
# check centered=True produces the same result as centered=(True, True, True)
|
||||
for val in b:
|
||||
s0 = Workplane("XY").cylinder(height, radius, centered=val)
|
||||
self.assertEqual(s0.size(), 1)
|
||||
s1 = Workplane("XY").cylinder(height, radius, centered=(val, val, val))
|
||||
self.assertEqual(s1.size(), 1)
|
||||
self.assertTupleAlmostEquals(
|
||||
s0.val().Center().toTuple(), s1.val().Center().toTuple(), 3
|
||||
)
|
||||
|
||||
def testWedgeDefaults(self):
|
||||
s = Workplane("XY").wedge(10, 10, 10, 5, 5, 5, 5)
|
||||
self.saveModel(s)
|
||||
|
Reference in New Issue
Block a user