Commit 0218146c authored by sumpfralle's avatar sumpfralle

added support for EngraveCutter to the toolpath generator


git-svn-id: https://pycam.svn.sourceforge.net/svnroot/pycam/trunk@368 bbaffbd6-741e-11dd-a85d-61de82d9cad9
parent f12dc1a3
......@@ -20,37 +20,39 @@ You should have received a copy of the GNU General Public License
along with PyCAM. If not, see <http://www.gnu.org/licenses/>.
"""
from pycam.PathGenerators import DropCutter, PushCutter
from pycam.PathGenerators import DropCutter, PushCutter, EngraveCutter
import pycam.PathProcessors
import pycam.Cutters
import pycam.Toolpath.SupportGrid
import pycam.Geometry.Model
import sys
DIRECTIONS = frozenset(("x", "y", "xy"))
PATH_GENERATORS = frozenset(("DropCutter", "PushCutter"))
PATH_GENERATORS = frozenset(("DropCutter", "PushCutter", "EngraveCutter"))
PATH_POSTPROCESSORS = frozenset(("ContourCutter", "PathAccumulator", "PolygonCutter", "SimpleCutter", "ZigZagCutter"))
CALCULATION_BACKENDS = frozenset((None, "ODE"))
def generate_toolpath(model, tool_settings=None, bounds=None, direction="x",
path_generator="DropCutter", path_postprocessor="ZigZagCutter",
material_allowance=0.0, safety_height=None, overlap=0.0, step_down=0.0,
def generate_toolpath(model, tool_settings=None,
bounds=None, direction="x", path_generator="DropCutter",
path_postprocessor="ZigZagCutter", material_allowance=0.0,
safety_height=None, overlap=0.0, step_down=0.0,
support_grid_distance=None, support_grid_thickness=None,
calculation_backend=None, callback=None):
""" abstract interface for generating a toolpath
@type model: pycam.Geometry.Model.Model
@value model: a model contains the surface triangles
@type direction: str
@value direction: any member of the DIRECTIONS set (e.g. "x", "y" or "xy")
@type bounds: tuple(float) | list(float)
@value bounds: the processing boundary (relative to the center of the tool)
(order: minx, maxx, miny, maxy, minz, maxz)
@value model: a model contains surface triangles or a contour
@type tool_settings: dict
@value tool_settings: contains at least the following keys (depending on
the tool type):
"shape": any of possible cutter shape (see "pycam.Cutters")
"radius": main radius of the tools
"torus_radius": (only for ToroidalCutter) second toroidal radius
@type bounds: tuple(float) | list(float)
@value bounds: the processing boundary (relative to the center of the tool)
(order: minx, maxx, miny, maxy, minz, maxz)
@type direction: str
@value direction: any member of the DIRECTIONS set (e.g. "x", "y" or "xy")
@type path_generator: str
@value path_generator: any member of the PATH_GENERATORS set
@type path_postprocessor: str
......@@ -79,6 +81,13 @@ def generate_toolpath(model, tool_settings=None, bounds=None, direction="x",
minz, maxz = model.minz, model.maxz
else:
minx, maxx, miny, maxy, minz, maxz = bounds
# trimesh model or contour model?
if isinstance(model, pycam.Geometry.Model.Model):
trimesh_model = model
contour_model = None
else:
trimesh_model = pycam.Geometry.Model.Model()
contour_model = model
# create the grid model if requested
if (not support_grid_distance is None) \
and (not support_grid_thickness is None):
......@@ -89,7 +98,7 @@ def generate_toolpath(model, tool_settings=None, bounds=None, direction="x",
support_grid_model = pycam.Toolpath.SupportGrid.get_support_grid(
minx, maxx, miny, maxy, minz, support_grid_distance,
support_grid_distance, support_grid_thickness)
model += support_grid_model
trimesh_model += support_grid_model
# Due to some weirdness the height of the drill must be bigger than the object's size.
# Otherwise some collisions are not detected.
cutter_height = 4 * (maxy - miny)
......@@ -97,10 +106,10 @@ def generate_toolpath(model, tool_settings=None, bounds=None, direction="x",
if isinstance(cutter, basestring):
return cutter
cutter.set_required_distance(material_allowance)
physics = _get_physics(model, cutter, calculation_backend)
physics = _get_physics(trimesh_model, cutter, calculation_backend)
if isinstance(physics, basestring):
return physics
generator = _get_pathgenerator_instance(model, cutter, path_generator, path_postprocessor, material_allowance, safety_height, physics)
generator = _get_pathgenerator_instance(trimesh_model, contour_model, cutter, path_generator, path_postprocessor, material_allowance, safety_height, physics)
if isinstance(generator, basestring):
return generator
if (overlap < 0) or (overlap >= 1):
......@@ -117,7 +126,7 @@ def generate_toolpath(model, tool_settings=None, bounds=None, direction="x",
return "Safety height (%.4f) is within the bounding box height (%.4f) - this can cause collisions of the tool with the material." % (safety_height, maxz)
toolpath = generator.GenerateToolPath(minx, maxx, miny, maxy, minz, maxz,
effective_toolradius, effective_toolradius, direction_param, callback)
else:
elif path_generator == "PushCutter":
if step_down > 0:
dz = step_down
else:
......@@ -131,9 +140,16 @@ def generate_toolpath(model, tool_settings=None, bounds=None, direction="x",
else:
return "Invalid direction (%s): not one of %s" % (direction, DIRECTIONS)
toolpath = generator.GenerateToolPath(minx, maxx, miny, maxy, minz, maxz, dx, dy, dz, callback)
else:
# EngraveCutter
if step_down > 0:
dz = step_down
else:
dz = maxz - minz
toolpath = generator.GenerateToolPath(minz, maxz, effective_toolradius, dz, callback)
return toolpath
def _get_pathgenerator_instance(model, cutter, pathgenerator, pathprocessor,
def _get_pathgenerator_instance(trimesh_model, contour_model, cutter, pathgenerator, pathprocessor,
material_allowance, safety_height, physics):
if pathgenerator == "DropCutter":
if pathprocessor == "ZigZagCutter":
......@@ -142,7 +158,7 @@ def _get_pathgenerator_instance(model, cutter, pathgenerator, pathprocessor,
processor = pycam.PathProcessors.PathAccumulator()
else:
return "Invalid postprocessor (%s) for 'DropCutter': only 'ZigZagCutter' or 'PathAccumulator' are allowed" % str(pathprocessor)
return DropCutter.DropCutter(cutter, model, processor, physics=physics,
return DropCutter.DropCutter(cutter, trimesh_model, processor, physics=physics,
safety_height=safety_height)
elif pathgenerator == "PushCutter":
if pathprocessor == "PathAccumulator":
......@@ -157,17 +173,25 @@ def _get_pathgenerator_instance(model, cutter, pathgenerator, pathprocessor,
processor = pycam.PathProcessors.ContourCutter()
else:
return "Invalid postprocessor (%s) for 'PushCutter' - it should be one of these: %s" % (processor, PATH_POSTPROCESSORS)
return PushCutter.PushCutter(cutter, model, processor, physics=physics)
return PushCutter.PushCutter(cutter, trimesh_model, processor, physics=physics)
elif pathgenerator == "EngraveCutter":
if pathprocessor == "SimpleCutter":
processor = pycam.PathProcessors.SimpleCutter()
else:
return "Invalid postprocessor (%s) for 'EngraveCutter' - it should be one of these: %s" % (processor, PATH_POSTPROCESSORS)
if not contour_model:
return "The EngraveCutter requires a contour model (e.g. from a DXF file)."
return EngraveCutter.EngraveCutter(cutter, trimesh_model, contour_model, processor, physics=physics)
else:
return "Invalid path generator (%s): not one of %s" % (pathgenerator, PATH_GENERATORS)
def _get_physics(model, cutter, calculation_backend):
def _get_physics(trimesh_model, cutter, calculation_backend):
if calculation_backend is None:
# triangular collision detection does not need any physical model
return None
elif calculation_backend == "ODE":
import pycam.Physics.ode_physics
return pycam.Physics.ode_physics.generate_physics(model, cutter)
return pycam.Physics.ode_physics.generate_physics(trimesh_model, cutter)
else:
return "Invalid calculation backend (%s): not one of %s" % (calculation_backend, CALCULATION_BACKENDS)
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment