The API now allows to specify where on the print bed to put the sliced model's center

This commit is contained in:
Gina Häußge 2014-12-04 12:52:33 +01:00
parent b935e96448
commit 636e79672a
6 changed files with 53 additions and 13 deletions

View file

@ -311,6 +311,9 @@ Issue a file command
* ``slicer``: The slicing engine to use, defaults to ``cura`` if not set, which is also the only supported slicer right now. * ``slicer``: The slicing engine to use, defaults to ``cura`` if not set, which is also the only supported slicer right now.
* ``gcode``: Name of the GCODE file to generated, in the same location as the STL file. Defaults to the STL file name * ``gcode``: Name of the GCODE file to generated, in the same location as the STL file. Defaults to the STL file name
with extension ``.gco`` if not set. with extension ``.gco`` if not set.
* ``position``: Position of the object-to-slice's center on the print bed. A dictionary containing both ``x`` and ``y``
coordinate in mm is expected
* ``printerProfile``: Name of the printer profile to use, if not set the default printer profile will be used.
* ``profile``: Name of the slicing profile to use, if not set the default slicing profile of the slicer will be used. * ``profile``: Name of the slicing profile to use, if not set the default slicing profile of the slicer will be used.
* ``profile.*``: Override parameters, the ``profile.`` prefix will be stripped and the matching profile key will * ``profile.*``: Override parameters, the ``profile.`` prefix will be stripped and the matching profile key will
be overridden with the supplied value. Use this if you want to specify things that change often like a different be overridden with the supplied value. Use this if you want to specify things that change often like a different
@ -352,9 +355,11 @@ Issue a file command
"command": "slice", "command": "slice",
"slicer": "cura", "slicer": "cura",
"gcode": "some_model.first_try.gcode", "gcode": "some_model.first_try.gcode",
"printerProfile": "my_custom_reprap",
"profile": "high_quality", "profile": "high_quality",
"profile.infill": 75, "profile.infill": 75,
"profile.fill_density": 15 "profile.fill_density": 15,
"position": {"x": 100, "y": 100}
} }
.. sourcecode:: http .. sourcecode:: http

View file

@ -152,7 +152,7 @@ class FileManager(object):
def default_slicer(self): def default_slicer(self):
return self._slicing_manager.default_slicer return self._slicing_manager.default_slicer
def slice(self, slicer_name, source_location, source_path, dest_location, dest_path, profile=None, printer_profile_id=None, overrides=None, callback=None, callback_args=None): def slice(self, slicer_name, source_location, source_path, dest_location, dest_path, position=None, profile=None, printer_profile_id=None, overrides=None, callback=None, callback_args=None):
absolute_source_path = self.get_absolute_path(source_location, source_path) absolute_source_path = self.get_absolute_path(source_location, source_path)
def stlProcessed(source_location, source_path, tmp_path, dest_location, dest_path, start_time, printer_profile_id, callback, callback_args, _error=None, _cancelled=False): def stlProcessed(source_location, source_path, tmp_path, dest_location, dest_path, start_time, printer_profile_id, callback, callback_args, _error=None, _cancelled=False):
@ -233,6 +233,7 @@ class FileManager(object):
temp_path, temp_path,
profile, profile,
stlProcessed, stlProcessed,
position=position,
callback_args=args, callback_args=args,
overrides=overrides, overrides=overrides,
printer_profile_id=printer_profile_id, printer_profile_id=printer_profile_id,

View file

