def isNextMovementReversalWorthy(self, threshold, starttoken, endtoken): """ Returns True if we should activate reversal on the next movement, False otherwise. The given threshold defines the movement distance under which we don't reverse. starttoken,endtoken is the movement delimiter (M101,M103 for thread, M103,M101 for stop) """ line = self.lines[self.lineIndex] splitLine = gcodec.getSplitLineBeforeBracketSemicolon(line) lastThreadLocation = gcodec.getLocationFromSplitLine(self.newLocation, splitLine) startTokenReached = False endTokenReached = False totalDistance = 0.0 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': location = gcodec.getLocationFromSplitLine(lastThreadLocation, splitLine) if startTokenReached: totalDistance += location.distance(lastThreadLocation) if totalDistance >= threshold: if DEBUG: self.distanceFeedRate.addLine("( Next movement worthy: " + str(totalDistance) + " )") return True lastThreadLocation = location elif firstWord == endtoken: endTokenReached = True if startTokenReached: return False elif firstWord == starttoken: startTokenReached = True return False
def setEarlyStartupDistance(self, splitLine): "Set the early startup distance." if self.earlyStartupDistance is not None: return self.distanceFromThreadEndToThreadBeginning = 0.0 lastThreadLocation = gcodec.getLocationFromSplitLine(self.oldLocation, splitLine) if self.oldLocation is not None: self.distanceFromThreadEndToThreadBeginning = lastThreadLocation.distance(self.oldLocation) 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": location = gcodec.getLocationFromSplitLine(lastThreadLocation, splitLine) self.distanceFromThreadEndToThreadBeginning += location.distance(lastThreadLocation) lastThreadLocation = location elif firstWord == "M101": distanceConstantRatio = self.distanceFromThreadEndToThreadBeginning / self.earlyStartupDistanceConstant earlyStartupOperatingDistance = self.earlyStartupMaximumDistance * ( 1.0 - math.exp(-distanceConstantRatio) ) if self.isFirstExtrusion: earlyStartupOperatingDistance = self.oozebaneRepository.firstEarlyStartupDistance.value self.isFirstExtrusion = False self.earlyStartupDistance = earlyStartupOperatingDistance * self.getActiveFeedRateRatio() return
def getDistanceToThreadBeginningAfterThreadEnd( self, remainingDistance ): "Get the distance to the thread beginning after the end of this thread." extruderOnReached = False line = self.lines[self.lineIndex] splitLine = gcodec.getSplitLineBeforeBracketSemicolon(line) lastThreadLocation = gcodec.getLocationFromSplitLine(self.oldLocation, splitLine) threadEndReached = False totalDistance = 0.0 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': location = gcodec.getLocationFromSplitLine( lastThreadLocation, splitLine ) if threadEndReached: totalDistance += location.distance( lastThreadLocation ) if totalDistance >= remainingDistance: return None if extruderOnReached: return totalDistance lastThreadLocation = location elif firstWord == 'M101': extruderOnReached = True elif firstWord == 'M103': threadEndReached = True return None
def parseLine(self, line): "Parse a gcode line and add it to the vector output." splitLine = gcodec.getSplitLineBeforeBracketSemicolon(line) if len(splitLine) < 1: return firstWord = splitLine[0] if self.isLayerStart( firstWord, splitLine ): self.extrusionNumber = 0 self.skeinPane = [] self.skeinPanes.append( self.skeinPane ) if firstWord == 'G1': location = gcodec.getLocationFromSplitLine(self.oldLocation, splitLine) self.linearMove( line, location ) self.oldLocation = location elif firstWord == 'M101': self.extruderActive = True self.extrusionNumber += 1 elif firstWord == 'M103': self.extruderActive = False if firstWord == 'G2' or firstWord == 'G3': relativeLocation = gcodec.getLocationFromSplitLine(self.oldLocation, splitLine) relativeLocation.z = 0.0 location = self.oldLocation + relativeLocation self.linearMove( line, location ) self.oldLocation = location
def getDimensionedLinearMovement( self, line, splitLine ): 'Get a dimensioned linear movement.' distance = 0.0 if self.absoluteDistanceMode: location = gcodec.getLocationFromSplitLine(self.oldLocation, splitLine) if self.oldLocation != None: distance = abs( location - self.oldLocation ) if distance > self.maxDistancePerMove * 1.1: extra = '' while distance > self.maxDistancePerMove * 1.1: self.oldLocation.z = location.z self.oldLocation += (location - self.oldLocation) / distance * self.maxDistancePerMove distance -= self.maxDistancePerMove e = self.getExtrusionDistanceString(self.maxDistancePerMove, splitLine) extra += self.distanceFeedRate.getLinearGcodeMovementWithFeedRate(self.feedRateMinute, self.oldLocation.dropAxis(), self.oldLocation.z) + e + '\n' line = extra + line self.oldLocation = location else: if self.oldLocation is None: print('Warning: There was no absolute location when the G91 command was parsed, so the absolute location will be set to the origin.') self.oldLocation = Vector3() location = gcodec.getLocationFromSplitLine(None, splitLine) distance = abs( location ) self.oldLocation += location return line + self.getExtrusionDistanceString( distance, splitLine )
def parseLine(self, line): "Parse a gcode line and add it to the vector output." splitLine = gcodec.getSplitLineBeforeBracketSemicolon(line) if len(splitLine) < 1: return firstWord = splitLine[0] if tableau.getIsLayerStart(firstWord, self, splitLine): self.extrusionNumber = 0 self.layerCount.printProgressIncrement("skeinlayer") self.skeinPane = [] self.skeinPanes.append(self.skeinPane) if firstWord == "G1": location = gcodec.getLocationFromSplitLine(self.oldLocation, splitLine) self.linearMove(line, location) self.oldLocation = location elif firstWord == "M101": self.extruderActive = True self.extrusionNumber += 1 elif firstWord == "M103": self.extruderActive = False if firstWord == "G2" or firstWord == "G3": relativeLocation = gcodec.getLocationFromSplitLine(self.oldLocation, splitLine) relativeLocation.z = 0.0 location = self.oldLocation + relativeLocation self.linearMove(line, location) self.oldLocation = location
def parseLine(self, line): 'Parse a gcode line and add it to the cool skein.' splitLine = gcodec.getSplitLineBeforeBracketSemicolon(line) if len(splitLine) < 1: return firstWord = splitLine[0] if firstWord == 'G1': location = gcodec.getLocationFromSplitLine(self.oldLocation, splitLine) self.highestZ = max(location.z, self.highestZ) if self.isExtruderActive: line = self.getCoolMove(line, location, splitLine) self.oldLocation = location elif firstWord == 'M101': self.isExtruderActive = True elif firstWord == 'M103': self.isExtruderActive = False elif firstWord == 'M104': self.oldTemperature = gcodec.getDoubleAfterFirstLetter(splitLine[1]) elif firstWord == 'M108': self.oldFlowRate = float(splitLine[1][1 :]) self.addFlowRate(self.multiplier * self.oldFlowRate) return elif firstWord == '(<boundaryPoint>': self.boundaryLoop.append(gcodec.getLocationFromSplitLine(None, splitLine).dropAxis()) elif firstWord == '(<layer>': self.layerCount.printProgressIncrement('cool') self.distanceFeedRate.addLine(line) if self.repository.turnFanOnAtBeginning.value and self.repository.fanTurnOnLayerNr.value == self.layerCount.layerIndex: self.fanEnabled = True self.distanceFeedRate.addLinesSetAbsoluteDistanceMode(self.coolStartLines) layerTime = self.getLayerTime() remainingOrbitTime = max(self.repository.minimumLayerTime.value - layerTime, 0.0) self.addCoolTemperature(remainingOrbitTime) if self.fanEnabled: self.addFanSpeed(remainingOrbitTime) if self.repository.orbit.value: self.addOrbitsIfNecessary(remainingOrbitTime) else: self.setMultiplier(remainingOrbitTime) if self.oldFlowRate != None: self.addFlowRate(self.multiplier * self.oldFlowRate) z = float(splitLine[1]) self.boundaryLayer = euclidean.LoopLayer(z) self.highestZ = max(z, self.highestZ) self.distanceFeedRate.addLinesSetAbsoluteDistanceMode(self.coolEndLines) return elif firstWord == '(</layer>)': self.isBridgeLayer = False self.multiplier = 1.0 if self.coolTemperature != None: self.addTemperature(self.oldTemperature) self.coolTemperature = None if self.oldFlowRate != None: self.addFlowRate(self.oldFlowRate) elif firstWord == '(<nestedRing>)': self.boundaryLoop = [] self.boundaryLayer.loops.append(self.boundaryLoop) self.distanceFeedRate.addLine(line)
def parseLine(self, line): "Parse a gcode line and add it to the cool skein." splitLine = gcodec.getSplitLineBeforeBracketSemicolon(line) if len(splitLine) < 1: return firstWord = splitLine[0] if firstWord == "G1": location = gcodec.getLocationFromSplitLine(self.oldLocation, splitLine) self.highestZ = max(location.z, self.highestZ) if self.isExtruderActive: line = self.getCoolMove(line, location, splitLine) self.oldLocation = location elif firstWord == "M101": # todo delete? self.isExtruderActive = True elif firstWord == "M103": self.isExtruderActive = False elif firstWord == "M104": self.oldTemperature = gcodec.getDoubleAfterFirstLetter(splitLine[1]) elif firstWord == "M108": self.setOperatingFlowString(splitLine) self.addFlowRateMultipliedLineIfNecessary(self.oldFlowRate) return elif firstWord == "(<boundaryPoint>": self.boundaryLoop.append(gcodec.getLocationFromSplitLine(None, splitLine).dropAxis()) elif firstWord == "(<layer>": self.layerCount.printProgressIncrement("cool") self.distanceFeedRate.addLine(line) self.distanceFeedRate.addLinesSetAbsoluteDistanceMode(self.coolStartLines) layerTime = self.getLayerTime() remainingOrbitTime = max(self.repository.minimumLayerTime.value - layerTime, 0.0) self.addCoolTemperature(remainingOrbitTime) if self.repository.orbit.value: self.addOrbitsIfNecessary(remainingOrbitTime) else: self.setMultiplier(layerTime) z = float(splitLine[1]) self.boundaryLayer = euclidean.LoopLayer(z) self.highestZ = max(z, self.highestZ) self.distanceFeedRate.addLinesSetAbsoluteDistanceMode(self.coolEndLines) return elif firstWord == "(</layer>)": self.isBridgeLayer = False self.multiplier = 1.0 if self.coolTemperature != None: self.addTemperature(self.oldTemperature) self.coolTemperature = None self.addFlowRateLineIfNecessary(self.oldFlowRate) elif firstWord == "(<nestedRing>)": self.boundaryLoop = [] self.boundaryLayer.loops.append(self.boundaryLoop) self.distanceFeedRate.addLine(line)
def getSplodgeLineGivenDistance( self, feedRateMinute, line, liftOverExtraThickness, location, startupDistance ): "Add the splodge line." locationComplex = location.dropAxis() relativeStartComplex = None nextLocationComplex = self.getNextActiveLocationComplex() if nextLocationComplex != None: if nextLocationComplex != locationComplex: relativeStartComplex = locationComplex - nextLocationComplex if relativeStartComplex == None: relativeStartComplex = complex( 19.9, 9.9 ) if self.oldLocation != None: oldLocationComplex = self.oldLocation.dropAxis() if oldLocationComplex != locationComplex: relativeStartComplex = oldLocationComplex - locationComplex relativeStartComplex *= startupDistance / abs( relativeStartComplex ) startComplex = self.getStartInsideBoundingRectangle( locationComplex, relativeStartComplex ) feedRateMultiplier = feedRateMinute / self.operatingFeedRatePerSecond / 60.0 splodgeLayerThickness = self.layerThickness / math.sqrt( feedRateMultiplier ) extraLayerThickness = splodgeLayerThickness - self.layerThickness lift = extraLayerThickness * liftOverExtraThickness startLine = self.distanceFeedRate.getLinearGcodeMovementWithFeedRate( self.feedRateMinute, startComplex, location.z + lift ) self.addLineUnlessIdenticalReactivate( startLine ) self.addLineUnlessIdenticalReactivate('M101') splitLine = gcodec.getSplitLineBeforeBracketSemicolon(line) lineLocation = gcodec.getLocationFromSplitLine(self.oldLocation, splitLine) self.distanceFeedRate.addGcodeMovementZWithFeedRate( feedRateMinute, locationComplex, lineLocation.z + lift ) return ''
def parseLine(self, line): "Parse a gcode line and add it to the inset skein." splitLine = gcodec.getSplitLineBeforeBracketSemicolon(line) if len(splitLine) < 1: return firstWord = splitLine[0] if firstWord == '(<boundaryPoint>': location = gcodec.getLocationFromSplitLine(None, splitLine) self.boundary.append(location.dropAxis()) elif firstWord == '(<bridgeRotation>': self.loopLayer.rotation = gcodec.getRotationBySplitLine(splitLine) elif firstWord == '(</crafting>)': self.distanceFeedRate.addLine(line) if self.repository.turnExtruderHeaterOffAtShutDown.value: self.distanceFeedRate.addLine('M104 S0') # Turn extruder heater off. return elif firstWord == '(<layer>': self.layerCount.printProgressIncrement('inset') self.loopLayer = euclidean.LoopLayer(float(splitLine[1])) self.distanceFeedRate.addLine(line) elif firstWord == '(</layer>)': self.addInset(self.loopLayer) self.loopLayer = None elif firstWord == '(<nestedRing>)': self.boundary = [] self.loopLayer.loops.append(self.boundary) if self.loopLayer == None: self.distanceFeedRate.addLine(line)
def getLocationSetFeedRateToSplitLine( self, splitLine ): "Get location ans set feed rate to the plsit line." location = gcodec.getLocationFromSplitLine( self.oldLocation, splitLine ) indexOfF = gcodec.indexOfStartingWithSecond( "F", splitLine ) if indexOfF > 0: self.feedRateMinute = gcodec.getDoubleAfterFirstLetter( splitLine[ indexOfF ] ) return location
def linearCorner( self, splitLine ): "Update the bounding corners." location = gcodec.getLocationFromSplitLine(self.oldLocation, splitLine) if self.extruderActive or self.goAroundExtruderOffTravel: self.cornerMaximum.maximize(location) self.cornerMinimum.minimize(location) self.oldLocation = location
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 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 getDimensionedLinearMovement( self, line, splitLine ): 'Get a dimensioned linear movement.' distance = 0.0 if self.absoluteDistanceMode: location = gcodec.getLocationFromSplitLine(self.oldLocation, splitLine) if self.oldLocation != None: distance = abs( location - self.oldLocation ) self.oldLocation = location else: if self.oldLocation == None: print('Warning: There was no absolute location when the G91 command was parsed, so the absolute location will be set to the origin.') self.oldLocation = Vector3() location = gcodec.getLocationFromSplitLine(None, splitLine) distance = abs( location ) self.oldLocation += location return line + self.getExtrusionDistanceString( distance, splitLine )
def parseBoundaries(self): 'Parse the boundaries and add them to the boundary layers.' self.boundaryLayers = [] self.layerIndexTop = -1 boundaryLoop = None boundaryLayer = None for line in self.lines[self.lineIndex :]: splitLine = gcodec.getSplitLineBeforeBracketSemicolon(line) firstWord = gcodec.getFirstWord(splitLine) if firstWord == '(</boundaryPerimeter>)': boundaryLoop = None elif firstWord == '(<boundaryPoint>': location = gcodec.getLocationFromSplitLine(None, splitLine) if boundaryLoop == None: boundaryLoop = [] boundaryLayer.loops.append(boundaryLoop) boundaryLoop.append(location.dropAxis()) elif firstWord == '(<layer>': boundaryLayer = euclidean.LoopLayer(float(splitLine[1])) self.boundaryLayers.append(boundaryLayer) self.layerIndexTop += 1 for boundaryLayerIndex, boundaryLayer in enumerate(self.boundaryLayers): if len(boundaryLayer.loops) > 0: self.layersFromBottom += boundaryLayerIndex return
def setCorners(self): 'Set maximum and minimum corners and z.' cornerMaximumComplex = complex(-987654321.0, -987654321.0) cornerMinimumComplex = -cornerMaximumComplex for line in self.lines[self.lineIndex :]: splitLine = gcodec.getSplitLineBeforeBracketSemicolon(line) firstWord = gcodec.getFirstWord(splitLine) if firstWord == 'G1': location = gcodec.getLocationFromSplitLine(self.oldLocation, splitLine) if self.isExtrusionActive: locationComplex = location.dropAxis() cornerMaximumComplex = euclidean.getMaximum(locationComplex, cornerMaximumComplex) cornerMinimumComplex = euclidean.getMinimum(locationComplex, cornerMinimumComplex) self.oldLocation = location elif firstWord == 'M101': self.isExtrusionActive = True elif firstWord == 'M103': self.isExtrusionActive = False self.extent = cornerMaximumComplex - cornerMinimumComplex self.shapeCenter = 0.5 * (cornerMaximumComplex + cornerMinimumComplex) self.separation = self.repository.separationOverPerimeterWidth.value * self.absolutePerimeterWidth self.extentPlusSeparation = self.extent + complex(self.separation, self.separation) columnsMinusOne = self.numberOfColumns - 1 rowsMinusOne = self.numberOfRows - 1 self.arrayExtent = complex(self.extentPlusSeparation.real * columnsMinusOne, self.extentPlusSeparation.imag * rowsMinusOne) self.arrayCenter = 0.5 * self.arrayExtent
def parseLine(self, line): "Parse a gcode line and add it to the mill skein." splitLine = gcodec.getSplitLineBeforeBracketSemicolon(line) if len(splitLine) < 1: return firstWord = splitLine[0] if firstWord == 'G1': location = gcodec.getLocationFromSplitLine(self.oldLocation, splitLine) if self.isExtruderActive: self.average.addValue(location.z) if self.oldLocation != None: euclidean.addValueSegmentToPixelTable( self.oldLocation.dropAxis(), location.dropAxis(), self.aroundPixelTable, None, self.aroundWidth ) self.oldLocation = location elif firstWord == 'M101': self.isExtruderActive = True elif firstWord == 'M103': self.isExtruderActive = False elif firstWord == '(<layer>': self.layerCount.printProgressIncrement('mill') self.aroundPixelTable = {} self.average.reset() elif firstWord == '(</layer>)': if len( self.boundaryLayers ) > self.layerIndex: self.addMillThreads() self.layerIndex += 1 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 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 getTransferClosestNestedRingLines( self, oldOrderedLocation, remainingNestedRings ): "Get and transfer the closest remaining nested ring." if len( remainingNestedRings ) > 0: oldOrderedLocation.z = remainingNestedRings[0].z closestDistance = 999999999987654321.0 closestNestedRing = None for remainingNestedRing in remainingNestedRings: distance = euclidean.getClosestDistanceIndexToLine(oldOrderedLocation.dropAxis(), remainingNestedRing.boundary).distance if distance < closestDistance: closestDistance = distance closestNestedRing = remainingNestedRing remainingNestedRings.remove(closestNestedRing) hasTravelledHighRoad = False for line in closestNestedRing.lines: splitLine = gcodec.getSplitLineBeforeBracketSemicolon(line) firstWord = gcodec.getFirstWord(splitLine) if firstWord == 'G1': location = gcodec.getLocationFromSplitLine(self.oldLocation, splitLine) if not hasTravelledHighRoad: hasTravelledHighRoad = True self.addHighThread(location) if location.z > self.highestZ: self.highestZ = location.z self.oldLocation = location self.distanceFeedRate.addLine(line) return closestNestedRing
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 getAddShutSlowDownLine(self, line): "Add the shutdown and slowdown lines." if self.shutdownStepIndex >= len( self.earlyShutdownDistances ): self.shutdownStepIndex = len( self.earlyShutdownDistances ) + 99999999 return False splitLine = gcodec.getSplitLineBeforeBracketSemicolon(line) distanceThreadEnd = self.getDistanceToExtruderOffCommand( self.earlyShutdownDistances[ self.shutdownStepIndex ] ) location = gcodec.getLocationFromSplitLine(self.oldLocation, splitLine) if distanceThreadEnd == None: distanceThreadEnd = self.getDistanceToExtruderOffCommand( self.earlyShutdownDistances[0] ) if distanceThreadEnd != None: shutdownFlowRateMultiplier = self.getShutdownFlowRateMultiplier( 1.0 - distanceThreadEnd / self.earlyShutdownDistance, len( self.earlyShutdownDistances ) ) line = self.getLinearMoveWithFeedRate( self.feedRateMinute * shutdownFlowRateMultiplier, location ) self.distanceFeedRate.addLine(line) return False segment = self.oldLocation - location segmentLength = segment.magnitude() distanceBack = self.earlyShutdownDistances[ self.shutdownStepIndex ] - distanceThreadEnd locationBack = location if segmentLength > 0.0: locationBack = location + segment * distanceBack / segmentLength if self.shutdownStepIndex == 0: if not self.isCloseToEither( locationBack, location, self.oldLocation ): line = self.getLinearMoveWithFeedRate( self.feedRateMinute, locationBack ) self.distanceFeedRate.addLine(line) self.addLineSetShutdowns('M103') return True if self.isClose( locationBack, self.oldLocation ): return True feedRate = self.feedRateMinute * self.earlyShutdownFlowRates[ self.shutdownStepIndex ] line = self.getLinearMoveWithFeedRate( feedRate, locationBack ) if self.isClose( locationBack, location ): line = self.getLinearMoveWithFeedRate( feedRate, location ) self.distanceFeedRate.addLine(line) return True
def getLinearMove( self, line, splitLine ): "Get the linear move." location = gcodec.getLocationFromSplitLine(self.oldLocation, splitLine) self.movementLines.append(line) z = location.z + self.layerDeltas[0] self.oldLocation = location return self.distanceFeedRate.getLineWithZ( line, splitLine, z )
def getLimitedLinearMovement( self, line, splitLine ): "Get a limited linear movement." location = gcodec.getLocationFromSplitLine( self.oldLocation, splitLine ) if self.oldLocation == None: line = self.distanceFeedRate.getLineWithFeedRate( 60.0 * self.repository.maximumInitialFeedRate.value, line, splitLine ) self.oldLocation = location 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 getRelativeStretch( self, locationComplex, lineIterator ): "Get relative stretch for a location." lastLocationComplex = locationComplex oldTotalLength = 0.0 pointComplex = locationComplex totalLength = 0.0 while 1: try: line = lineIterator.getNext() except StopIteration: locationMinusPoint = locationComplex - pointComplex locationMinusPointLength = abs( locationMinusPoint ) if locationMinusPointLength > 0.0: return locationMinusPoint / locationMinusPointLength return complex() splitLine = gcodec.getSplitLineBeforeBracketSemicolon(line) firstWord = splitLine[0] pointComplex = gcodec.getLocationFromSplitLine(self.oldLocation, splitLine).dropAxis(2) locationMinusPoint = lastLocationComplex - pointComplex locationMinusPointLength = abs( locationMinusPoint ) totalLength += locationMinusPointLength if totalLength >= self.stretchFromDistance: distanceFromRatio = ( self.stretchFromDistance - oldTotalLength ) / locationMinusPointLength totalPoint = distanceFromRatio * pointComplex + ( 1.0 - distanceFromRatio ) * lastLocationComplex locationMinusTotalPoint = locationComplex - totalPoint return locationMinusTotalPoint / self.stretchFromDistance lastLocationComplex = pointComplex oldTotalLength = totalLength
def getDistanceToNextThread(self, lineIndex): 'Get the travel distance to the next thread.' if self.oldLocation == None: return None isActive = False location = self.oldLocation for afterIndex in xrange(lineIndex + 1, len(self.lines)): line = self.lines[afterIndex] splitLine = gcodec.getSplitLineBeforeBracketSemicolon(line) firstWord = gcodec.getFirstWord(splitLine) if firstWord == 'G1': if isActive: if not self.repository.retractWithinIsland.value: locationEnclosureIndex = self.getSmallestEnclosureIndex(location.dropAxis()) if locationEnclosureIndex != self.getSmallestEnclosureIndex(self.oldLocation.dropAxis()): return None locationMinusOld = location - self.oldLocation xyTravel = abs(locationMinusOld.dropAxis()) zTravelMultiplied = locationMinusOld.z * self.zDistanceRatio return math.sqrt(xyTravel * xyTravel + zTravelMultiplied * zTravelMultiplied) location = gcodec.getLocationFromSplitLine(location, splitLine) elif firstWord == 'M101': isActive = True elif firstWord == 'M103': isActive = False return None
def linearCorner( self, splitLine ): "Update the bounding corners." location = gcodec.getLocationFromSplitLine(self.oldLocation, splitLine) if self.extruderActive or self.repository.goAroundExtruderOffTravel.value: self.cornerHigh = euclidean.getPointMaximum( self.cornerHigh, location ) self.cornerLow = euclidean.getPointMinimum( self.cornerLow, location ) self.oldLocation = location
def parseBoundaries(self): "Parse the boundaries and add them to the boundary layers." boundaryLoop = None boundaryLayer = None for line in self.lines[self.lineIndex :]: splitLine = gcodec.getSplitLineBeforeBracketSemicolon(line) firstWord = gcodec.getFirstWord(splitLine) if len(self.shutdownLines) > 0: self.shutdownLines.append(line) if firstWord == "(</boundaryPerimeter>)": boundaryLoop = None elif firstWord == "(<boundaryPoint>": location = gcodec.getLocationFromSplitLine(None, splitLine) if boundaryLoop == None: boundaryLoop = [] boundaryLayer.loops.append(boundaryLoop) boundaryLoop.append(location.dropAxis()) elif firstWord == "(<layer>": boundaryLayer = euclidean.LoopLayer(float(splitLine[1])) self.boundaryLayers.append(boundaryLayer) elif firstWord == "(</crafting>)": self.shutdownLines = [line] for boundaryLayer in self.boundaryLayers: if not euclidean.isWiddershins(boundaryLayer.loops[0]): boundaryLayer.loops[0].reverse() self.boundaryReverseLayers = self.boundaryLayers[:] self.boundaryReverseLayers.reverse()
def parseLine(self, line): "Parse a gcode line and add it to the bevel gcode." splitLine = gcodec.getSplitLineBeforeBracketSemicolon(line) if len(splitLine) < 1: return firstWord = splitLine[0] if firstWord == 'G1': self.addHomeTravel(splitLine) self.oldLocation = gcodec.getLocationFromSplitLine(self.oldLocation, splitLine) elif firstWord == '(<layer>': self.layerCount.printProgressIncrement('home') if len(self.homeLines) > 0: self.shouldHome = True elif firstWord == 'M101': self.extruderActive = True elif firstWord == 'M103': self.extruderActive = False self.distanceFeedRate.addLine(line)
def parseLine(self, line): "Parse a gcode line and add it to the lift skein." splitLine = gcodec.getSplitLineBeforeBracketSemicolon(line) if len(splitLine) < 1: return firstWord = splitLine[0] if firstWord == 'G1': location = gcodec.getLocationFromSplitLine(self.oldLocation, splitLine) line = self.getLinearMove(line, location, splitLine) self.previousActiveMovementLine = line self.oldLocation = location elif firstWord == 'M101': self.addPreviousInactiveMovementLineIfNecessary() self.extruderActive = True elif firstWord == 'M103': self.extruderActive = False self.distanceFeedRate.addLine(line)
def parseLine( self, line ): "Parse a gcode line and add it to the bevel gcode." splitLine = gcodec.getSplitLineBeforeBracketSemicolon( line ) if len( splitLine ) < 1: return firstWord = splitLine[ 0 ] if firstWord == 'G1': self.addWipeTravel( splitLine ) self.oldLocation = gcodec.getLocationFromSplitLine( self.oldLocation, splitLine ) elif firstWord == '(<layer>': self.layerIndex += 1 if self.layerIndex % self.wipePeriod == 0: self.shouldWipe = True elif firstWord == 'M101': self.extruderActive = True elif firstWord == 'M103': self.extruderActive = False self.distanceFeedRate.addLine( line )
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 parseLine( self, lineIndex ): 'Parse a gcode line and add it to the limit skein.' line = self.lines[lineIndex].lstrip() splitLine = gcodec.getSplitLineBeforeBracketSemicolon(line) if len(splitLine) < 1: return firstWord = gcodec.getFirstWord(splitLine) if firstWord == 'G1': location = gcodec.getLocationFromSplitLine(self.oldLocation, splitLine) line = self.getLimitedInitialMovement(line, splitLine) line = self.getZLimitedLineLinear(line, location, splitLine) self.oldLocation = location elif firstWord == 'G2' or firstWord == 'G3': line = self.getZLimitedLineArc(line, splitLine) elif firstWord == 'M101': self.maximumZFeedRatePerSecond = self.maximumZDrillFeedRatePerSecond elif firstWord == 'M103': self.maximumZFeedRatePerSecond = self.maximumZTravelFeedRatePerSecond self.distanceFeedRate.addLine(line)
def parseLine(self, line): "Parse a gcode line and add it to the bevel gcode." splitLine = gcodec.getSplitLineBeforeBracketSemicolon(line) if len(splitLine) < 1: return firstWord = splitLine[0] if firstWord == 'G1': self.setEarlyStartupDistance(splitLine) line = self.getOozebaneLine(line) self.oldLocation = gcodec.getLocationFromSplitLine( self.oldLocation, splitLine) elif firstWord == 'M101': self.isExtruderActive = True self.extruderInactiveLongEnough = False if self.getDistanceToExtruderOffCommand( self.earlyShutdownDistance) == None: self.setEarlyShutdown() if self.getDistanceToExtruderOffCommand( 1.03 * (self.earlyShutdownDistance + self.afterStartupDistance)) == None: afterStartupRatio = 1.0 if self.minimumDistanceForEarlyStartup > 0.0: if self.distanceFromThreadEndToThreadBeginning != None: afterStartupRatio = self.distanceFromThreadEndToThreadBeginning / self.minimumDistanceForEarlyStartup self.setAfterStartupFlowRates(afterStartupRatio) self.startupStepIndex = 9999999999 if len(self.afterStartupDistances) > 0: self.startupStepIndex = 0 if self.isStartupEarly: self.isStartupEarly = False return elif firstWord == 'M103': self.isExtruderActive = False self.shutdownStepIndex = 999999999 if self.getDistanceToThreadBeginning() == None: self.extruderInactiveLongEnough = True self.distanceFromThreadEndToThreadBeginning = None self.earlyStartupDistance = None if self.isShutdownEarly: self.distanceFeedRate.addLine("(<EarlyShutdownFinished>)") self.isShutdownEarly = False return self.distanceFeedRate.addLine(line)
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 parseLine(self, line): "Parse a gcode line and add it to the bevel gcode." splitLine = gcodec.getSplitLineBeforeBracketSemicolon(line) if len(splitLine) < 1: return firstWord = splitLine[0] if self.distanceFeedRate.getIsAlteration(line): return if firstWord == 'G1': line = self.getHopLine(line) self.oldLocation = gcodec.getLocationFromSplitLine( self.oldLocation, splitLine) self.justDeactivated = False elif firstWord == 'M101': self.extruderActive = True elif firstWord == 'M103': self.extruderActive = False self.justDeactivated = True self.distanceFeedRate.addLineCheckAlteration(line)
def getCrossLimitedStretch( self, crossLimitedStretch, crossLineIterator, locationComplex ): "Get cross limited relative stretch for a location." try: line = crossLineIterator.getNext() except StopIteration: return crossLimitedStretch splitLine = gcodec.getSplitLineBeforeBracketSemicolon(line) pointComplex = gcodec.getLocationFromSplitLine(self.oldLocation, splitLine).dropAxis() pointMinusLocation = locationComplex - pointComplex pointMinusLocationLength = abs( pointMinusLocation ) if pointMinusLocationLength <= self.crossLimitDistanceFraction: return crossLimitedStretch parallelNormal = pointMinusLocation / pointMinusLocationLength parallelStretch = euclidean.getDotProduct( parallelNormal, crossLimitedStretch ) * parallelNormal if pointMinusLocationLength > self.crossLimitDistance: return parallelStretch crossNormal = complex( parallelNormal.imag, - parallelNormal.real ) crossStretch = euclidean.getDotProduct( crossNormal, crossLimitedStretch ) * crossNormal crossPortion = ( self.crossLimitDistance - pointMinusLocationLength ) / self.crossLimitDistanceRemainder return parallelStretch + crossStretch * crossPortion
def parseLine(self, line): "Parse a gcode line and add it to the widen skein." splitLine = gcodec.getSplitLineBeforeBracketSemicolon(line) if len(splitLine) < 1: return firstWord = splitLine[0] if firstWord == '(<boundaryPoint>': location = gcodec.getLocationFromSplitLine(None, splitLine) self.boundary.append( location.dropAxis(2) ) elif firstWord == '(<layer>': self.rotatedBoundaryLayer = euclidean.RotatedLoopLayer( float(splitLine[1]) ) self.distanceFeedRate.addLine(line) elif firstWord == '(</layer>)': self.addWiden( self.rotatedBoundaryLayer ) self.rotatedBoundaryLayer = None elif firstWord == '(<surroundingLoop>)': self.boundary = [] self.rotatedBoundaryLayer.loops.append( self.boundary ) if self.rotatedBoundaryLayer == None: self.distanceFeedRate.addLine(line)
def parseBoundaries(self): 'Parse the boundaries and add them to the boundary layers.' boundaryLoop = None boundaryLayer = None for line in self.lines[self.lineIndex :]: splitLine = gcodec.getSplitLineBeforeBracketSemicolon(line) firstWord = gcodec.getFirstWord(splitLine) if firstWord == '(</boundaryPerimeter>)': boundaryLoop = None elif firstWord == '(<boundaryPoint>': location = gcodec.getLocationFromSplitLine(None, splitLine) if boundaryLoop == None: boundaryLoop = [] boundaryLayer.loops.append(boundaryLoop) boundaryLoop.append(location.dropAxis()) elif firstWord == '(<layer>': boundaryLayer = euclidean.LoopLayer(float(splitLine[1])) self.boundaryLayers.append(boundaryLayer) for boundaryLayer in self.boundaryLayers: triangle_mesh.sortLoopsInOrderOfArea(False, boundaryLayer.loops)
def parseLine(self, line): 'Parse a gcode line and add it to the widen skein.' splitLine = gcodec.getSplitLineBeforeBracketSemicolon(line) if len(splitLine) < 1: return firstWord = splitLine[0] if firstWord == '(<boundaryPoint>': location = gcodec.getLocationFromSplitLine(None, splitLine) self.boundary.append(location.dropAxis()) elif firstWord == '(<layer>': self.layerCount.printProgressIncrement('widen') self.loopLayer = euclidean.LoopLayer(float(splitLine[1])) self.distanceFeedRate.addLine(line) elif firstWord == '(</layer>)': self.addWiden(self.loopLayer) self.loopLayer = None elif firstWord == '(<nestedRing>)': self.boundary = [] self.loopLayer.loops.append(self.boundary) if self.loopLayer == None: self.distanceFeedRate.addLine(line)
def parseLine(self, line): "Parse a gcode line and add it to the outset skein." splitLine = gcodec.getSplitLineBeforeBracketSemicolon(line) if len(splitLine) < 1: return firstWord = splitLine[0] if firstWord == 'G1': self.linearMove(splitLine) elif firstWord == 'M101': self.extruderActive = True elif firstWord == 'M103': self.extruderActive = False if self.isLoop: self.addToLoops() return if self.isPerimeter: self.addToPerimeters() return self.rotatedBoundaryLayer.paths.append(self.thread) self.thread = [] elif firstWord == '(</boundaryPerimeter>)': self.boundaryLoop = None elif firstWord == '(<boundaryPoint>': location = gcodec.getLocationFromSplitLine(None, splitLine) if self.boundaryLoop == None: self.boundaryLoop = [] self.rotatedBoundaryLayer.boundaryLoops.append( self.boundaryLoop) self.boundaryLoop.append(location.dropAxis(2)) elif firstWord == '(<layer>': self.addRotatedLoopLayer(float(splitLine[1])) elif firstWord == '(</loop>)': self.addToLoops() elif firstWord == '(<loop>': self.isLoop = True elif firstWord == '(<perimeter>': self.isPerimeter = True self.isOuter = (splitLine[1] == 'outer') elif firstWord == '(</perimeter>)': self.addToPerimeters()
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 parseBoundaries(self): 'Parse the boundaries and add them to the boundary layers.' boundaryLoop = None boundaryLayer = None for line in self.lines[self.lineIndex :]: splitLine = gcodec.getSplitLineBeforeBracketSemicolon(line) firstWord = gcodec.getFirstWord(splitLine) if firstWord == '(</boundaryPerimeter>)': boundaryLoop = None elif firstWord == '(<boundaryPoint>': location = gcodec.getLocationFromSplitLine(None, splitLine) if boundaryLoop == None: boundaryLoop = [] boundaryLayer.loops.append(boundaryLoop) boundaryLoop.append(location.dropAxis()) elif firstWord == '(<layer>': boundaryLayer = euclidean.LoopLayer(float(splitLine[1])) self.boundaryLayers.append(boundaryLayer) if len(self.boundaryLayers) < 2: return for boundaryLayer in self.boundaryLayers: boundaryLayer.innerOutsetLoops = intercircle.getInsetSeparateLoopsFromLoops(boundaryLayer.loops, -self.loopInnerOutset) boundaryLayer.outerOutsetLoops = intercircle.getInsetSeparateLoopsFromLoops(boundaryLayer.loops, -self.loopOuterOutset) boundaryLayer.innerHorizontalTable = self.getHorizontalXIntersectionsTable( boundaryLayer.innerOutsetLoops ) boundaryLayer.outerHorizontalTable = self.getHorizontalXIntersectionsTable( boundaryLayer.outerOutsetLoops ) boundaryLayer.innerVerticalTable = self.getHorizontalXIntersectionsTable( euclidean.getDiagonalFlippedLoops( boundaryLayer.innerOutsetLoops ) ) boundaryLayer.outerVerticalTable = self.getHorizontalXIntersectionsTable( euclidean.getDiagonalFlippedLoops( boundaryLayer.outerOutsetLoops ) ) for boundaryLayerIndex in xrange( len(self.boundaryLayers) - 2, - 1, - 1 ): boundaryLayer = self.boundaryLayers[ boundaryLayerIndex ] boundaryLayerBelow = self.boundaryLayers[ boundaryLayerIndex + 1 ] euclidean.joinXIntersectionsTables( boundaryLayerBelow.outerHorizontalTable, boundaryLayer.outerHorizontalTable ) euclidean.joinXIntersectionsTables( boundaryLayerBelow.outerVerticalTable, boundaryLayer.outerVerticalTable ) for boundaryLayerIndex in xrange( 1, len(self.boundaryLayers) ): boundaryLayer = self.boundaryLayers[ boundaryLayerIndex ] boundaryLayerAbove = self.boundaryLayers[ boundaryLayerIndex - 1 ] euclidean.joinXIntersectionsTables( boundaryLayerAbove.innerHorizontalTable, boundaryLayer.innerHorizontalTable ) euclidean.joinXIntersectionsTables( boundaryLayerAbove.innerVerticalTable, boundaryLayer.innerVerticalTable ) for boundaryLayerIndex in xrange( len(self.boundaryLayers) ): self.addSegmentTableLoops(boundaryLayerIndex)
def parseLine( self, lineIndex ): "Parse a gcode line and add it to the outset skein." line = self.lines[lineIndex].lstrip() splitLine = gcodec.getSplitLineBeforeBracketSemicolon(line) if len(splitLine) < 1: return firstWord = splitLine[0] if firstWord == '(<boundaryPoint>': location = gcodec.getLocationFromSplitLine(None, splitLine) self.boundary.append( location.dropAxis(2) ) elif firstWord == '(<layer>': self.layerCount.printProgressIncrement('outset') self.rotatedBoundaryLayer = euclidean.RotatedLoopLayer(float(splitLine[1])) self.distanceFeedRate.addLine(line) elif firstWord == '(</layer>)': self.addOutset( self.rotatedBoundaryLayer ) self.rotatedBoundaryLayer = None elif firstWord == '(<surroundingLoop>)': self.boundary = [] self.rotatedBoundaryLayer.loops.append( self.boundary ) if self.rotatedBoundaryLayer == None: self.distanceFeedRate.addLine(line)
def getNextThreadIsACloseLoop(self, path): "Determine if the next thread is a loop." if self.oldLocation == None: return False isLoop = False location = self.oldLocation for afterIndex in xrange(self.lineIndex + 1, len(self.lines)): line = self.lines[afterIndex] splitLine = gcodec.getSplitLineBeforeBracketSemicolon(line) firstWord = gcodec.getFirstWord(splitLine) if firstWord == '(<loop>' or firstWord == '(<perimeter>': isLoop = True elif firstWord == 'G1': location = gcodec.getLocationFromSplitLine( self.oldLocation, splitLine) elif firstWord == 'M101': if not isLoop: return False return self.getConnectionIsCloseWithoutOverlap(location, path) elif firstWord == '(<layer>': return False return False
def parseCorner(self, line): "Parse a gcode line and use the location to update the bounding corners." splitLine = gcodec.getSplitLineBeforeBracketSemicolon(line) if len(splitLine) < 1: return firstWord = splitLine[0] if tableau.getIsLayerStart(firstWord, self, splitLine): if firstWord == '(<layer>': self.layerTopZ = float(splitLine[1]) + self.thirdLayerThickness else: self.layerTopZ = gcodec.getLocationFromSplitLine(self.oldLocation, splitLine).z + self.thirdLayerThickness self.layerTops.append( self.layerTopZ ) if firstWord == 'G1': self.linearCorner(splitLine) elif firstWord == 'M101': self.extruderActive = True elif firstWord == 'M103': self.extruderActive = False elif firstWord == '(<layerThickness>': self.thirdLayerThickness = 0.33333333333 * float(splitLine[1]) if firstWord == '(<surroundingLoop>)': if self.layerTopZ > self.getLayerTop(): self.layerTops.append( self.layerTopZ )
def getDimensionedArcMovement( self, line, splitLine ): "Get a dimensioned arc movement." if self.oldLocation == None: return line 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 ) return line + self.getExtrusionDistanceString( distance, splitLine )
def addWipeTravel(self, splitLine): "Add the wipe travel gcode." location = gcodec.getLocationFromSplitLine(self.oldLocation, splitLine) self.highestZ = max(self.highestZ, location.z) if not self.shouldWipe: return self.shouldWipe = False if self.extruderActive: self.distanceFeedRate.addLine('M103') if self.oldLocation != None: self.addHop(self.oldLocation, self.locationArrival) self.distanceFeedRate.addLine( self.getLinearMoveWithFeedRate(self.travelFeedRateMinute, self.locationArrival)) self.distanceFeedRate.addLine( self.getLinearMoveWithFeedRate(self.travelFeedRateMinute, self.locationWipe)) self.distanceFeedRate.addLine( self.getLinearMoveWithFeedRate(self.travelFeedRateMinute, self.locationDeparture)) self.addHop(self.locationDeparture, location) if self.extruderActive: self.distanceFeedRate.addLine('M101')
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 setCorners(self): "Set maximum and minimum corners and z." locationComplexes = [] for line in self.lines[self.lineIndex:]: splitLine = gcodec.getSplitLineBeforeBracketSemicolon(line) firstWord = gcodec.getFirstWord(splitLine) if firstWord == 'G1': location = gcodec.getLocationFromSplitLine( self.oldLocation, splitLine) locationComplexes.append(location.dropAxis(2)) self.oldLocation = location cornerHighComplex = euclidean.getMaximumFromPoints(locationComplexes) cornerLowComplex = euclidean.getMinimumFromPoints(locationComplexes) self.extent = cornerHighComplex - cornerLowComplex self.shapeCenter = 0.5 * (cornerHighComplex + cornerLowComplex) self.separation = self.multiplyRepository.separationOverPerimeterWidth.value * self.absolutePerimeterWidth self.extentPlusSeparation = self.extent + complex( self.separation, self.separation) columnsMinusOne = self.numberOfColumns - 1 rowsMinusOne = self.numberOfRows - 1 self.arrayExtent = complex( self.extentPlusSeparation.real * columnsMinusOne, self.extentPlusSeparation.imag * rowsMinusOne) self.arrayCenter = 0.5 * self.arrayExtent
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 parseBoundaries(self): 'Parse the boundaries and union them.' self.createSegmentDictionaries(self.unifiedLoop) if self.repository.layersTo.value < 1: return loopCrossDictionary = None layerIndex = -1 for line in self.lines[self.lineIndex:]: splitLine = gcodec.getSplitLineBeforeBracketSemicolon(line) firstWord = gcodec.getFirstWord(splitLine) if firstWord == '(</boundaryPerimeter>)' or firstWord == '(</raftPerimeter>)': self.createSegmentDictionaries(loopCrossDictionary) self.unifyLayer(loopCrossDictionary) loopCrossDictionary = None elif firstWord == '(<boundaryPoint>' or firstWord == '(<raftPoint>': location = gcodec.getLocationFromSplitLine(None, splitLine) if loopCrossDictionary == None: loopCrossDictionary = LoopCrossDictionary() loopCrossDictionary.loop.append(location.dropAxis()) elif firstWord == '(<layer>': layerIndex += 1 if layerIndex > self.repository.layersTo.value: return settings.printProgress(layerIndex, 'skirt')
def linearMove( self, splitLine ): "Comment a linear move." location = gcodec.getLocationFromSplitLine(self.oldLocation, splitLine) self.addComment( "Linear move to " + str( location ) + "." ); self.oldLocation = location
def getLinearMoveWithFeedRateSplitLine(self, feedRate, splitLine): "Get a linear move line with the feed rate and split line." location = gcodec.getLocationFromSplitLine(self.oldLocation, splitLine) return self.getLinearMoveWithFeedRate(feedRate, location)
def getMovedLocationSetOldLocation(self, offset, splitLine): 'Get the moved location and set the old location.' location = gcodec.getLocationFromSplitLine(self.oldLocation, splitLine) self.oldLocation = location return Vector3(location.x + offset.real, location.y + offset.imag, location.z)
def parseLine(self, line): 'Parse a gcode line and add it to the cool skein.' splitLine = gcodec.getSplitLineBeforeBracketSemicolon(line) if len(splitLine) < 1: return firstWord = splitLine[0] if firstWord == 'G1': location = gcodec.getLocationFromSplitLine(self.oldLocation, splitLine) self.highestZ = max(location.z, self.highestZ) if self.isExtruderActive: line = self.getCoolMove(line, location, splitLine) self.oldLocation = location elif firstWord == 'M101': self.isExtruderActive = True elif firstWord == 'M103': self.isExtruderActive = False elif firstWord == 'M104': self.oldTemperature = gcodec.getDoubleAfterFirstLetter( splitLine[1]) elif firstWord == 'M108': self.oldFlowRate = float(splitLine[1][1:]) self.addFlowRate(self.multiplier * self.oldFlowRate) return elif firstWord == '(<boundaryPoint>': self.boundaryLoop.append( gcodec.getLocationFromSplitLine(None, splitLine).dropAxis()) elif firstWord == '(<layer>': self.layerCount.printProgressIncrement('cool') self.distanceFeedRate.addLine(line) if self.repository.turnFanOnAtBeginning.value and self.repository.fanTurnOnLayerNr.value == self.layerCount.layerIndex: self.fanEnabled = True self.distanceFeedRate.addLinesSetAbsoluteDistanceMode( self.coolStartLines) layerTime = self.getLayerTime() remainingOrbitTime = max( self.repository.minimumLayerTime.value - layerTime, 0.0) self.addCoolTemperature(remainingOrbitTime) if self.fanEnabled: self.addFanSpeed(remainingOrbitTime) if self.repository.orbit.value: self.addOrbitsIfNecessary(remainingOrbitTime) else: self.setMultiplier(remainingOrbitTime) if self.oldFlowRate != None: self.addFlowRate(self.multiplier * self.oldFlowRate) z = float(splitLine[1]) self.boundaryLayer = euclidean.LoopLayer(z) self.highestZ = max(z, self.highestZ) self.distanceFeedRate.addLinesSetAbsoluteDistanceMode( self.coolEndLines) return elif firstWord == '(</layer>)': self.isBridgeLayer = False self.multiplier = 1.0 if self.coolTemperature != None: self.addTemperature(self.oldTemperature) self.coolTemperature = None if self.oldFlowRate != None: self.addFlowRate(self.oldFlowRate) elif firstWord == '(<nestedRing>)': self.boundaryLoop = [] self.boundaryLayer.loops.append(self.boundaryLoop) self.distanceFeedRate.addLine(line)
def addToBoundary(self, splitLine): "Add to the boundary if it is not complete." if self.boundingLoop == None: location = gcodec.getLocationFromSplitLine(None, splitLine) self.boundary.append(location.dropAxis()) self.z = location.z