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:
|
else:
|
||||||
return self.union(spheres, clean=clean)
|
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(
|
def wedge(
|
||||||
self: T,
|
self: T,
|
||||||
dx: float,
|
dx: float,
|
||||||
|
@ -90,6 +90,7 @@ Some 3D operations also require an active 2D workplane, but some do not.
|
|||||||
Workplane.cutThruAll
|
Workplane.cutThruAll
|
||||||
Workplane.box
|
Workplane.box
|
||||||
Workplane.sphere
|
Workplane.sphere
|
||||||
|
Workplane.cylinder
|
||||||
Workplane.union
|
Workplane.union
|
||||||
Workplane.combine
|
Workplane.combine
|
||||||
Workplane.intersect
|
Workplane.intersect
|
||||||
|
@ -81,7 +81,6 @@ rotation/transform that return a copy
|
|||||||
primitive creation
|
primitive creation
|
||||||
Need primitive creation for:
|
Need primitive creation for:
|
||||||
* cone
|
* cone
|
||||||
* cylinder
|
|
||||||
* torus
|
* torus
|
||||||
* wedge
|
* wedge
|
||||||
|
|
||||||
|
@ -2443,6 +2443,39 @@ class TestCadQuery(BaseTest):
|
|||||||
self.assertEqual(1, s.solids().size())
|
self.assertEqual(1, s.solids().size())
|
||||||
self.assertEqual(4, s.faces().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):
|
def testWedgeDefaults(self):
|
||||||
s = Workplane("XY").wedge(10, 10, 10, 5, 5, 5, 5)
|
s = Workplane("XY").wedge(10, 10, 10, 5, 5, 5, 5)
|
||||||
self.saveModel(s)
|
self.saveModel(s)
|
||||||
|
Reference in New Issue
Block a user