chiark / gitweb /
Make sure the print fits on the bed with dual-extrusion-support.
[cura.git] / Cura / util / sliceEngine.py
index 8944b057af500109d285cbfda646034a0d5982d8..87c539fec2351a9a1f2d3760d166d0b16f40f47c 100644 (file)
@@ -46,7 +46,7 @@ class Slicer(object):
                self._objCount = 0
                self._sliceLog = []
                self._printTimeSeconds = None
-               self._filamentMM = None
+               self._filamentMM = [0.0, 0.0]
                self._modelHash = None
                self._id = 0
 
@@ -83,21 +83,21 @@ class Slicer(object):
        def getID(self):
                return self._id
 
-       def getFilamentWeight(self):
+       def getFilamentWeight(self, e=0):
                #Calculates the weight of the filament in kg
                radius = float(profile.getProfileSetting('filament_diameter')) / 2
-               volumeM3 = (self._filamentMM * (math.pi * radius * radius)) / (1000*1000*1000)
+               volumeM3 = (self._filamentMM[e] * (math.pi * radius * radius)) / (1000*1000*1000)
                return volumeM3 * profile.getPreferenceFloat('filament_physical_density')
 
-       def getFilamentCost(self):
+       def getFilamentCost(self, e=0):
                cost_kg = profile.getPreferenceFloat('filament_cost_kg')
                cost_meter = profile.getPreferenceFloat('filament_cost_meter')
                if cost_kg > 0.0 and cost_meter > 0.0:
-                       return "%.2f / %.2f" % (self.getFilamentWeight() * cost_kg, self._filamentMM / 1000.0 * cost_meter)
+                       return "%.2f / %.2f" % (self.getFilamentWeight(e) * cost_kg, self._filamentMM[e] / 1000.0 * cost_meter)
                elif cost_kg > 0.0:
-                       return "%.2f" % (self.getFilamentWeight() * cost_kg)
+                       return "%.2f" % (self.getFilamentWeight(e) * cost_kg)
                elif cost_meter > 0.0:
-                       return "%.2f" % (self._filamentMM / 1000.0 * cost_meter)
+                       return "%.2f" % (self._filamentMM[e] / 1000.0 * cost_meter)
                return None
 
        def getPrintTime(self):
@@ -107,8 +107,10 @@ class Slicer(object):
                        return '%d hour %d minutes' % (int(self._printTimeSeconds / 60 / 60), int(self._printTimeSeconds / 60) % 60)
                return '%d hours %d minutes' % (int(self._printTimeSeconds / 60 / 60), int(self._printTimeSeconds / 60) % 60)
 
-       def getFilamentAmount(self):
-               return '%0.2f meter %0.0f gram' % (float(self._filamentMM) / 1000.0, self.getFilamentWeight() * 1000.0)
+       def getFilamentAmount(self, e=0):
+               if self._filamentMM[e] == 0.0:
+                       return None
+               return '%0.2f meter %0.0f gram' % (float(self._filamentMM[e]) / 1000.0, self.getFilamentWeight(e) * 1000.0)
 
        def runSlicer(self, scene):
                extruderCount = 1
@@ -116,6 +118,8 @@ class Slicer(object):
                        if scene.checkPlatform(obj):
                                extruderCount = max(extruderCount, len(obj._meshList))
 
+               extruderCount = max(extruderCount, profile.minimalExtruderCount())
+
                commandList = [getEngineFilename(), '-vv']
                for k, v in self._engineSettings(extruderCount).iteritems():
                        commandList += ['-s', '%s=%s' % (k, str(v))]
@@ -127,6 +131,21 @@ class Slicer(object):
                        order = scene.printOrder()
                        if order is None:
                                pos = numpy.array(profile.getMachineCenterCoords()) * 1000
+                               objMin = None
+                               objMax = None
+                               for obj in scene.objects():
+                                       if scene.checkPlatform(obj):
+                                               oMin = obj.getMinimum()[0:2] + obj.getPosition()
+                                               oMax = obj.getMaximum()[0:2] + obj.getPosition()
+                                               if objMin is None:
+                                                       objMin = oMin
+                                                       objMax = oMax
+                                               else:
+                                                       objMin[0] = min(oMin[0], objMin[0])
+                                                       objMin[1] = min(oMin[1], objMin[1])
+                                                       objMax[0] = max(oMax[0], objMax[0])
+                                                       objMax[1] = max(oMax[1], objMax[1])
+                               pos += (objMin + objMax) / 2.0 * 1000
                                commandList += ['-s', 'posx=%d' % int(pos[0]), '-s', 'posy=%d' % int(pos[1])]
 
                                vertexTotal = 0
@@ -184,7 +203,7 @@ class Slicer(object):
                self._callback(0.0, False)
                self._sliceLog = []
                self._printTimeSeconds = None
-               self._filamentMM = None
+               self._filamentMM = [0.0, 0.0]
 
                line = self._process.stdout.readline()
                objectNr = 0
