Exemplo n.º 1
0
 def get_potential_contour_lines(self, cutter, model, minx, maxx, miny, maxy, z,
         progress_counter=None):
     # use only the first model for the contour
     follow_model = model
     waterline_triangles = CollisionPaths()
     triangles = follow_model.triangles(minx=minx, miny=miny, maxx=maxx,
             maxy=maxy)
     args = [(follow_model, cutter, self._up_vector, t, z)
             for t in triangles if not id(t) in self._processed_triangles]
     results_iter = run_in_parallel(_process_one_triangle, args,
             unordered=True, callback=progress_counter.update)
     for result, ignore_triangle_id_list in results_iter:
         if ignore_triangle_id_list:
             self._processed_triangles.extend(ignore_triangle_id_list)
         for edge, shifted_edge in result:
             waterline_triangles.add(edge, shifted_edge)
         if (not progress_counter is None) \
                 and (progress_counter.increment()):
             # quit requested
             break
     if not _DEBUG_DISABLE_EXTEND_LINES:
         waterline_triangles.extend_shifted_lines()
     result = []
     for line in waterline_triangles.get_shifted_lines():
         cropped_line = line.get_cropped_line(minx, maxx, miny, maxy, z, z)
         if not cropped_line is None:
             result.append(cropped_line)
     return result
Exemplo n.º 2
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
Exemplo n.º 3
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
Exemplo n.º 4
0
    def GenerateToolPathSlice(self, cutter, models, layer_grid, draw_callback=None,
            progress_counter=None):
        path = []

        # settings for calculation of depth
        accuracy = 20
        max_depth = 20
        min_depth = 4

        # the ContourCutter pathprocessor does not work with combined models
        if self.waterlines:
            models = models[:1]
        else:
            models = models

        args = []
        for line in layer_grid:
            p1, p2 = line
            # calculate the required calculation depth (recursion)
            distance = pdist(p2, p1)
            # TODO: accessing cutter.radius here is slightly ugly
            depth = math.log(accuracy * distance / cutter.radius) / math.log(2)
            depth = min(max(ceil(depth), 4), max_depth)
            args.append((p1, p2, depth, models, cutter, self.physics))

        for points in run_in_parallel(_process_one_line, args,
                callback=progress_counter.update):
            if points:
                if self.waterlines:
                    self.pa.new_scanline()
                    for point in points:
                        self.pa.append(point)
                else:
                    for index in range(len(points) / 2):
                        path.append((MOVE_STRAIGHT, points[2 * index]))
                        path.append((MOVE_STRAIGHT, points[2 * index + 1]))
                        path.append((MOVE_SAFETY, None))
                if self.waterlines:
                    if draw_callback:
                        draw_callback(tool_position=points[-1])
                    self.pa.end_scanline()
                else:
                    if draw_callback:
                        draw_callback(tool_position=points[-1], toolpath=path)
            # update the progress counter
            if progress_counter and progress_counter.increment():
                # quit requested
                break

        if not self.waterlines:
            return path
