def _get_sorted_polygons(models, callback=None): # Sort the polygons according to their directions (first inside, then # outside. This reduces the problem of break-away pieces. inner_polys = [] outer_polys = [] for model in models: for poly in model.get_polygons(): if poly.get_area() <= 0: inner_polys.append(poly) else: outer_polys.append(poly) inner_sorter = PolygonSorter(inner_polys, callback=callback) outer_sorter = PolygonSorter(outer_polys, callback=callback) return inner_sorter.get_polygons() + outer_sorter.get_polygons()
def GenerateToolPath(self, minz, maxz, horiz_step, dz, draw_callback=None): quit_requested = False # calculate the number of steps num_of_layers = 1 + ceil(abs(maxz - minz) / dz) if num_of_layers > 1: z_step = abs(maxz - minz) / (num_of_layers - 1) z_steps = [(maxz - i * z_step) for i in range(num_of_layers)] # The top layer is treated as the current surface - thus it does not # require engraving. z_steps = z_steps[1:] else: z_steps = [minz] num_of_layers = len(z_steps) current_layer = 0 num_of_lines = self.contour_model.get_num_of_lines() progress_counter = ProgressCounter(len(z_steps) * num_of_lines, draw_callback) if draw_callback: draw_callback(text="Engrave: optimizing polygon order") # Sort the polygons according to their directions (first inside, then # outside. This reduces the problem of break-away pieces. inner_polys = [] outer_polys = [] for poly in self.contour_model.get_polygons(): if poly.get_area() <= 0: inner_polys.append(poly) else: outer_polys.append(poly) inner_sorter = PolygonSorter(inner_polys, callback=draw_callback) outer_sorter = PolygonSorter(outer_polys, callback=draw_callback) line_groups = inner_sorter.get_polygons() + outer_sorter.get_polygons() if self.clockwise: for line_group in line_groups: line_group.reverse_direction() # push slices for all layers above ground if maxz == minz: # only one layer - use PushCutter instead of DropCutter # put "last_z" clearly above the model plane last_z = maxz + 1 push_steps = z_steps drop_steps = [] else: # multiple layers last_z = maxz push_steps = z_steps[:-1] drop_steps = [z_steps[-1]] for z in push_steps: # update the progress bar and check, if we should cancel the process if draw_callback and draw_callback( text="Engrave: processing" + " layer %d/%d" % (current_layer + 1, num_of_layers) ): # cancel immediately break for line_group in line_groups: for line in line_group.get_lines(): self.GenerateToolPathLinePush(self.pa_push, line, z, last_z, draw_callback=draw_callback) if progress_counter.increment(): # cancel requested quit_requested = True # finish the current path self.pa_push.finish() break self.pa_push.finish() # break the outer loop if requested if quit_requested: break current_layer += 1 last_z = z if quit_requested: return self.pa_push.paths for z in drop_steps: if draw_callback: draw_callback(text="Engrave: processing layer %d/%d" % (current_layer + 1, num_of_layers)) # process the final layer with a drop cutter for line_group in line_groups: self.pa_drop.new_direction(0) self.pa_drop.new_scanline() for line in line_group.get_lines(): self.GenerateToolPathLineDrop( self.pa_drop, line, z, maxz, horiz_step, last_z, draw_callback=draw_callback ) if progress_counter.increment(): # quit requested quit_requested = True break self.pa_drop.end_scanline() self.pa_drop.end_direction() # break the outer loop if requested if quit_requested: break current_layer += 1 last_z = z self.pa_drop.finish() return self.pa_push.paths + self.pa_drop.paths
def GenerateToolPath(self, minz, maxz, horiz_step, dz, draw_callback=None): quit_requested = False # calculate the number of steps num_of_layers = 1 + ceil(abs(maxz - minz) / dz) if num_of_layers > 1: z_step = abs(maxz - minz) / (num_of_layers - 1) z_steps = [(maxz - i * z_step) for i in range(num_of_layers)] # The top layer is treated as the current surface - thus it does not # require engraving. z_steps = z_steps[1:] else: z_steps = [minz] num_of_layers = len(z_steps) current_layer = 0 num_of_lines = self.contour_model.get_num_of_lines() progress_counter = ProgressCounter(len(z_steps) * num_of_lines, draw_callback) if draw_callback: draw_callback(text="Engrave: optimizing polygon order") # Sort the polygons according to their directions (first inside, then # outside. This reduces the problem of break-away pieces. inner_polys = [] outer_polys = [] for poly in self.contour_model.get_polygons(): if poly.get_area() <= 0: inner_polys.append(poly) else: outer_polys.append(poly) inner_sorter = PolygonSorter(inner_polys, callback=draw_callback) outer_sorter = PolygonSorter(outer_polys, callback=draw_callback) line_groups = inner_sorter.get_polygons() + outer_sorter.get_polygons() if self.clockwise: for line_group in line_groups: line_group.reverse_direction() # push slices for all layers above ground if maxz == minz: # only one layer - use PushCutter instead of DropCutter # put "last_z" clearly above the model plane last_z = maxz + 1 push_steps = z_steps drop_steps = [] else: # multiple layers last_z = maxz push_steps = z_steps[:-1] drop_steps = [z_steps[-1]] for z in push_steps: # update the progress bar and check, if we should cancel the process if draw_callback and draw_callback(text="Engrave: processing" \ + " layer %d/%d" % (current_layer + 1, num_of_layers)): # cancel immediately break for line_group in line_groups: for line in line_group.get_lines(): self.GenerateToolPathLinePush(self.pa_push, line, z, last_z, draw_callback=draw_callback) if progress_counter.increment(): # cancel requested quit_requested = True # finish the current path self.pa_push.finish() break self.pa_push.finish() # break the outer loop if requested if quit_requested: break current_layer += 1 last_z = z if quit_requested: return self.pa_push.paths for z in drop_steps: if draw_callback: draw_callback(text="Engrave: processing layer %d/%d" \ % (current_layer + 1, num_of_layers)) # process the final layer with a drop cutter for line_group in line_groups: self.pa_drop.new_direction(0) self.pa_drop.new_scanline() for line in line_group.get_lines(): self.GenerateToolPathLineDrop(self.pa_drop, line, z, maxz, horiz_step, last_z, draw_callback=draw_callback) if progress_counter.increment(): # quit requested quit_requested = True break self.pa_drop.end_scanline() self.pa_drop.end_direction() # break the outer loop if requested if quit_requested: break current_layer += 1 last_z = z self.pa_drop.finish() return self.pa_push.paths + self.pa_drop.paths