@@ -208,10 +227,15 @@ class Slicer(object):
                        elif line.startswith('Print time:'):
                                self._printTimeSeconds = int(line.split(':')[1].strip())
                        elif line.startswith('Filament:'):
-                               self._filamentMM = int(line.split(':')[1].strip())
+                               self._filamentMM[0] = int(line.split(':')[1].strip())
                                if profile.getMachineSetting('gcode_flavor') == 'UltiGCode':
                                        radius = profile.getProfileSettingFloat('filament_diameter') / 2.0
-                                       self._filamentMM /= (math.pi * radius * radius)
+                                       self._filamentMM[0] /= (math.pi * radius * radius)
+                       elif line.startswith('Filament2:'):
+                               self._filamentMM[1] = int(line.split(':')[1].strip())
+                               if profile.getMachineSetting('gcode_flavor') == 'UltiGCode':
+                                       radius = profile.getProfileSettingFloat('filament_diameter') / 2.0
+                                       self._filamentMM[1] /= (math.pi * radius * radius)
                        else:
                                self._sliceLog.append(line.strip())
                        line = self._process.stdout.readline()
@@ -249,7 +273,6 @@ class Slicer(object):
                        'printSpeed': int(profile.getProfileSettingFloat('print_speed')),
                        'infillSpeed': int(profile.getProfileSettingFloat('infill_speed')) if int(profile.getProfileSettingFloat('infill_speed')) > 0 else int(profile.getProfileSettingFloat('print_speed')),
                        'moveSpeed': int(profile.getProfileSettingFloat('travel_speed')),
-                       'fanOnLayerNr': int(profile.getProfileSettingFloat('fan_layer')),
                        'fanSpeedMin': int(profile.getProfileSettingFloat('fan_speed')) if profile.getProfileSetting('fan_enabled') == 'True' else 0,
                        'fanSpeedMax': int(profile.getProfileSettingFloat('fan_speed_max')) if profile.getProfileSetting('fan_enabled') == 'True' else 0,
                        'supportAngle': int(-1) if profile.getProfileSetting('support') == 'None' else int(60),
@@ -257,7 +280,7 @@ class Slicer(object):
                        'supportLineDistance': int(100 * profile.calculateEdgeWidth() * 1000 / profile.getProfileSettingFloat('support_fill_rate')) if profile.getProfileSettingFloat('support_fill_rate') > 0 else -1,
                        'supportXYDistance': int(1000 * profile.getProfileSettingFloat('support_xy_distance')),
                        'supportZDistance': int(1000 * profile.getProfileSettingFloat('support_z_distance')),
-                       'supportExtruder': 0 if profile.getProfileSetting('support_dual_extrusion') == 'First extruder' else (1 if profile.getProfileSetting('support_dual_extrusion') == 'Second extruder' else -1),
+                       'supportExtruder': 0 if profile.getProfileSetting('support_dual_extrusion') == 'First extruder' else (1 if profile.getProfileSetting('support_dual_extrusion') == 'Second extruder' and profile.minimalExtruderCount() > 1 else -1),
                        'retractionAmount': int(profile.getProfileSettingFloat('retraction_amount') * 1000) if profile.getProfileSetting('retraction_enable') == 'True' else 0,
                        'retractionSpeed': int(profile.getProfileSettingFloat('retraction_speed')),
                        'retractionMinimalDistance': int(profile.getProfileSettingFloat('retraction_min_travel') * 1000),
@@ -280,6 +303,11 @@ class Slicer(object):
                        'extruderOffset[3].Y': int(profile.getMachineSettingFloat('extruder_offset_y3') * 1000),
                        'fixHorrible': 0,
                }
+               fanFullHeight = int(profile.getProfileSettingFloat('fan_full_height') * 1000)
+               settings['fanFullOnLayerNr'] = (fanFullHeight - settings['initialLayerThickness'] - 1) / settings['layerThickness'] + 1
+               if settings['fanFullOnLayerNr'] < 0:
+                       settings['fanFullOnLayerNr'] = 0
+
                if profile.getProfileSettingFloat('fill_density') == 0:
                        settings['sparseInfillLineDistance'] = -1
                elif profile.getProfileSettingFloat('fill_density') == 100:
@@ -320,6 +348,12 @@ class Slicer(object):
                        settings['layerThickness'] = 1000
                if profile.getMachineSetting('gcode_flavor') == 'UltiGCode':
                        settings['gcodeFlavor'] = 1
+               if profile.getProfileSetting('spiralize') == 'True':
+                       settings['spiralizeMode'] = 1
+               if profile.getProfileSetting('wipe_tower') == 'True':
+                       settings['enableWipeTower'] = 1
+               if profile.getProfileSetting('ooze_shield') == 'True':
+                       settings['enableOozeShield'] = 1
                return settings
 
        def _runSliceProcess(self, cmdList):