Source code for pyrobopath.toolpath.preprocessing

from __future__ import annotations
from typing import List, Dict
from abc import ABC, abstractmethod
import numpy as np

from pyrobopath.tools.types import *
from pyrobopath.tools.geometry import segment_path
from .toolpath_core import Toolpath, Contour, split_by_layers
from .path import Rotation, Transform


[docs] class ToolpathPreprocessor: """ A container for a sequence of toolpath preprocessing steps. Methods ------- process(toolpath): Applies all registered preprocessing steps to the given toolpath. add_step(step): Adds a preprocessing step to the pipeline. """ def __init__(self): self.steps: List[PreprocessingStep] = [] def process(self, toolpath: Toolpath) -> Toolpath: for step in self.steps: toolpath = step.apply(toolpath) return toolpath def add_step(self, step: PreprocessingStep): self.steps.append(step)
[docs] class PreprocessingStep(ABC): """ Abstract base class for toolpath preprocessing steps. """
[docs] @abstractmethod def apply(self, toolpath: Toolpath) -> Toolpath: """ Apply the preprocessing step to the given toolpath. Parameters ---------- toolpath : Toolpath The toolpath to process. Returns ------- Toolpath The processed toolpath. """ pass
[docs] class ScalingStep(PreprocessingStep): """ A preprocessing step that uniformly scales all path points. Parameters ---------- scale : float The uniform scale factor to apply to each point. """ def __init__(self, scale: float): self._scale = scale
[docs] def apply(self, toolpath: Toolpath) -> Toolpath: for c in toolpath.contours: for p in c.path: p *= self._scale return toolpath
[docs] class TranslateStep(PreprocessingStep): """ A preprocessing step that translates all path points. Parameters ---------- trans : ArrayLike3 The translation vector to add to each point. """ def __init__(self, trans: ArrayLike3): self._trans = np.array(trans)
[docs] def apply(self, toolpath: Toolpath) -> Toolpath: for c in toolpath.contours: c.path = list(c.path + self._trans) return toolpath
[docs] class RotateStep(PreprocessingStep): """ A preprocessing step that rotates all path points. Parameters ---------- rot : Rotation The rotation to apply to each point. """ def __init__(self, rot: Rotation): self._rot = rot
[docs] def apply(self, toolpath: Toolpath) -> Toolpath: for c in toolpath.contours: c.path = [self._rot * p for p in c.path] return toolpath
[docs] class TranformStep(PreprocessingStep): """ A preprocessing step that applies a general transform to all path points. Parameters ---------- trans : Transform The transformation to apply to each point. """ def __init__(self, trans: Transform): self._trans = trans
[docs] def apply(self, toolpath: Toolpath) -> Toolpath: for c in toolpath.contours: c.path = [self._trans * p for p in c.path] return toolpath
[docs] class SubstituteToolStep(PreprocessingStep): """ A preprocessing step that replaces tool types in contours using a mapping. Parameters ---------- tool_map : dict A dictionary mapping existing tool names to new tool names. """ def __init__(self, tool_map: Dict): self._tool_map = tool_map
[docs] def apply(self, toolpath: Toolpath) -> Toolpath: for c in toolpath.contours: if c.tool in self._tool_map: c.tool = self._tool_map[c.tool] return toolpath
[docs] class MaxContourLengthStep(PreprocessingStep): """ A preprocessing step that splits contours into smaller segments if their total length exceeds a specified maximum. Parameters ---------- length : float The maximum allowed length for any single contour. """ def __init__(self, length: float): self._length = length
[docs] def apply(self, toolpath: Toolpath) -> Toolpath: contours = [] for c in toolpath.contours: seg_paths = segment_path(c.path, self._length) for p in seg_paths: contours.append(Contour(p, tool=c.tool)) toolpath.contours = contours return toolpath
[docs] class ShuffleStep(PreprocessingStep): """ Reorders contours in a toolpath to interleave by tool as much as possible. """
[docs] def apply(self, toolpath: Toolpath) -> Toolpath: contours = [] unique_tools = toolpath.tools() while unique_tools: for tool in unique_tools: found = False for i, c in enumerate(toolpath.contours): if c.tool == tool: contours.append(toolpath.contours.pop(i)) found = True break if not found: unique_tools.remove(tool) toolpath.contours = contours return toolpath
[docs] class LayerRangeStep(PreprocessingStep): """ Selects a range of layers from a toolpath based on Z-height slicing. Parameters ---------- start : int The starting layer index (inclusive) to include in the result. stop : int The stopping layer index (exclusive). step : int, optional The step size for slicing. Defaults to 1. """ def __init__(self, start: int, stop: int, step: int = 1): self.start = start self.stop = stop self.step = step
[docs] def apply(self, toolpath: Toolpath) -> Toolpath: layers = split_by_layers(toolpath) toolpath.contours = Toolpath.combine( layers[self.start : self.stop : self.step] ).contours return toolpath