Ejemplo n.º 1
0
    def generate_toolpath(self,
                          cutter,
                          models,
                          motion_grid,
                          minz=None,
                          maxz=None,
                          draw_callback=None):
        path = []
        quit_requested = False
        model = pycam.Geometry.Model.get_combined_model(models)

        # Transfer the grid (a generator) into a list of lists and count the
        # items.
        lines = []
        # usually there is only one layer - but an xy-grid consists of two
        for layer in motion_grid:
            for line in layer:
                lines.append(line)

        num_of_lines = len(lines)
        progress_counter = ProgressCounter(len(lines), draw_callback)
        current_line = 0

        args = []
        for one_grid_line in lines:
            # simplify the data (useful for remote processing)
            xy_coords = [(pos[0], pos[1]) for pos in one_grid_line]
            args.append((xy_coords, minz, maxz, model, cutter))
        for points in run_in_parallel(_process_one_grid_line,
                                      args,
                                      callback=progress_counter.update):
            if draw_callback and draw_callback(
                    text="DropCutter: processing line %d/%d" %
                (current_line + 1, num_of_lines)):
                # cancel requested
                quit_requested = True
                break
            for point in points:
                if point is None:
                    # exceeded maxz - the cutter has to skip this point
                    path.append(MoveSafety())
                else:
                    path.append(MoveStraight(point))
                # The progress counter may return True, if cancel was requested.
                if draw_callback and draw_callback(tool_position=point,
                                                   toolpath=path):
                    quit_requested = True
                    break
            # add a move to safety height after each line of moves
            path.append(MoveSafety())
            progress_counter.increment()
            # update progress
            current_line += 1
            if quit_requested:
                break
        return path
Ejemplo n.º 2
0
    def GenerateToolPath(self, cutter, models, motion_grid, minz=None, maxz=None, draw_callback=None):
        quit_requested = False
        model = pycam.Geometry.Model.get_combined_model(models)

        # Transfer the grid (a generator) into a list of lists and count the
        # items.
        lines = []
        # usually there is only one layer - but an xy-grid consists of two
        for layer in motion_grid:
            for line in layer:
                lines.append(line)

        num_of_lines = len(lines)
        progress_counter = ProgressCounter(len(lines), draw_callback)
        current_line = 0

        self.pa.new_direction(0)

        args = []
        for one_grid_line in lines:
            # simplify the data (useful for remote processing)
            xy_coords = [(pos.x, pos.y) for pos in one_grid_line]
            args.append((xy_coords, minz, maxz, model, cutter,
                    self.physics))
        for points in run_in_parallel(_process_one_grid_line, args,
                callback=progress_counter.update):
            self.pa.new_scanline()
            if draw_callback and draw_callback(text="DropCutter: processing " \
                        + "line %d/%d" % (current_line + 1, num_of_lines)):
                # cancel requested
                quit_requested = True
                break
            for point in points:
                if point is None:
                    # exceeded maxz - the cutter has to skip this point
                    self.pa.end_scanline()
                    self.pa.new_scanline()
                    continue
                self.pa.append(point)
                # "draw_callback" returns true, if the user requested to quit
                # via the GUI.
                # The progress counter may return True, if cancel was requested.
                if draw_callback and draw_callback(tool_position=point,
                        toolpath=self.pa.paths):
                    quit_requested = True
                    break
            progress_counter.increment()
            self.pa.end_scanline()
            # update progress
            current_line += 1
            if quit_requested:
                break
        self.pa.end_direction()
        self.pa.finish()
        return self.pa.paths
Ejemplo n.º 3
0
    def GenerateToolPath(self, cutter, models, motion_grid, minz=None, maxz=None, draw_callback=None):
        path = []
        quit_requested = False
        model = pycam.Geometry.Model.get_combined_model(models)

        # Transfer the grid (a generator) into a list of lists and count the
        # items.
        lines = []
        # usually there is only one layer - but an xy-grid consists of two
        for layer in motion_grid:
            for line in layer:
                lines.append(line)

        num_of_lines = len(lines)
        progress_counter = ProgressCounter(len(lines), draw_callback)
        current_line = 0


        args = []
        for one_grid_line in lines:
            # simplify the data (useful for remote processing)
            xy_coords = [(pos[0], pos[1]) for pos in one_grid_line]
            args.append((xy_coords, minz, maxz, model, cutter,
                    self.physics))
        for points in run_in_parallel(_process_one_grid_line, args,
                callback=progress_counter.update):
            if draw_callback and draw_callback(text="DropCutter: processing " \
                        + "line %d/%d" % (current_line + 1, num_of_lines)):
                # cancel requested
                quit_requested = True
                break
            for point in points:
                if point is None:
                    # exceeded maxz - the cutter has to skip this point
                    path.append((MOVE_SAFETY, None))
                else:
                    path.append((MOVE_STRAIGHT, point))
                # The progress counter may return True, if cancel was requested.
                if draw_callback and draw_callback(tool_position=point,
                        toolpath=path):
                    quit_requested = True
                    break
            # add a move to safety height after each line of moves
            path.append((MOVE_SAFETY, None))
            progress_counter.increment()
            # update progress
            current_line += 1
            if quit_requested:
                break
        return path
Ejemplo n.º 4
0
    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
Ejemplo n.º 5
0
    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