Commit f8942e03 authored by sumpfralle's avatar sumpfralle

added progress indicator to non-GUI mode

improved some minor issues


git-svn-id: https://pycam.svn.sourceforge.net/svnroot/pycam/trunk@600 bbaffbd6-741e-11dd-a85d-61de82d9cad9
parent 0125e03a
[EXAMPLES]
.nf
.B pycam \-\-export\-gcode=output.ngc \-\-bounds\-type=relative\-margin \-\-bounds-lower=0.1,0.05,-0.1 foo.stl
.fi
Use the default settings to process the model \fBfoo.stl\fR with an adjusted
lower margin (minx, miny, minz) of 10% (for x), 5% (for y) and -10% (for z).
[ENVIRONMENT] [ENVIRONMENT]
.IP PYCAM_DATA_DIR .IP PYCAM_DATA_DIR
Override the default data directory of PyCAM. This allows Override the default data directory of PyCAM. This allows
......
...@@ -29,6 +29,7 @@ sys.path.insert(0, os.path.join(os.path.dirname(__file__), "src")) ...@@ -29,6 +29,7 @@ sys.path.insert(0, os.path.join(os.path.dirname(__file__), "src"))
from pycam.Physics.ode_physics import override_ode_availability from pycam.Physics.ode_physics import override_ode_availability
import pycam.Gui.common as GuiCommon import pycam.Gui.common as GuiCommon
import pycam.Gui.Settings import pycam.Gui.Settings
import pycam.Gui.Console
import pycam.Importers.TestModel import pycam.Importers.TestModel
import pycam.Importers import pycam.Importers
import pycam.Exporters.SimpleGCodeExporter import pycam.Exporters.SimpleGCodeExporter
...@@ -47,7 +48,7 @@ EXAMPLE_MODEL_LOCATIONS = ( ...@@ -47,7 +48,7 @@ EXAMPLE_MODEL_LOCATIONS = (
os.path.join("usr", "share", "pycam", "samples")) os.path.join("usr", "share", "pycam", "samples"))
DEFAULT_MODEL_FILE = "pycam.stl" DEFAULT_MODEL_FILE = "pycam.stl"
EXIT_CODES = {"ok": 0, "requirements": 1, "load_model_failed": 2, EXIT_CODES = {"ok": 0, "requirements": 1, "load_model_failed": 2,
"write_output_failed": 3} "write_output_failed": 3, "parsing_failed": 4}
def show_gui(inputfile=None, task_settings_file=None): def show_gui(inputfile=None, task_settings_file=None):
...@@ -146,8 +147,8 @@ if __name__ == "__main__": ...@@ -146,8 +147,8 @@ if __name__ == "__main__":
+ "is disabled.") + "is disabled.")
group_tool = parser.add_option_group("Tool definition", group_tool = parser.add_option_group("Tool definition",
"Specify the tool paramters. The default tool is spherical and " \ "Specify the tool paramters. The default tool is spherical and " \
+ "has a diameter of 1mm. The default speeds are 1000 (feedrate) " \ + "has a diameter of 1 unit. The default speeds are 1000 " \
+ "and 250 (drill spindle rotations per minute)") + "units/minute (feedrate) and 250 (spindle rotations per minute)")
group_process = parser.add_option_group("Process definition", group_process = parser.add_option_group("Process definition",
"Specify the process parameters: toolpath strategy, layer height," \ "Specify the process parameters: toolpath strategy, layer height," \
+ " and others. A typical roughing operation is configured by " \ + " and others. A typical roughing operation is configured by " \
...@@ -193,6 +194,11 @@ if __name__ == "__main__": ...@@ -193,6 +194,11 @@ if __name__ == "__main__":
group_general.add_option("-q", "--quiet", dest="quiet", group_general.add_option("-q", "--quiet", dest="quiet",
default=False, action="store_true", help="show only warnings and " \ default=False, action="store_true", help="show only warnings and " \
+ "errors.") + "errors.")
group_general.add_option("", "--progress", dest="progress",
default="text", action="store", type="choice",
choices=["none", "text", "bar", "dot"],
help="specify the type of progress bar used in non-GUI mode. " \
+ "The following options are available: text, none, bar, dot.")
group_general.add_option("-v", "--version", dest="show_version", group_general.add_option("-v", "--version", dest="show_version",
default=False, action="store_true", help="show the current " \ default=False, action="store_true", help="show the current " \
+ "version of PyCAM and exit") + "version of PyCAM and exit")
...@@ -254,7 +260,7 @@ if __name__ == "__main__": ...@@ -254,7 +260,7 @@ if __name__ == "__main__":
type="int", help="how much should two adjacent parallel " \ type="int", help="how much should two adjacent parallel " \
+ "toolpaths overlap each other (0..99)") + "toolpaths overlap each other (0..99)")
group_process.add_option("", "--safety-height", dest="safety_height", group_process.add_option("", "--safety-height", dest="safety_height",
default=0.0, action="store", type="float", default=25.0, action="store", type="float",
help="height for safe re-positioning moves") help="height for safe re-positioning moves")
group_process.add_option("", "--process-engrave-offset", group_process.add_option("", "--process-engrave-offset",
dest="process_engrave_offset", default=0.0, action="store", dest="process_engrave_offset", default=0.0, action="store",
...@@ -262,7 +268,7 @@ if __name__ == "__main__": ...@@ -262,7 +268,7 @@ if __name__ == "__main__":
+ "given distance (only for 'engrave' strategy)") + "given distance (only for 'engrave' strategy)")
# bounds settings # bounds settings
group_bounds.add_option("", "--bounds-type", dest="bounds_type", group_bounds.add_option("", "--bounds-type", dest="bounds_type",
default="relative-margin", action="store", type="choice", default="fixed-margin", action="store", type="choice",
choices=["relative-margin", "fixed-margin", "custom"], choices=["relative-margin", "fixed-margin", "custom"],
help="type of the boundary definition (relative-margin, " \ help="type of the boundary definition (relative-margin, " \
+ "fixed-margin, custom)") + "fixed-margin, custom)")
...@@ -278,9 +284,13 @@ if __name__ == "__main__": ...@@ -278,9 +284,13 @@ if __name__ == "__main__":
group_support_grid.add_option("", "--enable-support-grid", group_support_grid.add_option("", "--enable-support-grid",
dest="support_grid_enabled", default=False, action="store_true", dest="support_grid_enabled", default=False, action="store_true",
help="enable the support grid") help="enable the support grid")
group_support_grid.add_option("", "--support-grid-distance", group_support_grid.add_option("", "--support-grid-distance-x",
dest="support_grid_distance", default=10.0, action="store", dest="support_grid_distance_x", default=10.0, action="store",
type="float", help="horizontal and vertical distance between two " \ type="float", help="distance along the x-axis between two " \
+ "adjacent parallel lines of the support grid pattern")
group_support_grid.add_option("", "--support-grid-distance-y",
dest="support_grid_distance_y", default=10.0, action="store",
type="float", help="distance along the y-axis between two " \
+ "adjacent parallel lines of the support grid pattern") + "adjacent parallel lines of the support grid pattern")
group_support_grid.add_option("", "--support-grid-height", group_support_grid.add_option("", "--support-grid-height",
dest="support_grid_height", default=2.0, action="store", dest="support_grid_height", default=2.0, action="store",
...@@ -346,8 +356,9 @@ if __name__ == "__main__": ...@@ -346,8 +356,9 @@ if __name__ == "__main__":
0.5 * opts.tool_torus_diameter, opts.tool_spindle_speed, 0.5 * opts.tool_torus_diameter, opts.tool_spindle_speed,
opts.tool_feedrate) opts.tool_feedrate)
if opts.support_grid_enabled: if opts.support_grid_enabled:
tps.set_support_grid(opts.support_grid_distance, tps.set_support_grid(opts.support_grid_distance_x,
opts.support_grid_thickness, opts.support_grid_height) opts.support_grid_distance_y, opts.support_grid_thickness,
opts.support_grid_height)
if opts.collision_engine == "ode": if opts.collision_engine == "ode":
tps.set_calculation_backend("ODE") tps.set_calculation_backend("ODE")
tps.set_unit_size(opts.unit_size) tps.set_unit_size(opts.unit_size)
...@@ -386,12 +397,12 @@ if __name__ == "__main__": ...@@ -386,12 +397,12 @@ if __name__ == "__main__":
# set the bounds type and let the default bounding box match the model # set the bounds type and let the default bounding box match the model
if opts.bounds_type == "relative-margin": if opts.bounds_type == "relative-margin":
bounds.set_type(Bounds.TYPE_RELATIVE_MARGIN) bounds.set_type(Bounds.TYPE_RELATIVE_MARGIN)
bounds_default_low = (10, 10, 0) bounds_default_low = (0, 0, 0)
bounds_default_high = (10, 10, 0) bounds_default_high = (0, 0, 0)
elif opts.bounds_type == "fixed-margin": elif opts.bounds_type == "fixed-margin":
bounds.set_type(Bounds.TYPE_FIXED_MARGIN) bounds.set_type(Bounds.TYPE_FIXED_MARGIN)
bounds_default_low = (10, 10, 0) bounds_default_low = (0, 0, 0)
bounds_default_high = (10, 10, 0) bounds_default_high = (0, 0, 0)
else: else:
# custom boundary setting # custom boundary setting
bounds.set_type(Bounds.TYPE_CUSTOM) bounds.set_type(Bounds.TYPE_CUSTOM)
...@@ -407,23 +418,27 @@ if __name__ == "__main__": ...@@ -407,23 +418,27 @@ if __name__ == "__main__":
try: try:
result.append(float(num)) result.append(float(num))
except ValueError: except ValueError:
return None if num == "":
result.append(0.0)
else:
return None
return result return result
bounds_lower_nums = parse_triple_float(opts.bounds_lower) bounds_lower_nums = parse_triple_float(opts.bounds_lower)
if opts.bounds_lower and not bounds_lower_nums:
log.error("Failed to parse the lower boundary limit: %s" \
% opts.bounds_lower)
sys.exit(EXIT_CODES["parsing_failed"])
bounds_upper_nums = parse_triple_float(opts.bounds_upper) bounds_upper_nums = parse_triple_float(opts.bounds_upper)
if bounds_lower_nums is None \ if opts.bounds_upper and not bounds_upper_nums:
and bounds_upper_nums is None: log.error("Failed to parse the upper boundary limit: %s" \
# no bound was given % opts.bounds_upper)
bounds.set_bounds(bounds_default_low, bounds_default_high) sys.exit(EXIT_CODES["parsing_failed"])
elif bounds_lower_nums is None: if bounds_lower_nums is None:
# only the upper bound was specified bounds_lower_nums = bounds_default_low
bounds.set_bounds(bounds_default_low, bounds_upper_nums) if bounds_upper_nums is None:
elif bounds_upper_nums is None: bounds_upper_nums = bounds_default_high
# only the lower bound was specified # both lower and upper bounds were specified
bounds.set_bounds(bounds_lower_nums, bounds_default_high) bounds.set_bounds(bounds_lower_nums, bounds_upper_nums)
else:
# both lower and upper bounds were specified
bounds.set_bounds(bounds_lower_nums, bounds_upper_nums)
# adjust the bounding box according to the "boundary_mode" # adjust the bounding box according to the "boundary_mode"
if opts.boundary_mode == "along": if opts.boundary_mode == "along":
offset = (0, 0, 0) offset = (0, 0, 0)
...@@ -438,7 +453,10 @@ if __name__ == "__main__": ...@@ -438,7 +453,10 @@ if __name__ == "__main__":
if opts.export_gcode: if opts.export_gcode:
# generate the toolpath # generate the toolpath
start_time = time.time() start_time = time.time()
toolpath = pycam.Toolpath.Generator.generate_toolpath_from_settings(model, tps) progress_bar = pycam.Gui.Console.ConsoleProgressBar(sys.stdout)
toolpath = pycam.Toolpath.Generator.generate_toolpath_from_settings(
model, tps, callback=progress_bar.update)
progress_bar.finish()
log.info("Toolpath generation time: %f" \ log.info("Toolpath generation time: %f" \
% (time.time() - start_time)) % (time.time() - start_time))
# write result # write result
......
# -*- coding: utf-8 -*-
"""
$Id$
Copyright 2010 Lars Kruse <devel@sumpfralle.de>
This file is part of PyCAM.
PyCAM is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
PyCAM is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with PyCAM. If not, see <http://www.gnu.org/licenses/>.
"""
__all__ = ["ConsoleProgressBar"]
import os
class ConsoleProgressBar(object):
def __init__(self, output):
self.output = output
self.last_length = 0
self.text = ""
self.percent = 0
def update(self, text=None, percent=None, **kwargs):
if not text is None:
self.text = text
if not percent is None:
self.percent = int(percent)
if self.last_length > 0:
# delete the previous line
self.output.write("\x08" * self.last_length)
result = "%d%% %s" % (self.percent, self.text)
self.last_length = len(result)
self.output.write(result)
self.output.flush()
def finish(self):
self.output.write(os.linesep)
...@@ -633,6 +633,10 @@ class ToolpathSettings: ...@@ -633,6 +633,10 @@ class ToolpathSettings:
def set_support_grid(self, distance_x, distance_y, thickness, height, def set_support_grid(self, distance_x, distance_y, thickness, height,
offset_x=0.0, offset_y=0.0, adjustments_x=None, offset_x=0.0, offset_y=0.0, adjustments_x=None,
adjustments_y=None): adjustments_y=None):
if adjustments_x is None:
adjustments_x = []
if adjustments_y is None:
adjustments_y = []
self.support_grid["distance_x"] = distance_x self.support_grid["distance_x"] = distance_x
self.support_grid["distance_y"] = distance_y self.support_grid["distance_y"] = distance_y
self.support_grid["offset_x"] = offset_x self.support_grid["offset_x"] = offset_x
......
...@@ -20,4 +20,6 @@ You should have received a copy of the GNU General Public License ...@@ -20,4 +20,6 @@ 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/>.
""" """
__all__ = ["Vizualisation"] __all__ = ["common", "Console", "OpenGLTools", "Project", "Settings",
"Vizualisation"]
...@@ -112,7 +112,7 @@ class DropCutter: ...@@ -112,7 +112,7 @@ class DropCutter:
last_position = None last_position = None
if draw_callback and draw_callback(text="DropCutter: processing " \ if draw_callback and draw_callback(text="DropCutter: processing " \
+ "line %d/%d" % (current_line, num_of_lines)): + "line %d/%d" % (current_line + 1, num_of_lines)):
# cancel requested # cancel requested
quit_requested = True quit_requested = True
break break
......
...@@ -118,7 +118,7 @@ class EngraveCutter: ...@@ -118,7 +118,7 @@ class EngraveCutter:
if draw_callback: if draw_callback:
draw_callback(text="Engrave: processing layer %d/%d" \ draw_callback(text="Engrave: processing layer %d/%d" \
% (current_layer, num_of_layers)) % (current_layer + 1, num_of_layers))
# process the final layer with a drop cutter # process the final layer with a drop cutter
for line_group in self.contour_model.get_polygons(): for line_group in self.contour_model.get_polygons():
......
...@@ -67,7 +67,7 @@ class PushCutter: ...@@ -67,7 +67,7 @@ class PushCutter:
for z in z_steps: for z in z_steps:
# update the progress bar and check, if we should cancel the process # update the progress bar and check, if we should cancel the process
if draw_callback and draw_callback(text="PushCutter: processing" \ if draw_callback and draw_callback(text="PushCutter: processing" \
+ " layer %d/%d" % (current_layer, num_of_layers)): + " layer %d/%d" % (current_layer + 1, num_of_layers)):
# cancel immediately # cancel immediately
break break
......
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