Exemplo n.º 5
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
Exemplo n.º 6
0
    def generate_toolpath_slice(self,
                                cutter,
                                models,
                                layer_grid,
                                draw_callback=None,
                                progress_counter=None):
        path = []
        # the ContourCutter pathprocessor does not work with combined models
        if self.waterlines:
            models = models[:1]
        else:
            models = models
        args = []
        for line in layer_grid:
            p1, p2 = line
            args.append((p1, p2, models, cutter))
        for points in run_in_parallel(_process_one_line,
                                      args,
                                      callback=progress_counter.update):
            if points:
                if self.waterlines:
                    self.pa.new_scanline()
                    for point in points:
                        self.pa.append(point)
                else:
                    for index in range(len(points) // 2):
                        path.append(MoveStraight(points[2 * index]))
                        path.append(MoveStraight(points[2 * index + 1]))
                        path.append(MoveSafety())
                if self.waterlines:
                    if draw_callback:
                        draw_callback(tool_position=points[-1])
                    self.pa.end_scanline()
                else:
                    if draw_callback:
                        draw_callback(tool_position=points[-1], toolpath=path)
            # update the progress counter
            if progress_counter and progress_counter.increment():
                # quit requested
                break

        if not self.waterlines:
            return path
Exemplo n.º 7
0
    def GenerateToolPathSlice(self,
                              layer_grid,
                              draw_callback=None,
                              progress_counter=None):
        """ only dx or (exclusive!) dy may be bigger than zero
        """
        # max_deviation_x = dx/accuracy
        accuracy = 20
        max_depth = 20

        # calculate the required number of steps in each direction
        distance = layer_grid[0][-1].sub(layer_grid[0][0]).norm
        step_width = distance / len(layer_grid[0])
        depth = math.log(accuracy * distance / step_width) / math.log(2)
        depth = max(ceil(depth), 4)
        depth = min(depth, max_depth)

        # the ContourCutter pathprocessor does not work with combined models
        if self._use_polygon_extractor:
            models = self.models[:1]
        else:
            models = self.models

        args = []
        for line in layer_grid:
            p1, p2 = line
            args.append((p1, p2, depth, models, self.cutter, self.physics))

        for points in run_in_parallel(_process_one_line,
                                      args,
                                      callback=progress_counter.update):
            if points:
                self.pa.new_scanline()
                for point in points:
                    self.pa.append(point)
                if draw_callback:
                    draw_callback(tool_position=points[-1],
                                  toolpath=self.pa.paths)
                self.pa.end_scanline()
            # update the progress counter
            if progress_counter and progress_counter.increment():
                # quit requested
                break
Exemplo n.º 8
0
    def GenerateToolPathSlice(self,
                              cutter,
                              models,
                              layer_grid,
                              draw_callback=None,
                              progress_counter=None):
        # settings for calculation of depth
        accuracy = 20
        max_depth = 20
        min_depth = 4

        # the ContourCutter pathprocessor does not work with combined models
        if self._use_polygon_extractor:
            models = models[:1]
        else:
            models = models

        args = []
        for line in layer_grid:
            p1, p2 = line
            # calculate the required calculation depth (recursion)
            distance = p2.sub(p1).norm
            # TODO: accessing cutter.radius here is slightly ugly
            depth = math.log(accuracy * distance / cutter.radius) / math.log(2)
            depth = min(max(ceil(depth), 4), max_depth)
            args.append((p1, p2, depth, models, cutter, self.physics))

        for points in run_in_parallel(_process_one_line,
                                      args,
                                      callback=progress_counter.update):
            if points:
                self.pa.new_scanline()
                for point in points:
                    self.pa.append(point)
                if draw_callback:
                    draw_callback(tool_position=points[-1],
                                  toolpath=self.pa.paths)
                self.pa.end_scanline()
            # update the progress counter
            if progress_counter and progress_counter.increment():
                # quit requested
                break
Exemplo n.º 9
0
    def GenerateToolPathSlice(self, layer_grid, draw_callback=None,
            progress_counter=None):
        """ only dx or (exclusive!) dy may be bigger than zero
        """
        # max_deviation_x = dx/accuracy
        accuracy = 20
        max_depth = 20

        # calculate the required number of steps in each direction
        distance = layer_grid[0][-1].sub(layer_grid[0][0]).norm
        step_width = distance / len(layer_grid[0])
        depth = math.log(accuracy * distance / step_width) / math.log(2)
        depth = max(ceil(depth), 4)
        depth = min(depth, max_depth)

        # the ContourCutter pathprocessor does not work with combined models
        if self._use_polygon_extractor:
            models = self.models[:1]
        else:
            models = self.models

        args = []
        for line in layer_grid:
            p1, p2 = line
            args.append((p1, p2, depth, models, self.cutter, self.physics))

        for points in run_in_parallel(_process_one_line, args,
                callback=progress_counter.update):
            if points:
                self.pa.new_scanline()
                for point in points:
                    self.pa.append(point)
                if draw_callback:
                    draw_callback(tool_position=points[-1], toolpath=self.pa.paths)
                self.pa.end_scanline()
            # update the progress counter
            if progress_counter and progress_counter.increment():
                # quit requested
                break
Exemplo n.º 10
0
    def GenerateToolPathSlice(self, cutter, models, layer_grid, draw_callback=None,
            progress_counter=None):
        # settings for calculation of depth
        accuracy = 20
        max_depth = 20
        min_depth = 4

        # the ContourCutter pathprocessor does not work with combined models
        if self._use_polygon_extractor:
            models = models[:1]
        else:
            models = models

        args = []
        for line in layer_grid:
            p1, p2 = line
            # calculate the required calculation depth (recursion)
            distance = p2.sub(p1).norm
            # TODO: accessing cutter.radius here is slightly ugly
            depth = math.log(accuracy * distance / cutter.radius) / math.log(2)
            depth = min(max(ceil(depth), 4), max_depth)
            args.append((p1, p2, depth, models, cutter, self.physics))

        for points in run_in_parallel(_process_one_line, args,
                callback=progress_counter.update):
            if points:
                self.pa.new_scanline()
                for point in points:
                    self.pa.append(point)
                if draw_callback:
                    draw_callback(tool_position=points[-1], toolpath=self.pa.paths)
                self.pa.end_scanline()
            # update the progress counter
            if progress_counter and progress_counter.increment():
                # quit requested
                break