diff --git a/cadquery/cq.py b/cadquery/cq.py index cd00c9b79..bc289659c 100644 --- a/cadquery/cq.py +++ b/cadquery/cq.py @@ -1346,6 +1346,47 @@ def move(self, xDist=0, yDist=0): newCenter = p + Vector(xDist, yDist, 0) return self.newObject([self.plane.toWorldCoords(newCenter)]) + def slot2D(self, length, diameter, angle=0): + """ + Creates a rounded slot for each point on the stack. + + :param diameter: desired diameter, or width, of slot + :param length: desired end to end length of slot + :param angle: angle of slot in degrees, with 0 being along x-axis + :return: a new CQ object with the created wires on the stack + + Can be used to create arrays of slots, such as in cooling applications: + + result = cq.Workplane("XY").box(10,25,1).rarray(1,2,1,10).slot(8,1,0).cutThruAll() + """ + + def _makeslot(pnt): + """ + Inner function that is used to create a slot for each point/object on the workplane + :param pnt: The center point for the slot + :return: A CQ object representing a slot + """ + + radius = diameter/2 + + p1 = pnt + Vector((-length/2) + radius, diameter/2) + p2 = p1 + Vector(length - diameter, 0) + p3 = p1 + Vector(length - diameter, -diameter) + p4 = p1 + Vector(0, -diameter) + arc1 = p2 + Vector(radius, -radius) + arc2 = p4 + Vector(-radius, radius) + + edges=[(Edge.makeLine(p1,p2))] + edges.append(Edge.makeThreePointArc(p2, arc1, p3)) + edges.append(Edge.makeLine(p3, p4)) + edges.append(Edge.makeThreePointArc(p4, arc2, p1)) + + slot = Wire.assembleEdges(edges) + + return slot.rotate(pnt, pnt + Vector(0,0,1), angle) + + return self.eachpoint(_makeslot, True) + def spline(self, listOfXYTuple, tangents=None, periodic=False, forConstruction=False, includeCurrent=False, makeWire=False): """ diff --git a/tests/TestCadQuery.py b/tests/TestCadQuery.py index 6a93374d1..205c1d8ec 100644 --- a/tests/TestCadQuery.py +++ b/tests/TestCadQuery.py @@ -2059,3 +2059,24 @@ def testFindSolid(self): s = r.findSolid() self.assertEqual(len(s.Solids()),2) self.assertTrue(isinstance(s,Compound)) + + def testSlot2D(self): + + decimal_places = 9 + + # Ensure it produces a solid with the correct volume + result = Workplane("XY").slot2D(4,1,0).extrude(1) + self.assertAlmostEqual(result.val().Volume(), 3.785398163, decimal_places) + + # Test for proper expected behaviour when cutting + box = Workplane("XY").box(5,5,1) + result = box.faces(">Z").workplane().slot2D(4,1,0).cutThruAll() + self.assertAlmostEqual(result.val().Volume(), 21.214601837, decimal_places) + result = box.faces(">Z").workplane().slot2D(4,1,0).cutBlind(-0.5) + self.assertAlmostEqual(result.val().Volume(), 23.107300918, decimal_places) + + # Test to see if slot is rotated correctly + result = Workplane("XY").slot2D(4,1,45).extrude(1) + point = result.faces(">Z").edges(">X").first().val().startPoint().toTuple() + self.assertTupleAlmostEquals(point, (0.707106781, 1.414213562, 1.0), decimal_places) +