@ -229,13 +229,20 @@ class CuraPlugin(octoprint.plugin.SlicerPlugin,
self._save_profile(path, new_profile, allow_overwrite=allow_overwrite) self._save_profile(path, new_profile, allow_overwrite=allow_overwrite)
def do_slice(self, model_path, printer_profile, machinecode_path=None, profile_path=None, on_progress=None, on_progress_args=None, on_progress_kwargs=None): def do_slice(self, model_path, printer_profile, machinecode_path=None, profile_path=None, position=None, on_progress=None, on_progress_args=None, on_progress_kwargs=None):
if not profile_path: if not profile_path:
profile_path = s.get(["default_profile"]) profile_path = s.get(["default_profile"])
if not machinecode_path: if not machinecode_path:
path, _ = os.path.splitext(model_path) path, _ = os.path.splitext(model_path)
machinecode_path = path + ".gco" machinecode_path = path + ".gco"
if position and isinstance(position, dict) and "x" in position and "y" in position:
posX = position["x"]
posY = position["y"]
else:
posX = None
posY = None
if on_progress: if on_progress:
if not on_progress_args: if not on_progress_args:
on_progress_args = () on_progress_args = ()
@ -244,7 +251,7 @@ class CuraPlugin(octoprint.plugin.SlicerPlugin,
self._cura_logger.info("### Slicing %s to %s using profile stored at %s" % (model_path, machinecode_path, profile_path)) self._cura_logger.info("### Slicing %s to %s using profile stored at %s" % (model_path, machinecode_path, profile_path))
engine_settings = self._convert_to_engine(profile_path, printer_profile) engine_settings = self._convert_to_engine(profile_path, printer_profile, posX, posY)
executable = s.get(["cura_engine"]) executable = s.get(["cura_engine"])
if not executable: if not executable:
@ -381,8 +388,8 @@ class CuraPlugin(octoprint.plugin.SlicerPlugin,
with open(path, "wb") as f: with open(path, "wb") as f:
yaml.safe_dump(profile, f, default_flow_style=False, indent=" ", allow_unicode=True) yaml.safe_dump(profile, f, default_flow_style=False, indent=" ", allow_unicode=True)
def _convert_to_engine(self, profile_path, printer_profile): def _convert_to_engine(self, profile_path, printer_profile, posX, posY):
profile = Profile(self._load_profile(profile_path), printer_profile) profile = Profile(self._load_profile(profile_path), printer_profile, posX, posY)
return profile.convert_to_engine() return profile.convert_to_engine()
def _sanitize_name(name): def _sanitize_name(name):

View file

@ -514,9 +514,11 @@ class Profile(object):
return result return result
def __init__(self, profile, printer_profile, overrides=None): def __init__(self, profile, printer_profile, posX, posY, overrides=None):
self._profile = self.__class__.merge_profile(profile, overrides=overrides) self._profile = self.__class__.merge_profile(profile, overrides=overrides)
self._printer_profile = printer_profile self._printer_profile = printer_profile
self._posX = posX
self._posY = posY
def profile(self): def profile(self):
import copy import copy
@ -796,6 +798,24 @@ class Profile(object):
return 2 return 2
return 1 return 1
def get_pos_x(self):
if self._posX:
try:
return int(float(self._posX) * 1000)
except ValueError:
pass
return int(self.get_float("machine_width") / 2.0 * 1000) if not self.get_boolean("machine_center_is_zero") else 0.0
def get_pos_y(self):
if self._posY:
try:
return int(float(self._posY) * 1000)
except ValueError:
pass
return int(self.get_float("machine_depth") / 2.0 * 1000) if not self.get_boolean("machine_center_is_zero") else 0.0
def convert_to_engine(self): def convert_to_engine(self):
edge_width, line_count = self.calculate_edge_width_and_line_count() edge_width, line_count = self.calculate_edge_width_and_line_count()
@ -844,8 +864,8 @@ class Profile(object):
"coolHeadLift": 1 if self.get_boolean("cool_head_lift") else 0, "coolHeadLift": 1 if self.get_boolean("cool_head_lift") else 0,
# model positioning # model positioning
"posx": int(self.get_float("machine_width") / 2.0 * 1000) if not self.get_boolean("machine_center_is_zero") else 0.0, "posx": self.get_pos_x(),
"posy": int(self.get_float("machine_depth") / 2.0 * 1000) if not self.get_boolean("machine_center_is_zero") else 0.0, "posy": self.get_pos_y(),
# gcodes # gcodes
"startCode": self.get_gcode("start_gcode"), "startCode": self.get_gcode("start_gcode"),

View file

@ -340,12 +340,18 @@ def gcodeFileCommand(filename, target):
else: else:
printerProfile = None printerProfile = None
if "position" in data.keys() and data["position"] and isinstance(data["position"], dict) and "x" in data["position"] and "y" in data["position"]:
position = data["position"]
del data["position"]
else:
position = None
override_keys = [k for k in data if k.startswith("profile.") and data[k] is not None] override_keys = [k for k in data if k.startswith("profile.") and data[k] is not None]
overrides = dict() overrides = dict()
for key in override_keys: for key in override_keys:
overrides[key[len("profile."):]] = data[key] overrides[key[len("profile."):]] = data[key]
ok, result = fileManager.slice(slicer, target, filename, target, gcode_name, profile=profile, printer_profile_id=printerProfile, overrides=overrides) ok, result = fileManager.slice(slicer, target, filename, target, gcode_name, profile=profile, printer_profile_id=printerProfile, position=position, overrides=overrides)
if ok: if ok:
files = {} files = {}
location = url_for(".readGcodeFile", target=target, filename=gcode_name, _external=True) location = url_for(".readGcodeFile", target=target, filename=gcode_name, _external=True)

View file

@ -95,7 +95,7 @@ class SlicingManager(object):
def get_slicer(self, slicer, require_configured=True): def get_slicer(self, slicer, require_configured=True):
return self._slicers[slicer] if slicer in self._slicers and (not require_configured or self._slicers[slicer].is_slicer_configured()) else None return self._slicers[slicer] if slicer in self._slicers and (not require_configured or self._slicers[slicer].is_slicer_configured()) else None
def slice(self, slicer_name, source_path, dest_path, profile_name, callback, callback_args=None, callback_kwargs=None, overrides=None, on_progress=None, on_progress_args=None, on_progress_kwargs=None, printer_profile_id=None): def slice(self, slicer_name, source_path, dest_path, profile_name, callback, callback_args=None, callback_kwargs=None, overrides=None, on_progress=None, on_progress_args=None, on_progress_kwargs=None, printer_profile_id=None, position=None):
if callback_args is None: if callback_args is None:
callback_args = () callback_args = ()
if callback_kwargs is None: if callback_kwargs is None:
@ -119,7 +119,7 @@ class SlicingManager(object):
if printer_profile is None: if printer_profile is None:
printer_profile = self._printer_profile_manager.get_current_or_default() printer_profile = self._printer_profile_manager.get_current_or_default()
def slicer_worker(slicer, model_path, machinecode_path, profile_name, overrides, printer_profile, callback, callback_args, callback_kwargs): def slicer_worker(slicer, model_path, machinecode_path, profile_name, overrides, printer_profile, position, callback, callback_args, callback_kwargs):
try: try:
slicer_name = slicer.get_slicer_properties()["type"] slicer_name = slicer.get_slicer_properties()["type"]
with self.temporary_profile(slicer_name, name=profile_name, overrides=overrides) as profile_path: with self.temporary_profile(slicer_name, name=profile_name, overrides=overrides) as profile_path:
@ -128,6 +128,7 @@ class SlicingManager(object):
printer_profile, printer_profile,
machinecode_path=machinecode_path, machinecode_path=machinecode_path,
profile_path=profile_path, profile_path=profile_path,
position=position,
on_progress=on_progress, on_progress=on_progress,
on_progress_args=on_progress_args, on_progress_args=on_progress_args,
on_progress_kwargs=on_progress_kwargs on_progress_kwargs=on_progress_kwargs
@ -142,7 +143,7 @@ class SlicingManager(object):
import threading import threading
slicer_worker_thread = threading.Thread(target=slicer_worker, slicer_worker_thread = threading.Thread(target=slicer_worker,
args=(slicer, source_path, dest_path, profile_name, overrides, printer_profile, callback, callback_args, callback_kwargs)) args=(slicer, source_path, dest_path, profile_name, overrides, printer_profile, position, callback, callback_args, callback_kwargs))
slicer_worker_thread.daemon = True slicer_worker_thread.daemon = True
slicer_worker_thread.start() slicer_worker_thread.start()
return True, None return True, None