def updateBoundingBox( self, splitLine ): "Updates the information about the first layer bounding box" location = gcodec.getLocationFromSplitLine(None, splitLine); self.firstZ = location.z if location.x < self.minX or self.firstFeed == -1: self.minX = location.x elif location.x > self.maxX or self.firstFeed == -1: self.maxX = location.x if location.y < self.minY or self.firstFeed == -1: self.minY = location.y elif location.y > self.maxY or self.firstFeed == -1: self.maxY = location.y if gcodec.getFeedRateMinute(self.firstFeed, splitLine) < self.firstFeed or self.firstFeed == -1: self.firstFeed = gcodec.getFeedRateMinute(self.firstFeed, splitLine)
def parseLine(self, line): """Parse a gcode line and add it to the skin skein.""" splitLine = gcodec.getSplitLineBeforeBracketSemicolon(line) if len(splitLine) < 1: return firstWord = splitLine[0] if firstWord == '(<boundaryPerimeter>)': self.boundaryLayerIndex = max(0, self.boundaryLayerIndex) elif firstWord == 'G1': self.feedRateMinute = gcodec.getFeedRateMinute(self.feedRateMinute, splitLine) location = gcodec.getLocationFromSplitLine(self.oldLocation, splitLine) self.oldLocation = location if self.perimeter is not None: self.perimeter.append(location.dropAxis()) return elif firstWord == '(<layer>': if self.boundaryLayerIndex > -1: self.boundaryLayerIndex += 1 elif firstWord == 'M101' or firstWord == 'M103': if self.perimeter is not None: return elif firstWord == 'M108': self.oldFlowRate = gcodec.getDoubleAfterFirstLetter(splitLine[1]) elif firstWord == '(<perimeter>': if self.boundaryLayerIndex >= self.repository.layersFrom.value: self.perimeter = [] elif firstWord == '(</perimeter>)': self.addSkinnedPerimeter() self.perimeter = None self.distanceFeedRate.addLine(line)
def parseLine(self, line): "Parse a gcode line and add it to the skirt skein." splitLine = gcodec.getSplitLineBeforeBracketSemicolon(line) if len(splitLine) < 1: return firstWord = splitLine[0] if firstWord == "(<raftPerimeter>)" or firstWord == "(</raftPerimeter>)" or firstWord == "(<raftPoint>": return self.distanceFeedRate.addLine(line) if firstWord == "G1": self.feedRateMinute = gcodec.getFeedRateMinute(self.feedRateMinute, splitLine) elif firstWord == "(<layer>": self.layerIndex += 1 if self.layerIndex < self.repository.layersTo.value: self.addSkirt(float(splitLine[1])) elif firstWord == "M101": self.isExtruderActive = True elif firstWord == "M103": self.isExtruderActive = False elif firstWord == "M104": self.oldTemperatureInput = gcodec.getDoubleAfterFirstLetter(splitLine[1]) self.skirtTemperature = self.oldTemperatureInput elif firstWord == "M108": self.oldFlowRate = gcodec.getDoubleAfterFirstLetter(splitLine[1]) self.skirtFlowRate = self.oldFlowRate elif firstWord == "(<supportLayer>)": self.isSupportLayer = True elif firstWord == "(</supportLayer>)": self.isSupportLayer = False
def getLayerTimeActive(self): 'Get the time the extruder spends on the layer while active.' feedRateMinute = self.feedRateMinute isExtruderActive = self.isExtruderActive layerTime = 0.0 lastThreadLocation = self.oldLocation for lineIndex in xrange(self.lineIndex, len(self.lines)): line = self.lines[lineIndex] splitLine = gcodec.getSplitLineBeforeBracketSemicolon(line) firstWord = gcodec.getFirstWord(splitLine) if firstWord == 'G1': location = gcodec.getLocationFromSplitLine(lastThreadLocation, splitLine) feedRateMinute = gcodec.getFeedRateMinute(feedRateMinute, splitLine) if lastThreadLocation != None and isExtruderActive: feedRateSecond = feedRateMinute / 60.0 layerTime += location.distance(lastThreadLocation) / feedRateSecond lastThreadLocation = location elif firstWord == 'M101': isExtruderActive = True elif firstWord == 'M103': isExtruderActive = False elif firstWord == '(<bridgeRotation>': self.isBridgeLayer = True elif firstWord == '(</layer>)': return layerTime return layerTime
def parseLine(self, line): 'Parse a gcode line and add it to the joris skein.' splitLine = gcodec.getSplitLineBeforeBracketSemicolon(line) if len(splitLine) < 1: return firstWord = splitLine[0] if firstWord == 'G1' and self.doJoris: self.feedRateMinute = gcodec.getFeedRateMinute(self.feedRateMinute, splitLine) location = gcodec.getLocationFromSplitLine(self.oldLocation, splitLine) self.oldLocation = location if self.perimeter != None: self.perimeter.append(location.dropAxis()) return elif firstWord == '(<layer>': self.layerIndex += 1 settings.printProgress(self.layerIndex, 'joris') elif firstWord == 'M108': self.oldFlowRate = gcodec.getDoubleAfterFirstLetter(splitLine[1]) elif firstWord == '(<edge>': if self.layerIndex >= self.layersFromBottom: self.doJoris = True elif firstWord == 'M101' and self.doJoris: self.perimeter = [] return elif firstWord == 'M103' and self.doJoris: self.addJorisedPerimeter() return elif firstWord == '(</edge>)': self.doJoris = False self.distanceFeedRate.addLine(line)
def getHopLine(self, line): "Get hopped gcode line." splitLine = gcodec.getSplitLineBeforeBracketSemicolon(line) self.feedRateMinute = gcodec.getFeedRateMinute( self.feedRateMinute, splitLine ) if self.extruderActive: return line location = gcodec.getLocationFromSplitLine(self.oldLocation, splitLine) highestZ = location.z if self.oldLocation is not None: highestZ = max( highestZ, self.oldLocation.z ) highestZHop = highestZ + self.hopHeight locationComplex = location.dropAxis() if self.justDeactivated: oldLocationComplex = self.oldLocation.dropAxis() distance = abs( locationComplex - oldLocationComplex ) if distance < self.minimumDistance: if self.isNextTravel() or distance == 0.0: return self.distanceFeedRate.getLineWithZ( line, splitLine, highestZHop ) alongRatio = min( 0.41666666, self.hopDistance / distance ) oneMinusAlong = 1.0 - alongRatio closeLocation = oldLocationComplex * oneMinusAlong + locationComplex * alongRatio self.distanceFeedRate.addLine( self.distanceFeedRate.getLineWithZ( line, splitLine, highestZHop ) ) if self.isNextTravel(): return self.distanceFeedRate.getLineWithZ( line, splitLine, highestZHop ) farLocation = oldLocationComplex * alongRatio + locationComplex * oneMinusAlong self.distanceFeedRate.addGcodeMovementZWithFeedRate( self.feedRateMinute, farLocation, highestZHop ) return line if self.isNextTravel(): return self.distanceFeedRate.getLineWithZ( line, splitLine, highestZHop ) return line
def addExtrusionIntro( self, line ): "Adds the additional linear gcode movement for the extrusion intro." splitG1Line = self.firstLinearGcodeMovement.split() firstMovementLocation = gcodec.getLocationFromSplitLine(None, splitG1Line) firstMovementFeedrate = gcodec.getFeedRateMinute(self.feedRateMinute/self.raftlessRepository.firstPerimeterFeedrateOverFeedrate.value, splitG1Line) introX = abs( self.raftlessRepository.absMaxXIntro.value ) introY = abs( self.raftlessRepository.absMaxYIntro.value ) xAxisFirst=False if abs( firstMovementLocation.x ) < abs( firstMovementLocation.y ): xAxisFirst=True if (xAxisFirst and firstMovementLocation.x > 0) or (not xAxisFirst and firstMovementLocation.x < 0): introX = -introX; if (xAxisFirst and firstMovementLocation.y < 0) or (not xAxisFirst and firstMovementLocation.y > 0): introY = -introY; introLine = self.deriveIntroLine(self.firstLinearGcodeMovement, splitG1Line, introX, introY, firstMovementFeedrate) self.distanceFeedRate.addLine(introLine) self.distanceFeedRate.addLine( line ) if xAxisFirst: introLine = self.deriveIntroLine(self.firstLinearGcodeMovement, splitG1Line, firstMovementLocation.x, introY, self.feedRateMinute) else: introLine = self.deriveIntroLine(self.firstLinearGcodeMovement, splitG1Line, introX, firstMovementLocation.y, self.feedRateMinute) self.distanceFeedRate.addLine(introLine) introLine = self.getRaftlessSpeededLine(self.firstLinearGcodeMovement, splitG1Line) self.distanceFeedRate.addLine(introLine) self.wantsExtrusionIntro = False
def getUnpausedArcMovement( self, line, splitLine ): "Get an unpaused arc movement." if self.oldLocation == None: return line self.feedRateMinute = gcodec.getFeedRateMinute( self.feedRateMinute, splitLine ) relativeLocation = gcodec.getLocationFromSplitLine(self.oldLocation, splitLine) location = self.oldLocation + relativeLocation self.oldLocation = location halfPlaneLineDistance = 0.5 * abs( relativeLocation.dropAxis(2) ) radius = gcodec.getDoubleFromCharacterSplitLine('R', splitLine ) if radius == None: relativeCenter = complex( gcodec.getDoubleFromCharacterSplitLine('I', splitLine ), gcodec.getDoubleFromCharacterSplitLine('J', splitLine ) ) radius = abs( relativeCenter ) angle = 0.0 if radius > 0.0: angle = math.pi if halfPlaneLineDistance < radius: angle = 2.0 * math.asin( halfPlaneLineDistance / radius ) else: angle *= halfPlaneLineDistance / radius deltaZ = abs( relativeLocation.z ) arcDistanceZ = complex( abs(angle) * radius, relativeLocation.z ) distance = abs( arcDistanceZ ) if distance <= 0.0: return '' unpausedFeedRateMinute = self.distanceFeedRate.getZLimitedFeedRate( deltaZ, distance, self.feedRateMinute ) return self.distanceFeedRate.getLineWithFeedRate( unpausedFeedRateMinute, line, splitLine )
def getAddBeforeStartupLines(self, line): "Get and / or add before the startup lines." distanceThreadBeginning = self.getDistanceToThreadBeginning() if distanceThreadBeginning is None: return line splitLine = gcodec.getSplitLineBeforeBracketSemicolon(line) self.extruderInactiveLongEnough = False self.isStartupEarly = True location = gcodec.getLocationFromSplitLine(self.oldLocation, splitLine) segment = self.oldLocation - location segmentLength = segment.magnitude() distanceBack = self.earlyStartupDistance - distanceThreadBeginning if segmentLength <= 0.0: print("This should never happen, segmentLength is zero in getAddBeforeStartupLines in oozebane.") print(line) self.extruderInactiveLongEnough = True self.isStartupEarly = False return line locationBack = location + segment * distanceBack / segmentLength self.distanceFeedRate.addLine( self.getLinearMoveWithFeedRate(gcodec.getFeedRateMinute(self.feedRateMinute, splitLine), locationBack) ) self.distanceFeedRate.addLine("M101") if self.isCloseToEither(locationBack, location, self.oldLocation): return "" return self.getLinearMoveWithFeedRate(self.operatingFeedRateMinute, location)
def setSkirtFeedFlowTemperature(self): "Set the skirt feed rate, flow rate and temperature to that of the next extrusion." isExtruderActive = self.isExtruderActive isSupportLayer = self.isSupportLayer for lineIndex in xrange(self.lineIndex, len(self.lines)): line = self.lines[lineIndex] splitLine = gcodec.getSplitLineBeforeBracketSemicolon(line) firstWord = gcodec.getFirstWord(splitLine) if firstWord == "G1": self.feedRateMinute = gcodec.getFeedRateMinute(self.feedRateMinute, splitLine) if isExtruderActive: if not isSupportLayer: return elif firstWord == "M101": isExtruderActive = True elif firstWord == "M103": isExtruderActive = False elif firstWord == "M104": self.skirtTemperature = gcodec.getDoubleAfterFirstLetter(splitLine[1]) elif firstWord == "M108": self.skirtFlowRate = gcodec.getDoubleAfterFirstLetter(splitLine[1]) elif firstWord == "(<supportLayer>)": isSupportLayer = True elif firstWord == "(</supportLayer>)": isSupportLayer = False
def parseLine(self, line): "Parse a gcode line and add it to the dwindle skein." splitLine = gcodec.getSplitLineBeforeBracketSemicolon(line) if len(splitLine) < 1: return firstWord = splitLine[0] if firstWord == "G1": self.feedRateMinute = gcodec.getFeedRateMinute(self.feedRateMinute, splitLine) location = gcodec.getLocationFromSplitLine(self.oldLocation, splitLine) if self.isActive: self.threadSections.append( ThreadSection(self.feedRateMinute, self.oldFlowRate, location, self.oldLocation) ) self.oldLocation = location elif firstWord == "(<layer>": self.layerIndex += 1 settings.printProgress(self.layerIndex, "dwindle") elif firstWord == "M101": self.isActive = True elif firstWord == "M103": self.isActive = False self.addThread() elif firstWord == "M108": self.oldFlowRate = gcodec.getDoubleAfterFirstLetter(splitLine[1]) if len(self.threadSections) == 0: self.distanceFeedRate.addLine(line)
def getExtrusionDistanceString( self, distance, splitLine ): "Get the extrusion distance string." self.feedRateMinute = gcodec.getFeedRateMinute( self.feedRateMinute, splitLine ) if not self.isExtruderActive: return '' if distance <= 0.0: return '' return self.getExtrusionDistanceStringFromExtrusionDistance( self.flowRate * 60.0 / self.feedRateMinute * distance )
def getUnpausedArcMovement( self, line, splitLine ): """Get an unpaused arc movement.""" self.feedRateMinute = gcodec.getFeedRateMinute( self.feedRateMinute, splitLine ) if self.oldLocation is None: return line relativeLocation = gcodec.getLocationFromSplitLine(self.oldLocation, splitLine) self.oldLocation += relativeLocation distance = gcodec.getArcDistance(relativeLocation, splitLine) return self.getUnpausedMovement(distance, line, splitLine)
def getCoolMove(self, line, location, splitLine): 'Get cool line according to time spent on layer.' self.feedRateMinute = gcodec.getFeedRateMinute(self.feedRateMinute, splitLine) calcCoolFeedrate = self.multiplier * self.feedRateMinute if calcCoolFeedrate >= self.repository.minimumLayerFeedrate.value*60: coolFeedrate = calcCoolFeedrate else: coolFeedrate = self.repository.minimumLayerFeedrate.value*60 return self.distanceFeedRate.getLineWithFeedRate(coolFeedrate, line, splitLine)
def getExtrusionDistanceString( self, distance, splitLine ): 'Get the extrusion distance string.' self.feedRateMinute = gcodec.getFeedRateMinute( self.feedRateMinute, splitLine ) if not self.isExtruderActive: return '' if distance <= 0.0: return '' scaledFlowRate = self.flowRate * self.flowScaleSixty return self.getExtrusionDistanceStringFromExtrusionDistance(scaledFlowRate / self.feedRateMinute * distance)
def getStretchedLine( self, splitLine ): "Get stretched gcode line." location = gcodec.getLocationFromSplitLine(self.oldLocation, splitLine) self.feedRateMinute = gcodec.getFeedRateMinute( self.feedRateMinute, splitLine ) self.oldLocation = location if self.extruderActive and self.threadMaximumAbsoluteStretch > 0.0: return self.getStretchedLineFromIndexLocation( self.lineIndex - 1, self.lineIndex + 1, location ) if self.isJustBeforeExtrusion() and self.threadMaximumAbsoluteStretch > 0.0: return self.getStretchedLineFromIndexLocation( self.lineIndex - 1, self.lineIndex + 1, location ) return self.lines[ self.lineIndex ]
def getCoolMove(self, line, location, splitLine): "Add line to time spent on layer." self.feedRateMinute = gcodec.getFeedRateMinute(self.feedRateMinute, splitLine) self.addFlowRateMultipliedLineIfNecessary(self.oldFlowRate) coolFeedRate = self.multiplier * self.feedRateMinute if coolFeedRate > self.repository.minimumLayerFeedrate.value * 60: coolFeedRate = coolFeedRate else: coolFeedRate = self.repository.minimumLayerFeedrate.value * 60 return self.distanceFeedRate.getLineWithFeedRate(coolFeedRate, line, splitLine)
def getZLimitedLineLinear(self, line, location, splitLine): """Get a replaced z limited gcode linear movement line.""" self.feedRateMinute = gcodec.getFeedRateMinute(self.feedRateMinute, splitLine) if location == self.oldLocation: return '' if self.feedRateMinute is None or self.oldLocation is None: return line deltaZ = abs(location.z - self.oldLocation.z) distance = abs(location - self.oldLocation) return self.getZLimitedLine(deltaZ, distance, line, splitLine)
def getUnpausedLinearMovement( self, line, splitLine ): """Get an unpaused linear movement.""" self.feedRateMinute = gcodec.getFeedRateMinute( self.feedRateMinute, splitLine ) location = gcodec.getLocationFromSplitLine(self.oldLocation, splitLine) if self.oldLocation is None: self.oldLocation = location return line distance = abs(self.oldLocation - location) self.oldLocation = location return self.getUnpausedMovement(distance, line, splitLine)
def getZLimitedLineArc(self, line, splitLine): """Get a replaced z limited gcode arc movement line.""" self.feedRateMinute = gcodec.getFeedRateMinute(self.feedRateMinute, splitLine) if self.feedRateMinute is None or self.oldLocation is None: return line relativeLocation = gcodec.getLocationFromSplitLine(self.oldLocation, splitLine) self.oldLocation += relativeLocation deltaZ = abs(relativeLocation.z) distance = gcodec.getArcDistance(relativeLocation, splitLine) return self.getZLimitedLine(deltaZ, distance, line, splitLine)
def linearMove( self, splitLine ): "Bevel a linear move." location = gcodec.getLocationFromSplitLine(self.oldLocation, splitLine) self.feedRateMinute = gcodec.getFeedRateMinute( self.feedRateMinute, splitLine ) if self.oldLocation != None: nextLocation = self.getNextLocation() if nextLocation != None: location = self.splitPointGetAfter( location, nextLocation ) self.oldLocation = location self.oldFeedRateMinute = self.feedRateMinute
def linearMove( self, splitLine ): "Add to loop path if this is a loop or path." location = gcodec.getLocationFromSplitLine( self.oldLocation, splitLine ) self.feedRateMinute = gcodec.getFeedRateMinute( self.feedRateMinute, splitLine ) if self.isLoopPerimeter: if self.isNextExtruderOn(): self.loopPath = euclidean.PathZ( location.z ) if self.loopPath == None: if self.extruderActive: self.oldWiddershins = None else: self.loopPath.path.append( location.dropAxis( 2 ) ) self.oldLocation = location
def getUnpausedFeedRateMinute( self, location, splitLine ): "Get the feed rate which will compensate for the pause." self.feedRateMinute = gcodec.getFeedRateMinute( self.feedRateMinute, splitLine ) if self.oldLocation == None: return self.feedRateMinute distance = location.distance( self.oldLocation ) if distance <= 0.0: return self.feedRateMinute specifiedFeedRateSecond = self.feedRateMinute / 60.0 resultantReciprocal = 1.0 - self.delaySecond / distance * specifiedFeedRateSecond if resultantReciprocal < self.minimumSpeedUpReciprocal: return self.feedRateMinute * self.maximumSpeed return self.feedRateMinute / resultantReciprocal
def getExtrusionDistanceString( self, distance, splitLine ): 'Get the extrusion distance string.' self.feedRateMinute = gcodec.getFeedRateMinute( self.feedRateMinute, splitLine ) if not self.isExtruderActive: return '' if distance == 0.0: return '' if distance < 0.0: print('Warning, the distance is less than zero in getExtrusionDistanceString in dimension; so there will not be an E value') print(distance) print(splitLine) return '' scaledFlowRate = self.flowRate * self.flowScaleSixty return self.getExtrusionDistanceStringFromExtrusionDistance(scaledFlowRate / self.feedRateMinute * distance)
def getActiveFeedRateRatio(self): "Get the feed rate of the first active move over the operating feed rate." isSearchExtruderActive = self.isExtruderActive for afterIndex in xrange( self.lineIndex, len(self.lines) ): line = self.lines[ afterIndex ] splitLine = gcodec.getSplitLineBeforeBracketSemicolon(line) firstWord = gcodec.getFirstWord(splitLine) if firstWord == 'G1': if isSearchExtruderActive: return gcodec.getFeedRateMinute( self.feedRateMinute, splitLine ) / self.operatingFeedRateMinute elif firstWord == 'M101': isSearchExtruderActive = True print('active feed rate ratio was not found in oozebane.') return 1.0
def parseLine(self, line): "Parse a gcode line." splitLine = gcodec.getSplitLineBeforeBracketSemicolon(line) firstWord = gcodec.getFirstWord(splitLine) if len(firstWord) < 1: return firstLetter = firstWord[0] if firstWord == "(<operatingFeedRatePerSecond>": self.feedRateMinute = 60.0 * float(splitLine[1]) elif firstWord == "(<operatingFlowRate>": self.operatingFlowRate = float(splitLine[1]) self.flowRate = self.operatingFlowRate if firstLetter == "(": return if firstWord == "M101": self.isExtruderActive = True elif firstWord == "M103": self.isExtruderActive = False elif firstWord == "M108": self.flowRate = float(splitLine[1][1:]) if firstWord != "G1" and firstWord != "G2" and firstWord != "G3": self.addLine(line) return self.feedRateMinute = gcodec.getFeedRateMinute(self.feedRateMinute, splitLine) lineStringIO = cStringIO.StringIO() lineStringIO.write(firstWord) location = gcodec.getLocationFromSplitLine(self.oldLocation, splitLine) self.addCharacterInteger( "X", lineStringIO, self.repository.xOffset.value, splitLine, self.repository.xStep.value ) self.addCharacterInteger( "Y", lineStringIO, self.repository.yOffset.value, splitLine, self.repository.yStep.value ) zString = getCharacterIntegerString("Z", self.repository.zOffset.value, splitLine, self.repository.zStep.value) if zString == None: zString = self.oldZString self.addStringToLine(lineStringIO, zString) duration = self.repository.initialTime.value if self.oldLocation != None: distance = abs(location - self.oldLocation) duration = 60.0 / self.feedRateMinute * distance extrusionDistance = 0.0 if self.isExtruderActive: extrusionDistance = self.flowRate * duration self.addStringToLine(lineStringIO, "E%s" % int(round(extrusionDistance / self.repository.extrusionStep.value))) self.addStringToLine(lineStringIO, "D%s" % int(round(duration * 1000000.0 / self.repository.timeStep.value))) self.addLine(lineStringIO.getvalue()) self.oldLocation = location self.oldZString = zString
def getOozebaneLine(self, line): "Get oozebaned gcode line." splitLine = gcodec.getSplitLineBeforeBracketSemicolon(line) self.feedRateMinute = gcodec.getFeedRateMinute( self.feedRateMinute, splitLine ) if self.oldLocation == None: return line if self.startupStepIndex < len( self.afterStartupDistances ): return self.getAddAfterStartupLines(line) if self.extruderInactiveLongEnough: return self.getAddBeforeStartupLines(line) if self.shutdownStepIndex < len( self.earlyShutdownDistances ): return self.getAddShutSlowDownLines(line) if self.isStartupEarly: return self.getLinearMoveWithFeedRateSplitLine( self.operatingFeedRateMinute, splitLine ) return line
def setFeedRateLocationLoopPath(self, line, splitLine): 'Set the feedRateMinute, oldLocation and loopPath.' self.feedRateMinute = gcodec.getFeedRateMinute(self.feedRateMinute, splitLine) self.oldLocation = gcodec.getLocationFromSplitLine(self.oldLocation, splitLine) if not self.isLoopPerimeter or self.loopPath != None: return for afterIndex in xrange(self.lineIndex + 1, len(self.lines)): line = self.lines[afterIndex] splitLine = gcodec.getSplitLineBeforeBracketSemicolon(line) firstWord = gcodec.getFirstWord(splitLine) if firstWord == 'G1' or firstWord == 'M103': return elif firstWord == 'M101': self.loopPath = euclidean.PathZ(self.oldLocation.z) return
def getLinearMove( self, line, splitLine ): "Add to loop path if this is a loop or path." location = gcodec.getLocationFromSplitLine( self.oldLocation, splitLine ) self.feedRateMinute = gcodec.getFeedRateMinute( self.feedRateMinute, splitLine ) if self.isLoopPerimeter: if self.isNextExtruderOn(): self.loopPath = euclidean.PathZ( location.z ) if self.oldLocation != None: self.beforeLoopLocation = self.oldLocation.dropAxis( 2 ) self.oldLocation = location if self.loopPath == None: self.oldLoopLocationComplex = None return line self.loopPath.path.append( location.dropAxis( 2 ) ) return ''
def linearMove(self, splitLine): "Add to loop path if this is a loop or path." location = gcodec.getLocationFromSplitLine(self.oldLocation, splitLine) self.feedRateMinute = gcodec.getFeedRateMinute(self.feedRateMinute, splitLine) if self.isLoop or self.isEdge: if self.isNextExtruderOn(): self.loopPath = euclidean.PathZ(location.z) if self.loopPath == None: if self.extruderActive: self.oldWiddershins = None else: if self.oldConnectionPoint != None: self.addSegmentToPixelTables(self.oldConnectionPoint, location.dropAxis()) self.oldConnectionPoint = None self.loopPath.path.append(location.dropAxis()) self.oldLocation = location
def setFeedRateLocationLoopPath(self, line, splitLine): 'Set the feedRateMinute, oldLocation and loopPath.' self.feedRateMinute = gcodec.getFeedRateMinute(self.feedRateMinute, splitLine) self.oldLocation = gcodec.getLocationFromSplitLine( self.oldLocation, splitLine) if not self.isLoopPerimeter or self.loopPath != None: return for afterIndex in xrange(self.lineIndex + 1, len(self.lines)): line = self.lines[afterIndex] splitLine = gcodec.getSplitLineBeforeBracketSemicolon(line) firstWord = gcodec.getFirstWord(splitLine) if firstWord == 'G1' or firstWord == 'M103': return elif firstWord == 'M101': self.loopPath = euclidean.PathZ(self.oldLocation.z) return
def parseLine(self, line): 'Parse a gcode line and add it to the skin skein.' splitLine = gcodec.getSplitLineBeforeBracketSemicolon(line) if len(splitLine) < 1: return firstWord = splitLine[0] if firstWord == 'G1': self.feedRateMinute = gcodec.getFeedRateMinute(self.feedRateMinute, splitLine) location = gcodec.getLocationFromSplitLine(self.oldLocation, splitLine) self.oldLocation = location if self.infillBoundaries is not None: return if self.perimeter is not None: self.perimeter.append(location.dropAxis()) return elif firstWord == '(<infill>)': if self.layerIndex >= self.layersFromBottom and self.layerIndex == self.layerIndexTop: self.infillBoundaries = [] elif firstWord == '(</infill>)': self.addSkinnedInfill() elif firstWord == '(<infillBoundary>)': if self.infillBoundaries is not None: self.infillBoundary = [] self.infillBoundaries.append(self.infillBoundary) elif firstWord == '(<infillPoint>': if self.infillBoundaries is not None: location = gcodec.getLocationFromSplitLine(None, splitLine) self.infillBoundary.append(location.dropAxis()) elif firstWord == '(<layer>': self.layerIndex += 1 settings.printProgress(self.layerIndex, 'skin') elif firstWord == 'M101' or firstWord == 'M103': if self.infillBoundaries is not None or self.perimeter is not None: return elif firstWord == 'M108': self.oldFlowRate = gcodec.getDoubleAfterFirstLetter(splitLine[1]) elif firstWord == '(<perimeter>': if self.layerIndex >= self.layersFromBottom: self.perimeter = [] elif firstWord == '(<rotation>': self.rotation = gcodec.getRotationBySplitLine(splitLine) self.reverseRotation = complex(self.rotation.real, -self.rotation.imag) elif firstWord == '(</perimeter>)': self.addSkinnedPerimeter() self.distanceFeedRate.addLine(line)
def parseLine(self, line): 'Parse a gcode line and add it to the leadin skein.' splitLine = gcodec.getSplitLineBeforeBracketSemicolon(line) if len(splitLine) < 1: return firstWord = splitLine[0] if firstWord == 'G1': self.feedRateMinute = gcodec.getFeedRateMinute(self.feedRateMinute, splitLine) location = gcodec.getLocationFromSplitLine(self.oldLocation, splitLine) self.oldLocation = location if self.infill != None: self.infill.append(location.dropAxis()) return if self.perimeter != None: self.perimeter.append(location.dropAxis()) return elif firstWord == '(<layer>': self.layerCount.printProgressIncrement('leadin') self.layerIndex += 1 self.setInfill() elif firstWord == '(<loop>': self.infill = None elif firstWord == '(</loop>)': self.setInfill() elif firstWord == 'M108': self.oldFlowRate = gcodec.getDoubleAfterFirstLetter(splitLine[1]) elif firstWord == '(<perimeter>': self.infill = None if self.layerIndex >= self.layersFromBottom: self.perimeter = [] elif firstWord == '(</perimeter>)': self.addLeadinnedPerimeter() self.setInfill() self.perimeter = None if firstWord == 'M103': if self.infill != None: self.addLeadinnedInfill() self.setInfill() return if firstWord == 'M101' or firstWord == 'M103': if self.infill != None: return if self.perimeter != None: return self.distanceFeedRate.addLine(line)
def parseLine(self, line): "Parse a gcode line." splitLine = gcodec.getSplitLineBeforeBracketSemicolon(line) firstWord = gcodec.getFirstWord(splitLine) if len(firstWord) < 1: return firstLetter = firstWord[0] if firstWord == '(<operatingFeedRatePerSecond>': self.feedRateMinute = 60.0 * float(splitLine[1]) elif firstWord == '(<operatingFlowRate>': self.operatingFlowRate = float(splitLine[1]) self.flowRate = self.operatingFlowRate if firstLetter == '(': return if firstWord == 'M101': self.isExtruderActive = True elif firstWord == 'M103': self.isExtruderActive = False elif firstWord == 'M108': self.flowRate = float(splitLine[1][1 :]) if firstWord != 'G1' and firstWord != 'G2' and firstWord != 'G3': self.addLine(line) return self.feedRateMinute = gcodec.getFeedRateMinute(self.feedRateMinute, splitLine) lineStringIO = cStringIO.StringIO() lineStringIO.write(firstWord) location = gcodec.getLocationFromSplitLine(self.oldLocation, splitLine) self.addCharacterInteger('X', lineStringIO, self.repository.xOffset.value, splitLine, self.repository.xStep.value ) self.addCharacterInteger('Y', lineStringIO, self.repository.yOffset.value, splitLine, self.repository.yStep.value ) zString = getCharacterIntegerString('Z', self.repository.zOffset.value, splitLine, self.repository.zStep.value ) if zString == None: zString = self.oldZString self.addStringToLine(lineStringIO, zString) duration = self.repository.initialTime.value if self.oldLocation != None: distance = abs(location - self.oldLocation) duration = 60.0 / self.feedRateMinute * distance extrusionDistance = 0.0 if self.isExtruderActive: extrusionDistance = self.flowRate * duration self.addStringToLine(lineStringIO, 'E%s' % int(round(extrusionDistance / self.repository.extrusionStep.value))) self.addStringToLine(lineStringIO, 'D%s' % int(round(duration * 1000000.0 / self.repository.timeStep.value))) self.addLine(lineStringIO.getvalue()) self.oldLocation = location self.oldZString = zString
def getExtrusionDistanceString(self, distance, splitLine): 'Get the extrusion distance string.' self.feedRateMinute = gcodec.getFeedRateMinute(self.feedRateMinute, splitLine) if not self.isExtruderActive: return '' if distance == 0.0: return '' if distance < 0.0: print( 'Warning, the distance is less than zero in getExtrusionDistanceString in dimension; so there will not be an E value' ) print(distance) print(splitLine) return '' scaledFlowRate = self.flowRate * self.flowScaleSixty return self.getExtrusionDistanceStringFromExtrusionDistance( scaledFlowRate / self.extrusionReduction * distance)
def getLayerTime(self): "Get the time the extruder spends on the layer." feedRateMinute = self.feedRateMinute layerTime = 0.0 lastThreadLocation = self.oldLocation for lineIndex in xrange( self.lineIndex, len( self.lines ) ): line = self.lines[lineIndex] splitLine = gcodec.getSplitLineBeforeBracketSemicolon(line) firstWord = gcodec.getFirstWord(splitLine) if firstWord == 'G1': location = gcodec.getLocationFromSplitLine( lastThreadLocation, splitLine ) feedRateMinute = gcodec.getFeedRateMinute( feedRateMinute, splitLine ) if lastThreadLocation != None: feedRateSecond = feedRateMinute / 60.0 layerTime += location.distance( lastThreadLocation ) / feedRateSecond lastThreadLocation = location elif firstWord == '(</layer>)': return layerTime return layerTime
def getAnimationLineDelay( self, coloredLine ): 'Get the animation line delay in milliseconds.' # maybe later, add animation along line # nextLayerIndex = self.repository.layer.value # nextLineIndex = self.repository.line.value + 1 # coloredLinesLength = len( self.getColoredLines() ) # self.skein.feedRateMinute # if nextLineIndex >= coloredLinesLength: # if nextLayerIndex + 1 < len( self.skeinPanes ): # nextLayerIndex += 1 # nextLineIndex = 0 # else: # nextLineIndex = self.repository.line.value splitLine = gcodec.getSplitLineBeforeBracketSemicolon( coloredLine.displayString ) self.skein.feedRateMinute = gcodec.getFeedRateMinute( self.skein.feedRateMinute, splitLine ) feedRateSecond = self.skein.feedRateMinute / 60.0 coloredLineLength = abs( coloredLine.end - coloredLine.begin ) / self.repository.scale.value duration = coloredLineLength / feedRateSecond animationLineDelay = int( round( 1000.0 * duration / self.repository.animationLineQuickening.value ) ) return max( animationLineDelay, 1 )
def parseLine(self, line): 'Parse a gcode line and add it to the smooth skein.' splitLine = gcodec.getSplitLineBeforeBracketSemicolon(line) if len(splitLine) < 1: return firstWord = splitLine[0] if firstWord == '(<boundaryPerimeter>)': if self.boundaryLayerIndex < 0: self.boundaryLayerIndex = 0 elif firstWord == 'G1': self.feedRateMinute = gcodec.getFeedRateMinute( self.feedRateMinute, splitLine) location = gcodec.getLocationFromSplitLine(self.oldLocation, splitLine) self.oldLocation = location if self.infill != None: self.infill.append(location.dropAxis()) return elif firstWord == '(<infill>)': if self.boundaryLayerIndex >= self.layersFromBottom: self.infill = [] elif firstWord == '(</infill>)': self.infill = None elif firstWord == '(<layer>': self.layerCount.printProgressIncrement('smooth') if self.boundaryLayerIndex >= 0: self.boundaryLayerIndex += 1 elif firstWord == 'M101': if self.infill != None: if len(self.infill) > 1: self.infill = [self.infill[0]] return elif firstWord == 'M103': if self.infill != None: self.addSmoothedInfill() self.infill = [] return elif firstWord == '(<rotation>': self.rotation = gcodec.getRotationBySplitLine(splitLine) self.distanceFeedRate.addLine(line)
def getHopLine(self, line): "Get hopped gcode line." splitLine = gcodec.getSplitLineBeforeBracketSemicolon(line) self.feedRateMinute = gcodec.getFeedRateMinute(self.feedRateMinute, splitLine) if self.extruderActive: return line location = gcodec.getLocationFromSplitLine(self.oldLocation, splitLine) highestZ = location.z if self.oldLocation != None: highestZ = max(highestZ, self.oldLocation.z) highestZHop = highestZ + self.hopHeight locationComplex = location.dropAxis(2) if self.justDeactivated: oldLocationComplex = self.oldLocation.dropAxis(2) distance = abs(locationComplex - oldLocationComplex) if distance < self.minimumDistance: if self.isNextTravel(): return self.distanceFeedRate.getLineWithZ( line, splitLine, highestZHop) alongRatio = min(0.41666666, self.hopDistance / distance) oneMinusAlong = 1.0 - alongRatio closeLocation = oldLocationComplex * oneMinusAlong + locationComplex * alongRatio self.distanceFeedRate.addLine( self.distanceFeedRate.getLineWithZ(line, splitLine, highestZHop)) if self.isNextTravel(): return self.distanceFeedRate.getLineWithZ( line, splitLine, highestZHop) farLocation = oldLocationComplex * alongRatio + locationComplex * oneMinusAlong self.distanceFeedRate.addGcodeMovementZWithFeedRate( self.feedRateMinute, farLocation, highestZHop) return line if self.isNextTravel(): return self.distanceFeedRate.getLineWithZ(line, splitLine, highestZHop) return line
def parseLine(self, line): 'Parse a gcode line and add it to the skirt skein.' splitLine = gcodec.getSplitLineBeforeBracketSemicolon(line) if len(splitLine) < 1: return firstWord = splitLine[0] if firstWord == '(<raftPerimeter>)' or firstWord == '(</raftPerimeter>)' or firstWord == '(<raftPoint>': return self.distanceFeedRate.addLine(line) if firstWord == 'G1': self.feedRateMinute = gcodec.getFeedRateMinute( self.feedRateMinute, splitLine) elif firstWord == '(<layer>': self.layerIndex += 1 if self.repository.activateSkirt.value and ( self.layerIndex < self.repository.layersTo.value): self.addSkirt(float(splitLine[1])) if (self.repository.activateSkirt.value or self.repository.activateBrim.value) and (self.layerIndex < 1): self.addBrimAndBaseSkirt(float(splitLine[1])) elif firstWord == 'M101': self.isExtruderActive = True elif firstWord == 'M103': self.isExtruderActive = False elif firstWord == 'M104': self.oldTemperatureInput = gcodec.getDoubleAfterFirstLetter( splitLine[1]) self.skirtTemperature = self.oldTemperatureInput elif firstWord == 'M108': self.oldFlowRate = gcodec.getDoubleAfterFirstLetter(splitLine[1]) self.skirtFlowRate = self.oldFlowRate elif firstWord == '(<supportLayer>)': self.isSupportLayer = True elif firstWord == '(</supportLayer>)': self.isSupportLayer = False
def parseLine(self, line): 'Parse a gcode line and add it to the dwindle skein.' splitLine = gcodec.getSplitLineBeforeBracketSemicolon(line) if len(splitLine) < 1: return firstWord = splitLine[0] if firstWord == 'G1': self.feedRateMinute = gcodec.getFeedRateMinute(self.feedRateMinute, splitLine) location = gcodec.getLocationFromSplitLine(self.oldLocation, splitLine) if self.isActive: self.threadSections.append(ThreadSection(self.feedRateMinute, self.oldFlowRate, location, self.oldLocation)) self.oldLocation = location elif firstWord == '(<layer>': self.layerIndex += 1 settings.printProgress(self.layerIndex, 'dwindle') elif firstWord == 'M101': self.isActive = True elif firstWord == 'M103': self.isActive = False self.addThread() elif firstWord == 'M108': self.oldFlowRate = gcodec.getDoubleAfterFirstLetter(splitLine[1]) if len(self.threadSections) == 0: self.distanceFeedRate.addLine(line)
def getAddBeforeStartupLines(self, line): "Get and / or add before the startup lines." distanceThreadBeginning = self.getDistanceToThreadBeginning() if distanceThreadBeginning == None: return line splitLine = gcodec.getSplitLineBeforeBracketSemicolon(line) self.extruderInactiveLongEnough = False self.isStartupEarly = True location = gcodec.getLocationFromSplitLine(self.oldLocation, splitLine) segment = self.oldLocation - location segmentLength = segment.magnitude() distanceBack = self.earlyStartupDistance - distanceThreadBeginning if segmentLength <= 0.0: print('This should never happen, segmentLength is zero in getAddBeforeStartupLines in oozebane.') print(line) self.extruderInactiveLongEnough = True self.isStartupEarly = False return line locationBack = location + segment * distanceBack / segmentLength self.distanceFeedRate.addLine( self.getLinearMoveWithFeedRate( gcodec.getFeedRateMinute( self.feedRateMinute, splitLine ) , locationBack ) ) self.distanceFeedRate.addLine('M101') if self.isCloseToEither( locationBack, location, self.oldLocation ): return '' return self.getLinearMoveWithFeedRate( self.operatingFeedRateMinute, location )
def parseLine(self, line): """Parse a gcode line and add it to the reversal gcode. Overview: o Keep track of gcode state: current flowrate (self.flowrate), current position (self.newLocation/oldLocation) current feedrate (self.feedRateMinute) current logical extruder state (self.extruderOn) o Keep track of reversal state: (self.didReverse, self.reversalActive) o If early reversal is NOT active, it will insert a pause command at the end of each thread (G4). This will cause the extruder to move without XYZ. This is not recommended as it might cause some blobbing o If early reversal is active """ if DEBUG: self.distanceFeedRate.addLine("( line: " + line + " )") splitLine = gcodec.getSplitLineBeforeBracketSemicolon(line) if len(splitLine) < 1: return firstWord = splitLine[0] if firstWord == 'M108': # If we didn't already rpmify the M108 commands, do this now line = line.replace('M108 S', 'M108 R') splitLine = gcodec.getSplitLineBeforeBracketSemicolon(line) # Keep track of current flowrate indexOfR = gcodec.getIndexOfStartingWithSecond('R', splitLine) if indexOfR > 0: self.flowrate = gcodec.getDoubleAfterFirstLetter( splitLine[indexOfR]) # Pick up all movement commands elif firstWord == 'G1': # Location at the start of this movement self.oldLocation = self.newLocation # Location at the end start of this movement self.newLocation = gcodec.getLocationFromSplitLine( self.oldLocation, splitLine) self.feedRateMinute = gcodec.getFeedRateMinute( self.feedRateMinute, splitLine) if self.activateEarlyReversal: # If we did reverse and we're not already pushing back if (not self.extruderOn and self.filamentState == ReversalSkein.FILAMENT_REVERSED and self.pushbackWorthy and not self.pushbackActive): # If this movement crosses the push-back point, this will # move us to where pushback starts and return true. if self.detectAndMoveToReversalEvent( 'M101', self.pushbackTime): if DEBUG: self.distanceFeedRate.addLine( "( activating pushback: )") self.distanceFeedRate.addLine("M108 R" + str(self.reversalRPM)) self.distanceFeedRate.addLine("M101") self.pushbackActive = True self.filamentState = ReversalSkein.FILAMENT_READY # If we're going to reverse on next stop and we're not already reversing if (self.extruderOn and self.filamentState == ReversalSkein.FILAMENT_READY and self.reversalWorthy and not self.reversalActive): # If this movement crosses the reversal point, this will # move us to where reversal starts and return true. if self.detectAndMoveToReversalEvent( 'M103', self.reversalTime): if DEBUG: self.distanceFeedRate.addLine( "( activating reverse: )") self.distanceFeedRate.addLine("M108 R" + str(self.reversalRPM)) self.distanceFeedRate.addLine("M102") self.reversalActive = True self.filamentState = ReversalSkein.FILAMENT_REVERSED # Note: We don't return here since the current G1 command will # keep moving to the end of the current movement thread with # reversal/push-back potentially active. # Detect extruder ON commands elif firstWord == 'M101': self.extruderOn = True self.reversalWorthy = self.isNextMovementReversalWorthy( self.reversalThreshold, 'M103', 'M101') if (not self.activateEarlyReversal and self.pushbackWorthy and self.filamentState == ReversalSkein.FILAMENT_REVERSED): self.distanceFeedRate.addLine("M108 R" + str(self.reversalRPM)) self.distanceFeedRate.addLine("M101") self.distanceFeedRate.addLine("G04 P" + str(self.reversalTime)) self.pushbackActive = True if self.pushbackActive: self.distanceFeedRate.addLine("M108 R" + str(self.flowrate)) self.pushbackActive = False self.filamentState = ReversalSkein.FILAMENT_READY if DEBUG: self.printState() return # Motor is already on - no need to emit the M101 # Detect extruder OFF commands elif firstWord == 'M103': self.extruderOn = False self.pushbackWorthy = self.isNextMovementReversalWorthy( self.reversalThreshold, 'M101', 'M103') if (not self.activateEarlyReversal and self.reversalWorthy and self.filamentState == ReversalSkein.FILAMENT_READY): self.distanceFeedRate.addLine("M108 R" + str(self.reversalRPM)) self.distanceFeedRate.addLine("M102") self.distanceFeedRate.addLine("G04 P" + str(self.pushbackTime)) self.filamentState = ReversalSkein.FILAMENT_REVERSED if self.reversalActive: self.reversalActive = False self.filamentState = ReversalSkein.FILAMENT_REVERSED # For safety, reset feedrate here. It's a known issue # that some other plugins keep track of flowrate state # and removed redundant settings, so we need to keep # the original state whenever we're done with an operation self.distanceFeedRate.addLine("M108 R" + str(self.flowrate)) # If someone else inserted a reverse command, detect this and update state # (e.g. end.gcode for Makerbots does this for retracting the filament) elif firstWord == 'M102': self.extruderOn = True self.filamentState = ReversalSkein.FILAMENT_REVERSED self.reversalActive = True if DEBUG: if firstWord == 'M101' or firstWord == 'M102' or firstWord == 'M103': self.printState() # The reversal may change the feedrate for the remaining reversal movements if (self.reversalActive or self.pushbackActive) and firstWord == 'G1': line = self.distanceFeedRate.getLineWithFeedRate( self.reversalFeedrate, line, splitLine) self.distanceFeedRate.addLine(line)
def getSplodgeLine( self, line, location, splitLine ): "Add splodged gcode line." self.feedRateMinute = gcodec.getFeedRateMinute( self.feedRateMinute, splitLine ) if not self.hasInitialSplodgeBeenAdded: return self.getInitialSplodgeLine( line, location ) return self.getOperatingSplodgeLine( line, location )
def getCoolMove( self, line, location, splitLine ): "Add line to time spent on layer." self.feedRateMinute = gcodec.getFeedRateMinute( self.feedRateMinute, splitLine ) self.highestZ = max( location.z, self.highestZ ) self.addFlowRateMultipliedLineIfNecessary( self.oldFlowRate ) return self.distanceFeedRate.getLineWithZLimitedFeedRate( self.multiplier * self.feedRateMinute, line, location, splitLine )
def getCoolMove(self, line, location, splitLine): 'Get cool line according to time spent on layer.' self.feedRateMinute = gcodec.getFeedRateMinute(self.feedRateMinute, splitLine) self.addFlowRate(self.multiplier * self.oldFlowRate) return self.distanceFeedRate.getLineWithFeedRate(self.multiplier * self.feedRateMinute, line, splitLine)