Commit b69e28ad authored by sumpfralle's avatar sumpfralle

added conventional/climb settings to the GUI

updated Changelog


git-svn-id: https://pycam.svn.sourceforge.net/svnroot/pycam/trunk@705 bbaffbd6-741e-11dd-a85d-61de82d9cad9
parent c60d883e
Version 0.3.1 - UNRELEASED Version 0.3.1 - UNRELEASED
* added automatic support grid positioning for contour models * added automatic support grid positioning for contour models
* added an improved contour toolpath strategy (ContourFollow)
* see http://fab.senselab.org/node/43
* added options for conventional/climb milling
* allow to reverse the direction of a 2D contour model * allow to reverse the direction of a 2D contour model
* added optional "orthogonal" view (instead of perspective) * added optional "orthogonal" view (instead of perspective)
* added a "recent files" item to the file menu * added a "recent files" item to the file menu
......
This diff is collapsed.
...@@ -414,10 +414,12 @@ if __name__ == "__main__": ...@@ -414,10 +414,12 @@ if __name__ == "__main__":
"contour": "ContourCutter", "contour": "ContourCutter",
"polygon": "PolygonCutter", "polygon": "PolygonCutter",
}[opts.process_path_postprocessor] }[opts.process_path_postprocessor]
# TODO: add the miling_style option
tps.set_process_settings(path_generator, postprocessor, tps.set_process_settings(path_generator, postprocessor,
opts.process_path_direction, opts.process_material_allowance, opts.process_path_direction, reverse=False,
opts.safety_height, opts.process_overlap_percent / 100.0, material_allowance=opts.process_material_allowance,
opts.process_step_down, opts.process_engrave_offset) overlap=opts.process_overlap_percent / 100.0,
step_down=opts.process_step_down, engrave_offset=opts.process_engrave_offset)
# set locations of external programs # set locations of external programs
program_locations = {} program_locations = {}
if opts.external_program_inkscape: if opts.external_program_inkscape:
......
This diff is collapsed.
This diff is collapsed.
...@@ -130,11 +130,11 @@ speed: 1000 ...@@ -130,11 +130,11 @@ speed: 1000
[ProcessDefault] [ProcessDefault]
name: Remove material name: Remove material
path_direction: x
engrave_offset: 0.0 engrave_offset: 0.0
path_generator: PushCutter path_strategy: PushCutter
path_postprocessor: PolygonCutter path_direction: x
material_allowance: 0.5 milling_style: ignore
material_allowance: 0.0
step_down: 3.0 step_down: 3.0
overlap_percent: 0 overlap_percent: 0
...@@ -180,37 +180,35 @@ tool_radius: 0.5 ...@@ -180,37 +180,35 @@ tool_radius: 0.5
[ProcessDefault] [ProcessDefault]
path_direction: x path_direction: x
path_strategy: SurfaceStrategy
milling_style: ignore
engrave_offset: 0.0 engrave_offset: 0.0
step_down: 3.0
material_allowance: 0.0
[Process0] [Process0]
name: Remove material name: Remove material
path_generator: PushCutter path_strategy: PushRemoveStrategy
path_postprocessor: PolygonCutter
material_allowance: 0.5 material_allowance: 0.5
step_down: 3.0 step_down: 3.0
overlap_percent: 0 overlap_percent: 0
[Process1] [Process1]
name: Carve contour name: Carve contour
path_generator: PushCutter path_strategy: ContourFollowStrategy
path_postprocessor: ContourCutter
material_allowance: 0.2 material_allowance: 0.2
step_down: 1.5 step_down: 1.5
overlap_percent: 20 overlap_percent: 20
[Process2] [Process2]
name: Cleanup name: Cleanup
path_generator: DropCutter path_strategy: SurfaceStrategy
path_postprocessor: ZigZagCutter
material_allowance: 0.0 material_allowance: 0.0
step_down: 1.0
overlap_percent: 60 overlap_percent: 60
[Process3] [Process3]
name: Gravure name: Gravure
path_generator: EngraveCutter path_strategy: EngraveStrategy
path_postprocessor: SimpleCutter
material_allowance: 0.0
step_down: 1.0 step_down: 1.0
overlap_percent: 50 overlap_percent: 50
...@@ -267,9 +265,9 @@ process: 3 ...@@ -267,9 +265,9 @@ process: 3
"torus_radius": float, "torus_radius": float,
"speed": float, "speed": float,
"feedrate": float, "feedrate": float,
"path_strategy": str,
"path_direction": str, "path_direction": str,
"path_generator": str, "milling_style": str,
"path_postprocessor": str,
"material_allowance": float, "material_allowance": float,
"overlap_percent": int, "overlap_percent": int,
"step_down": float, "step_down": float,
...@@ -290,8 +288,8 @@ process: 3 ...@@ -290,8 +288,8 @@ process: 3
CATEGORY_KEYS = { CATEGORY_KEYS = {
"tool": ("name", "shape", "tool_radius", "torus_radius", "feedrate", "tool": ("name", "shape", "tool_radius", "torus_radius", "feedrate",
"speed"), "speed"),
"process": ("name", "path_generator", "path_postprocessor", "process": ("name", "path_strategy", "path_direction",
"path_direction", "material_allowance", "milling_style", "material_allowance",
"overlap_percent", "step_down", "engrave_offset"), "overlap_percent", "step_down", "engrave_offset"),
"bounds": ("name", "type", "x_low", "x_high", "y_low", "bounds": ("name", "type", "x_low", "x_high", "y_low",
"y_high", "z_low", "z_high"), "y_high", "z_low", "z_high"),
...@@ -588,6 +586,7 @@ class ToolpathSettings: ...@@ -588,6 +586,7 @@ class ToolpathSettings:
"generator": str, "generator": str,
"postprocessor": str, "postprocessor": str,
"path_direction": str, "path_direction": str,
"reverse": bool,
"material_allowance": float, "material_allowance": float,
"overlap": float, "overlap": float,
"step_down": float, "step_down": float,
...@@ -699,12 +698,16 @@ class ToolpathSettings: ...@@ -699,12 +698,16 @@ class ToolpathSettings:
return "mm" return "mm"
def set_process_settings(self, generator, postprocessor, path_direction, def set_process_settings(self, generator, postprocessor, path_direction,
material_allowance=0.0, overlap=0.0, reverse=False, material_allowance=0.0, overlap=0.0,
step_down=1.0, engrave_offset=0.0): step_down=1.0, engrave_offset=0.0):
# TODO: this hack should be somewhere else, I guess
if generator in ("ContourFollow", "EngraveCutter"):
material_allowance = 0.0
self.process_settings = { self.process_settings = {
"generator": generator, "generator": generator,
"postprocessor": postprocessor, "postprocessor": postprocessor,
"path_direction": path_direction, "path_direction": path_direction,
"reverse": reverse,
"material_allowance": material_allowance, "material_allowance": material_allowance,
"overlap": overlap, "overlap": overlap,
"step_down": step_down, "step_down": step_down,
......
...@@ -20,7 +20,8 @@ You should have received a copy of the GNU General Public License ...@@ -20,7 +20,8 @@ You should have received a copy of the GNU General Public License
along with PyCAM. If not, see <http://www.gnu.org/licenses/>. along with PyCAM. If not, see <http://www.gnu.org/licenses/>.
""" """
from pycam.PathGenerators import DropCutter, PushCutter, EngraveCutter, Waterline from pycam.PathGenerators import DropCutter, PushCutter, EngraveCutter, \
ContourFollow
from pycam.Geometry.utils import number from pycam.Geometry.utils import number
import pycam.PathProcessors import pycam.PathProcessors
import pycam.Cutters import pycam.Cutters
...@@ -33,7 +34,8 @@ log = pycam.Utils.log.get_logger() ...@@ -33,7 +34,8 @@ log = pycam.Utils.log.get_logger()
DIRECTIONS = frozenset(("x", "y", "xy")) DIRECTIONS = frozenset(("x", "y", "xy"))
PATH_GENERATORS = frozenset(("DropCutter", "PushCutter", "EngraveCutter", "WaterlineCutter")) PATH_GENERATORS = frozenset(("DropCutter", "PushCutter", "EngraveCutter",
"ContourFollow"))
PATH_POSTPROCESSORS = frozenset(("ContourCutter", "PathAccumulator", PATH_POSTPROCESSORS = frozenset(("ContourCutter", "PathAccumulator",
"PolygonCutter", "SimpleCutter", "ZigZagCutter")) "PolygonCutter", "SimpleCutter", "ZigZagCutter"))
CALCULATION_BACKENDS = frozenset((None, "ODE")) CALCULATION_BACKENDS = frozenset((None, "ODE"))
...@@ -48,6 +50,7 @@ def generate_toolpath_from_settings(model, tp_settings, callback=None): ...@@ -48,6 +50,7 @@ def generate_toolpath_from_settings(model, tp_settings, callback=None):
return generate_toolpath(model, tp_settings.get_tool_settings(), return generate_toolpath(model, tp_settings.get_tool_settings(),
bounds_low, bounds_high, process["path_direction"], bounds_low, bounds_high, process["path_direction"],
process["generator"], process["postprocessor"], process["generator"], process["postprocessor"],
process["reverse"],
process["material_allowance"], process["overlap"], process["material_allowance"], process["overlap"],
process["step_down"], process["engrave_offset"], process["step_down"], process["engrave_offset"],
grid["type"], grid["distance_x"], grid["distance_y"], grid["type"], grid["distance_x"], grid["distance_y"],
...@@ -59,6 +62,7 @@ def generate_toolpath_from_settings(model, tp_settings, callback=None): ...@@ -59,6 +62,7 @@ def generate_toolpath_from_settings(model, tp_settings, callback=None):
def generate_toolpath(model, tool_settings=None, def generate_toolpath(model, tool_settings=None,
bounds_low=None, bounds_high=None, direction="x", bounds_low=None, bounds_high=None, direction="x",
path_generator="DropCutter", path_postprocessor="ZigZagCutter", path_generator="DropCutter", path_postprocessor="ZigZagCutter",
reverse=False,
material_allowance=0, overlap=0, step_down=0, engrave_offset=0, material_allowance=0, overlap=0, step_down=0, engrave_offset=0,
support_grid_type=None, support_grid_distance_x=None, support_grid_type=None, support_grid_distance_x=None,
support_grid_distance_y=None, support_grid_thickness=None, support_grid_distance_y=None, support_grid_thickness=None,
...@@ -255,7 +259,7 @@ def generate_toolpath(model, tool_settings=None, ...@@ -255,7 +259,7 @@ def generate_toolpath(model, tool_settings=None,
for next_model in trimesh_models[1:]: for next_model in trimesh_models[1:]:
combined_models += next_model combined_models += next_model
generator = _get_pathgenerator_instance(combined_models, contour_model, generator = _get_pathgenerator_instance(combined_models, contour_model,
cutter, path_generator, path_postprocessor, physics) cutter, path_generator, path_postprocessor, reverse, physics)
if isinstance(generator, basestring): if isinstance(generator, basestring):
return generator return generator
if (overlap < 0) or (overlap >= 1): if (overlap < 0) or (overlap >= 1):
...@@ -298,7 +302,7 @@ def generate_toolpath(model, tool_settings=None, ...@@ -298,7 +302,7 @@ def generate_toolpath(model, tool_settings=None,
dz = maxz - minz dz = maxz - minz
toolpath = generator.GenerateToolPath(minz, maxz, stepping, dz, toolpath = generator.GenerateToolPath(minz, maxz, stepping, dz,
callback) callback)
elif path_generator == "WaterlineCutter": elif path_generator == "ContourFollow":
if step_down > 0: if step_down > 0:
dz = step_down dz = step_down
else: else:
...@@ -313,12 +317,13 @@ def generate_toolpath(model, tool_settings=None, ...@@ -313,12 +317,13 @@ def generate_toolpath(model, tool_settings=None,
return toolpath return toolpath
def _get_pathgenerator_instance(trimesh_model, contour_model, cutter, def _get_pathgenerator_instance(trimesh_model, contour_model, cutter,
pathgenerator, pathprocessor, physics): pathgenerator, pathprocessor, reverse, physics):
if pathgenerator == "DropCutter": if pathgenerator == "DropCutter":
if pathprocessor == "ZigZagCutter": if pathprocessor == "ZigZagCutter":
processor = pycam.PathProcessors.PathAccumulator(zigzag=True) processor = pycam.PathProcessors.PathAccumulator(zigzag=True,
reverse=reverse)
elif pathprocessor == "PathAccumulator": elif pathprocessor == "PathAccumulator":
processor = pycam.PathProcessors.PathAccumulator() processor = pycam.PathProcessors.PathAccumulator(reverse=reverse)
else: else:
return ("Invalid postprocessor (%s) for 'DropCutter': only " \ return ("Invalid postprocessor (%s) for 'DropCutter': only " \
+ "'ZigZagCutter' or 'PathAccumulator' are allowed") \ + "'ZigZagCutter' or 'PathAccumulator' are allowed") \
...@@ -327,15 +332,15 @@ def _get_pathgenerator_instance(trimesh_model, contour_model, cutter, ...@@ -327,15 +332,15 @@ def _get_pathgenerator_instance(trimesh_model, contour_model, cutter,
physics=physics) physics=physics)
elif pathgenerator == "PushCutter": elif pathgenerator == "PushCutter":
if pathprocessor == "PathAccumulator": if pathprocessor == "PathAccumulator":
processor = pycam.PathProcessors.PathAccumulator() processor = pycam.PathProcessors.PathAccumulator(reverse=reverse)
elif pathprocessor == "SimpleCutter": elif pathprocessor == "SimpleCutter":
processor = pycam.PathProcessors.SimpleCutter() processor = pycam.PathProcessors.SimpleCutter(reverse=reverse)
elif pathprocessor == "ZigZagCutter": elif pathprocessor == "ZigZagCutter":
processor = pycam.PathProcessors.ZigZagCutter() processor = pycam.PathProcessors.ZigZagCutter(reverse=reverse)
elif pathprocessor == "PolygonCutter": elif pathprocessor == "PolygonCutter":
processor = pycam.PathProcessors.PolygonCutter() processor = pycam.PathProcessors.PolygonCutter(reverse=reverse)
elif pathprocessor == "ContourCutter": elif pathprocessor == "ContourCutter":
processor = pycam.PathProcessors.ContourCutter() processor = pycam.PathProcessors.ContourCutter(reverse=reverse)
else: else:
return ("Invalid postprocessor (%s) for 'PushCutter' - it should " \ return ("Invalid postprocessor (%s) for 'PushCutter' - it should " \
+ "be one of these: %s") % (processor, PATH_POSTPROCESSORS) + "be one of these: %s") % (processor, PATH_POSTPROCESSORS)
...@@ -343,7 +348,7 @@ def _get_pathgenerator_instance(trimesh_model, contour_model, cutter, ...@@ -343,7 +348,7 @@ def _get_pathgenerator_instance(trimesh_model, contour_model, cutter,
physics=physics) physics=physics)
elif pathgenerator == "EngraveCutter": elif pathgenerator == "EngraveCutter":
if pathprocessor == "SimpleCutter": if pathprocessor == "SimpleCutter":
processor = pycam.PathProcessors.SimpleCutter() processor = pycam.PathProcessors.SimpleCutter(reverse=reverse)
else: else:
return ("Invalid postprocessor (%s) for 'EngraveCutter' - it " \ return ("Invalid postprocessor (%s) for 'EngraveCutter' - it " \
+ "should be one of these: %s") \ + "should be one of these: %s") \
...@@ -353,14 +358,14 @@ def _get_pathgenerator_instance(trimesh_model, contour_model, cutter, ...@@ -353,14 +358,14 @@ def _get_pathgenerator_instance(trimesh_model, contour_model, cutter,
+ "DXF file)." + "DXF file)."
return EngraveCutter.EngraveCutter(cutter, trimesh_model, return EngraveCutter.EngraveCutter(cutter, trimesh_model,
contour_model, processor, physics=physics) contour_model, processor, physics=physics)
elif pathgenerator == "WaterlineCutter": elif pathgenerator == "ContourFollow":
if pathprocessor == "PathAccumulator": if pathprocessor == "PathAccumulator":
processor = pycam.PathProcessors.PathAccumulator() processor = pycam.PathProcessors.PathAccumulator(reverse=reverse)
else: else:
return ("Invalid postprocessor (%s) for 'WaterlineCutter' - it " \ return ("Invalid postprocessor (%s) for 'ContourFollow' - it " \
+ "should be one of these: %s") \ + "should be one of these: %s") \
% (processor, PATH_POSTPROCESSORS) % (processor, PATH_POSTPROCESSORS)
return Waterline.Waterline(cutter, trimesh_model, processor, return ContourFollow.ContourFollow(cutter, trimesh_model, processor,
physics=physics) physics=physics)
else: else:
return "Invalid path generator (%s): not one of %s" \ return "Invalid path generator (%s): not one of %s" \
......
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