def lens_holes(left_c, right_c, thickness): """Generates the toolpath for the lens holes (holes, groove and tabs).""" print 'Calculating the lens holes' tool_radius = 3.175 if not poly.is_ccw(left_c): left_c = poly.reverse(left_c) if not poly.is_ccw(right_c): right_c = poly.reverse(right_c) # drawing = dxf.drawing('test.dxf') # drawing.add_layer('OUTLINE', color=1) # polyline = dxf.polyline(layer="OUTLINE") # polyline.add_vertices(left_c) # drawing.add(polyline) lhole = poly.erode(tool_radius/2.0, left_c)[0] rhole = poly.erode(tool_radius/2.001, right_c); rhole = rhole[0] # polyline = dxf.polyline(layer="OUTLINE") # polyline.add_vertices(lhole) # drawing.add(polyline) right_rough = poly.erode((tool_radius + 0.3)/2, right_c)[0] left_rough = poly.erode((tool_radius+0.3)/2, left_c)[0] #lgroove = poly.erode(0.8, left_c)[0] #rgroove = poly.erode(0.8, right_c)[0] left_entry = poly.erode(5.0, left_c)[0][0]; right_entry = poly.erode(5.0, right_c)[0][0]; lhole = poly.reverse(lhole) rhole = poly.reverse(rhole) r = [ "(Lens Holes)", cam.change_tool("1/8in endmill"), cam.start_spindle(22000), cam.feedrate(2000), cam.rmh(right_entry + [-thickness - 1.0], 1.5, 0.5, 1.0), cam.contour(right_rough, True), cam.feedrate(1000), cam.contour(rhole, True), cam.feedrate(2000), cam.rmh(left_entry + [-thickness - 1.0], 1.5, 0.5, 1.0), cam.contour(left_rough, True), cam.feedrate(1000), cam.contour(lhole, True), ] return r
def lens_groove(left_c, right_c, height): """Generates the toolpath for the lens holes (holes, groove and tabs).""" print 'Generating lens grooves' if not poly.is_ccw(left_c): left_c = poly.reverse(left_c) if not poly.is_ccw(right_c): right_c = poly.reverse(right_c) lgroove = poly.erode(1.8, left_c)[0] rgroove = poly.erode(1.8, right_c)[0] left_entry = poly.erode(7.0, left_c)[0][0]; right_entry = poly.erode(7.0, right_c)[0][0]; r = [ "(Lens Grooves)", cam.change_tool("vgroove"), cam.start_spindle(20000), cam.dwell(5), cam.feedrate(2000), cam.rmp(right_entry + [height]), cam.contour(rgroove, True), cam.move(right_entry), # Get out from under the overhang cam.rmp(left_entry + [height]), cam.contour(lgroove, True), cam.move(left_entry), # Get out from under the overhang ] return r
def generic_nose_contour(face_con, thickness, thin_back, centering_shift): """ Use the tapered endmill to create a nose relief along the curve of the glasses frame. First construct a path that is a simple, average shape for a nose: 8 mm nose radius, 34 degree splay. Compare the curve to the spline of the glasses, if the spline crosses our naive curve, follow the glasses curve until it crosses the naive curve again, then keep following the naive curve. """ curve_offset = 0 # Set so tapered endmill cuts about 1mm from front face of frame nose_sa = math.radians(34) # Experiment with this nose_rad = 9 xfloor = -26 # set to avoid hitting clamp nose_height = 8 # again, experiment naive_poly = nose.nose_poly(nose_rad, nose_height, nose_sa, nose_sa, xfloor, curve_offset, 0) # close it #naive_poly = naive_poly + [naive_poly[0]] intersect = poly.difference(naive_poly, face_con) intersect = intersect[1:] + [intersect[0]] eroded = poly.erode(2, intersect)[0] finish = poly.erode(1.5, intersect)[0] hole_radius = 4.85/2 # Measured from dowel pin tool_radius = 3.175/2 helix_radius = hole_radius - tool_radius return [ cam.change_tool("tapered"), cam.start_spindle(20000), cam.feedrate(1000), cam.rmh(eroded[0] + [-thickness - 1.0], helix_radius, 0.5, 1), cam.contour(eroded, False), cam.contour(finish[::-1], False), ]
def index_holes(contours, thickness): # We put the index holes 1/2 between top and bottom, 160mm apart # log(str(poly.right(face_c))) # log(str(poly.left(face_c))) # log(str(poly.right(face_c) - poly.left(face_c))) # log(str((poly.right(face_c) - poly.left(face_c))/2)) # log(str(poly.right(face_c) - (poly.right(face_c) - poly.left(face_c))/2)) rightmost = -1000000 leftmost = 1000000 for contour in contours: right = poly.right(contour) left = poly.left(contour) rightmost = max(right, rightmost) leftmost = min(left, leftmost) # x_offset = poly.right(face_c) - (poly.right(face_c) - poly.left(face_c))/2 x_offset = rightmost - (rightmost - leftmost) / 2 hole_radius = 4.85 / 2 # Measured from dowel pin tool_radius = 3.175 / 2 helix_radius = hole_radius - tool_radius r_hole = [x_offset, 90] l_hole = [x_offset, -90] r = [ cam.comment("Index Holes for secondary operations"), cam.change_tool("1/8in endmill"), cam.start_spindle(15000), cam.feedrate(1000), cam.dwell(3), cam.rmh(r_hole + [-thickness - 1.0], helix_radius, 0.5, 1), cam.rmh(l_hole + [-thickness - 1.0], helix_radius, 0.5, 1), ] return r
def surface_front(amount): if amount < 0.1: print 'Not surfacing front, returning' return None print "Surfacing front with amount", amount surface_amount = min(amount, 4) surface_heights = [] while surface_amount <= amount: surface_heights.append(surface_amount) surface_amount = max(surface_amount+2, amount) print "surface amounts", surface_heights program = [ cam.comment("Surface front by %f mm" % amount), cam.flip_stock(), cam.change_tool("3/8in endmill"), cam.spindle_speed(20000), cam.feedrate(2000), cam.start_spindle(),] for height in surface_heights: program = program + cam.surface_along_y(-40, -110, 40, 110, 4.7625, -height) program = program + [ cam.stop_spindle(), cam.retract_spindle(), cam.flip_stock(), ] return program
def nose_contour(nose_rad, nose_h, nose_sa, nose_ra, face_con, thickness): """Creates the nose contour feature toolpath. Angular arguments are in degrees.""" nr = nose_rad h = nose_h sa = math.radians(nose_sa) ra = math.radians(nose_ra) xfloor = poly.left(face_con) - 3.175 # bottom most point minus tool radius xfloor = max(xfloor, -27.0) # miminum safe distance without hitting clamp nose_tool_radius = 3.175 nextpoly = nose.nose_poly(nr, h, sa, ra, xfloor, nose_tool_radius, 0.0) r = [ "(Nose Contour)", cam.change_tool("1/4in ballmill"), cam.start_spindle(20000), cam.feedrate(2000), cam.rmp(nextpoly[0] + [2.0]) # Start near our first contour ] direction = 1 for i in range(-20, (thickness + 2) * 10): z = -i / 10.0 # r += cam.move(nextpoly[0]) if (direction < 0): nextpoly.reverse() direction = direction * -1 r += cam.contour(nextpoly, False) r += cam.move([None, None, z]) nextpoly = nose.nose_poly(nr, h, sa, ra, xfloor, nose_tool_radius, z) return r
def nose_contour(nose_rad, nose_h, nose_sa, nose_ra, face_con, thickness): """Creates the nose contour feature toolpath. Angular arguments are in degrees.""" nr = nose_rad h = nose_h sa = math.radians(nose_sa) ra = math.radians(nose_ra) xfloor = poly.left(face_con) - 3.175 # bottom most point minus tool radius xfloor = max(xfloor, -27.0) # miminum safe distance without hitting clamp nose_tool_radius = 3.175 nextpoly = nose.nose_poly(nr, h, sa, ra, xfloor, nose_tool_radius, 0.0) r = [ "(Nose Contour)", cam.change_tool("1/4in ballmill"), cam.start_spindle(20000), cam.feedrate(2000), cam.rmp(nextpoly[0] + [2.0]) # Start near our first contour ] direction = 1 for i in range(-20, (thickness+2)*10): z = -i/10.0 # r += cam.move(nextpoly[0]) if(direction < 0): nextpoly.reverse() direction = direction * -1 r += cam.contour(nextpoly, False) r += cam.move([None, None, z]) nextpoly = nose.nose_poly(nr, h, sa, ra, xfloor, nose_tool_radius, z) return r
def lens_holes(left_c, right_c, thickness): """Generates the toolpath for the lens holes (holes, groove and tabs).""" if not poly.is_ccw(left_c): left_c = poly.reverse(left_c) if not poly.is_ccw(right_c): right_c = poly.reverse(right_c) lhole = poly.erode(3.175 / 2.0, left_c)[0] rhole = poly.erode(3.175 / 2.0, right_c)[0] right_rough = poly.erode(0.1, rhole)[0] left_rough = poly.erode(0.1, lhole)[0] lgroove = poly.erode(0.8, left_c)[0] rgroove = poly.erode(0.8, right_c)[0] left_entry = poly.erode(2.0, lhole)[0][0] right_entry = poly.erode(2.0, rhole)[0][0] lhole = poly.reverse(lhole) rhole = poly.reverse(rhole) r = [ "(Lens Holes)", cam.change_tool("1/8in endmill"), cam.start_spindle(20000), cam.feedrate(2000), cam.rmh(right_entry + [-thickness - 1.0], 1.5, 0.5, 1.0), cam.contour(right_rough, True), cam.contour(rhole, True), cam.rmh(left_entry + [-thickness - 1.0], 1.5, 0.5, 1.0), cam.contour(left_rough, True), cam.contour(lhole, True), ] return r
def rough_temple_bevel(temple, thinning): p1 = extendLine(temple[-1], temple[-2], 3.175/2 - 0.5) p2 = extendLine(temple[0], temple[1], 3.175/2 - 0.5) p3 = extendLine(temple[0], temple[1], 15) p4 = extendLine(temple[-1], temple[-2], 15) # room for dovetail # p1 and p2 are just extensions of the temple - move them to the side a bit to # clearance for when the dovetail cutter comes through p1 = extendLine(p1, p2, 3) p2 = extendLine(p2, p1, 3) p3 = extendLine(p3, p4, 3) p4 = extendLine(p4, p3, 3) # Move to the dovetail cutter entry point, helix through stock. # Cut a circle big enough to admit the dovetail cutter. # Rough cut the end of the temple # Clear a return path for the dovetail cutter. return [ cam.change_tool("1/8in endmill"), cam.feedrate(1000), cam.rmh(p4 + [-5-thinning], 1, pitch=1), cam.move(p1), cam.move(p2), cam.move(p3), cam.move(p4), cam.rapid(p4 + [10]) ]
def index_holes(contours, thickness): # We put the index holes 1/2 between top and bottom, 160mm apart # log(str(poly.right(face_c))) # log(str(poly.left(face_c))) # log(str(poly.right(face_c) - poly.left(face_c))) # log(str((poly.right(face_c) - poly.left(face_c))/2)) # log(str(poly.right(face_c) - (poly.right(face_c) - poly.left(face_c))/2)) rightmost = -1000000 leftmost = 1000000 for contour in contours: right = poly.right(contour) left = poly.left(contour) rightmost = max(right, rightmost) leftmost = min(left, leftmost) # x_offset = poly.right(face_c) - (poly.right(face_c) - poly.left(face_c))/2 x_offset = rightmost - (rightmost - leftmost)/2 hole_radius = 4.85/2 # Measured from dowel pin tool_radius = 3.175/2 helix_radius = hole_radius - tool_radius r_hole = [x_offset, 90] l_hole = [x_offset, -90] r = [ cam.comment("Index Holes for secondary operations"), cam.change_tool("1/8in endmill"), cam.start_spindle(15000), cam.feedrate(1000), cam.dwell(3), cam.rmh(r_hole + [-thickness - 1.0], helix_radius, 0.5, 1), cam.rmh(l_hole + [-thickness - 1.0], helix_radius, 0.5, 1), ] return r
def temple_hinge_pockets(temples): # We're operating in a 90 degree rotated fixture #l_hinge = poly.rotate_90(temples["left_hinge_contour"]) #r_hinge = poly.rotate_90(temples["right_hinge_contour"]) l_hinge = temples["left_hinge_contour"] r_hinge = temples["right_hinge_contour"] if not poly.is_ccw(l_hinge): l_hinge = poly.reverse(l_hinge) if not poly.is_ccw(r_hinge): r_hinge = poly.reverse(r_hinge) left_hinge_pocket_contours = [] while len(l_hinge) > 0: l_hinge = poly.erode(1.5875 / 2, l_hinge) if len(l_hinge) > 0: l_hinge = l_hinge[0] left_hinge_pocket_contours.append(l_hinge) right_hinge_pocket_contours = [] while len(r_hinge) > 0: r_hinge = poly.erode(1.5875 / 2, r_hinge) if len(r_hinge) > 0: r_hinge = r_hinge[0] right_hinge_pocket_contours.append(r_hinge) r = [ cam.comment("Hinge Pockets"), cam.feedrate(750), cam.change_tool("1/16in endmill"), cam.start_spindle(15000), cam.dwell(3), cam.comment("Right Hinge Pocket"), cam.pocket(right_hinge_pocket_contours, -abs(temples['pocket_depth']), retract=0), cam.rapid([None, None, 20.0]), cam.comment("Left Hinge Pocket"), cam.pocket(left_hinge_pocket_contours, -abs(temples['pocket_depth']), retract=0), cam.rapid([None, None, 20.0]), cam.comment("Hinge Holes"), cam.change_tool("1mm drill"), cam.start_spindle(4500), cam.dwell(2), [ cam.rmp(p + [-8.0], retract=10.0) for p in temples['right_hinge_holes'] ], [ cam.rmp(p + [-8.0], retract=10.0) for p in temples['left_hinge_holes'] ], cam.rapid([None, None, 20.0]), cam.move([None, None, 0]), cam.contour(poly.rotate_90(temples['left_temple_contour']), True), cam.contour(poly.rotate_90(temples['right_temple_contour']), True), ] return r
def face_hinge_pockets(hinge_num, xposition, yposition): left_hinge = hinges.get_hinge(hinge_num) right_hinge = hinges.get_hinge(hinge_num, False) left_translate = [xposition, -yposition] #left_translate = [xposition, 0] right_translate = [xposition, yposition] #right_translate = [xposition, 0] # Adjust by pocket depth of hinge pocket_depth = left_hinge['pocket_depth'] left_contour = poly.translate(left_hinge["face_contour"], left_translate[0], left_translate[1]) right_contour = poly.translate(right_hinge["face_contour"], right_translate[0], right_translate[1]) left_holes = poly.translate(left_hinge["face_holes"], left_translate[0], left_translate[1]) right_holes = poly.translate(right_hinge["face_holes"], right_translate[0], right_translate[1]) if not poly.is_ccw(left_contour): left_contour = poly.reverse(left_contour) if not poly.is_ccw(right_contour): right_contour = poly.reverse(right_contour) left_hinge_pocket_contours = []; while len(left_contour) > 0: left_contour = poly.erode(1.5875/2, left_contour) if len(left_contour) > 0: left_contour = left_contour[0] left_hinge_pocket_contours.append(left_contour) right_hinge_pocket_contours = []; while len(right_contour) > 0: right_contour = poly.erode(1.5875/2, right_contour) if len(right_contour) > 0: right_contour = right_contour[0] right_hinge_pocket_contours.append(right_contour) r = [ cam.comment("Hinge Pockets"), cam.feedrate(750), cam.change_tool("1/16in endmill"), cam.start_spindle(15000), cam.dwell(3), cam.comment("Right Hinge Pocket"), cam.pocket(right_hinge_pocket_contours, -abs(right_hinge['pocket_depth']), retract=0), cam.rapid([None, None, 20.0]), cam.comment("Left Hinge Pocket"), cam.pocket(left_hinge_pocket_contours, -abs(left_hinge['pocket_depth']), retract=0), cam.rapid([None, None, 20.0]), cam.comment("Hinge Holes"), cam.change_tool("1mm drill"), cam.start_spindle(4500), cam.dwell(2), [cam.rmp(p + [-8.0], retract=10.0) for p in right_holes], [cam.rmp(p + [-8.0], retract=10.0) for p in left_holes], cam.rapid([None, None, 20.0]), ] return r
def surface_back(amount): if amount < 0.1: return None print 'surfacing back with', amount surface_amount = min(amount, 4) surface_heights = [] while surface_amount <= amount: surface_heights.append(surface_amount); print surface_heights surface_amount = max(surface_amount+2, amount) print "surface amounts on back", surface_heights return [ cam.comment("Surface back by %f mm" % amount), cam.change_tool("3/8in endmill"), cam.spindle_speed(15000), cam.feedrate(1500), cam.start_spindle(), cam.dwell(5), cam.surface_along_y(-40, -110, 40, 110, 4.7625, -amount), cam.rapid([None, None, 20]), ] if amount > 0 else None program = [ cam.comment("Surface back by %f mm" % amount), cam.change_tool("3/8in endmill"), cam.spindle_speed(20000), cam.feedrate(2000), cam.start_spindle(), cam.dwell(5), ] for height in surface_heights: program = program + cam.surface_along_y(-40, -110, 40, 110, 4.7625, -height), program = program + [ cam.stop_spindle(), cam.retract_spindle(), ] return program
def surface_front(amount): log("Surfacing front with amount %f" % amount) return [ cam.flip_stock(), cam.change_tool("1/4in endmill"), cam.spindle_speed(20000), cam.feedrate(2000), cam.start_spindle(), cam.surface_along_y(-80, -100, -5, 100, 3.175, amount), cam.stop_spindle(), cam.retract_spindle(), cam.flip_stock(), ] if amount < 0 else None
def surface_front(amount): log("Surfacing front with amount %f" % amount) return [ cam.flip_stock(), cam.change_tool("1/4in endmill"), cam.spindle_speed(20000), cam.feedrate(2000), cam.start_spindle(), cam.surface_along_y(-80, -100, -5, 100, 3.175, amount), cam.stop_spindle(), cam.retract_spindle(), cam.flip_stock(), ] if amount < 0 else None
def bevel_entry_hole(temples, thickness): hole_radius = 8 tool_radius = 3.175/2 # 1/2 inch helix_radius = hole_radius - tool_radius r = [ cam.comment("Entry holes for temple bevelling operation"), cam.change_tool("1/8in endmill"), cam.start_spindle(22000), cam.feedrate(800), cam.dwell(5), ]
def temple_hinge_pockets(temples): # We're operating in a 90 degree rotated fixture #l_hinge = poly.rotate_90(temples["left_hinge_contour"]) #r_hinge = poly.rotate_90(temples["right_hinge_contour"]) l_hinge = temples["left_hinge_contour"] r_hinge = temples["right_hinge_contour"] if not poly.is_ccw(l_hinge): l_hinge = poly.reverse(l_hinge) if not poly.is_ccw(r_hinge): r_hinge = poly.reverse(r_hinge) left_hinge_pocket_contours = []; while len(l_hinge) > 0: l_hinge = poly.erode(1.5875/2, l_hinge) if len(l_hinge) > 0: l_hinge = l_hinge[0] left_hinge_pocket_contours.append(l_hinge) right_hinge_pocket_contours = []; while len(r_hinge) > 0: r_hinge = poly.erode(1.5875/2, r_hinge) if len(r_hinge) > 0: r_hinge = r_hinge[0] right_hinge_pocket_contours.append(r_hinge) r = [ cam.comment("Hinge Pockets"), cam.feedrate(750), cam.change_tool("1/16in endmill"), cam.start_spindle(15000), cam.dwell(3), cam.comment("Right Hinge Pocket"), cam.pocket(right_hinge_pocket_contours, -abs(temples['pocket_depth']), retract=0), cam.rapid([None, None, 20.0]), cam.comment("Left Hinge Pocket"), cam.pocket(left_hinge_pocket_contours, -abs(temples['pocket_depth']), retract=0), cam.rapid([None, None, 20.0]), cam.comment("Hinge Holes"), cam.change_tool("1mm drill"), cam.start_spindle(4500), cam.dwell(2), [cam.rmp(p + [-8.0], retract=10.0) for p in temples['right_hinge_holes']], [cam.rmp(p + [-8.0], retract=10.0) for p in temples['left_hinge_holes']], cam.rapid([None, None, 20.0]), cam.move([None, None, 0]), cam.contour(poly.rotate_90(temples['left_temple_contour']), True), cam.contour(poly.rotate_90(temples['right_temple_contour']), True), ] return r
def temple_hinge_clearance(temple, thinning): # Endpoints for the top bevel entry = extendLine(temple[-1], temple[-2], 7.5) p1 = extendLine(temple[0], temple[-1], 1) p2 = extendLine(temple[-1], temple[0], 1) return [ cam.change_tool("engraver"), cam.feedrate(750), cam.start_spindle(20000), cam.rmp(entry + [-2 - thinning]), cam.move(p1), cam.move(p2), cam.move(entry), cam.move(entry + [10]), ]
def nose_contour(nose_rad, nose_h, nose_sa, nose_ra, face_con, thickness, thin_back, centering_shift): """Creates the nose contour feature toolpath. Angular arguments are in degrees."""# print 'Generating nose contour' nr = nose_rad nose_tool_radius = 3.175 # We're cutting with a ball-end mill. Where it actually cuts is dependent on the # ridge angle. If you draw a line at the ridge angle and put it tangent to the ball mill, # that is the cutting line. The angle between the center of the ball mill and the intersection # of the cutting line and the surface is 1/2 of the ridge angle. From that and the radius # of the ball mill we can figure out the offset. cutter_offset = (nose_tool_radius)*math.tan(math.radians(nose_ra/2)) sa = math.radians(nose_sa) ra = math.radians(nose_ra) h = nose_h + centering_shift print 'centering shift', centering_shift # h = nose_h xfloor = poly.left(face_con) - 3.175 # bottom most point minus tool radius xfloor = max(xfloor, -27.0) # miminum safe distance without hitting clamp z_depth = -thin_back # Start a bit above the surface of the glasses nextpoly = nose.nose_poly(nr, h, sa, ra, xfloor, cutter_offset, z_depth) r = [ "(Nose Contour)", cam.change_tool("1/4in ballmill"), cam.start_spindle(20000), cam.feedrate(4000), cam.rmp(nextpoly[0] + [2.0]), # Start near our first contour ] direction = 1 z_start = int((z_depth)*10) # We have to use integers for the range, also step in 1/10 mm steps for i in range(-z_start, int(((thickness)+3)*10)): z = -i/10.0 # r += cam.move(nextpoly[0]) if(direction < 0): nextpoly.reverse() direction = direction * -1 r += cam.move([None, None, z-thin_back]) # Z adjusted for any surfacing that happened r += cam.contour(nextpoly, False) nextpoly = nose.nose_poly(nr, h, sa, ra, xfloor, cutter_offset, z) return r
def index_holes(thickness): # We put the index holes 1/2 between top and bottom, 160mm apart hole_radius = 4.85/2 # Measured from dowel pin tool_radius = 3.175/2 helix_radius = hole_radius - tool_radius r = [ cam.comment("Index holes for secondary operations"), cam.change_tool("1/8in endmill"), cam.start_spindle(22000), cam.feedrate(1000), cam.dwell(5), # Index holes should be at 90, -90 but are shifted a bit to compensate # for inaccuracy on laser fixture cam.rmh([0, 85.00, -thickness - 1.0], helix_radius, 0.5, 1), cam.rmh([0, -85.00, -thickness - 1.0], helix_radius, 0.5, 1), ] return r
def rough_nose_contour(nose_rad, nose_h, nose_sa, nose_ra, face_con, thickness, thin_back, centering_shift): sa = math.radians(nose_sa) ra = math.radians(nose_ra) h = nose_h + centering_shift h = nose_h xfloor = poly.left(face_con) - 3.175 # bottom most point minus tool radius xfloor = max(xfloor, -27.0) # miminum safe distance without hitting clamp cutter_offset = 1.5875 # radius of 1/8" cutter nosepoly = nose.nose_poly(nose_rad, h, sa, ra, xfloor, cutter_offset, thickness+thin_back) return [ "(Rough nose contour)", cam.change_tool("1/8in endmill"), cam.start_spindle(20000), cam.feedrate(2000), cam.rmp(nosepoly[0] + [1.0]), cam.rmh([0, 85.00, -thickness - 1.0], helix_radius, 0.5, 1), ]
def bevel_temple(temple, thinning): # Assume a 20 degree dovetail cutter, cutting 5mm from bottom dovetail_offset = 9.52/2 - 1.82 entry = extendLine(temple[-1], temple[-2], 7.5) # Endpoints for the undercut p1 = extendLine(temple[-1], temple[-2], dovetail_offset) p2 = extendLine(temple[0], temple[1], dovetail_offset) p2 = extendLine(p2, p1, 2) return [ cam.change_tool("dovetail"), cam.feedrate(750), cam.start_spindle(20000), cam.rmp(entry + [-5-thinning]), cam.move(p1), cam.move(p2), cam.move(entry), cam.move(entry + [10]), ]
def bevel_temple_ends(path1, path2, thinning): depth = -4 - thinning # Assume a 14 degree dovetail cutter, cutting 5mm from bottom dovetail_offset = 12.35/2 - 1.25 return [ cam.comment("Bevel temple ends"), cam.change_tool("dovetail"), cam.start_spindle(20000), cam.feedrate(750), cam.rapid(path1[0]), cam.rapid([None, None, depth]), cam.move(path1[1]), cam.move(path1[2]), cam.move(path1[0]), cam.rapid([None, None, 10]), cam.rapid(path2[0]), cam.rapid([None, None, depth]), cam.move(path2[1]), cam.move(path2[2]), cam.move(path2[0]), cam.move([None, None, 20]) ]
def lens_holes(left_c, right_c, thickness): """Generates the toolpath for the lens holes (holes, groove and tabs).""" if not poly.is_ccw(left_c): left_c = poly.reverse(left_c) if not poly.is_ccw(right_c): right_c = poly.reverse(right_c) lhole = poly.erode(3.175/2.0, left_c)[0] rhole = poly.erode(3.175/2.0, right_c)[0] right_rough = poly.erode(0.1, rhole)[0] left_rough = poly.erode(0.1, lhole)[0] lgroove = poly.erode(0.8, left_c)[0] rgroove = poly.erode(0.8, right_c)[0] left_entry = poly.erode(2.0, lhole)[0][0]; right_entry = poly.erode(2.0, rhole)[0][0]; lhole = poly.reverse(lhole) rhole = poly.reverse(rhole) r = [ "(Lens Holes)", cam.change_tool("1/8in endmill"), cam.start_spindle(20000), cam.feedrate(2000), cam.rmh(right_entry + [-thickness - 1.0], 1.5, 0.5, 1.0), cam.contour(right_rough, True), cam.contour(rhole, True), cam.rmh(left_entry + [-thickness - 1.0], 1.5, 0.5, 1.0), cam.contour(left_rough, True), cam.contour(lhole, True), ] return r
def contour_face(body_removal, hinge_removal, nosepad_removal, temple_height, face_c, lens_c, x_pos): ''' Create the heightmap of the frame, surfacing the back and adding thickness for the hinge location and the nosepads. ''' if body_removal == hinge_removal == nosepad_removal == 0: return [] # Nothing to do cutter_radius = 6.35/2 # 3/4 inch cutter entry_point = [x_pos, 110, 0] facing_contour = poly.dilate(0.05, lens_c) # Reshape the facing contour so the first point is near the hinge center_y = poly.bottom(facing_contour) + (poly.top(facing_contour) - poly.bottom(facing_contour))/2 center_x = poly.right(facing_contour) + (poly.left(facing_contour) - poly.right(facing_contour))/2 split_idx = -1 for idx, pt in enumerate(facing_contour): if pt[1] > center_y and (idx+1) < len(facing_contour): if (pt[0] < x_pos and facing_contour[idx+1][0] > x_pos) or (pt[0] > x_pos and facing_contour[idx+1][0] < x_pos): split_idx = idx break if split_idx < 0: print 'Error contouring back of frame: could not locate entry point for surfacing cut' return [] facing_contour = poly.new_start(facing_contour, split_idx) # Ensure we're going clockwise, i.e. starting at the hinge and moving up over the frame if poly.is_ccw(facing_contour): facing_contour = poly.reverse(facing_contour) # Calculate the Z values # We'll need a few helper values. nosepad_start is the inflection point of the nose bridge. nosepad_start = max([pt[0] for pt in face_c if pt[1] == 0]) + cutter_radius hinge_rampdown_start_x = x_pos + temple_height/2 + cutter_radius hinge_rampdown_start_y = facing_contour[0][1] - cutter_radius hinge_rampup_start_x = x_pos - temple_height/2 - cutter_radius hinge_rampup_start_y = facing_contour[0][1] - cutter_radius print nosepad_start, hinge_rampdown_start_x, hinge_rampdown_start_y, hinge_rampup_start_x, hinge_rampup_start_y ''' Arbitrary heuristic, adjusted for aesthetics. 1. If we're past the center point of the lens hole, we're either on the body of the frame or over the raised hinge point. 2. If we're before the center point we're either on the body or over the nosepiece. 1a. If we're above the cutter-radius-adjusted top of the temple, we're ramping down 1b. If we're below the cutter-radius-adjusted bottom of the temple, we're ramping up 1c. Otherwise we're at body thickness 2a. If we're above the top of the nose cutout, we're at body thickness 2b. When we reach nose cutout, we do a s-curve over 3 mm to nosepad height 2c. Continue for length of cutter diameter to get rear of cutter over highest point 2d. Continue for 10mm 2e. S-curve down over 10mm ''' print hinge_removal, body_removal def add_hinge_heights(contour): heightmap = [] over_hinge = True # Start over hinge items_to_skip = 0 # for fast-forwarding enumeration for idx, pt in enumerate(contour): if items_to_skip > 0: items_to_skip = items_to_skip - 1 if items_to_skip == 0: print 'first post ramp point', contour[idx+1] continue if pt[1] < center_y: heightmap = heightmap + [pt] # Going up and around: start ramping down when we're clear of X or Y elif pt[0] > x_pos: if pt[0] > hinge_rampdown_start_x or pt[1] < hinge_rampdown_start_y: if(over_hinge): # starting transition transition_length = poly.polyline_length(contour[:(idx+1)], False) ramp_segment = poly.segment(contour, transition_length, transition_length+5, False) ramp_segment = poly.ramp(ramp_segment, hinge_removal, body_removal, False) heightmap = heightmap + ramp_segment[:-1] items_to_skip = len(ramp_segment) print 'last ramp segment', ramp_segment[-1] over_hinge = False else: # past transition but still on hinge side of lens hole heightmap = heightmap + [pt + [body_removal]] else: # We're on the top part but haven't reached the transition yet heightmap = heightmap + [pt + [hinge_removal]] # Coming back up to the hinge: start ramping up if we encroach on both x and y elif pt[0] < x_pos and (pt[0] > hinge_rampup_start_x and pt[1] > hinge_rampdown_start_y): if(not over_hinge): # starting transition print pt, x_pos, hinge_rampup_start_x, hinge_rampdown_start_y, idx transition_length = poly.polyline_length(contour[:(idx+1)], False) ramp_segment = poly.segment(contour, transition_length, transition_length+5, False) ramp_segment = poly.ramp(ramp_segment, body_removal, hinge_removal, False) heightmap = heightmap + ramp_segment items_to_skip = len(ramp_segment) over_hinge = True else: # Over flat hinge area heightmap = heightmap + [pt + [hinge_removal]] else: # We're over the body area but back on the hinge side heightmap = heightmap + [pt + [body_removal]] return heightmap def add_nosepad_heights(contour): heightmap = [] over_nosepad = False past_nosepad = False nosepad_flat_idx = -1 items_to_skip = 0 # for fast-forwarding the enumeration for idx, pt in enumerate(contour): if items_to_skip > 0: items_to_skip = items_to_skip-1 continue if pt[1] >= center_y: heightmap = heightmap + [pt] elif not over_nosepad and not past_nosepad: if pt[0] < nosepad_start: # Transition transition_length = poly.polyline_length(contour[:(idx+1)], False) ramp_segment = poly.segment(contour, transition_length, transition_length+5, False) ramp_segment = poly.ramp(ramp_segment, body_removal, nosepad_removal, False) heightmap = heightmap + ramp_segment[:-1] items_to_skip = len(ramp_segment) nosepad_flat_idx = idx + items_to_skip # we'll need this to go down over_nosepad = True else: # we're past the nosepad heightmap = heightmap + [pt + [body_removal]] elif over_nosepad and not past_nosepad: if nosepad_flat_idx < 0: print "ERROR! I think I'm on the nosepad but have not transitioned yet" return [] # We'll be cutting the far side with the back of the cutter, so need to move at # least the diameter to get any flat at all flat_length = poly.polyline_length(contour[nosepad_flat_idx:(idx+1)], False) - (cutter_radius*2) if flat_length < 5: heightmap = heightmap + [pt + [nosepad_removal]] else: # ramp down transition_length = poly.polyline_length(contour[:(idx+1)], False) ramp_segment = poly.segment(contour, transition_length, transition_length+5, False) ramp_segment = poly.ramp(ramp_segment, nosepad_removal, body_removal, False) heightmap = heightmap + ramp_segment[:-1] items_to_skip = len(ramp_segment) nosepad_flat_idx = idx + items_to_skip # we'll need this to go down over_nosepad = False past_nosepad = True else: heightmap = heightmap + [pt + [body_removal]] return heightmap facing_contour = add_hinge_heights(facing_contour) facing_contour = add_nosepad_heights(facing_contour) facing_contour = poly.reverse(facing_contour) right_facing = poly.mirror_y(facing_contour, True) passes = [1] heights = [p[2] for p in facing_contour] r = [ cam.change_tool("1/4in ballmill"), cam.spindle_speed(22000), cam.feedrate(1000), cam.start_spindle(), cam.rmp(entry_point), cam.contour(facing_contour, True), ] for dilate in passes: dilated = poly.reverse(poly.dilate(dilate, facing_contour)) # dilated = add_hinge_heights(dilated) dilated = add_nosepad_heights(dilated) r = r + [ cam.contour(dilated, True),] return r
def contour_face(body_removal, hinge_removal, nosepad_removal, temple_height, face_c, lens_c, x_pos): ''' Create the heightmap of the frame, surfacing the back and adding thickness for the hinge location and the nosepads. ''' if body_removal == hinge_removal == nosepad_removal == 0: return [] # Nothing to do cutter_radius = 6.35 / 2 # 3/4 inch cutter entry_point = [x_pos, 110, 0] facing_contour = poly.dilate(0.05, lens_c) # Reshape the facing contour so the first point is near the hinge center_y = poly.bottom(facing_contour) + (poly.top(facing_contour) - poly.bottom(facing_contour)) / 2 center_x = poly.right(facing_contour) + (poly.left(facing_contour) - poly.right(facing_contour)) / 2 split_idx = -1 for idx, pt in enumerate(facing_contour): if pt[1] > center_y and (idx + 1) < len(facing_contour): if (pt[0] < x_pos and facing_contour[idx + 1][0] > x_pos) or ( pt[0] > x_pos and facing_contour[idx + 1][0] < x_pos): split_idx = idx break if split_idx < 0: print 'Error contouring back of frame: could not locate entry point for surfacing cut' return [] facing_contour = poly.new_start(facing_contour, split_idx) # Ensure we're going clockwise, i.e. starting at the hinge and moving up over the frame if poly.is_ccw(facing_contour): facing_contour = poly.reverse(facing_contour) # Calculate the Z values # We'll need a few helper values. nosepad_start is the inflection point of the nose bridge. nosepad_start = max([pt[0] for pt in face_c if pt[1] == 0]) + cutter_radius hinge_rampdown_start_x = x_pos + temple_height / 2 + cutter_radius hinge_rampdown_start_y = facing_contour[0][1] - cutter_radius hinge_rampup_start_x = x_pos - temple_height / 2 - cutter_radius hinge_rampup_start_y = facing_contour[0][1] - cutter_radius print nosepad_start, hinge_rampdown_start_x, hinge_rampdown_start_y, hinge_rampup_start_x, hinge_rampup_start_y ''' Arbitrary heuristic, adjusted for aesthetics. 1. If we're past the center point of the lens hole, we're either on the body of the frame or over the raised hinge point. 2. If we're before the center point we're either on the body or over the nosepiece. 1a. If we're above the cutter-radius-adjusted top of the temple, we're ramping down 1b. If we're below the cutter-radius-adjusted bottom of the temple, we're ramping up 1c. Otherwise we're at body thickness 2a. If we're above the top of the nose cutout, we're at body thickness 2b. When we reach nose cutout, we do a s-curve over 3 mm to nosepad height 2c. Continue for length of cutter diameter to get rear of cutter over highest point 2d. Continue for 10mm 2e. S-curve down over 10mm ''' print hinge_removal, body_removal def add_hinge_heights(contour): heightmap = [] over_hinge = True # Start over hinge items_to_skip = 0 # for fast-forwarding enumeration for idx, pt in enumerate(contour): if items_to_skip > 0: items_to_skip = items_to_skip - 1 if items_to_skip == 0: print 'first post ramp point', contour[idx + 1] continue if pt[1] < center_y: heightmap = heightmap + [pt] # Going up and around: start ramping down when we're clear of X or Y elif pt[0] > x_pos: if pt[0] > hinge_rampdown_start_x or pt[ 1] < hinge_rampdown_start_y: if (over_hinge): # starting transition transition_length = poly.polyline_length( contour[:(idx + 1)], False) ramp_segment = poly.segment(contour, transition_length, transition_length + 5, False) ramp_segment = poly.ramp(ramp_segment, hinge_removal, body_removal, False) heightmap = heightmap + ramp_segment[:-1] items_to_skip = len(ramp_segment) print 'last ramp segment', ramp_segment[-1] over_hinge = False else: # past transition but still on hinge side of lens hole heightmap = heightmap + [pt + [body_removal]] else: # We're on the top part but haven't reached the transition yet heightmap = heightmap + [pt + [hinge_removal]] # Coming back up to the hinge: start ramping up if we encroach on both x and y elif pt[0] < x_pos and (pt[0] > hinge_rampup_start_x and pt[1] > hinge_rampdown_start_y): if (not over_hinge): # starting transition print pt, x_pos, hinge_rampup_start_x, hinge_rampdown_start_y, idx transition_length = poly.polyline_length( contour[:(idx + 1)], False) ramp_segment = poly.segment(contour, transition_length, transition_length + 5, False) ramp_segment = poly.ramp(ramp_segment, body_removal, hinge_removal, False) heightmap = heightmap + ramp_segment items_to_skip = len(ramp_segment) over_hinge = True else: # Over flat hinge area heightmap = heightmap + [pt + [hinge_removal]] else: # We're over the body area but back on the hinge side heightmap = heightmap + [pt + [body_removal]] return heightmap def add_nosepad_heights(contour): heightmap = [] over_nosepad = False past_nosepad = False nosepad_flat_idx = -1 items_to_skip = 0 # for fast-forwarding the enumeration for idx, pt in enumerate(contour): if items_to_skip > 0: items_to_skip = items_to_skip - 1 continue if pt[1] >= center_y: heightmap = heightmap + [pt] elif not over_nosepad and not past_nosepad: if pt[0] < nosepad_start: # Transition transition_length = poly.polyline_length( contour[:(idx + 1)], False) ramp_segment = poly.segment(contour, transition_length, transition_length + 5, False) ramp_segment = poly.ramp(ramp_segment, body_removal, nosepad_removal, False) heightmap = heightmap + ramp_segment[:-1] items_to_skip = len(ramp_segment) nosepad_flat_idx = idx + items_to_skip # we'll need this to go down over_nosepad = True else: # we're past the nosepad heightmap = heightmap + [pt + [body_removal]] elif over_nosepad and not past_nosepad: if nosepad_flat_idx < 0: print "ERROR! I think I'm on the nosepad but have not transitioned yet" return [] # We'll be cutting the far side with the back of the cutter, so need to move at # least the diameter to get any flat at all flat_length = poly.polyline_length( contour[nosepad_flat_idx:(idx + 1)], False) - (cutter_radius * 2) if flat_length < 5: heightmap = heightmap + [pt + [nosepad_removal]] else: # ramp down transition_length = poly.polyline_length( contour[:(idx + 1)], False) ramp_segment = poly.segment(contour, transition_length, transition_length + 5, False) ramp_segment = poly.ramp(ramp_segment, nosepad_removal, body_removal, False) heightmap = heightmap + ramp_segment[:-1] items_to_skip = len(ramp_segment) nosepad_flat_idx = idx + items_to_skip # we'll need this to go down over_nosepad = False past_nosepad = True else: heightmap = heightmap + [pt + [body_removal]] return heightmap facing_contour = add_hinge_heights(facing_contour) facing_contour = add_nosepad_heights(facing_contour) facing_contour = poly.reverse(facing_contour) right_facing = poly.mirror_y(facing_contour, True) passes = [1] heights = [p[2] for p in facing_contour] r = [ cam.change_tool("1/4in ballmill"), cam.spindle_speed(22000), cam.feedrate(1000), cam.start_spindle(), cam.rmp(entry_point), cam.contour(facing_contour, True), ] for dilate in passes: dilated = poly.reverse(poly.dilate(dilate, facing_contour)) # dilated = add_hinge_heights(dilated) dilated = add_nosepad_heights(dilated) r = r + [ cam.contour(dilated, True), ] return r
def face_hinge_pockets(hinge_num, xposition, yposition): left_hinge = hinges.get_hinge(hinge_num) right_hinge = hinges.get_hinge(hinge_num, False) left_translate = [xposition, -yposition] #left_translate = [xposition, 0] right_translate = [xposition, yposition] #right_translate = [xposition, 0] # Adjust by pocket depth of hinge pocket_depth = left_hinge['pocket_depth'] left_contour = poly.translate(left_hinge["face_contour"], left_translate[0], left_translate[1]) right_contour = poly.translate(right_hinge["face_contour"], right_translate[0], right_translate[1]) left_holes = poly.translate(left_hinge["face_holes"], left_translate[0], left_translate[1]) right_holes = poly.translate(right_hinge["face_holes"], right_translate[0], right_translate[1]) if not poly.is_ccw(left_contour): left_contour = poly.reverse(left_contour) if not poly.is_ccw(right_contour): right_contour = poly.reverse(right_contour) left_hinge_pocket_contours = [] while len(left_contour) > 0: left_contour = poly.erode(1.5875 / 2, left_contour) if len(left_contour) > 0: left_contour = left_contour[0] left_hinge_pocket_contours.append(left_contour) right_hinge_pocket_contours = [] while len(right_contour) > 0: right_contour = poly.erode(1.5875 / 2, right_contour) if len(right_contour) > 0: right_contour = right_contour[0] right_hinge_pocket_contours.append(right_contour) r = [ cam.comment("Hinge Pockets"), cam.feedrate(750), cam.change_tool("1/16in endmill"), cam.start_spindle(15000), cam.dwell(3), cam.comment("Right Hinge Pocket"), cam.pocket(right_hinge_pocket_contours, -abs(right_hinge['pocket_depth']), retract=0), cam.rapid([None, None, 20.0]), cam.comment("Left Hinge Pocket"), cam.pocket(left_hinge_pocket_contours, -abs(left_hinge['pocket_depth']), retract=0), cam.rapid([None, None, 20.0]), cam.comment("Hinge Holes"), cam.change_tool("1mm drill"), cam.start_spindle(4500), cam.dwell(2), [cam.rmp(p + [-8.0], retract=10.0) for p in right_holes], [cam.rmp(p + [-8.0], retract=10.0) for p in left_holes], cam.rapid([None, None, 20.0]), ] return r
def temple_hinge_pockets(temples, thinned): # We're operating in a 90 degree rotated fixture #l_hinge = poly.rotate_90(temples["left_hinge_contour"]) #r_hinge = poly.rotate_90(temples["right_hinge_contour"]) print 'Generating temple hinge pockets' l_hinge = temples["left_hinge_contour"] r_hinge = temples["right_hinge_contour"] if not poly.is_ccw(l_hinge): l_hinge = poly.reverse(l_hinge) if not poly.is_ccw(r_hinge): r_hinge = poly.reverse(r_hinge) #pocket_depth = temples['pocket_depth'] + thinned pocket_depth = 1 + thinned; def pocket_contours(contour): contours = [] erode = poly.erode(1.5875/2, contour) making_progress = True while len(erode) > 0 and making_progress: making_progress = False for path in erode: if len(path) > 5: making_progress = True contours.append(path) erode = poly.erode(1.5875/2, contours[-1]) return contours left_hinge_pocket_contours = pocket_contours(l_hinge) right_hinge_pocket_contours = pocket_contours(r_hinge) # left_hinge_pocket_contours = []; # while len(l_hinge) > 0: # l_hinge = poly.erode(1.5875/2, l_hinge) # if len(l_hinge) > 0: # l_hinge = l_hinge[0] # left_hinge_pocket_contours.append(l_hinge) # right_hinge_pocket_contours = []; # while len(r_hinge) > 0: # r_hinge = poly.erode(1.5875/2, r_hinge) # if len(rhinge_) == 1: # right_hinge_pocket # if len(r_hinge) > 0: # r_hinge = r_hinge[0] # right_hinge_pocket_contours.append(r_hinge) r = [ cam.comment("Hinge Pockets"), cam.feedrate(750), cam.change_tool("1/16in endmill"), cam.start_spindle(22000), cam.dwell(5), cam.comment("Right Hinge Pocket"), cam.pocket(right_hinge_pocket_contours, -abs(pocket_depth), retract=0), cam.rapid([None, None, 20.0]), cam.comment("Left Hinge Pocket"), cam.pocket(left_hinge_pocket_contours, -abs(pocket_depth), retract=0), cam.rapid([None, None, 20.0]), cam.comment("Hinge Holes"), cam.change_tool("1mm drill"), cam.start_spindle(5000), cam.dwell(2), [cam.rmp(p + [-8.0], retract=10.0) for p in temples['right_hinge_holes']], [cam.rmp(p + [-8.0], retract=10.0) for p in temples['left_hinge_holes']], cam.rapid([None, None, 20.0]), ] return r
def face_hinge_pockets(hinge_num, hinge_height, temple_position, centering_shift, thin_back): print 'Generating face hinge pockets', hinge_num xposition = hinge_height; yposition = temple_position+3.0; # 4mm for the temple, but less 1mm for temple hinge pocket print 'Position is ', xposition, yposition left_hinge = hinges.get_hinge(hinge_num) print 'Got left hinge' right_hinge = hinges.get_hinge(hinge_num, False) print 'Retrieved hinge contours' left_translate = [xposition, yposition] right_translate = [xposition, -yposition] print 'Calculated hinge translations' #right_translate = [xposition, 0] # Adjust by pocket depth of hinge #pocket_depth = left_hinge['pocket_depth']+thin_back pocket_depth = 1 + thin_back drill_depth = -thin_back - 2.0 left_contour = poly.mirror_x(poly.rotate_90(left_hinge["face_contour"]), False) right_contour = poly.mirror_x(poly.rotate_90(right_hinge["face_contour"]), False) left_holes = poly.mirror_x(poly.rotate_90(left_hinge["face_holes"]), False) right_holes = poly.mirror_x(poly.rotate_90(right_hinge["face_holes"]), False) left_contour = poly.translate(left_contour, left_translate[0], -left_translate[1]) right_contour = poly.translate(right_contour, right_translate[0], -right_translate[1]) left_holes = poly.translate(left_holes, left_translate[0], -left_translate[1]) right_holes = poly.translate(right_holes, right_translate[0], -right_translate[1]) # Now center everything on the stock left_contour = poly.translate(left_contour, centering_shift[0], -centering_shift[1]) right_contour = poly.translate(right_contour, centering_shift[0], -centering_shift[1]) left_holes = poly.translate(left_holes, centering_shift[0], -centering_shift[1]) right_holes = poly.translate(right_holes, centering_shift[0], -centering_shift[1]) if not poly.is_ccw(left_contour): left_contour = poly.reverse(left_contour) if not poly.is_ccw(right_contour): right_contour = poly.reverse(right_contour) left_hinge_pocket_contours = []; while len(left_contour) > 0: left_contour = poly.erode(1.5875/2, left_contour) if len(left_contour) > 0: left_contour = left_contour[0] left_hinge_pocket_contours.append(left_contour) right_hinge_pocket_contours = []; while len(right_contour) > 0: right_contour = poly.erode(1.5875/2, right_contour) if len(right_contour) > 0: right_contour = right_contour[0] right_hinge_pocket_contours.append(right_contour) r = [ cam.comment("Hinge Pockets"), cam.feedrate(750), cam.change_tool("1/16in endmill"), cam.start_spindle(20000), cam.dwell(3), cam.comment("Right Hinge Pocket"), cam.pocket(right_hinge_pocket_contours, -abs(pocket_depth), retract=-abs(pocket_depth)), cam.rapid([None, None, 20.0]), cam.comment("Left Hinge Pocket"), cam.pocket(left_hinge_pocket_contours, -abs(pocket_depth), retract=-abs(pocket_depth)), cam.rapid([None, None, 20.0]), cam.comment("Hinge Holes"), cam.change_tool("1mm drill"), cam.start_spindle(5000), cam.dwell(2), [cam.rmp(p + [drill_depth], retract=10.0) for p in right_holes], [cam.rmp(p + [drill_depth], retract=10.0) for p in left_holes], cam.rapid([None, None, 20.0]), ] return r