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 rectAreaByOutline(area, bit_diameter, debug=False): """ Required arguments: area (as (x=length, y=width), bit_diameter. Assumes that the bit is already in the origin corner at required depth of cut. This version just cuts progressively smaller rectangles. For fastest progress, orient the largest area dimension with the fastest machine axis. """ length, width = area if bit_diameter > length or bit_diameter > width: raise ValueError("Bit is too large to cut specified area") # magic number 0.5 is the pass-to-pass overlap... not sure that I'll enforce it min_overlap = 0.5 min_passes = min(math.ceil(length / bit_diameter), math.ceil(width / bit_diameter)) min_passes += min_passes % 2 x_overlap = max(min_overlap, (((min_passes * bit_diameter) - length) / (min_passes - 1))) y_overlap = max(min_overlap, (((min_passes * bit_diameter) - width) / (min_passes - 1))) x_step = bit_diameter - x_overlap y_step = bit_diameter - y_overlap file_text = G.set_INCR_mode() current_x = 0 current_y = 0 if debug: file_text += "; length: " + str(length) + "\n" file_text += "; width: " + str(width) + "\n" file_text += "; bit_diameter: " + str(bit_diameter) + "\n" file_text += "; min_passes: " + str(min_passes) + "\n" file_text += "; x_overlap: " + str(x_overlap) + "\n" file_text += "; y_overlap: " + str(y_overlap) + "\n" file_text += "; x_step: " + str(x_step) + "\n" file_text += "; y_step: " + str(y_step) + "\n" file_text += _rectOutline(length, width, bit_diameter) min_passes -= 2 while min_passes > 0: file_text += G.G1_XY((x_step, y_step)) current_x += x_step current_y += y_step length -= (2 * x_step) width -= (2 * y_step) file_text += _rectOutline(length, width, bit_diameter) min_passes -= 2 file_text += G.G0_XY((-current_x, -current_y)) file_text += G.set_ABS_mode() 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