def rectangularPocket(area, target_depth, stock_thickness, safe_Z, cut_per_pass, bit_diameter, debug=False): """ area argument requires tuple (length, width). target_depth is an absolute Z coordinate. Assumes that the bit is already in the origin corner. Origin is (minCornerX + bit_radius, minCornerY + bit_radius) """ file_text = G.set_ABS_mode() if debug: file_text += "; target_depth: " + str(target_depth) + "\n" file_text += "; stock_thickness: " + str(stock_thickness) + "\n" file_text += "; cut_per_pass: "******"\n" file_text += "; bit_diameter: " + str(bit_diameter) + "\n" file_text += G.G0_Z(stock_thickness) while stock_thickness > target_depth: stock_thickness -= cut_per_pass if stock_thickness < target_depth: stock_thickness = target_depth # Z-axis move by ABSOLUTE coords file_text += G.set_ABS_mode() file_text += G.G1_Z(stock_thickness) file_text += rectAreaByOutline(area, bit_diameter) file_text += G.G0_Z(safe_Z) return file_text
def tenon(rail, stile, offsets, tenon, mortise_bit_diameter, bit_diameter, safe_Z, cut_per_pass): """ Assumed bit location (center) is at refs origin, at safe_Z, and machine is assumed in ABS mode. It is usual that mortise_bit_diameter == bit_diameter. Requires: rail = (rail_face_width, rail_thickness) stile = (stile_face_width, stile_thickness) offsets = (offset_from_face, offset_from_end) tenon = (length, width, depth) """ # Unpacking the tuples rail_face_width, rail_thickness = rail stile_face_width, stile_thickness = stile offset_from_face, offset_from_end = offsets length, width, depth = tenon bit_radius = bit_diameter / 2.0 corner_radius = mortise_bit_diameter / 2.0 file_text = '' # if debug: # file_text += "; target_depth: " + str(target_depth) + "\n" # file_text += "; stock_thickness: " + str(stock_thickness) + "\n" # file_text += "; cut_per_pass: "******"\n" # file_text += "; bit_diameter: " + str(bit_diameter) + "\n" if (offset_from_face <= bit_diameter) and (offset_from_end <= bit_diameter) and \ (rail_face_width - offset_from_end - length <= bit_diameter) and \ (rail_thickness - offset_from_face - width <= bit_diameter): file_text += G.set_ABS_mode() file_text += G.G0_Z(safe_Z) file_text += G.set_INCR_mode() file_text += G.G0_X(offset_from_end + corner_radius) file_text += G.set_ABS_mode() file_text += G.G0_Z(stile_face_width) # Making target_depth a reference from machine's Z = 0. target_depth = stile_face_width - depth while stile_face_width > target_depth: stile_face_width -= cut_per_pass if stile_face_width < target_depth: stile_face_width = target_depth # Z-axis move by ABSOLUTE coords file_text += G.set_ABS_mode() file_text += G.G1_Z(stile_face_width) file_text += G.set_INCR_mode() file_text += roundedRectangle(length, width, mortise_bit_diameter, bit_diameter, 'inside') else: file_text = 'Not implemented yet' file_text += G.set_ABS_mode() file_text += G.G0_Z(safe_Z) return file_text
def bore_circle_ID(Z_safe, stock_thickness, cut_per_pass, target_depth, cutter_diameter, circle_diameter): """use G2; from specified diameter and thickness; cutter compensation in function. Note that this method mixes ABSOLUTE with INCREMENTAL modes: all moves in XY are in INCR and all moves in Z are ABS.""" assert cutter_diameter <= circle_diameter, "bit is too large for desired hole" assert Z_safe > stock_thickness, "Z_safe is too short for stock thickness" # alternate path: do a straight drill if cutter_diameter == circle_diameter: file_text = G.set_ABS_mode() file_text += G.G0_Z(stock_thickness) file_text += G.G1_Z(target_depth) file_text += G.set_dwell(0.5) file_text += G.G0_Z(Z_safe) return file_text off_set = (circle_diameter - cutter_diameter) / 2.0 file_text = G.set_ABS_mode() file_text += G.G0_Z(Z_safe) # XY-plane move to starting point file_text += G.set_INCR_mode() file_text += G.G0_XY((-off_set, 0)) # Z-axis move to starting point file_text += G.set_ABS_mode() file_text += G.G0_Z(stock_thickness) while stock_thickness > target_depth: stock_thickness -= cut_per_pass if stock_thickness < target_depth: stock_thickness = target_depth # Z-axis move file_text += G.set_ABS_mode() file_text += G.G1_Z(stock_thickness) # XY-plane arc move file_text += G.G2XY_to_INCR_FULL((0, 0), (off_set, 0)) # At end of cut, ensures that the program reaches the very bottom file_text += G.set_dwell(0.5) # Z-axis move # TODO: move this to before the return to origin file_text += G.set_ABS_mode() file_text += G.G0_Z(Z_safe) # Then put the bit back to (0,0) file_text += G.set_INCR_mode() file_text += G.G0_XY((off_set, 0)) return file_text
def polar_holes(Z_safe, stock_thickness, cut_per_pass, target_depth, cutter_diameter, circle_diameter, num_holes, hole_circle_diameter): assert num_holes > 1, "too few holes to form a circle of holes; must be at least 2" hole_circle_radius = hole_circle_diameter / 2.0 file_text = G.set_ABS_mode() file_text += G.G0_Z(Z_safe) radians_increment = 2 * math.pi / num_holes # drill first hole x = math.cos(0) * hole_circle_radius y = math.sin(0) * hole_circle_radius file_text += G.set_INCR_mode() file_text += G.G0_XY((x, y)) file_text += bore_circle_ID(Z_safe, stock_thickness, cut_per_pass, target_depth, cutter_diameter, circle_diameter) # drill all other holes for i in xrange(1, int(num_holes)): x = -(math.cos((i - 1) * radians_increment) * hole_circle_radius) + ( math.cos(i * radians_increment) * hole_circle_radius) y = -(math.sin((i - 1) * radians_increment) * hole_circle_radius) + ( math.sin(i * radians_increment) * hole_circle_radius) file_text += G.set_INCR_mode() file_text += G.G0_XY((x, y)) file_text += bore_circle_ID(Z_safe, stock_thickness, cut_per_pass, target_depth, cutter_diameter, circle_diameter) # return to Z_safe and origin file_text += G.set_ABS_mode() file_text += G.G0_Z(Z_safe) file_text += G.set_INCR_mode() x = -(math.cos((num_holes - 1) * radians_increment) * hole_circle_radius) y = -(math.sin((num_holes - 1) * radians_increment) * hole_circle_radius) file_text += G.G0_XY((x, y)) return file_text
def bore_tabbed_ID(Z_safe, stock_thickness, cut_per_pass, tab_thickness, cutter_diameter, circle_diameter, tab_width): """ Cut three tabs.""" assert tab_thickness <= cut_per_pass, "script not set to handle cut_per_pass when it's less than tab thickness" off_set = (circle_diameter - cutter_diameter) / 2.0 path_length = math.pi * off_set * 2 # NOTE: radius = off_set, path_length is circumference of the circle that the cutter will be tracing assert path_length > 6.0 * ( tab_width + cutter_diameter), "tabs and/or bit are too large for the circle to cut" # gap_radians is the gap (in radians) between the start and stop of each pair of cuts gap_radians = (cutter_diameter + tab_width) / off_set # file_text = "% cutting bore_tabbed_ID \n" file_text = G.set_ABS_mode() file_text += G.G0_Z(Z_safe) # XY-plane move to starting point, creating the first tab # at approximately 180 degrees file_text += G.set_INCR_mode() x = -math.cos(gap_radians) * off_set y = math.sin(gap_radians) * off_set file_text += G.G0_XY((x, y)) file_text += G.set_ABS_mode() # 1 G2 cut after the first tab file_text += G.G1_Z(0) x = (math.cos(gap_radians) + math.cos(math.pi / 3.0)) * off_set y = (-math.sin(gap_radians) + math.sin((2 * math.pi) / 3.0)) * off_set i = math.cos(gap_radians) * off_set j = -math.sin(gap_radians) * off_set file_text += G.G2XY_to_INCR_FULL((x, y), (i, j)) # 2 G2 create the second tab # at approximately 60 degrees file_text += G.G0_Z(tab_thickness) x = (math.cos((math.pi / 3.0) - gap_radians) - math.cos(math.pi / 3.0)) * off_set y = (math.sin((math.pi / 3.0) - gap_radians) - math.sin(math.pi / 3.0)) * off_set i = -math.cos(math.pi / 3.0) * off_set j = -math.sin(math.pi / 3.0) * off_set file_text += G.G2XY_to_INCR_FULL((x, y), (i, j)) # 3 G2 cut after the second tab file_text += G.set_ABS_mode() file_text += G.G1_Z(0) x = 0 y = -2 * math.sin((math.pi / 3.0) - gap_radians) * off_set i = -math.cos((math.pi / 3.0) - gap_radians) * off_set j = -math.sin((math.pi / 3.0) - gap_radians) * off_set file_text += G.G2XY_to_INCR_FULL((x, y), (i, j)) # 4 G2 create the third tab file_text += G.G0_Z(tab_thickness) x = -(math.cos( (math.pi / 3.0) - gap_radians) - math.cos(math.pi / 3.0)) * off_set y = (math.sin((math.pi / 3.0) - gap_radians) - math.sin(math.pi / 3.0)) * off_set i = -math.cos((math.pi / 3.0) - gap_radians) * off_set j = math.sin((math.pi / 3.0) - gap_radians) * off_set file_text += G.G2XY_to_INCR_FULL((x, y), (i, j)) # 5 G2 cut after the third tab file_text += G.set_ABS_mode() file_text += G.G1_Z(0) x = -(1 + math.cos(math.pi / 3.0)) * off_set y = math.sin(math.pi / 3.0) * off_set i = -math.cos(math.pi / 3.0) * off_set j = math.sin(math.pi / 3.0) * off_set file_text += G.G2XY_to_INCR_FULL((x, y), (i, j)) # return to Z_safe and origin file_text += G.set_ABS_mode() file_text += G.G0_Z(Z_safe) file_text += G.set_INCR_mode() file_text += G.G0_XY((off_set, 0)) return file_text