From ade606023863667d89e238ba5c9958d60a2cda08 Mon Sep 17 00:00:00 2001 From: Jeremy Mack Wright Date: Fri, 23 Sep 2016 15:49:41 -0400 Subject: [PATCH] Added advanced example from @adam-urbanczyk as Ex032. --- .../Ex032_3D_Printer_Extruder_Support.py | 216 ++++++++++++++++++ 1 file changed, 216 insertions(+) create mode 100644 CadQuery/Examples/Ex032_3D_Printer_Extruder_Support.py diff --git a/CadQuery/Examples/Ex032_3D_Printer_Extruder_Support.py b/CadQuery/Examples/Ex032_3D_Printer_Extruder_Support.py new file mode 100644 index 0000000..556a4d1 --- /dev/null +++ b/CadQuery/Examples/Ex032_3D_Printer_Extruder_Support.py @@ -0,0 +1,216 @@ +# 3d printer for mounting hotend to X-carriage inspired by the P3steel Toolson +# edition - http://www.thingiverse.com/thing:1054909 +import cadquery as cq +from Helpers import show + + +def move_to_center(cqObject, shape): + ''' + Moves the origin of the current Workplane to the center of a given + geometry object + ''' + + # transform to workplane local coordinates + shape_center = shape.Center().sub(cqObject.plane.origin) + + # project onto plane using dot product + x_offset = shape_center.dot(cqObject.plane.xDir) + y_offset = shape_center.dot(cqObject.plane.yDir) + + return cqObject.center(x_offset, y_offset) + +# Parameter definitions + +main_plate_size_y = 67 # size of the main plate in y direction +main_plate_size_x = 50. # size of the main plate in x direction +main_plate_thickness = 10. # thickness of the main plate + +wing_size_x = 10. # size of the side wing supporting the bridge in x direction +wing_size_y = 10. # size of the side wing supporting the bridge in y direction + +bridge_depth = 35. # depth of the bridge + +support_depth = 18. # depth of the bridge support + +cutout_depth = 15. # depth of the hotend cutout +cutout_rad = 8. # radius of the cutout (cf groove mount sizes of E3D hotends) +cutout_offset = 2. # delta radius of the second cutout (cf groove mount sizes of E3D hotends) + +extruder_hole_spacing = 50. # spacing of the extruder mounting holes (Wade's geared extruder) + +m4_predrill = 3.7 # hole diameter for m4 tapping +m3_predrill = 2.5 # hole diameter for m3 tapping +m3_cbore = 5. # counterbore size for m3 socket screw + +mounting_hole_spacing = 28. # spacing of the mounting holes for attaching to x-carriage + +aux_hole_depth = 6. # depth of the auxiliary holes at the sides of the object +aux_hole_spacing = 5. # spacing of the auxiliary holes within a group +aux_hole_N = 2 # number of the auxiliary hole per group + +# make the main plate +res = cq.Workplane('front').box(main_plate_size_x, + main_plate_size_y, + main_plate_thickness) + + +def add_wing(obj, sign=1): + ''' + Adds a wing to the main plate, defined to keep the code DRY + ''' + obj = obj.workplane()\ + .hLine(sign*wing_size_x)\ + .vLine(-wing_size_y)\ + .line(-sign*wing_size_x, -2*wing_size_y)\ + .close().extrude(main_plate_thickness) + return obj + +# add wings + +# add right wing +res = res.faces('XY') +res = add_wing(res) + +# store sides of the plate for further reuse, their area is used later on to calculate "optimum" spacing of the aux hole groups +face_right = res.faces('>X[1]').val() +face_left = res.faces('>X[-2]').val() + +# add left wing +res = res.faces('Y').vertices('Z') # select top face +e = wp.edges('>Y') # select most extreme edge in Y direction + +bridge_length = e.val().Length() # the width of the bridge equals to the length of the selected edge + +# draw the bridge x-section and extrude +res = e.vertices('Z[1]') # take all faces in Z direction and select the middle one; note the new selector syntax +edge = faces.edges('>Y') # select the top edge of this face... +res = move_to_center(faces.workplane(), edge.val()).\ + transformed(rotate=(0, 90, 0)) # ...and make a workplane that is centered in this edge and oriented along X direction + +res = res.vLine(-support_depth).\ + line(-support_depth, support_depth).\ + close() # draw a triangle + +res = res.extrude(main_plate_size_x/2, both=True, clean=True) # extrude the triangle, now the bridge has a nice support making it much more stiff + +# Start cutting out a slot for hotend mounting +face = res.faces('>Y') # select the most extreme face in Y direction, i.e. top ot the "bridge" +res = move_to_center(face.workplane(), face.edges('>Z').val()) # shift the workplane to the center of the most extreme edge of the bridge + + +def make_slot(obj, depth=None): + ''' + Utility function that makes a slot for hotend mounting + ''' + obj = obj.moveTo(cutout_rad, -cutout_depth).\ + threePointArc((0, -cutout_depth-cutout_rad), + (-cutout_rad, -cutout_depth)).\ + vLineTo(0).hLineTo(cutout_rad).close() + + if depth is None: + obj = obj.cutThruAll() + else: + obj = obj.cutBlind(depth) + + return obj + +res = make_slot(res, None) # make the smaller slot + +cutout_rad += cutout_offset # increase the cutout radius... +res = make_slot(res.end().end(), -main_plate_thickness/2) # ...and make a slightly larger slot + +res = res.end().moveTo(0, 0) \ + .pushPoints([(-extruder_hole_spacing/2, -cutout_depth), (extruder_hole_spacing/2, -cutout_depth)]) \ + .hole(m4_predrill) # add extruder mounting holes at the top of the bridge + + +# make additional slot in the bridge support which allows the hotend's radiator to fit +cutout_rad += 3*cutout_offset +res = make_slot(res.end().moveTo(0, 0).workplane(offset=-main_plate_thickness)) + +# add reinforcement holes +cutout_rad -= 2*cutout_offset +res = res.faces('>Z').workplane().\ + pushPoints([(-cutout_rad, -main_plate_thickness/4), + (cutout_rad, -main_plate_thickness/4)]).\ + hole(m3_predrill) + +# add aux holes on the front face +res = res.moveTo(-main_plate_size_x/2., 0).workplane().rarray(aux_hole_spacing, 1, aux_hole_N, 1) \ + .hole(m3_predrill, depth=aux_hole_depth) +res = res.moveTo(main_plate_size_x, 0).workplane().rarray(aux_hole_spacing, 1, aux_hole_N, 1) \ + .hole(m3_predrill, depth=aux_hole_depth) + +# make a hexagonal cutout +res = res.faces('>Z[1]') +res = res.workplane(offset=bridge_depth). \ + transformed(rotate=(0, 0, 90)). \ + polygon(6, 30).cutThruAll() + +# make 4 mounting holes with cbores +res = res.end().moveTo(0, 0). \ + rect(mounting_hole_spacing, + mounting_hole_spacing, forConstruction=True) + +res = res.vertices(). \ + cboreHole(m3_predrill, + m3_cbore, + bridge_depth+m3_cbore/2) + +# make cutout and holes for mounting of the fan +res = res.transformed(rotate=(0, 0, 45)). \ + rect(35, 35).cutBlind(-bridge_depth).end(). \ + rect(25, 25, forConstruction=True).vertices().hole(m3_predrill) + + +def make_aux_holes(workplane, holes_span, N_hole_groups=3): + ''' + Utility function for creation of auxiliary mouting holes at the sides of the object + ''' + res = workplane.moveTo(-holes_span/2).workplane().rarray(aux_hole_spacing, 1, aux_hole_N, 1) \ + .hole(m3_predrill, depth=aux_hole_depth) + for i in range(N_hole_groups-1): + res = res.moveTo(holes_span/(N_hole_groups-1.)).workplane().rarray(aux_hole_spacing, 1, aux_hole_N, 1) \ + .hole(m3_predrill, depth=aux_hole_depth) + + return res + +# make aux holes at the bottom +res = res.faces('X').workplane().transformed((90, 0, 0)) +res = make_aux_holes(res, main_plate_size_x*2/3., 3) + +# make aux holes at the side (@main plate) +res = res.faces('|X').edges('X') +res = res.workplane() +res = move_to_center(res, face_right) +res = res.transformed((90, 0, 0)) +hole_sep = 0.5*face_right.Area()/main_plate_thickness +res = make_aux_holes(res, hole_sep, 2) + +# make aux holes at the side (@main plate) +res = res.faces('|X').edges('