From 22291be50e1c66b7c75111c41980948b2314c3a0 Mon Sep 17 00:00:00 2001 From: daid Date: Mon, 26 Mar 2012 15:03:26 +0200 Subject: [PATCH] Added experimental Slic3r option as backend. This does not support all options. --- Cura/fabmetheus_utilities/settings.py | 36 ++---------- Cura/newui/gcodeInterpreter.py | 11 ++++ Cura/newui/preferencesDialog.py | 3 + Cura/newui/profile.py | 38 +++++++++++++ Cura/newui/sliceRun.py | 81 +++++++++++++++++++++++++-- 5 files changed, 135 insertions(+), 34 deletions(-) diff --git a/Cura/fabmetheus_utilities/settings.py b/Cura/fabmetheus_utilities/settings.py index 75556f9..d9573c3 100644 --- a/Cura/fabmetheus_utilities/settings.py +++ b/Cura/fabmetheus_utilities/settings.py @@ -36,43 +36,19 @@ def storedPercentSetting(name): return lambda setting: float(profile.getProfileSetting(name)) / 100 def calculateEdgeWidth(setting): - wallThickness = float(profile.getProfileSetting('wall_thickness')) - nozzleSize = float(profile.getProfileSetting('nozzle_size')) - - if wallThickness < nozzleSize: - return wallThickness - - lineCount = int(wallThickness / nozzleSize) - lineWidth = wallThickness / lineCount - lineWidthAlt = wallThickness / (lineCount + 1) - if lineWidth > nozzleSize * 1.5: - return lineWidthAlt - return lineWidth + return profile.calculateEdgeWidth() def calculateShells(setting): - return calculateShellsImp(float(profile.getProfileSetting('wall_thickness'))) + return profile.calculateLineCount() - 1 def calculateShellsBase(setting): - return calculateShellsImp(float(profile.getProfileSetting('wall_thickness')) + float(profile.getProfileSetting('extra_base_wall_thickness'))) - -def calculateShellsImp(wallThickness): - nozzleSize = float(profile.getProfileSetting('nozzle_size')) + edgeWidth = profile.calculateEdgeWidth() + extraWall = float(profile.getProfileSetting('extra_base_wall_thickness')) - if wallThickness < nozzleSize: - return 0 - - lineCount = int(wallThickness / nozzleSize + 0.0001) - lineWidth = wallThickness / lineCount - lineWidthAlt = wallThickness / (lineCount + 1) - if lineWidth > nozzleSize * 1.5: - return lineCount - return lineCount - 1 + return profile.calculateLineCount() - 1 + int(extraWall / edgeWidth + 0.0001) def calculateSolidLayerCount(setting): - layerHeight = float(profile.getProfileSetting('layer_height')) - solidThickness = float(profile.getProfileSetting('solid_layer_thickness')) - ret = int(math.ceil(solidThickness / layerHeight - 0.0001)) - return ret + return profile.calculateSolidLayerCount() def firstLayerSpeedRatio(setting): bottomSpeed = float(profile.getProfileSetting('bottom_layer_speed')) diff --git a/Cura/newui/gcodeInterpreter.py b/Cura/newui/gcodeInterpreter.py index cd10cdf..bc591cf 100644 --- a/Cura/newui/gcodeInterpreter.py +++ b/Cura/newui/gcodeInterpreter.py @@ -46,6 +46,17 @@ class gcode(): pathType = line[6:].strip() if pathType != "CUSTOM": startCodeDone = True + if ';' in line: + comment = line[line.find(';')+1:].strip() + if comment == 'fill': + pathType = 'FILL' + elif comment == 'perimeter': + pathType = 'WALL-INNER' + elif comment == 'skirt': + pathType = 'SKIRT' + if pathType != "CUSTOM": + startCodeDone = True + line = line[0:line.find(';')] G = self.getCodeInt(line, 'G') if G is not None: if G == 0 or G == 1: #Move diff --git a/Cura/newui/preferencesDialog.py b/Cura/newui/preferencesDialog.py index 493807b..0cf19c7 100644 --- a/Cura/newui/preferencesDialog.py +++ b/Cura/newui/preferencesDialog.py @@ -28,6 +28,9 @@ class preferencesDialog(configBase.configWindowBase): configBase.TitleRow(left, 'Communication settings') c = configBase.SettingRow(left, 'Serial port', 'serial_port', ['AUTO'] + machineCom.serialList(), 'Serial port to use for communication with the printer', type = 'preference') c = configBase.SettingRow(left, 'Baudrate', 'serial_baud', '250000', 'Speed of the serial port communication\nNeeds to match your firmware settings\nCommon values are 250000, 115200, 57600', type = 'preference') + + configBase.TitleRow(left, 'Slicer settings') + c = configBase.SettingRow(left, 'Slicer selection', 'slicer', ['Cura (Skeinforge based)', 'Slic3r'], 'Which slicer to use to slice objects. Usually the Cura engine produces the best results. But Slic3r is developing fast and is faster with slicing.', type = 'preference') self.MakeModal(True) main.Fit() diff --git a/Cura/newui/profile.py b/Cura/newui/profile.py index 481932d..96e56ad 100644 --- a/Cura/newui/profile.py +++ b/Cura/newui/profile.py @@ -5,6 +5,7 @@ import __init__ import ConfigParser import os import traceback +import math #Single place to store the defaults, so we have a consistent set of default settings. profileDefaultSettings = { @@ -63,6 +64,7 @@ preferencesDefaultSettings = { 'steps_per_e': '0', 'serial_port': 'AUTO', 'serial_baud': '250000', + 'slicer': 'Cura (Skeinforge based)', } def getDefaultProfilePath(): @@ -146,3 +148,39 @@ def putPreference(name, value): globalPreferenceParser.add_section('preference') globalPreferenceParser.set('preference', name, str(value)) globalPreferenceParser.write(open(getPreferencePath(), 'w')) + +## Utility functions to calculate common profile values + +def calculateEdgeWidth(): + wallThickness = float(getProfileSetting('wall_thickness')) + nozzleSize = float(getProfileSetting('nozzle_size')) + + if wallThickness < nozzleSize: + return wallThickness + + lineCount = int(wallThickness / nozzleSize) + lineWidth = wallThickness / lineCount + lineWidthAlt = wallThickness / (lineCount + 1) + if lineWidth > nozzleSize * 1.5: + return lineWidthAlt + return lineWidth + +def calculateLineCount(): + wallThickness = float(getProfileSetting('wall_thickness')) + nozzleSize = float(getProfileSetting('nozzle_size')) + + if wallThickness < nozzleSize: + return 1 + + lineCount = int(wallThickness / nozzleSize + 0.0001) + lineWidth = wallThickness / lineCount + lineWidthAlt = wallThickness / (lineCount + 1) + if lineWidth > nozzleSize * 1.5: + return lineCount + 1 + return lineCount + +def calculateSolidLayerCount(): + layerHeight = float(getProfileSetting('layer_height')) + solidThickness = float(getProfileSetting('solid_layer_thickness')) + return int(math.ceil(solidThickness / layerHeight - 0.0001)) + diff --git a/Cura/newui/sliceRun.py b/Cura/newui/sliceRun.py index 2232768..b8c420d 100644 --- a/Cura/newui/sliceRun.py +++ b/Cura/newui/sliceRun.py @@ -3,6 +3,7 @@ from __future__ import absolute_import import platform, os, subprocess, sys from skeinforge_application.skeinforge_utilities import skeinforge_craft +from newui import profile def getPyPyExe(): "Return the path to the pypy executable if we can find it. Else return False" @@ -23,6 +24,25 @@ def getPyPyExe(): return pypyExe return False +def getSlic3rExe(): + "Return the path to the pypy executable if we can find it. Else return False" + if platform.system() == "Windows": + exeName = "slic3r.exe" + slic3rExe = os.path.normpath(os.path.join(os.path.dirname(os.path.abspath(__file__)), "../../Slic3r/bin/slic3r.exe")); + else: + exeName = "slic3r" + slic3rExe = os.path.normpath(os.path.join(os.path.dirname(os.path.abspath(__file__)), "../../Slic3r/bin/slic3r")); + if os.path.exists(slic3rExe): + return slic3rExe + + path = os.environ['PATH'] + paths = path.split(os.pathsep) + for p in paths: + slic3rExe = os.path.join(p, exeName) + if os.path.exists(slic3rExe): + return slic3rExe + return False + def runSlice(fileNames): "Run the slicer on the files. If we are running with PyPy then just do the slicing action. If we are running as Python, try to find pypy." pypyExe = getPyPyExe() @@ -41,7 +61,60 @@ def runSlice(fileNames): subprocess.call([pypyExe, os.path.join(sys.path[0], sys.argv[0]), fileName]) def getSliceCommand(filename): - pypyExe = getPyPyExe() - if pypyExe == False: - pypyExe = sys.executable - return [pypyExe, os.path.join(sys.path[0], os.path.split(sys.argv[0])[1]), filename] + if profile.getPreference('slicer').startswith('Slic3r'): + slic3rExe = getSlic3rExe() + if slic3rExe == False: + return False + cmd = [slic3rExe, + '--output-filename-format', '[input_filename_base]_export.gcode', + '--nozzle-diameter', str(profile.calculateEdgeWidth()), + '--print-center', '%s,%s' % (profile.getProfileSetting('machine_center_x'), profile.getProfileSetting('machine_center_y')), + '--z-offset', '0', + '--gcode-flavor', 'reprap', + '--gcode-comments', + '--filament-diameter', profile.getProfileSetting('filament_diameter'), + '--extrusion-multiplier', profile.getProfileSetting('filament_density'), + '--temperature', profile.getProfileSetting('print_temperature'), + '--travel-speed', profile.getProfileSetting('travel_speed'), + '--perimeter-speed', profile.getProfileSetting('print_speed'), + '--small-perimeter-speed', profile.getProfileSetting('print_speed'), + '--infill-speed', profile.getProfileSetting('print_speed'), + '--solid-infill-speed', profile.getProfileSetting('print_speed'), + '--bridge-speed', profile.getProfileSetting('print_speed'), + '--bottom-layer-speed-ratio', str(float(profile.getProfileSetting('bottom_layer_speed')) / float(profile.getProfileSetting('print_speed'))), + '--layer-height', profile.getProfileSetting('layer_height'), + '--first-layer-height-ratio', '1.0', + '--infill-every-layers', '1', + '--perimeters', str(profile.calculateLineCount()), + '--solid-layers', str(profile.calculateSolidLayerCount()), + '--fill-density', str(float(profile.getProfileSetting('fill_density'))/100), + '--fill-angle', '45', + '--fill-pattern', 'rectilinear', + '--solid-fill-pattern', 'rectilinear', + '--start-gcode', '', + '--end-gcode', '', + '--retract-length', profile.getProfileSetting('retraction_amount'), + '--retract-speed', str(int(float(profile.getProfileSetting('retraction_speed')))), + '--retract-restart-extra', profile.getProfileSetting('retraction_extra'), + '--retract-before-travel', profile.getProfileSetting('retraction_min_travel'), + '--retract-lift', '0', + '--slowdown-below-layer-time', profile.getProfileSetting('cool_min_layer_time'), + '--min-print-speed', profile.getProfileSetting('cool_min_feedrate'), + '--skirts', profile.getProfileSetting('skirt_line_count'), + '--skirt-distance', str(int(float(profile.getProfileSetting('skirt_gap')))), + '--skirt-height', '1', + '--scale', profile.getProfileSetting('model_scale'), + '--rotate', profile.getProfileSetting('model_rotate_base'), + '--duplicate-x', profile.getProfileSetting('model_multiply_x'), + '--duplicate-y', profile.getProfileSetting('model_multiply_y'), + '--duplicate-distance', '10'] + if profile.getProfileSetting('support') != 'None': + cmd.extend(['--support-material']) + cmd.extend([filename]) + return cmd + else: + pypyExe = getPyPyExe() + if pypyExe == False: + pypyExe = sys.executable + return [pypyExe, os.path.join(sys.path[0], os.path.split(sys.argv[0])[1]), filename] +