The API now allows to specify where on the print bed to put the sliced model's center
This commit is contained in:
parent
b935e96448
commit
636e79672a
6 changed files with 53 additions and 13 deletions
|
|
@ -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.
|
||||
* ``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.
|
||||
* ``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.*``: 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
|
||||
|
|
@ -352,9 +355,11 @@ Issue a file command
|
|||
"command": "slice",
|
||||
"slicer": "cura",
|
||||
"gcode": "some_model.first_try.gcode",
|
||||
"printerProfile": "my_custom_reprap",
|
||||
"profile": "high_quality",
|
||||
"profile.infill": 75,
|
||||
"profile.fill_density": 15
|
||||
"profile.fill_density": 15,
|
||||
"position": {"x": 100, "y": 100}
|
||||
}
|
||||
|
||||
.. sourcecode:: http
|
||||
|
|
|
|||
|
|
@ -152,7 +152,7 @@ class FileManager(object):
|
|||
def default_slicer(self):
|
||||
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)
|
||||
|
||||
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,
|
||||
profile,
|
||||
stlProcessed,
|
||||
position=position,
|
||||
callback_args=args,
|
||||
overrides=overrides,
|
||||
printer_profile_id=printer_profile_id,
|
||||
|
|
|
|||
|
|
@ -229,13 +229,20 @@ class CuraPlugin(octoprint.plugin.SlicerPlugin,
|
|||
|
||||
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:
|
||||
profile_path = s.get(["default_profile"])
|
||||
if not machinecode_path:
|
||||
path, _ = os.path.splitext(model_path)
|
||||
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 not 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))
|
||||
|
||||
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"])
|
||||
if not executable:
|
||||
|
|
@ -381,8 +388,8 @@ class CuraPlugin(octoprint.plugin.SlicerPlugin,
|
|||
with open(path, "wb") as f:
|
||||
yaml.safe_dump(profile, f, default_flow_style=False, indent=" ", allow_unicode=True)
|
||||
|
||||
def _convert_to_engine(self, profile_path, printer_profile):
|
||||
profile = Profile(self._load_profile(profile_path), printer_profile)
|
||||
def _convert_to_engine(self, profile_path, printer_profile, posX, posY):
|
||||
profile = Profile(self._load_profile(profile_path), printer_profile, posX, posY)
|
||||
return profile.convert_to_engine()
|
||||
|
||||
def _sanitize_name(name):
|
||||
|
|
|
|||
|
|
@ -514,9 +514,11 @@ class Profile(object):
|
|||
|
||||
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._printer_profile = printer_profile
|
||||
self._posX = posX
|
||||
self._posY = posY
|
||||
|
||||
def profile(self):
|
||||
import copy
|
||||
|
|
@ -796,6 +798,24 @@ class Profile(object):
|
|||
return 2
|
||||
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):
|
||||
|
||||
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,
|
||||
|
||||
# model positioning
|
||||
"posx": int(self.get_float("machine_width") / 2.0 * 1000) if not self.get_boolean("machine_center_is_zero") else 0.0,
|
||||
"posy": int(self.get_float("machine_depth") / 2.0 * 1000) if not self.get_boolean("machine_center_is_zero") else 0.0,
|
||||
"posx": self.get_pos_x(),
|
||||
"posy": self.get_pos_y(),
|
||||
|
||||
# gcodes
|
||||
"startCode": self.get_gcode("start_gcode"),
|
||||
|
|
|
|||
|
|
@ -340,12 +340,18 @@ def gcodeFileCommand(filename, target):
|
|||
else:
|
||||
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]
|
||||
overrides = dict()
|
||||
for key in override_keys:
|
||||
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:
|
||||
files = {}
|
||||
location = url_for(".readGcodeFile", target=target, filename=gcode_name, _external=True)
|
||||
|
|
|
|||
|
|
@ -95,7 +95,7 @@ class SlicingManager(object):
|
|||
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
|
||||
|
||||
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:
|
||||
callback_args = ()
|
||||
if callback_kwargs is None:
|
||||
|
|
@ -119,7 +119,7 @@ class SlicingManager(object):
|
|||
if printer_profile is None:
|
||||
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:
|
||||
slicer_name = slicer.get_slicer_properties()["type"]
|
||||
with self.temporary_profile(slicer_name, name=profile_name, overrides=overrides) as profile_path:
|
||||
|
|
@ -128,6 +128,7 @@ class SlicingManager(object):
|
|||
printer_profile,
|
||||
machinecode_path=machinecode_path,
|
||||
profile_path=profile_path,
|
||||
position=position,
|
||||
on_progress=on_progress,
|
||||
on_progress_args=on_progress_args,
|
||||
on_progress_kwargs=on_progress_kwargs
|
||||
|
|
@ -142,7 +143,7 @@ class SlicingManager(object):
|
|||
|
||||
import threading
|
||||
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.start()
|
||||
return True, None
|
||||
|
|
|
|||
Loading…
Reference in a new issue