def mcStateChange(self, state): if self.comm is None: return if self.comm.isOperational(): if self._wizardState == 0: wx.CallAfter(self.infoBox.SetInfo, 'Homing printer...') self.comm.sendCommand('M105') self.comm.sendCommand('G28') self._wizardState = 1 elif self._wizardState == 10 and not self.comm.isPrinting(): self.comm.sendCommand( 'G1 Z15 F%d' % (profile.getProfileSettingFloat('max_z_speed') * 60)) self.comm.sendCommand('G92 E0') self.comm.sendCommand( 'G1 E-10 F%d' % (profile.getProfileSettingFloat('retraction_speed') * 60)) self.comm.sendCommand('M104 S0') wx.CallAfter( self.infoBox.SetInfo, 'Calibration finished.\nThe squares on the bed should slightly touch each other.' ) wx.CallAfter(self.infoBox.SetReadyIndicator) wx.CallAfter(self.GetParent().FindWindowById( wx.ID_FORWARD).Enable) wx.CallAfter(self.connectButton.Enable, True) self._wizardState = 11 elif self.comm.isError(): wx.CallAfter( self.infoBox.SetError, 'Failed to establish connection with the printer.', 'http://wiki.ultimaker.com/Cura:_Connection_problems')
def loadModelFiles(self, filelist, showWarning = False): while len(filelist) > len(self.objectList): self.objectList.append(previewObject()) for idx in xrange(len(filelist), len(self.objectList)): self.objectList[idx].mesh = None self.objectList[idx].filename = None for idx in xrange(0, len(filelist)): obj = self.objectList[idx] if obj.filename != filelist[idx]: obj.fileTime = None self.gcodeFileTime = None self.logFileTime = None obj.filename = filelist[idx] self.gcodeFilename = sliceRun.getExportFilename(filelist[0]) #Do the STL file loading in a background thread so we don't block the UI. if self.loadThread != None and self.loadThread.isAlive(): self.loadThread.join() self.loadThread = threading.Thread(target=self.doFileLoadThread) self.loadThread.daemon = True self.loadThread.start() if showWarning: if profile.getProfileSettingFloat('model_scale') != 1.0 or profile.getProfileSettingFloat('model_rotate_base') != 0 or profile.getProfileSetting('flip_x') != 'False' or profile.getProfileSetting('flip_y') != 'False' or profile.getProfileSetting('flip_z') != 'False' or profile.getProfileSetting('swap_xz') != 'False' or profile.getProfileSetting('swap_yz') != 'False' or len(profile.getPluginConfig()) > 0: self.ShowWarningPopup('Reset scale, rotation, mirror and plugins?', self.OnResetAll)
def OnScaleMax(self): if self.objectsMinV is None: return vMin = self.objectsMinV vMax = self.objectsMaxV skirtSize = 3 if profile.getProfileSettingFloat('skirt_line_count') > 0: skirtSize = 3 + profile.getProfileSettingFloat( 'skirt_line_count') * profile.calculateEdgeWidth( ) + profile.getProfileSettingFloat('skirt_gap') scaleX1 = (self.machineSize.x - self.machineCenter.x - skirtSize) / ( (vMax[0] - vMin[0]) / 2) scaleY1 = (self.machineSize.y - self.machineCenter.y - skirtSize) / ( (vMax[1] - vMin[1]) / 2) scaleX2 = (self.machineCenter.x - skirtSize) / ( (vMax[0] - vMin[0]) / 2) scaleY2 = (self.machineCenter.y - skirtSize) / ( (vMax[1] - vMin[1]) / 2) scaleZ = self.machineSize.z / (vMax[2] - vMin[2]) scale = min(scaleX1, scaleY1, scaleX2, scaleY2, scaleZ) self.matrix *= numpy.matrix( [[scale, 0, 0], [0, scale, 0], [0, 0, scale]], numpy.float64) if self.glCanvas.viewMode == 'GCode' or self.glCanvas.viewMode == 'Mixed': self.setViewMode('Normal') self.updateModelTransform()
def OnResume(self, e): feedZ = profile.getProfileSettingFloat('max_z_speed') * 60 feedTravel = profile.getProfileSettingFloat('travel_speed') * 60 if self._wizardState == 2: wx.CallAfter(self.infoBox.SetBusy, 'Moving head to back left corner...') self.comm.sendCommand('G1 Z3 F%d' % (feedZ)) self.comm.sendCommand('G1 X%d Y%d F%d' % (0, profile.getPreferenceFloat('machine_depth'), feedTravel)) self.comm.sendCommand('G1 Z0 F%d' % (feedZ)) self.comm.sendCommand('M400') self._wizardState = 3 elif self._wizardState == 4: wx.CallAfter(self.infoBox.SetBusy, 'Moving head to back right corner...') self.comm.sendCommand('G1 Z3 F%d' % (feedZ)) self.comm.sendCommand('G1 X%d Y%d F%d' % (profile.getPreferenceFloat('machine_width'), profile.getPreferenceFloat('machine_depth') - 20, feedTravel)) self.comm.sendCommand('G1 Z0 F%d' % (feedZ)) self.comm.sendCommand('M400') self._wizardState = 5 elif self._wizardState == 6: wx.CallAfter(self.infoBox.SetBusy, 'Moving head to front right corner...') self.comm.sendCommand('G1 Z3 F%d' % (feedZ)) self.comm.sendCommand('G1 X%d Y%d F%d' % (profile.getPreferenceFloat('machine_width'), 20, feedTravel)) self.comm.sendCommand('G1 Z0 F%d' % (feedZ)) self.comm.sendCommand('M400') self._wizardState = 7 elif self._wizardState == 8: wx.CallAfter(self.infoBox.SetBusy, 'Heating up printer...') self.comm.sendCommand('G1 Z15 F%d' % (feedZ)) self.comm.sendCommand('M104 S%d' % (profile.getProfileSettingFloat('print_temperature'))) self.comm.sendCommand('G1 X%d Y%d F%d' % (0, 0, feedTravel)) self._wizardState = 9 self.resumeButton.Enable(False)
def mcStateChange(self, state): if self.comm is None: return if self.comm.isOperational(): if self._wizardState == 0: wx.CallAfter(self.infoBox.SetInfo, "Homing printer...") self.comm.sendCommand("M105") self.comm.sendCommand("G28") self._wizardState = 1 elif self._wizardState == 10 and not self.comm.isPrinting(): self.comm.sendCommand("G1 Z15 F%d" % (profile.getProfileSettingFloat("max_z_speed") * 60)) self.comm.sendCommand("G92 E0") self.comm.sendCommand("G1 E-10 F%d" % (profile.getProfileSettingFloat("retraction_speed") * 60)) self.comm.sendCommand("M104 S0") wx.CallAfter( self.infoBox.SetInfo, "Calibration finished.\nThe squares on the bed should slightly touch each other.", ) wx.CallAfter(self.infoBox.SetReadyIndicator) wx.CallAfter(self.GetParent().FindWindowById(wx.ID_FORWARD).Enable) wx.CallAfter(self.connectButton.Enable, True) self._wizardState = 11 elif self.comm.isError(): wx.CallAfter( self.infoBox.SetError, "Failed to establish connection with the printer.", "http://wiki.ultimaker.com/Cura:_Connection_problems", )
def validate(self): from Cura.util import profile try: wallThickness = profile.getProfileSettingFloat('wall_thickness') nozzleSize = profile.getProfileSettingFloat('nozzle_size') if wallThickness < 0.01: return SUCCESS, '' if wallThickness <= nozzleSize * 0.5: return ERROR, 'Trying to print walls thinner then the half of your nozzle size, this will not produce anything usable' if wallThickness <= nozzleSize * 0.85: return WARNING, 'Trying to print walls thinner then the 0.8 * nozzle size. Small chance that this will produce usable results' if wallThickness < nozzleSize: return SUCCESS, '' if nozzleSize <= 0: return ERROR, 'Incorrect nozzle size' lineCount = int(wallThickness / nozzleSize) lineWidth = wallThickness / lineCount lineWidthAlt = wallThickness / (lineCount + 1) if lineWidth >= nozzleSize * 1.5 and lineWidthAlt <= nozzleSize * 0.85: return WARNING, 'Current selected wall thickness results in a line thickness of ' + str( lineWidthAlt ) + 'mm which is not recommended with your nozzle of ' + str( nozzleSize) + 'mm' return SUCCESS, '' except ValueError: #We already have an error by the int/float validator in this case. return SUCCESS, ''
def validate(self): from Cura.util import profile try: nozzleSize = profile.getProfileSettingFloat("nozzle_size") layerHeight = profile.getProfileSettingFloat("layer_height") raw_user_input = self.setting.getValue() new_print_speed = raw_user_input.replace(",", ".") try: evaluated = eval(new_print_speed, {}, {}) # Converts unicode into numeric except SyntaxError: # Caused by unicode string being empty evaluated = 0.0 printSpeed = float(evaluated) if printSpeed == 0.0: printSpeed = profile.getProfileSettingFloat("print_speed") printVolumePerMM = layerHeight * nozzleSize printVolumePerSecond = printVolumePerMM * printSpeed # Using 8mm3 per second with a 0.4mm nozzle maxPrintVolumePerSecond = 8 / (math.pi * (0.2 * 0.2)) * (math.pi * (nozzleSize / 2 * nozzleSize / 2)) if printVolumePerSecond > maxPrintVolumePerSecond: return ( WARNING, "You are trying to print more then %.1fmm^3 of filament per second. This might cause filament slipping. (You are printing at %0.1fmm^3 per second)" % (maxPrintVolumePerSecond, printVolumePerSecond), ) return SUCCESS, "You are printing at %0.1fmm^3 per second" % (printVolumePerSecond) except ValueError: # We already have an error by the int/float validator in this case. return SUCCESS, ""
def validate(self): from Cura.util import profile try: nozzleSize = profile.getProfileSettingFloat('nozzle_size') layerHeight = profile.getProfileSettingFloat('layer_height') printSpeed = float( eval(self.setting.getValue().replace(',', '.'), {}, {})) if printSpeed == 0.0: printSpeed = profile.getProfileSettingFloat('print_speed') printVolumePerMM = layerHeight * nozzleSize printVolumePerSecond = printVolumePerMM * printSpeed #Using 8mm3 per second with a 0.4mm nozzle maxPrintVolumePerSecond = 8 / (math.pi * (0.2 * 0.2)) * ( math.pi * (nozzleSize / 2 * nozzleSize / 2)) if printVolumePerSecond > maxPrintVolumePerSecond: return WARNING, 'You are trying to print more then %.1fmm^3 of filament per second. This might cause filament slipping. (You are printing at %0.1fmm^3 per second)' % ( maxPrintVolumePerSecond, printVolumePerSecond) return SUCCESS, 'You are printing at %0.1fmm^3 per second' % ( printVolumePerSecond) except ValueError: #We already have an error by the int/float validator in this case. return SUCCESS, ''
def validate(self): from Cura.util import profile try: wallThickness = profile.getProfileSettingFloat('wall_thickness') nozzleSize = profile.getProfileSettingFloat('nozzle_size') if wallThickness < 0.01: return SUCCESS, '' if wallThickness <= nozzleSize * 0.5: return ERROR, 'Trying to print walls thinner then the half of your nozzle size, this will not produce anything usable' if wallThickness <= nozzleSize * 0.85: return WARNING, 'Trying to print walls thinner then the 0.8 * nozzle size. Small chance that this will produce usable results' if wallThickness < nozzleSize: return SUCCESS, '' if nozzleSize <= 0: return ERROR, 'Incorrect nozzle size' lineCount = int(wallThickness / nozzleSize) lineWidth = wallThickness / lineCount lineWidthAlt = wallThickness / (lineCount + 1) if lineWidth >= nozzleSize * 1.5 and lineWidthAlt <= nozzleSize * 0.85: return WARNING, 'Current selected wall thickness results in a line thickness of ' + str(lineWidthAlt) + 'mm which is not recommended with your nozzle of ' + str(nozzleSize) + 'mm' return SUCCESS, '' except ValueError: #We already have an error by the int/float validator in this case. return SUCCESS, ''
def calcLayerSkip(setting): bottomThickness = profile.getProfileSettingFloat('bottom_thickness') layerThickness = profile.getProfileSettingFloat('layer_height') if bottomThickness < layerThickness: return 0 return int( math.ceil((bottomThickness - layerThickness) / layerThickness + 0.0001) - 1)
def calculateCost(self): cost_kg = profile.getProfileSettingFloat('filament_cost_kg') cost_meter = profile.getProfileSettingFloat('filament_cost_meter') if cost_kg > 0.0 and cost_meter > 0.0: return "%.2f euros / %.2f euros" % (self.calculateWeight() * cost_kg, self.extrusionAmount / 1000 * cost_meter) elif cost_kg > 0.0: return "%.2f euros" % (self.calculateWeight() * cost_kg) elif cost_meter > 0.0: return "%.2f euros" % (self.extrusionAmount / 1000 * cost_meter) return None
def __init__(self): self._feedPrint = profile.getProfileSettingFloat('print_speed') * 60 self._feedTravel = profile.getProfileSettingFloat('travel_speed') * 60 self._feedRetract = profile.getProfileSettingFloat('retraction_speed') * 60 filamentRadius = profile.getProfileSettingFloat('filament_diameter') / 2 filamentArea = math.pi * filamentRadius * filamentRadius self._ePerMM = (profile.getProfileSettingFloat('nozzle_size') * 0.1) / filamentArea self._eValue = 0.0 self._x = 0 self._y = 0 self._z = 0 self._list = ['M110', 'G92 E0']
def updateModelTransform(self, f=0): if len(self.objectList) < 1 or self.objectList[0].mesh == None: return rotate = profile.getProfileSettingFloat('model_rotate_base') mirrorX = profile.getProfileSetting('flip_x') == 'True' mirrorY = profile.getProfileSetting('flip_y') == 'True' mirrorZ = profile.getProfileSetting('flip_z') == 'True' swapXZ = profile.getProfileSetting('swap_xz') == 'True' swapYZ = profile.getProfileSetting('swap_yz') == 'True' for obj in self.objectList: if obj.mesh == None: continue obj.mesh.setRotateMirror(rotate, mirrorX, mirrorY, mirrorZ, swapXZ, swapYZ) minV = self.objectList[0].mesh.getMinimum() maxV = self.objectList[0].mesh.getMaximum() objectsBounderyCircleSize = self.objectList[0].mesh.bounderyCircleSize for obj in self.objectList: if obj.mesh == None: continue obj.mesh.getMinimumZ() minV = numpy.minimum(minV, obj.mesh.getMinimum()) maxV = numpy.maximum(maxV, obj.mesh.getMaximum()) objectsBounderyCircleSize = max(objectsBounderyCircleSize, obj.mesh.bounderyCircleSize) self.objectsMaxV = maxV self.objectsMinV = minV self.objectsBounderyCircleSize = objectsBounderyCircleSize for obj in self.objectList: if obj.mesh == None: continue obj.mesh.vertexes -= numpy.array([minV[0] + (maxV[0] - minV[0]) / 2, minV[1] + (maxV[1] - minV[1]) / 2, minV[2]]) #for v in obj.mesh.vertexes: # v[2] -= minV[2] # v[0] -= minV[0] + (maxV[0] - minV[0]) / 2 # v[1] -= minV[1] + (maxV[1] - minV[1]) / 2 obj.mesh.getMinimumZ() obj.dirty = True scale = profile.getProfileSettingFloat('model_scale') size = (self.objectsMaxV - self.objectsMinV) * scale self.toolbarInfo.SetValue('%0.1f %0.1f %0.1f' % (size[0], size[1], size[2])) self.glCanvas.Refresh()
def calculateWeight(self): #Calculates the weight of the filament in kg radius = getProfileSettingFloat('filament_diameter') / 2 volumeM3 = (self.extrusionAmount * (math.pi * radius * radius)) / (1000 * 1000 * 1000) return volumeM3 * profile.getProfileSettingFloat( 'filament_physical_density')
def _load_profile_settings(self): self._layer_height = profile.getProfileSettingFloat('layer_height') self._spiralize = profile.getProfileSetting('spiralize') self._filament_diameter = profile.getProfileSetting('filament_diameter') self._filament_physical_density = profile.getPreferenceFloat('filament_physical_density') self._filament_cost_kg = profile.getPreferenceFloat('filament_cost_kg') self._filament_cost_meter = profile.getPreferenceFloat('filament_cost_meter')
def OnPaint(self,e): dc = wx.PaintDC(self) if not hasOpenGLlibs: dc.Clear() dc.DrawText("No PyOpenGL installation found.\nNo preview window available.", 10, 10) return self.SetCurrent(self.context) opengl.InitGL(self, self.view3D, self.zoom) if self.view3D: glTranslate(0,0,-self.zoom) glRotate(-self.pitch, 1,0,0) glRotate(self.yaw, 0,0,1) if self.viewMode == "GCode" or self.viewMode == "Mixed": if self.parent.gcode != None and len(self.parent.gcode.layerList) > self.parent.layerSpin.GetValue() and len(self.parent.gcode.layerList[self.parent.layerSpin.GetValue()]) > 0: glTranslate(0,0,-self.parent.gcode.layerList[self.parent.layerSpin.GetValue()][0].list[-1].z) else: if self.parent.objectsMaxV != None: glTranslate(0,0,-(self.parent.objectsMaxV[2]-self.parent.objectsMinV[2]) * profile.getProfileSettingFloat('model_scale') / 2) else: glTranslate(self.offsetX, self.offsetY, 0) self.viewport = glGetIntegerv(GL_VIEWPORT); self.modelMatrix = glGetDoublev(GL_MODELVIEW_MATRIX); self.projMatrix = glGetDoublev(GL_PROJECTION_MATRIX); glTranslate(-self.parent.machineCenter.x, -self.parent.machineCenter.y, 0) self.OnDraw() self.SwapBuffers()
def mcStateChange(self, state): if self.comm is None: return if self.comm.isOperational(): if self._wizardState == 0: wx.CallAfter(self.infoBox.SetInfo, 'Homing printer and heating up both extruders.') self.comm.sendCommand('M105') self.comm.sendCommand('M104 S220 T0') self.comm.sendCommand('M104 S220 T1') self.comm.sendCommand('G28') self.comm.sendCommand('G1 Z15 F%d' % (profile.getProfileSettingFloat('print_speed') * 60)) self._wizardState = 1 if not self.comm.isPrinting(): if self._wizardState == 3: self._wizardState = 4 wx.CallAfter(self.infoBox.SetAttention, 'Please measure the distance between the vertical lines in millimeters.') wx.CallAfter(self.textEntry.SetValue, '0.0') wx.CallAfter(self.textEntry.Enable, True) wx.CallAfter(self.resumeButton.Enable, True) wx.CallAfter(self.resumeButton.SetFocus) elif self._wizardState == 6: self._wizardState = 7 wx.CallAfter(self.infoBox.SetAttention, 'Which vertical line number lays perfect on top of each other? Leftmost line is zero.') wx.CallAfter(self.textEntry.SetValue, '10') wx.CallAfter(self.textEntry.Enable, True) wx.CallAfter(self.resumeButton.Enable, True) wx.CallAfter(self.resumeButton.SetFocus) elif self.comm.isError(): wx.CallAfter(self.infoBox.SetError, 'Failed to establish connection with the printer.', 'http://wiki.ultimaker.com/Cura:_Connection_problems')
def OnSettingChange(self, e): changed_panel = e.GetEventObject().GetParent() panelChildren = changed_panel.GetSizer().GetChildren() for panelChild in panelChildren: panelWidget = panelChild.GetWindow() # The only disabled textctrl by line is the one containing the height info if isinstance(panelWidget, wx.TextCtrl) and not panelWidget.IsEnabled(): height_value = 0 try: height_value = float( e.GetEventObject().GetValue()) * float( profile.getProfileSettingFloat('layer_height')) except: print "Invalid user value in pause input: '%s'" % e.GetEventObject( ).GetValue() if (e.IsCommandEvent()): panelWidget.SetValue(str(height_value) + ' mm') for panel in self.panelList: idx = self.panelList.index(panel) for k in panel.paramCtrls.keys(): self.pluginConfig[idx]['params'][k] = panel.paramCtrls[ k].GetValue() pluginInfo.setPostProcessPluginConfig(self.pluginConfig) self.callback()
def StoreData(self): profile.putPreference('machine_width', self.machineWidth.GetValue()) profile.putPreference('machine_depth', self.machineDepth.GetValue()) profile.putPreference('machine_height', self.machineHeight.GetValue()) profile.putProfileSetting('nozzle_size', self.nozzleSize.GetValue()) profile.putProfileSetting('wall_thickness', float(profile.getProfileSettingFloat('nozzle_size')) * 2) profile.putPreference('has_heated_bed', str(self.heatedBed.GetValue()))
def updateHeadSize(self, obj=None): xMin = profile.getMachineSettingFloat('extruder_head_size_min_x') xMax = profile.getMachineSettingFloat('extruder_head_size_max_x') yMin = profile.getMachineSettingFloat('extruder_head_size_min_y') yMax = profile.getMachineSettingFloat('extruder_head_size_max_y') gantryHeight = profile.getMachineSettingFloat( 'extruder_head_size_height') objectSink = profile.getProfileSettingFloat("object_sink") self._leftToRight = xMin < xMax self._frontToBack = yMin < yMax self._headSizeOffsets[0] = min(xMin, xMax) self._headSizeOffsets[1] = min(yMin, yMax) self._gantryHeight = gantryHeight self._oneAtATime = self._gantryHeight > 0 and profile.getPreference( 'oneAtATime') == 'True' for obj in self._objectList: if obj.getSize()[2] - objectSink > self._gantryHeight: self._oneAtATime = False headArea = numpy.array( [[-xMin, -yMin], [xMax, -yMin], [xMax, yMax], [-xMin, yMax]], numpy.float32) if obj is None: for obj in self._objectList: obj.setHeadArea(headArea, self._headSizeOffsets) else: obj.setHeadArea(headArea, self._headSizeOffsets)
def _renderObject(self, obj, brightness = False, addSink = True): glPushMatrix() if addSink: glTranslate(obj.getPosition()[0], obj.getPosition()[1], obj.getSize()[2] / 2 - profile.getProfileSettingFloat('object_sink')) else: glTranslate(obj.getPosition()[0], obj.getPosition()[1], obj.getSize()[2] / 2) if self.tempMatrix is not None and obj == self._selectedObj: tempMatrix = opengl.convert3x3MatrixTo4x4(self.tempMatrix) glMultMatrixf(tempMatrix) offset = obj.getDrawOffset() glTranslate(-offset[0], -offset[1], -offset[2] - obj.getSize()[2] / 2) tempMatrix = opengl.convert3x3MatrixTo4x4(obj.getMatrix()) glMultMatrixf(tempMatrix) n = 0 for m in obj._meshList: if m.vbo is None: m.vbo = opengl.GLVBO(m.vertexes, m.normal) if brightness: glColor4fv(map(lambda n: n * brightness, self._objColors[n])) n += 1 m.vbo.render() glPopMatrix()
def validate(self): from Cura.util import profile try: wallThickness = profile.getProfileSettingFloat("wall_thickness") nozzleSize = profile.getProfileSettingFloat("nozzle_size") if wallThickness < 0.01: return SUCCESS, "" if wallThickness <= nozzleSize * 0.5: return ( ERROR, "Trying to print walls thinner then the half of your nozzle size, this will not produce anything usable", ) if wallThickness <= nozzleSize * 0.85: return ( WARNING, "Trying to print walls thinner then the 0.8 * nozzle size. Small chance that this will produce usable results", ) if wallThickness < nozzleSize: return SUCCESS, "" if nozzleSize <= 0: return ERROR, "Incorrect nozzle size" lineCount = int(wallThickness / nozzleSize) lineWidth = wallThickness / lineCount lineWidthAlt = wallThickness / (lineCount + 1) if lineWidth >= nozzleSize * 1.5 and lineWidthAlt <= nozzleSize * 0.85: return ( WARNING, "Current selected shell thickness results in a line thickness of " + str(lineWidthAlt) + "mm which is not recommended with your nozzle of " + str(nozzleSize) + "mm", ) if ( abs((lineCount * nozzleSize) - wallThickness) > 0.01 and abs(((lineCount + 1) * nozzleSize) - wallThickness) > 0.01 ): return ( WARNING, "Currently selected shell thickness is not a multiple of the nozzle size. While this prints fine, it does not give optimal results.", ) return SUCCESS, "" except ValueError: # We already have an error by the int/float validator in this case. return SUCCESS, ""
def _buildPluginPanel(self, pluginConfig): pausePluginPanel = wx.Panel(self.pluginEnabledPanel) s = wx.GridBagSizer(1, 4) pausePluginPanel.SetSizer(s) pausePluginPanel.paramCtrls = {} scene = self.GetParent().GetParent().GetParent().GetParent().scene remButton1 = wx.Button(pausePluginPanel, id=-1, label="x", style=wx.BU_EXACTFIT) s.Add(remButton1, pos=(0, 0), span=(1, 1), flag=wx.ALIGN_LEFT) i = 1 for param in self.plugin.getParams(): #value = param['default'] value = '' if param['name'] in pluginConfig['params']: value = pluginConfig['params'][param['name']] ctrl = wx.TextCtrl(pausePluginPanel, -1, value) height_value = float(value) * float( profile.getProfileSettingFloat('layer_height')) height_label = wx.TextCtrl(pausePluginPanel, -1, str(height_value) + ' mm') height_label.Disable() if value == '': ctrl.Disable() s.Add(ctrl, pos=(0, i), span=(1, 1), flag=wx.EXPAND) s.Add(height_label, pos=(0, i + 1), span=(1, 1), flag=wx.EXPAND) ctrl.Bind(wx.EVT_TEXT, self.OnSettingChange) pausePluginPanel.paramCtrls[param['name']] = ctrl i += 1 remButton2 = wx.Button(pausePluginPanel, id=-1, label="x", style=wx.BU_EXACTFIT) s.Add(remButton2, pos=(0, i + 1), span=(1, 1), flag=wx.ALIGN_LEFT) s.AddGrowableCol(1) s.AddGrowableCol(2) self.Bind(wx.EVT_BUTTON, self.OnRem, remButton1) self.Bind(wx.EVT_BUTTON, self.OnRem, remButton2) pausePluginPanel.SetBackgroundColour( self.GetParent().GetBackgroundColour()) pausePluginPanel.Layout() self.pluginEnabledPanel.GetSizer().Add(pausePluginPanel, flag=wx.EXPAND | wx.LEFT | wx.RIGHT) self.pluginEnabledPanel.Layout() self.pluginEnabledPanel.SetSize((1, 1)) self.Layout() self.pluginEnabledPanel.ScrollChildIntoView(pausePluginPanel) self.panelList.append(pausePluginPanel) return True
def StoreData(self): profile.putPreference("machine_width", self.machineWidth.GetValue()) profile.putPreference("machine_depth", self.machineDepth.GetValue()) profile.putPreference("machine_height", self.machineHeight.GetValue()) profile.putProfileSetting("nozzle_size", self.nozzleSize.GetValue()) profile.putProfileSetting("wall_thickness", float(profile.getProfileSettingFloat("nozzle_size")) * 2) profile.putPreference("has_heated_bed", str(self.heatedBed.GetValue())) profile.putPreference("machine_center_is_zero", str(self.HomeAtCenter.GetValue()))
def validate(self): from Cura.util import profile try: fill_distance = profile.getProfileSettingFloat('fill_distance') infill_type = profile.getProfileSetting('infill_type') # print infill_type if infill_type == 'None': return DISABLED, 'Infill has been disabled' else : if profile.getProfileSettingFloat('fill_distance') < profile.calculateEdgeWidth() : return ERROR, 'Distance between infill cannot be less than extrusion width : '+str(profile.calculateEdgeWidth()) +'mm' #elif profile.getProfileSettingFloat('fill_distance') > 0: # return SUCCESS return SUCCESS, '' except ValueError: #We already have an error by the int/float validator in this case. return SUCCESS, ''
def OnScaleMax(self): if self.objectsMinV is None: return vMin = self.objectsMinV vMax = self.objectsMaxV skirtSize = 3 if profile.getProfileSettingFloat('skirt_line_count') > 0: skirtSize = 3 + profile.getProfileSettingFloat('skirt_line_count') * profile.calculateEdgeWidth() + profile.getProfileSettingFloat('skirt_gap') scaleX1 = (self.machineSize.x - self.machineCenter.x - skirtSize) / ((vMax[0] - vMin[0]) / 2) scaleY1 = (self.machineSize.y - self.machineCenter.y - skirtSize) / ((vMax[1] - vMin[1]) / 2) scaleX2 = (self.machineCenter.x - skirtSize) / ((vMax[0] - vMin[0]) / 2) scaleY2 = (self.machineCenter.y - skirtSize) / ((vMax[1] - vMin[1]) / 2) scaleZ = self.machineSize.z / (vMax[2] - vMin[2]) scale = min(scaleX1, scaleY1, scaleX2, scaleY2, scaleZ) self.matrix *= numpy.matrix([[scale,0,0],[0,scale,0],[0,0,scale]], numpy.float64) if self.glCanvas.viewMode == 'GCode' or self.glCanvas.viewMode == 'Mixed': self.setViewMode('Normal') self.updateModelTransform()
def validate(self): try: nozzleSize = profile.getProfileSettingFloat('nozzle_size') layerHeight = profile.getProfileSettingFloat('layer_height') printSpeed = profile.getProfileSettingFloat('print_speed') printVolumePerMM = layerHeight * nozzleSize printVolumePerSecond = printVolumePerMM * printSpeed #Using 10mm3 per second with a 0.4mm nozzle (normal max according to Joergen Geerds) maxPrintVolumePerSecond = 10 / (math.pi*(0.2*0.2)) * (math.pi*(nozzleSize/2*nozzleSize/2)) if printVolumePerSecond > maxPrintVolumePerSecond: return WARNING, 'You are trying to print more then %.1fmm^3 of filament per second. This might cause filament slipping. (You are printing at %0.1fmm^3 per second)' % (maxPrintVolumePerSecond, printVolumePerSecond) return SUCCESS, '' except ValueError: #We already have an error by the int/float validator in this case. return SUCCESS, ''
def _gcodeToVBO_quads(self, gcodeLayers, extrudeType): useFilamentArea = profile.getMachineSetting( 'gcode_flavor') == 'UltiGCode' filamentRadius = profile.getProfileSettingFloat( 'filament_diameter') / 2 filamentArea = math.pi * filamentRadius * filamentRadius if ':' in extrudeType: extruder = int(extrudeType[extrudeType.find(':') + 1:]) extrudeType = extrudeType[0:extrudeType.find(':')] else: extruder = None verts = numpy.zeros((0, 3), numpy.float32) indices = numpy.zeros((0), numpy.uint32) for layer in gcodeLayers: for path in layer: if path['type'] == 'extrude' and path[ 'pathType'] == extrudeType and ( extruder is None or path['extruder'] == extruder): a = path['points'] if extrudeType == 'FILL': a[:, 2] += 0.01 #Construct the normals of each line 90deg rotated on the X/Y plane normals = a[1:] - a[:-1] lengths = numpy.sqrt(normals[:, 0]**2 + normals[:, 1]**2) normals[:, 0], normals[:, 1] = -normals[:, 1] / lengths, normals[:, 0] / lengths normals[:, 2] /= lengths ePerDist = path['extrusion'][1:] / lengths if useFilamentArea: lineWidth = ePerDist / path['layerThickness'] / 2.0 else: lineWidth = ePerDist * (filamentArea / path['layerThickness'] / 2) normals[:, 0] *= lineWidth normals[:, 1] *= lineWidth b = numpy.zeros((len(a) - 1, 0), numpy.float32) b = numpy.concatenate((b, a[1:] + normals), 1) b = numpy.concatenate((b, a[1:] - normals), 1) b = numpy.concatenate((b, a[:-1] - normals), 1) b = numpy.concatenate((b, a[:-1] + normals), 1) b = b.reshape((len(b) * 4, 3)) i = numpy.arange(len(verts), len(verts) + len(b), 1, numpy.uint32) verts = numpy.concatenate((verts, b)) indices = numpy.concatenate((indices, i)) return openglHelpers.GLVBO(GL_QUADS, verts, indicesArray=indices)
def updateProfileToControls(self): self.scale.SetValue(profile.getProfileSetting('model_scale')) self.rotate.SetValue(profile.getProfileSettingFloat('model_rotate_base')) self.mirrorX.SetValue(profile.getProfileSetting('flip_x') == 'True') self.mirrorY.SetValue(profile.getProfileSetting('flip_y') == 'True') self.mirrorZ.SetValue(profile.getProfileSetting('flip_z') == 'True') self.swapXZ.SetValue(profile.getProfileSetting('swap_xz') == 'True') self.swapYZ.SetValue(profile.getProfileSetting('swap_yz') == 'True') self.updateModelTransform() self.glCanvas.updateProfileToControls()
def OnScaleMax(self, e = None, onlyScaleDown = False): if self.objectsMinV is None: return vMin = self.objectsMinV vMax = self.objectsMaxV skirtSize = 3 if profile.getProfileSettingFloat('skirt_line_count') > 0: skirtSize = 3 + profile.getProfileSettingFloat('skirt_line_count') * profile.calculateEdgeWidth() + profile.getProfileSettingFloat('skirt_gap') scaleX1 = (self.machineSize.x - self.machineCenter.x - skirtSize) / ((vMax[0] - vMin[0]) / 2) scaleY1 = (self.machineSize.y - self.machineCenter.y - skirtSize) / ((vMax[1] - vMin[1]) / 2) scaleX2 = (self.machineCenter.x - skirtSize) / ((vMax[0] - vMin[0]) / 2) scaleY2 = (self.machineCenter.y - skirtSize) / ((vMax[1] - vMin[1]) / 2) scaleZ = self.machineSize.z / (vMax[2] - vMin[2]) scale = min(scaleX1, scaleY1, scaleX2, scaleY2, scaleZ) if scale > 1.0 and onlyScaleDown: return if self.glCanvas.viewMode == 'GCode' or self.glCanvas.viewMode == 'Mixed': self.setViewMode('Normal') self.glCanvas.Refresh()
def OnResume(self, e): feedZ = profile.getProfileSettingFloat('max_z_speed') * 60 feedTravel = profile.getProfileSettingFloat('travel_speed') * 60 if self._wizardState == 2: wx.CallAfter(self.infoBox.SetBusy, 'Moving head to back left corner...') self.comm.sendCommand('G1 Z3 F%d' % (feedZ)) self.comm.sendCommand( 'G1 X%d Y%d F%d' % (0, profile.getPreferenceFloat('machine_depth'), feedTravel)) self.comm.sendCommand('G1 Z0 F%d' % (feedZ)) self.comm.sendCommand('M400') self._wizardState = 3 elif self._wizardState == 4: wx.CallAfter(self.infoBox.SetBusy, 'Moving head to back right corner...') self.comm.sendCommand('G1 Z3 F%d' % (feedZ)) self.comm.sendCommand( 'G1 X%d Y%d F%d' % (profile.getPreferenceFloat('machine_width'), profile.getPreferenceFloat('machine_depth') - 25, feedTravel)) self.comm.sendCommand('G1 Z0 F%d' % (feedZ)) self.comm.sendCommand('M400') self._wizardState = 5 elif self._wizardState == 6: wx.CallAfter(self.infoBox.SetBusy, 'Moving head to front right corner...') self.comm.sendCommand('G1 Z3 F%d' % (feedZ)) self.comm.sendCommand( 'G1 X%d Y%d F%d' % (profile.getPreferenceFloat('machine_width'), 20, feedTravel)) self.comm.sendCommand('G1 Z0 F%d' % (feedZ)) self.comm.sendCommand('M400') self._wizardState = 7 elif self._wizardState == 8: wx.CallAfter(self.infoBox.SetBusy, 'Heating up printer...') self.comm.sendCommand('G1 Z15 F%d' % (feedZ)) self.comm.sendCommand( 'M104 S%d' % (profile.getProfileSettingFloat('print_temperature'))) self.comm.sendCommand('G1 X%d Y%d F%d' % (0, 0, feedTravel)) self._wizardState = 9 self.resumeButton.Enable(False)
def _load_profile_settings(self): self._layer_height = profile.getProfileSettingFloat('layer_height') self._spiralize = profile.getProfileSetting('spiralize') self._filament_diameter = profile.getProfileSetting( 'filament_diameter') self._filament_physical_density = profile.getPreferenceFloat( 'filament_physical_density') self._filament_cost_kg = profile.getPreferenceFloat('filament_cost_kg') self._filament_cost_meter = profile.getPreferenceFloat( 'filament_cost_meter')
def _watchStderr(self, stderr): objectNr = 0 line = stderr.readline() while len(line) > 0: line = line.strip() if line.startswith('Progress:'): line = line.split(':') if line[1] == 'process': objectNr += 1 elif line[1] in self._progressSteps: progressValue = float(line[2]) / float(line[3]) progressValue /= len(self._progressSteps) progressValue += 1.0 / len( self._progressSteps) * self._progressSteps.index( line[1]) progressValue /= self._objCount progressValue += 1.0 / self._objCount * objectNr try: self._callback(progressValue) except: pass elif line.startswith('Print time:'): self._result._printTimeSeconds = int( line.split(':')[1].strip()) elif line.startswith('Filament:'): self._result._filamentMM[0] = int(line.split(':')[1].strip()) if profile.getMachineSetting('gcode_flavor') == 'UltiGCode': radius = profile.getProfileSettingFloat( 'filament_diameter') / 2.0 self._result._filamentMM[0] /= (math.pi * radius * radius) elif line.startswith('Filament2:'): self._result._filamentMM[1] = int(line.split(':')[1].strip()) if profile.getMachineSetting('gcode_flavor') == 'UltiGCode': radius = profile.getProfileSettingFloat( 'filament_diameter') / 2.0 self._result._filamentMM[1] /= (math.pi * radius * radius) elif line.startswith('Replace:'): self._result._replaceInfo[line.split( ':')[1].strip()] = line.split(':')[2].strip() else: self._result.addLog(line) line = stderr.readline()
def getExtraHeadSize(self): extraSizeMin = self.headSizeMin extraSizeMax = self.headSizeMax if profile.getProfileSettingFloat('skirt_line_count') > 0: skirtSize = profile.getProfileSettingFloat('skirt_line_count') * profile.calculateEdgeWidth() + profile.getProfileSettingFloat('skirt_gap') extraSizeMin = extraSizeMin + numpy.array([skirtSize, skirtSize, 0]) extraSizeMax = extraSizeMax + numpy.array([skirtSize, skirtSize, 0]) if profile.getProfileSetting('enable_raft') != 'False': raftSize = profile.getProfileSettingFloat('raft_margin') * 2 extraSizeMin = extraSizeMin + numpy.array([raftSize, raftSize, 0]) extraSizeMax = extraSizeMax + numpy.array([raftSize, raftSize, 0]) if profile.getProfileSetting('support') != 'None': extraSizeMin = extraSizeMin + numpy.array([3.0, 0, 0]) extraSizeMax = extraSizeMax + numpy.array([3.0, 0, 0]) if self.printMode == 1: extraSizeMin = numpy.array([6.0, 6.0, 0]) extraSizeMax = numpy.array([6.0, 6.0, 0]) return extraSizeMin, extraSizeMax
def StoreData(self): profile.putPreference('machine_width', self.machineWidth.GetValue()) profile.putPreference('machine_depth', self.machineDepth.GetValue()) profile.putPreference('machine_height', self.machineHeight.GetValue()) profile.putProfileSetting('nozzle_size', self.nozzleSize.GetValue()) profile.putProfileSetting( 'wall_thickness', float(profile.getProfileSettingFloat('nozzle_size')) * 2) profile.putPreference('has_heated_bed', str(self.heatedBed.GetValue())) profile.putPreference('machine_center_is_zero', str(self.HomeAtCenter.GetValue()))
def OnAddHeight(self, e): scene = self.GetParent().GetParent().GetParent().GetParent().scene if scene.viewMode == 'normal': pauseLevel = 5.0 else: pauseLevel = scene._engineResultView.layerSelect.getValue() * float(profile.getProfileSettingFloat('layer_height')) newConfig = {'filename': self.plugin.getFilename(), 'params': { 'pauseLevel': str(pauseLevel) }} if not self._buildPluginPanel(newConfig): return self.pluginConfig.append(newConfig) pluginInfo.setPostProcessPluginConfig(self.pluginConfig) self.callback()
def validate(self): from Cura.util import profile try: nozzleSize = profile.getProfileSettingFloat('nozzle_size') layerHeight = profile.getProfileSettingFloat('layer_height') printSpeed = float(eval(self.setting.getValue().replace(',','.'), {}, {})) if printSpeed == 0.0: printSpeed = profile.getProfileSettingFloat('print_speed') printVolumePerMM = layerHeight * nozzleSize printVolumePerSecond = printVolumePerMM * printSpeed #Using 8mm3 per second with a 0.4mm nozzle maxPrintVolumePerSecond = 8 / (math.pi*(0.2*0.2)) * (math.pi*(nozzleSize/2*nozzleSize/2)) if printVolumePerSecond > maxPrintVolumePerSecond: return WARNING, 'You are trying to print more then %.1fmm^3 of filament per second. This might cause filament slipping. (You are printing at %0.1fmm^3 per second)' % (maxPrintVolumePerSecond, printVolumePerSecond) return SUCCESS, 'You are printing at %0.1fmm^3 per second' % (printVolumePerSecond) except ValueError: #We already have an error by the int/float validator in this case. return SUCCESS, ''
def getExtraHeadSize(self): extraSizeMin = self.headSizeMin extraSizeMax = self.headSizeMax if profile.getProfileSettingFloat("skirt_line_count") > 0: skirtSize = profile.getProfileSettingFloat( "skirt_line_count" ) * profile.calculateEdgeWidth() + profile.getProfileSettingFloat("skirt_gap") extraSizeMin = extraSizeMin + numpy.array([skirtSize, skirtSize, 0]) extraSizeMax = extraSizeMax + numpy.array([skirtSize, skirtSize, 0]) if profile.getProfileSetting("enable_raft") != "False": raftSize = profile.getProfileSettingFloat("raft_margin") * 2 extraSizeMin = extraSizeMin + numpy.array([raftSize, raftSize, 0]) extraSizeMax = extraSizeMax + numpy.array([raftSize, raftSize, 0]) if profile.getProfileSetting("support") != "None": extraSizeMin = extraSizeMin + numpy.array([3.0, 0, 0]) extraSizeMax = extraSizeMax + numpy.array([3.0, 0, 0]) if self.printMode == 1: extraSizeMin = numpy.array([6.0, 6.0, 0]) extraSizeMax = numpy.array([6.0, 6.0, 0]) return extraSizeMin, extraSizeMax
def checkPlatform(self, obj): objectSink = profile.getProfileSettingFloat("object_sink") area = obj._printAreaHull + obj.getPosition() if obj.getSize()[2] - objectSink > self._machineSize[2]: return False if not polygon.fullInside(area, self._machinePolygons[0]): return False #Check the "no go zones" for poly in self._machinePolygons[1:]: if polygon.polygonCollision(poly, area): return False return True
def mcTempUpdate(self, temp, bedTemp, targetTemp, bedTargetTemp): if self._wizardState == 1: self._wizardState = 2 wx.CallAfter(self.infoBox.SetAttention, 'Adjust the front left screw of your printer bed\nSo the nozzle just hits the bed.') wx.CallAfter(self.resumeButton.Enable, True) elif self._wizardState == 3: self._wizardState = 4 wx.CallAfter(self.infoBox.SetAttention, 'Adjust the back left screw of your printer bed\nSo the nozzle just hits the bed.') wx.CallAfter(self.resumeButton.Enable, True) elif self._wizardState == 5: self._wizardState = 6 wx.CallAfter(self.infoBox.SetAttention, 'Adjust the back right screw of your printer bed\nSo the nozzle just hits the bed.') wx.CallAfter(self.resumeButton.Enable, True) elif self._wizardState == 7: self._wizardState = 8 wx.CallAfter(self.infoBox.SetAttention, 'Adjust the front right screw of your printer bed\nSo the nozzle just hits the bed.') wx.CallAfter(self.resumeButton.Enable, True) elif self._wizardState == 9: if temp < profile.getProfileSettingFloat('print_temperature') - 5: wx.CallAfter(self.infoBox.SetInfo, 'Heating up printer: %d/%d' % (temp, profile.getProfileSettingFloat('print_temperature'))) else: self._wizardState = 10 wx.CallAfter(self.infoBox.SetInfo, 'Printing a square on the printer bed at 0.3mm height.') feedZ = profile.getProfileSettingFloat('max_z_speed') * 60 feedPrint = profile.getProfileSettingFloat('print_speed') * 60 feedTravel = profile.getProfileSettingFloat('travel_speed') * 60 w = profile.getPreferenceFloat('machine_width') d = profile.getPreferenceFloat('machine_depth') filamentRadius = profile.getProfileSettingFloat('filament_diameter') / 2 filamentArea = math.pi * filamentRadius * filamentRadius ePerMM = (profile.calculateEdgeWidth() * 0.3) / filamentArea eValue = 0.0 gcodeList = [ 'G1 Z2 F%d' % (feedZ), 'G92 E0', 'G1 X%d Y%d F%d' % (5, 5, feedTravel), 'G1 Z0.3 F%d' % (feedZ)] eValue += 5; gcodeList.append('G1 E%f F%d' % (eValue, profile.getProfileSettingFloat('retraction_speed') * 60)) for i in xrange(0, 3): dist = 5.0 + 0.4 * i eValue += (d - 2*dist) * ePerMM gcodeList.append('G1 X%d Y%d E%f F%d' % (dist, d - dist, eValue, feedPrint)) eValue += (w - 2*dist) * ePerMM gcodeList.append('G1 X%d Y%d E%f F%d' % (w - dist, d - dist, eValue, feedPrint)) eValue += (d - 2*dist) * ePerMM gcodeList.append('G1 X%d Y%d E%f F%d' % (w - dist, dist, eValue, feedPrint)) eValue += (w - 2*dist) * ePerMM gcodeList.append('G1 X%d Y%d E%f F%d' % (dist, dist, eValue, feedPrint)) gcodeList.append('M400') self.comm.printGCode(gcodeList)
def gcodePath(newType, pathType, layerThickness, startPoint): """ Build a gcodePath object. This used to be objects, however, this code is timing sensitive and dictionaries proved to be faster. """ if layerThickness <= 0.0: layerThickness = 0.01 if profile.getProfileSetting('spiralize') == 'True': layerThickness = profile.getProfileSettingFloat('layer_height') return {'type': newType, 'pathType': pathType, 'layerThickness': layerThickness, 'points': [startPoint], 'extrusion': [0.0]}
def StoreData(self): profile.putPreference('machine_width', self.machineWidth.GetValue()) profile.putPreference('machine_depth', self.machineDepth.GetValue()) profile.putPreference('machine_height', self.machineHeight.GetValue()) profile.putProfileSetting('nozzle_size', self.nozzleSize.GetValue()) profile.putProfileSetting('wall_thickness', float(profile.getProfileSettingFloat('nozzle_size')) * 2) profile.putPreference('has_heated_bed', str(self.heatedBed.GetValue())) profile.putPreference('machine_center_is_zero', str(self.HomeAtCenter.GetValue())) profile.putPreference('extruder_head_size_min_x', '0') profile.putPreference('extruder_head_size_min_y', '0') profile.putPreference('extruder_head_size_max_x', '0') profile.putPreference('extruder_head_size_max_y', '0') profile.putPreference('extruder_head_size_height', '0')
def updateHeadSize(self, obj=None): xMin = profile.getMachineSettingFloat('extruder_head_size_min_x') xMax = profile.getMachineSettingFloat('extruder_head_size_max_x') yMin = profile.getMachineSettingFloat('extruder_head_size_min_y') yMax = profile.getMachineSettingFloat('extruder_head_size_max_y') gantryHeight = profile.getMachineSettingFloat( 'extruder_head_size_height') objectSink = profile.getProfileSettingFloat("object_sink") self._leftToRight = xMin < xMax self._frontToBack = yMin < yMax self._headSizeOffsets[0] = min(xMin, xMax) self._headSizeOffsets[1] = min(yMin, yMax) self._gantryHeight = gantryHeight printOneAtATime = profile.getPreference('oneAtATime') == 'True' self._oneAtATime = self._gantryHeight > 0 and printOneAtATime if self._oneAtATime: if not self._lastOneAtATime: #print mode was changed by user. We need to reset that value to test with current scene content self._lastResultOneAtATime = True for obj in self._objectList: if obj.getSize()[2] - objectSink > self._gantryHeight: self._oneAtATime = False if self._lastResultOneAtATime: if self._sceneView: self._sceneView.notification.message( "Info: Print one at a time mode disabled. Object too tall." ) break if self._lastOneAtATime and self._oneAtATime and not self._lastResultOneAtATime: if self._sceneView: self._sceneView.notification.message( "Info: Print one at a time mode re-enabled.") self._lastResultOneAtATime = self._oneAtATime self._lastOneAtATime = printOneAtATime headArea = numpy.array( [[-xMin, -yMin], [xMax, -yMin], [xMax, yMax], [-xMin, yMax]], numpy.float32) if obj is None: for obj in self._objectList: obj.setHeadArea(headArea, self._headSizeOffsets) else: obj.setHeadArea(headArea, self._headSizeOffsets)
def OnScaleMax(self, onlyScaleDown=False): if self.objectsMinV is None: return vMin = self.objectsMinV vMax = self.objectsMaxV skirtSize = 3 if profile.getProfileSettingFloat("skirt_line_count") > 0: skirtSize = ( 3 + profile.getProfileSettingFloat("skirt_line_count") * profile.calculateEdgeWidth() + profile.getProfileSettingFloat("skirt_gap") ) scaleX1 = (self.machineSize.x - self.machineCenter.x - skirtSize) / ((vMax[0] - vMin[0]) / 2) scaleY1 = (self.machineSize.y - self.machineCenter.y - skirtSize) / ((vMax[1] - vMin[1]) / 2) scaleX2 = (self.machineCenter.x - skirtSize) / ((vMax[0] - vMin[0]) / 2) scaleY2 = (self.machineCenter.y - skirtSize) / ((vMax[1] - vMin[1]) / 2) scaleZ = self.machineSize.z / (vMax[2] - vMin[2]) scale = min(scaleX1, scaleY1, scaleX2, scaleY2, scaleZ) if scale > 1.0 and onlyScaleDown: return self.matrix *= numpy.matrix([[scale, 0, 0], [0, scale, 0], [0, 0, scale]], numpy.float64) if self.glCanvas.viewMode == "GCode" or self.glCanvas.viewMode == "Mixed": self.setViewMode("Normal") self.updateModelTransform()
def getExtraHeadSize(self): extraSizeMin = self.headSizeMin extraSizeMax = self.headSizeMax if profile.getProfileSettingFloat('skirt_line_count') > 0: skirtSize = profile.getProfileSettingFloat( 'skirt_line_count') * profile.calculateEdgeWidth( ) + profile.getProfileSettingFloat('skirt_gap') extraSizeMin = extraSizeMin + numpy.array( [skirtSize, skirtSize, 0]) extraSizeMax = extraSizeMax + numpy.array( [skirtSize, skirtSize, 0]) if profile.getProfileSetting('enable_raft') != 'False': raftSize = profile.getProfileSettingFloat('raft_margin') * 2 extraSizeMin = extraSizeMin + numpy.array([raftSize, raftSize, 0]) extraSizeMax = extraSizeMax + numpy.array([raftSize, raftSize, 0]) if profile.getProfileSetting('support') != 'None': extraSizeMin = extraSizeMin + numpy.array([3.0, 0, 0]) extraSizeMax = extraSizeMax + numpy.array([3.0, 0, 0]) if self.printMode == 1: extraSizeMin = numpy.array([6.0, 6.0, 0]) extraSizeMax = numpy.array([6.0, 6.0, 0]) return extraSizeMin, extraSizeMax
def mcTempUpdate(self, temp, bedTemp, targetTemp, bedTargetTemp): if self._wizardState == 1: self._wizardState = 2 wx.CallAfter(self.infoBox.SetAttention, 'Adjust the front left screw of your printer bed\nSo the nozzle just hits the bed.') wx.CallAfter(self.resumeButton.Enable, True) elif self._wizardState == 3: self._wizardState = 4 wx.CallAfter(self.infoBox.SetAttention, 'Adjust the back left screw of your printer bed\nSo the nozzle just hits the bed.') wx.CallAfter(self.resumeButton.Enable, True) elif self._wizardState == 5: self._wizardState = 6 wx.CallAfter(self.infoBox.SetAttention, 'Adjust the back right screw of your printer bed\nSo the nozzle just hits the bed.') wx.CallAfter(self.resumeButton.Enable, True) elif self._wizardState == 7: self._wizardState = 8 wx.CallAfter(self.infoBox.SetAttention, 'Adjust the front right screw of your printer bed\nSo the nozzle just hits the bed.') wx.CallAfter(self.resumeButton.Enable, True) elif self._wizardState == 9: if temp[0] < profile.getProfileSettingFloat('print_temperature') - 5: wx.CallAfter(self.infoBox.SetInfo, 'Heating up printer: %d/%d' % (temp[0], profile.getProfileSettingFloat('print_temperature'))) else: wx.CallAfter(self.infoBox.SetAttention, 'The printer is hot now. Please insert some PLA filament into the printer.') wx.CallAfter(self.resumeButton.Enable, True) self._wizardState = 10
def gcodePath(newType, pathType, layerThickness, startPoint): """ Build a gcodePath object. This used to be objects, however, this code is timing sensitive and dictionaries proved to be faster. """ if layerThickness <= 0.0: layerThickness = 0.01 if profile.getProfileSetting('spiralize') == 'True': layerThickness = profile.getProfileSettingFloat('layer_height') return { 'type': newType, 'pathType': pathType, 'layerThickness': layerThickness, 'points': [startPoint], 'extrusion': [0.0] }
def checkPlatform(self, obj): objectSink = profile.getProfileSettingFloat("object_sink") if profile.getPreference('startMode') == 'Simple': objectSink = float( profile.settingsDictionary["object_sink"].getDefault()) area = obj._printAreaHull + obj.getPosition() if obj.getSize()[2] - objectSink > self._machineSize[2]: return False if not polygon.fullInside(area, self._machinePolygons[0]): return False #Check the "no go zones" for poly in self._machinePolygons[1:]: if polygon.polygonCollision(poly, area): return False return True
def updateHeadSize(self, obj=None): xMin = profile.getMachineSettingFloat('extruder_head_size_min_x') xMax = profile.getMachineSettingFloat('extruder_head_size_max_x') yMin = profile.getMachineSettingFloat('extruder_head_size_min_y') yMax = profile.getMachineSettingFloat('extruder_head_size_max_y') gantryHeight = profile.getMachineSettingFloat( 'extruder_head_size_height') objectSink = profile.getProfileSettingFloat("object_sink") if profile.getPreference('startMode') == 'Simple': objectSink = float( profile.settingsDictionary["object_sink"].getDefault()) self._leftToRight = xMin < xMax self._frontToBack = yMin < yMax self._headSizeOffsets[0] = min(xMin, xMax) self._headSizeOffsets[1] = min(yMin, yMax) self._gantryHeight = gantryHeight printOneAtATime = profile.getPreference('oneAtATime') == 'True' self._oneAtATime = self._gantryHeight > 0 and printOneAtATime if self._oneAtATime: if not self._lastOneAtATime: #print mode was changed by user. We need to reset that value to test with current scene content self._lastResultOneAtATime = True for objIter in self._objectList: if objIter.getSize()[2] - objectSink > self._gantryHeight: self._oneAtATime = False if self._lastResultOneAtATime: if self._sceneView: self._sceneView.notification.message( "Object must be shorter than {}mm for this printer/tool head. Reduce object size or swap to \"All at once\" mode. " .format(self._gantryHeight)) break self._lastResultOneAtATime = self._oneAtATime self._lastOneAtATime = printOneAtATime headArea = numpy.array( [[-xMin, -yMin], [xMax, -yMin], [xMax, yMax], [-xMin, yMax]], numpy.float32) if obj is None: for obj in self._objectList: obj.setHeadArea(headArea, self._headSizeOffsets) else: obj.setHeadArea(headArea, self._headSizeOffsets)
def OnAddHeight(self, e): scene = self.GetParent().GetParent().GetParent().GetParent().scene if scene.viewMode == 'normal': pauseLevel = 5.0 else: pauseLevel = scene._engineResultView.layerSelect.getValue( ) * float(profile.getProfileSettingFloat('layer_height')) newConfig = { 'filename': self.plugin.getFilename(), 'params': { 'pauseLevel': str(pauseLevel) } } if not self._buildPluginPanel(newConfig): return self.pluginConfig.append(newConfig) pluginInfo.setPostProcessPluginConfig(self.pluginConfig) self.callback()
def stitchMultiExtruder(outputList, resultFile): print "Stitching %i files for multi-extrusion" % (len(outputList)) currentExtruder = 0 resultFile.write('T%d\n' % (currentExtruder)) layerNr = 0 hasLine = True outputList = map(lambda o: o.split('\n'), outputList) outputOrder = range(0, len(outputList)) outputSlice = [] for n in xrange(0, len(outputList)): outputSlice.append([0, 0]) currentX = 0 currentY = 0 currentZ = 0 currentF = 60 while hasLine: hasLine = layerNr < 1000 for n in xrange(0, len(outputList)): outputSlice[n][0] = outputSlice[n][1] + 1 outputSlice[n][1] = outputSlice[n][0] while outputSlice[n][1] < len(outputList[n]) and not outputList[n][ outputSlice[n][1]].startswith(';LAYER:'): outputSlice[n][1] += 1 outputOrder = range(currentExtruder, len(outputList)) + range( 0, currentExtruder) for n in outputOrder: if outputSlice[n][1] > outputSlice[n][0] + 1: nextExtruder = n resultFile.write(';LAYER:%d\n' % (layerNr)) resultFile.write(';EXTRUDER:%d\n' % (nextExtruder)) startSlice = outputSlice[n][0] endSlice = outputSlice[n][1] currentE = 0 while startSlice < len(outputList[n]) and not isPrintingLine( outputList[n][startSlice]): currentE = getCodeFloat(outputList[n][startSlice], 'E', currentE) currentX = getCodeFloat(outputList[n][startSlice], 'X', currentX) currentY = getCodeFloat(outputList[n][startSlice], 'Y', currentY) currentZ = getCodeFloat(outputList[n][startSlice], 'Z', currentZ) currentF = getCodeFloat(outputList[n][startSlice], 'F', currentF) startSlice += 1 while not isPrintingLine(outputList[n][endSlice - 1]): endSlice -= 1 if nextExtruder != currentExtruder: profile.setTempOverride('extruder', nextExtruder) profile.setTempOverride('new_x', currentX) profile.setTempOverride('new_y', currentY) profile.setTempOverride('new_z', currentZ) resultFile.write( profile.getAlterationFileContents( 'switchExtruder.gcode') + '\n') profile.resetTempOverride() currentExtruder = nextExtruder for idx in xrange(outputSlice[n][0], startSlice): if not 'G1' in outputList[n][idx]: resultFile.write(outputList[n][idx]) resultFile.write('\n') resultFile.write( 'G1 X%f Y%f Z%f F%f\n' % (currentX, currentY, currentZ, profile.getProfileSettingFloat('travel_speed') * 60)) resultFile.write('G1 F%f\n' % (currentF)) resultFile.write('G92 E%f\n' % (currentE)) for idx in xrange(startSlice, endSlice): resultFile.write(outputList[n][idx]) resultFile.write('\n') currentX = getCodeFloat(outputList[n][idx], 'X', currentX) currentY = getCodeFloat(outputList[n][idx], 'Y', currentY) currentZ = getCodeFloat(outputList[n][idx], 'Z', currentZ) hasLine = True resultFile.write('G92 E0\n') layerNr += 1
def OnDraw(self): if not self._enabled: return self._resultLock.acquire() result = self._result if result is not None: gcodeLayers = result.getGCodeLayers(self._gcodeLoadCallback) if result._polygons is not None and len(result._polygons) > 0: self.layerSelect.setRange(1, len(result._polygons)) elif gcodeLayers is not None and len(gcodeLayers) > 0: self.layerSelect.setRange(1, len(gcodeLayers)) else: gcodeLayers = None glPushMatrix() glEnable(GL_BLEND) if profile.getMachineSetting('machine_center_is_zero') != 'True': glTranslate(-profile.getMachineSettingFloat('machine_width') / 2, -profile.getMachineSettingFloat('machine_depth') / 2, 0) glLineWidth(2) layerNr = self.layerSelect.getValue() if layerNr == self.layerSelect.getMaxValue() and result is not None and len(result._polygons) > 0: layerNr = max(layerNr, len(result._polygons)) if result is not None and len(result._polygons) > layerNr-1 and 'inset0' in result._polygons[layerNr-1] and len(result._polygons[layerNr-1]['inset0']) > 0 and len(result._polygons[layerNr-1]['inset0'][0]) > 0: viewZ = result._polygons[layerNr-1]['inset0'][0][0][2] else: viewZ = (layerNr - 1) * profile.getProfileSettingFloat('layer_height') + profile.getProfileSettingFloat('bottom_thickness') self._parent._viewTarget[2] = viewZ msize = max(profile.getMachineSettingFloat('machine_width'), profile.getMachineSettingFloat('machine_depth')) lineTypeList = [ ('inset0', 'WALL-OUTER', [1,0,0,1]), ('insetx', 'WALL-INNER', [0,1,0,1]), ('openoutline', None, [1,0,0,1]), ('skin', 'SKIN', [1,1,0,1]), ('infill', 'FILL', [1,1,0,1]), ('support', 'SUPPORT', [0,1,1,1]), ('skirt', 'SKIRT', [0,1,1,1]), ('outline', None, [0,0,0,1]) ] n = layerNr - 1 generatedVBO = False if result is not None: while n >= 0: if layerNr - n > 30 and n % 20 == 0 and len(result._polygons) > 0: idx = n / 20 while len(self._layer20VBOs) < idx + 1: self._layer20VBOs.append({}) if result._polygons is not None and n + 20 < len(result._polygons): layerVBOs = self._layer20VBOs[idx] for typeName, typeNameGCode, color in lineTypeList: allow = typeName in result._polygons[n + 19] if typeName == 'skirt': for i in xrange(0, 20): if typeName in result._polygons[n + i]: allow = True if allow: if typeName not in layerVBOs: if generatedVBO: continue polygons = [] for i in xrange(0, 20): if typeName in result._polygons[n + i]: polygons += result._polygons[n + i][typeName] layerVBOs[typeName] = self._polygonsToVBO_lines(polygons) generatedVBO = True glColor4f(color[0]*0.5,color[1]*0.5,color[2]*0.5,color[3]) layerVBOs[typeName].render() n -= 20 else: c = 1.0 - ((layerNr - n) - 1) * 0.05 c = max(0.5, c) while len(self._layerVBOs) < n + 1: self._layerVBOs.append({}) layerVBOs = self._layerVBOs[n] if gcodeLayers is not None and ((layerNr - 10 < n < (len(gcodeLayers) - 1)) or len(result._polygons) < 1): for typeNamePolygons, typeName, color in lineTypeList: if typeName is None: continue if 'GCODE-' + typeName not in layerVBOs: layerVBOs['GCODE-' + typeName] = self._gcodeToVBO_quads(gcodeLayers[n+1:n+2], typeName) glColor4f(color[0]*c,color[1]*c,color[2]*c,color[3]) layerVBOs['GCODE-' + typeName].render() if n == layerNr - 1: if 'GCODE-MOVE' not in layerVBOs: layerVBOs['GCODE-MOVE'] = self._gcodeToVBO_lines(gcodeLayers[n+1:n+2]) glColor4f(0,0,c,1) layerVBOs['GCODE-MOVE'].render() elif n < len(result._polygons): polygons = result._polygons[n] for typeName, typeNameGCode, color in lineTypeList: if typeName in polygons: if typeName not in layerVBOs: layerVBOs[typeName] = self._polygonsToVBO_lines(polygons[typeName]) glColor4f(color[0]*c,color[1]*c,color[2]*c,color[3]) layerVBOs[typeName].render() n -= 1 glPopMatrix() if generatedVBO: self._parent._queueRefresh() if gcodeLayers is not None and self._gcodeLoadProgress != 0.0 and self._gcodeLoadProgress != 1.0: glPushMatrix() glLoadIdentity() glTranslate(0,-0.8,-2) glColor4ub(60,60,60,255) openglHelpers.glDrawStringCenter(_("Loading toolpath for visualization (%d%%)") % (self._gcodeLoadProgress * 100)) glPopMatrix() self._resultLock.release()
def _engineSettings(self, extruderCount): settings = { 'layerThickness': int(profile.getProfileSettingFloat('layer_height') * 1000), 'initialLayerThickness': int(profile.getProfileSettingFloat('bottom_thickness') * 1000) if profile.getProfileSettingFloat('bottom_thickness') > 0.0 else int( profile.getProfileSettingFloat('layer_height') * 1000), 'filamentDiameter': int(profile.getProfileSettingFloat('filament_diameter') * 1000), 'filamentFlow': int(profile.getProfileSettingFloat('filament_flow')), 'extrusionWidth': int(profile.calculateEdgeWidth() * 1000), 'insetCount': int(profile.calculateLineCount()), 'downSkinCount': int(profile.calculateSolidLayerCount()) if profile.getProfileSetting('solid_bottom') == 'True' else 0, 'upSkinCount': int(profile.calculateSolidLayerCount()) if profile.getProfileSetting('solid_top') == 'True' else 0, 'infillOverlap': int(profile.getProfileSettingFloat('fill_overlap')), 'initialSpeedupLayers': int(4), 'initialLayerSpeed': int(profile.getProfileSettingFloat('bottom_layer_speed')), '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')), 'inset0Speed': int(profile.getProfileSettingFloat('inset0_speed')) if int(profile.getProfileSettingFloat('inset0_speed')) > 0 else int( profile.getProfileSettingFloat('print_speed')), 'insetXSpeed': int(profile.getProfileSettingFloat('insetx_speed')) if int(profile.getProfileSettingFloat('insetx_speed')) > 0 else int( profile.getProfileSettingFloat('print_speed')), 'moveSpeed': int(profile.getProfileSettingFloat('travel_speed')), '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( profile.getProfileSettingFloat('support_angle')), 'supportEverywhere': int(1) if profile.getProfileSetting('support') == 'Everywhere' else int(0), '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' 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), 'retractionAmountExtruderSwitch': int( profile.getProfileSettingFloat('retraction_dual_amount') * 1000), 'retractionZHop': int(profile.getProfileSettingFloat('retraction_hop') * 1000), 'minimalExtrusionBeforeRetraction': int( profile.getProfileSettingFloat('retraction_minimal_extrusion') * 1000), 'enableCombing': 1 if profile.getProfileSetting('retraction_combing') == 'True' else 0, 'multiVolumeOverlap': int(profile.getProfileSettingFloat('overlap_dual') * 1000), 'objectSink': max(0, int(profile.getProfileSettingFloat('object_sink') * 1000)), 'minimalLayerTime': int(profile.getProfileSettingFloat('cool_min_layer_time')), 'minimalFeedrate': int(profile.getProfileSettingFloat('cool_min_feedrate')), 'coolHeadLift': 1 if profile.getProfileSetting('cool_head_lift') == 'True' else 0, 'startCode': profile.getAlterationFileContents('start.gcode', extruderCount), 'endCode': profile.getAlterationFileContents('end.gcode', extruderCount), 'relativeE': 1 if profile.getMachineSetting('relative_extrusion') == 'True' else 0, 'perimInset': int(profile.getProfileSettingFloat('perimeter_inset') * 1000), 'extruderOffset[1].X': int(profile.getMachineSettingFloat('extruder_offset_x1') * 1000), 'extruderOffset[1].Y': int(profile.getMachineSettingFloat('extruder_offset_y1') * 1000), 'extruderOffset[2].X': int(profile.getMachineSettingFloat('extruder_offset_x2') * 1000), 'extruderOffset[2].Y': int(profile.getMachineSettingFloat('extruder_offset_y2') * 1000), 'extruderOffset[3].X': int(profile.getMachineSettingFloat('extruder_offset_x3') * 1000), '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.getProfileSetting('support_type') == 'Lines': settings['supportType'] = 1 if profile.getProfileSettingFloat('fill_density') == 0: settings['sparseInfillLineDistance'] = -1 elif profile.getProfileSettingFloat('fill_density') == 100: settings['sparseInfillLineDistance'] = settings['extrusionWidth'] #Set the up/down skins height to 10000 if we want a 100% filled object. # This gives better results then normal 100% infill as the sparse and up/down skin have some overlap. settings['downSkinCount'] = 10000 settings['upSkinCount'] = 10000 else: settings['sparseInfillLineDistance'] = int( 100 * profile.calculateEdgeWidth() * 1000 / profile.getProfileSettingFloat('fill_density')) if profile.getProfileSetting('platform_adhesion') == 'Brim': settings['skirtDistance'] = 0 settings['skirtLineCount'] = int( profile.getProfileSettingFloat('brim_line_count')) elif profile.getProfileSetting('platform_adhesion') == 'Raft': settings['skirtDistance'] = 0 settings['skirtLineCount'] = 0 settings['raftMargin'] = int( profile.getProfileSettingFloat('raft_margin') * 1000) settings['raftLineSpacing'] = int( profile.getProfileSettingFloat('raft_line_spacing') * 1000) settings['raftBaseThickness'] = int( profile.getProfileSettingFloat('raft_base_thickness') * 1000) settings['raftBaseLinewidth'] = int( profile.getProfileSettingFloat('raft_base_linewidth') * 1000) settings['raftInterfaceThickness'] = int( profile.getProfileSettingFloat('raft_interface_thickness') * 1000) settings['raftInterfaceLinewidth'] = int( profile.getProfileSettingFloat('raft_interface_linewidth') * 1000) else: settings['skirtDistance'] = int( profile.getProfileSettingFloat('skirt_gap') * 1000) settings['skirtLineCount'] = int( profile.getProfileSettingFloat('skirt_line_count')) settings['skirtMinLength'] = int( profile.getProfileSettingFloat('skirt_minimal_length') * 1000) if profile.getProfileSetting( 'fix_horrible_union_all_type_a') == 'True': settings['fixHorrible'] |= 0x01 if profile.getProfileSetting( 'fix_horrible_union_all_type_b') == 'True': settings['fixHorrible'] |= 0x02 if profile.getProfileSetting('fix_horrible_use_open_bits') == 'True': settings['fixHorrible'] |= 0x10 if profile.getProfileSetting( 'fix_horrible_extensive_stitching') == 'True': settings['fixHorrible'] |= 0x04 if settings['layerThickness'] <= 0: settings['layerThickness'] = 1000 if profile.getMachineSetting('gcode_flavor') == 'UltiGCode': settings['gcodeFlavor'] = 1 elif profile.getMachineSetting('gcode_flavor') == 'MakerBot': settings['gcodeFlavor'] = 2 if profile.getProfileSetting('spiralize') == 'True': settings['spiralizeMode'] = 1 if profile.getProfileSetting( 'wipe_tower') == 'True' and extruderCount > 1: settings['wipeTowerSize'] = int( math.sqrt( profile.getProfileSettingFloat('wipe_tower_volume') * 1000 * 1000 * 1000 / settings['layerThickness'])) if profile.getProfileSetting('ooze_shield') == 'True': settings['enableOozeShield'] = 1 return settings
def main(): parser = OptionParser( usage= "usage: %prog [options] <X,Y> <filename>[, <X,Y> <filename>][, ...]") parser.add_option("-p", "--profile", action="store", type="string", dest="profile", help="Encoded profile to use for the print") parser.add_option("-o", "--output", action="store", type="string", dest="output", help="Output filename") (options, args) = parser.parse_args() if options.output is None: print 'Missing output filename' sys.exit(1) if options.profile is not None: profile.loadGlobalProfileFromString(options.profile) options.output = fixUTF8(options.output) clearZ = 0 resultFile = open(options.output, "w") for idx in xrange(0, len(args), 2): position = map(float, args[idx].split(',')) if len(position) < 9 + 2: position = position[0:2] position += [1, 0, 0] position += [0, 1, 0] position += [0, 0, 1] filenames = fixUTF8(args[idx + 1]).split('|') profile.setTempOverride('object_center_x', position[0]) profile.setTempOverride('object_center_y', position[1]) if idx == 0: resultFile.write(';TYPE:CUSTOM\n') resultFile.write( profile.getAlterationFileContents( 'start.gcode', len(filenames)).replace( '?filename?', ' '.join(filenames).encode('ascii', 'replace'))) else: resultFile.write(';TYPE:CUSTOM\n') n = output[-1].rfind('Z') + 1 zString = output[-1][n:n + 20] zString = zString[0:zString.find(' ')] clearZ = max(clearZ, float(zString) + 10) profile.setTempOverride('clear_z', clearZ) print position print profile.getAlterationFileContents('nextobject.gcode') resultFile.write( profile.getAlterationFileContents('nextobject.gcode').replace( '?filename?', ' '.join(filenames).encode('ascii', 'replace'))) output = [] for filename in filenames: extruderNr = filenames.index(filename) profile.resetTempOverride() if extruderNr > 0: profile.setTempOverride( 'object_center_x', position[0] - profile.getPreferenceFloat('extruder_offset_x%d' % (extruderNr))) profile.setTempOverride( 'object_center_y', position[1] - profile.getPreferenceFloat('extruder_offset_y%d' % (extruderNr))) profile.setTempOverride('fan_enabled', 'False') profile.setTempOverride('skirt_line_count', '0') profile.setTempOverride('alternative_center', filenames[0]) else: profile.setTempOverride('object_center_x', position[0]) profile.setTempOverride('object_center_y', position[1]) profile.setTempOverride('object_matrix', ','.join(map(str, position[2:11]))) if extruderNr > 0: if profile.getProfileSettingFloat('filament_diameter%d' % (extruderNr + 1)) > 0: profile.setTempOverride( 'filament_diameter', profile.getProfileSetting('filament_diameter%d' % (extruderNr + 1))) print extruderNr, profile.getPreferenceFloat( 'extruder_offset_x%d' % (extruderNr)), profile.getPreferenceFloat( 'extruder_offset_y%d' % (extruderNr)) output.append(export.getOutput(filename)) profile.resetTempOverride() if len(output) == 1: resultFile.write(output[0]) else: stitchMultiExtruder(output, resultFile) resultFile.write(';TYPE:CUSTOM\n') resultFile.write(profile.getAlterationFileContents('end.gcode')) resultFile.close() print "Running plugins" ret = profile.runPostProcessingPlugins(options.output) if ret is not None: print ret print "Finalizing %s" % (os.path.basename(options.output)) if profile.getPreference('submit_slice_information') == 'True': filenames = fixUTF8(args[idx + 1]).split('|') for filename in filenames: m = hashlib.sha512() f = open(filename, "rb") while True: chunk = f.read(1024) if not chunk: break m.update(chunk) f.close() data = { 'processor': platform.processor(), 'machine': platform.machine(), 'platform': platform.platform(), 'profile': profile.getGlobalProfileString(), 'preferences': profile.getGlobalPreferencesString(), 'modelhash': m.hexdigest(), 'version': version.getVersion(), } try: f = urllib2.urlopen("http://platform.ultimaker.com/curastats/", data=urllib.urlencode(data), timeout=5) f.read() f.close() except: pass
def _load(self, gcodeFile): self.layerList = [] pos = [0.0, 0.0, 0.0] posOffset = [0.0, 0.0, 0.0] currentE = 0.0 totalExtrusion = 0.0 maxExtrusion = 0.0 currentExtruder = 0 extrudeAmountMultiply = 1.0 totalMoveTimeMinute = 0.0 absoluteE = True scale = 1.0 posAbs = True feedRate = 3600.0 layerThickness = 0.1 pathType = 'CUSTOM' currentLayer = [] currentPath = gcodePath('move', pathType, layerThickness, pos[:]) currentPath['extruder'] = currentExtruder currentLayer.append(currentPath) for line in gcodeFile: if type(line) is tuple: line = line[0] #Parse Cura_SF comments if line.startswith(';TYPE:'): pathType = line[6:].strip() if ';' in line: #Slic3r GCode comment parser comment = line[line.find(';') + 1:].strip() if comment == 'fill': pathType = 'FILL' elif comment == 'perimeter': pathType = 'WALL-INNER' elif comment == 'skirt': pathType = 'SKIRT' if comment.startswith('LAYER:'): currentPath = gcodePath(moveType, pathType, layerThickness, currentPath['points'][-1]) currentPath['extruder'] = currentExtruder for path in currentLayer: path['points'] = numpy.array(path['points'], numpy.float32) path['extrusion'] = numpy.array( path['extrusion'], numpy.float32) self.layerList.append(currentLayer) if self.progressCallback is not None: if self.progressCallback( float(gcodeFile.tell()) / float(self._fileSize)): #Abort the loading, we can safely return as the results here will be discarded gcodeFile.close() return currentLayer = [currentPath] line = line[0:line.find(';')] T = getCodeInt(line, 'T') if T is not None: if currentExtruder > 0: posOffset[0] -= profile.getPreferenceFloat( 'extruder_offset_x%d' % (currentExtruder)) posOffset[1] -= profile.getPreferenceFloat( 'extruder_offset_y%d' % (currentExtruder)) currentExtruder = T if currentExtruder > 0: posOffset[0] += profile.getPreferenceFloat( 'extruder_offset_x%d' % (currentExtruder)) posOffset[1] += profile.getPreferenceFloat( 'extruder_offset_y%d' % (currentExtruder)) G = getCodeInt(line, 'G') if G is not None: if G == 0 or G == 1: #Move x = getCodeFloat(line, 'X') y = getCodeFloat(line, 'Y') z = getCodeFloat(line, 'Z') e = getCodeFloat(line, 'E') #f = getCodeFloat(line, 'F') oldPos = pos[:] if posAbs: if x is not None: pos[0] = x * scale + posOffset[0] if y is not None: pos[1] = y * scale + posOffset[1] if z is not None: pos[2] = z * scale + posOffset[2] else: if x is not None: pos[0] += x * scale if y is not None: pos[1] += y * scale if z is not None: pos[2] += z * scale #if f is not None: # feedRate = f #if x is not None or y is not None or z is not None: # diffX = oldPos[0] - pos[0] # diffY = oldPos[1] - pos[1] # totalMoveTimeMinute += math.sqrt(diffX * diffX + diffY * diffY) / feedRate moveType = 'move' if e is not None: if absoluteE: e -= currentE if e > 0.0: moveType = 'extrude' if e < 0.0: moveType = 'retract' totalExtrusion += e currentE += e if totalExtrusion > maxExtrusion: maxExtrusion = totalExtrusion else: e = 0.0 if moveType == 'move' and oldPos[2] != pos[2]: if oldPos[2] > pos[2] and abs( oldPos[2] - pos[2]) > 5.0 and pos[2] < 1.0: oldPos[2] = 0.0 layerThickness = abs(oldPos[2] - pos[2]) if currentPath['type'] != moveType or currentPath[ 'pathType'] != pathType: currentPath = gcodePath(moveType, pathType, layerThickness, currentPath['points'][-1]) currentPath['extruder'] = currentExtruder currentLayer.append(currentPath) currentPath['points'].append(pos[:]) currentPath['extrusion'].append(e * extrudeAmountMultiply) elif G == 4: #Delay S = getCodeFloat(line, 'S') if S is not None: totalMoveTimeMinute += S / 60.0 P = getCodeFloat(line, 'P') if P is not None: totalMoveTimeMinute += P / 60.0 / 1000.0 elif G == 20: #Units are inches scale = 25.4 elif G == 21: #Units are mm scale = 1.0 elif G == 28: #Home x = getCodeFloat(line, 'X') y = getCodeFloat(line, 'Y') z = getCodeFloat(line, 'Z') if profile.getPreference( 'machine_center_is_zero') == 'True': center = [ profile.getProfileSettingFloat('machine_width') / 2, profile.getProfileSettingFloat('machine_depth') / 2, 0.0 ] else: center = [0.0, 0.0, 0.0] if x is None and y is None and z is None: pos = center else: if x is not None: pos[0] = center[0] if y is not None: pos[0] = center[1] if z is not None: pos[0] = center[2] elif G == 90: #Absolute position posAbs = True elif G == 91: #Relative position posAbs = False elif G == 92: x = getCodeFloat(line, 'X') y = getCodeFloat(line, 'Y') z = getCodeFloat(line, 'Z') e = getCodeFloat(line, 'E') if e is not None: currentE = e if x is not None: posOffset[0] = pos[0] - x if y is not None: posOffset[1] = pos[1] - y if z is not None: posOffset[2] = pos[2] - z else: print "Unknown G code:" + str(G) else: M = getCodeInt(line, 'M') if M is not None: if M == 0: #Message with possible wait (ignored) pass elif M == 1: #Message with possible wait (ignored) pass elif M == 80: #Enable power supply pass elif M == 81: #Suicide/disable power supply pass elif M == 82: #Absolute E absoluteE = True elif M == 83: #Relative E absoluteE = False elif M == 84: #Disable step drivers pass elif M == 92: #Set steps per unit pass elif M == 101: #Enable extruder pass elif M == 103: #Disable extruder pass elif M == 104: #Set temperature, no wait pass elif M == 105: #Get temperature pass elif M == 106: #Enable fan pass elif M == 107: #Disable fan pass elif M == 108: #Extruder RPM (these should not be in the final GCode, but they are) pass elif M == 109: #Set temperature, wait pass elif M == 110: #Reset N counter pass elif M == 113: #Extruder PWM (these should not be in the final GCode, but they are) pass elif M == 117: #LCD message pass elif M == 140: #Set bed temperature pass elif M == 190: #Set bed temperature & wait pass elif M == 221: #Extrude amount multiplier s = getCodeFloat(line, 'S') if s is not None: extrudeAmountMultiply = s / 100.0 else: print "Unknown M code:" + str(M) for path in currentLayer: path['points'] = numpy.array(path['points'], numpy.float32) path['extrusion'] = numpy.array(path['extrusion'], numpy.float32) self.layerList.append(currentLayer) if self.progressCallback is not None and self._fileSize > 0: self.progressCallback( float(gcodeFile.tell()) / float(self._fileSize)) self.extrusionAmount = maxExtrusion self.totalMoveTimeMinute = totalMoveTimeMinute