def contour(self, bit_diameter, count=1, overlap=0.5): """ @brief Finds a set of isolines on a distance field image. @param bit_diameter Tool diameter (in mm) @param count Number of offsets @param overlap Overlap between offsets @returns A list of Paths """ if self.depth != 'f' or self.channels != 1: raise ValueError('Invalid image type for contour cut '+ '(requires floating-point, 1-channel image)') max_distance = max(self.array.flatten()) levels = [bit_diameter/2] step = bit_diameter * overlap if count == -1: while levels[-1] < max_distance: levels.append(levels[-1] + step) levels[-1] = max_distance else: for i in range(count-1): levels.append(levels[-1] + step) levels = (ctypes.c_float*len(levels))(*levels) ptr = ctypes.POINTER(ctypes.POINTER(Path_))() path_count = libfab.find_paths( self.width, self.height, self.pixels, 1./self.pixels_per_mm, len(levels), levels, ptr) paths = [Path.from_ptr(ptr[i]) for i in range(path_count)] libfab.free_paths(ptr, path_count) return Path.sort(paths)
def run(self, paths): """ @brief Convert the path from the previous panel into a shopbot file. @param paths List of Paths """ koko.FRAME.status = 'Converting to .sbp file' values = self.get_values() if not values: return False # Reverse direction for climb cutting if values['type']: paths = Path.sort([p.reverse() for p in paths]) # Check to see if all of the z values are the same. If so, # we can use 2D cutting commands; if not, we'll need # to do full three-axis motion control zmin = paths[0].points[0][2] flat = True for p in paths: if not all(pt[2] == zmin for pt in p.points): flat = False ## @var file # tempfile.NamedTemporaryFile to store OpenSBP commands self.file = tempfile.NamedTemporaryFile(suffix=self.extension) self.file.write("SA\r\n") # plot absolute self.file.write("TR,%s,1,\r\n" % values['spindle']) # spindle speed self.file.write("SO,1,1\r\n") # set output number 1 to on self.file.write("pause,2,\r\n") # pause for spindle to spin up scale = 1 if values['units'] else 1/25.4 # mm vs inch units # Cut and jog speeds self.file.write("MS,%f,%f\r\n" % (values['cut_speed']*scale, values['cut_speed']*scale)) self.file.write("JS,%f,%f\r\n" % (values['jog_speed']*scale, values['jog_speed']*scale)) self.file.write("JZ,%f\r\n" % (values['jog']*scale)) # Move up xy = lambda x,y: (scale*x, scale*y) xyz = lambda x,y,z: (scale*x, scale*y, scale*z) for p in paths: # Move to the start of this path with the pen up self.file.write("J2,%f,%f\r\n" % xy(*p.points[0][0:2])) if flat: self.file.write("MZ,%f\r\n" % (zmin*scale)) else: self.file.write("M3,%f,%f,%f\r\n" % xyz(*p.points[0])) # Cut each point in the segment for pt in p.points: if flat: self.file.write("M2,%f,%f\r\n" % xy(*pt[0:2])) else: self.file.write("M3,%f,%f,%f\r\n" % xyz(*pt)) # Lift then pen up at the end of the segment self.file.write("MZ,%f\r\n" % (values['jog']*scale)) self.file.flush() koko.FRAME.status = '' return True
def run(self, paths): ''' Convert the path from the previous panel into a g-code file ''' koko.FRAME.status = 'Converting to .g file' values = self.get_values() if not values: return False # Reverse direction for climb cutting if values['type']: paths = Path.sort([p.reverse() for p in paths]) # Check to see if all of the z values are the same. If so, # we can use 2D cutting commands; if not, we'll need # to do full three-axis motion control zmin = paths[0].points[0][2] flat = True for p in paths: if not all(pt[2] == zmin for pt in p.points): flat = False # Create a temporary file to store the .sbp instructions self.file = tempfile.NamedTemporaryFile(suffix=self.extension) self.file.write("%%\n") # tape start self.file.write("G17\n") # XY plane self.file.write("G20\n") # Inch mode self.file.write("G40\n") # Cancel tool diameter compensation self.file.write("G49\n") # Cancel tool length offset self.file.write("G54\n") # Coordinate system 1 self.file.write("G80\n") # Cancel motion self.file.write("G90\n") # Absolute programming self.file.write("G94\n") # Feedrate is per minute scale = 1 / 25.4 # inch units self.file.write("T%dM06\n" % values['tool']) # Tool selection + change self.file.write("F%0.4f\n" % (60 * scale * values['feed'])) # Feed rate self.file.write("S%0.4f\n" % values['spindle']) # spindle speed if values['coolant']: self.file.write("M08\n") # coolant on # Move up before starting spindle self.file.write("G00Z%0.4f\n" % (scale * values['jog'])) self.file.write("M03\n") # spindle on (clockwise) self.file.write("G04 P1\n") # pause one second to spin up spindle xy = lambda x, y: (scale * x, scale * y) xyz = lambda x, y, z: (scale * x, scale * y, scale * z) for p in paths: # Move to the start of this path at the jog height self.file.write("G00X%0.4fY%0.4fZ%0.4f\n" % xyz(p.points[0][0], p.points[0][1], values['jog'])) # Plunge to the desired depth self.file.write( "G01Z%0.4f F%0.4f\n" % (p.points[0][2] * scale, 60 * scale * values['plunge'])) # Restore XY feed rate self.file.write("F%0.4f\n" % (60 * scale * values['feed'])) # Cut each point in the segment for pt in p.points: if flat: self.file.write("X%0.4fY%0.4f\n" % xy(*pt[0:2])) else: self.file.write("X%0.4fY%0.4fZ%0.4f\n" % xyz(*pt)) # Lift the bit up to the jog height at the end of the segment self.file.write("Z%0.4f\n" % (scale * values['jog'])) self.file.write("M05\n") # spindle stop if values['coolant']: self.file.write("M09\n") # coolant off self.file.write("M30\n") # program end and reset self.file.write("%%\n") # tape end self.file.flush() koko.FRAME.status = '' return True
def run(self, paths): ''' Convert the path from the previous panel into a g-code file ''' koko.FRAME.status = 'Converting to .g file' values = self.get_values() if not values: return False # Reverse direction for climb cutting if values['type']: paths = Path.sort([p.reverse() for p in paths]) # Check to see if all of the z values are the same. If so, # we can use 2D cutting commands; if not, we'll need # to do full three-axis motion control zmin = paths[0].points[0][2] flat = True for p in paths: if not all(pt[2] == zmin for pt in p.points): flat = False # Create a temporary file to store the .sbp instructions self.file = tempfile.NamedTemporaryFile(suffix=self.extension) self.file.write("%%\n") # tape start self.file.write("G17\n") # XY plane self.file.write("G20\n") # Inch mode self.file.write("G40\n") # Cancel tool diameter compensation self.file.write("G49\n") # Cancel tool length offset self.file.write("G54\n") # Coordinate system 1 self.file.write("G80\n") # Cancel motion self.file.write("G90\n") # Absolute programming self.file.write("G94\n") # Feedrate is per minute scale = 1/25.4 # inch units self.file.write("T%dM06\n" % values['tool']) # Tool selection + change self.file.write("F%0.4f\n" % (60*scale*values['feed'])) # Feed rate self.file.write("S%0.4f\n" % values['spindle']) # spindle speed if values['coolant']: self.file.write("M08\n") # coolant on # Move up before starting spindle self.file.write("G00Z%0.4f\n" % (scale*values['jog'])) self.file.write("M03\n") # spindle on (clockwise) self.file.write("G04 P1\n") # pause one second to spin up spindle xy = lambda x,y: (scale*x, scale*y) xyz = lambda x,y,z: (scale*x, scale*y, scale*z) for p in paths: # Move to the start of this path at the jog height self.file.write("G00X%0.4fY%0.4fZ%0.4f\n" % xyz(p.points[0][0], p.points[0][1], values['jog'])) # Plunge to the desired depth self.file.write("G01Z%0.4f F%0.4f\n" % (p.points[0][2]*scale, 60*scale*values['plunge'])) # Restore XY feed rate self.file.write("F%0.4f\n" % (60*scale*values['feed'])) # Cut each point in the segment for pt in p.points: if flat: self.file.write("X%0.4fY%0.4f\n" % xy(*pt[0:2])) else: self.file.write("X%0.4fY%0.4fZ%0.4f\n" % xyz(*pt)) # Lift the bit up to the jog height at the end of the segment self.file.write("Z%0.4f\n" % (scale*values['jog'])) self.file.write("M05\n") # spindle stop if values['coolant']: self.file.write("M09\n") # coolant off self.file.write("M30\n") # program end and reset self.file.write("%%\n") # tape end self.file.flush() koko.FRAME.status = '' return True