Merge pull request #858 from martinbudden/cylinder

Added cylinder 3D primitive to Workplane.
This commit is contained in:
Jeremy Wright
2021-09-01 11:08:24 -04:00
committed by GitHub
4 changed files with 97 additions and 1 deletions

View File

@ -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,

View File

@ -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

View File

@ -81,7 +81,6 @@ rotation/transform that return a copy
primitive creation
Need primitive creation for:
* cone
* cylinder
* torus
* wedge

View File

@ -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)