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 setLayerPixelTable(self): "Parse a gcode line and add it to the clip skein." boundaryLoop = None extruderActive = False maskPixelTable = {} self.boundaryLoops = [] self.maskPixelTableTable = {} self.layerPixelTable = {} oldLocation = 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( oldLocation, splitLine) if extruderActive and oldLocation != None: self.addSegmentToPixelTables(location, maskPixelTable, oldLocation) oldLocation = location elif firstWord == 'M101': extruderActive = True elif firstWord == 'M103': extruderActive = False maskPixelTable = {} elif firstWord == '(</boundaryPerimeter>)': boundaryLoop = None elif firstWord == '(<boundaryPoint>': if boundaryLoop == None: boundaryLoop = [] self.boundaryLoops.append(boundaryLoop) location = gcodec.getLocationFromSplitLine(None, splitLine) boundaryLoop.append(location.dropAxis(2)) elif firstWord == '(</layer>)': return
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 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 setLayerPixelTable( self ): "Parse a gcode line and add it to the clip skein." boundaryLoop = None extruderActive = False maskPixelTable = {} self.boundaryLoops = [] self.maskPixelTableTable = {} self.layerPixelTable = {} oldLocation = 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( oldLocation, splitLine ) if extruderActive and oldLocation != None: self.addSegmentToPixelTables( location, maskPixelTable, oldLocation ) oldLocation = location elif firstWord == 'M101': extruderActive = True elif firstWord == 'M103': extruderActive = False maskPixelTable = {} elif firstWord == '(</boundaryPerimeter>)': boundaryLoop = None elif firstWord == '(<boundaryPoint>': if boundaryLoop == None: boundaryLoop = [] self.boundaryLoops.append( boundaryLoop ) location = gcodec.getLocationFromSplitLine( None, splitLine ) boundaryLoop.append( location.dropAxis( 2 ) ) elif firstWord == '(</layer>)': return
def parseSurroundingLoop( self, line ): "Parse a surrounding loop." splitLine = gcodec.getSplitLineBeforeBracketSemicolon( line ) if len( splitLine ) < 1: return firstWord = splitLine[ 0 ] if firstWord == 'G1': self.linearMove( splitLine ) if firstWord == 'M101': self.extruderActive = True elif firstWord == 'M103': self.extruderActive = False elif firstWord == '(<boundaryPoint>': location = gcodec.getLocationFromSplitLine( None, splitLine ) if self.boundary == None: self.boundary = [] self.boundary.append( location.dropAxis( 2 ) ) elif firstWord == '(<layer>': self.layerZ = float( splitLine[ 1 ] ) self.threadLayer = None elif firstWord == '(<boundaryPerimeter>)': self.addThreadLayerIfNone() elif firstWord == '(</boundaryPerimeter>)': if self.boundary != None: self.threadLayer.points.append( getPolygonCenter( self.boundary ) ) self.boundary = None
def linearMove( self, splitLine ): "Add a linear move to the loop." self.addThreadLayerIfNone() location = gcodec.getLocationFromSplitLine( self.oldLocation, splitLine ) if self.extruderActive: self.boundary = None self.oldLocation = location
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 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 getDimensionedLinearMovement( self, line, splitLine ): "Get an dimensioned linear movement." distance = 0.0 if self.distanceFeedRate.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 getTransferClosestSurroundingLoopLines(self, oldOrderedLocation, remainingSurroundingLoops): "Get and transfer the closest remaining surrounding loop." if len(remainingSurroundingLoops) > 0: oldOrderedLocation.z = remainingSurroundingLoops[0].z closestDistance = 999999999999999999.0 closestSurroundingLoop = None for remainingSurroundingLoop in remainingSurroundingLoops: distance = euclidean.getNearestDistanceIndex( oldOrderedLocation.dropAxis(2), remainingSurroundingLoop.boundary).distance if distance < closestDistance: closestDistance = distance closestSurroundingLoop = remainingSurroundingLoop remainingSurroundingLoops.remove(closestSurroundingLoop) hasTravelledHighRoad = False for line in closestSurroundingLoop.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 closestSurroundingLoop
def getDimensionedArcMovement(self, line, splitLine): "Get an 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 parseSurroundingLoop(self, line): "Parse a surrounding loop." splitLine = gcodec.getSplitLineBeforeBracketSemicolon(line) if len(splitLine) < 1: return firstWord = splitLine[0] if firstWord == 'G1': self.linearMove(splitLine) if firstWord == 'M101': self.extruderActive = True elif firstWord == 'M103': self.extruderActive = False elif firstWord == '(<boundaryPoint>': location = gcodec.getLocationFromSplitLine(None, splitLine) if self.boundary == None: self.boundary = [] self.boundary.append(location.dropAxis(2)) elif firstWord == '(<layer>': self.layerZ = float(splitLine[1]) self.threadLayer = None elif firstWord == '(<boundaryPerimeter>)': self.addThreadLayerIfNone() elif firstWord == '(</boundaryPerimeter>)': if self.boundary != None: self.threadLayer.points.append(getPolygonCenter(self.boundary)) self.boundary = None
def linearMove(self, splitLine): "Add a linear move to the loop." self.addThreadLayerIfNone() location = gcodec.getLocationFromSplitLine(self.oldLocation, splitLine) if self.extruderActive: self.boundary = None self.oldLocation = location
def getSplodgeLineGivenDistance( self, feedRateMinute, line, liftOverExtraThickness, location, startupDistance ): "Add the splodge line." locationComplex = location.dropAxis( 2 ) 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( 2 ) 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 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( 2 ), location.dropAxis( 2 ), self.aroundPixelTable, None, self.aroundWidth ) self.oldLocation = location elif firstWord == 'M101': self.isExtruderActive = True elif firstWord == 'M103': self.isExtruderActive = False elif firstWord == '(<layer>': self.aroundPixelTable = {} self.average.reset() elif firstWord == '(</layer>)': if len( self.boundaryLayers ) > self.layerIndex: self.addMillThreads() self.layerIndex += 1 self.distanceFeedRate.addLine( 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(2) 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 getTransferClosestSurroundingLoopLines( self, oldOrderedLocation, remainingSurroundingLoops ): "Get and transfer the closest remaining surrounding loop." if len( remainingSurroundingLoops ) > 0: oldOrderedLocation.z = remainingSurroundingLoops[ 0 ].z closestDistance = 999999999999999999.0 closestSurroundingLoop = None for remainingSurroundingLoop in remainingSurroundingLoops: distance = euclidean.getNearestDistanceIndex( oldOrderedLocation.dropAxis( 2 ), remainingSurroundingLoop.boundary ).distance if distance < closestDistance: closestDistance = distance closestSurroundingLoop = remainingSurroundingLoop remainingSurroundingLoops.remove( closestSurroundingLoop ) hasTravelledHighRoad = False for line in closestSurroundingLoop.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 closestSurroundingLoop
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 getHopLine(self, line): "Get hopped gcode line." splitLine = line.split(' ') indexOfF = gcodec.indexOfStartingWithSecond("F", splitLine) if indexOfF > 0: self.feedrateString = splitLine[indexOfF] if self.extruderActive: return line location = gcodec.getLocationFromSplitLine(self.oldLocation, splitLine) highestZ = location.z if self.oldLocation != None: highestZ = max(highestZ, self.oldLocation.z) 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.getMovementLineWithHop(locationComplex, highestZ) alongRatio = min(0.41666666, self.hopDistance / distance) oneMinusAlong = 1.0 - alongRatio closeLocation = oldLocationComplex * oneMinusAlong + locationComplex * alongRatio self.addLine(self.getMovementLineWithHop(locationComplex, highestZ)) if self.isNextTravel(): return self.getMovementLineWithHop(locationComplex, highestZ) farLocation = oldLocationComplex * alongRatio + locationComplex * oneMinusAlong self.addLine(self.getMovementLineWithHop(farLocation, highestZ)) return line if self.isNextTravel(): return self.getMovementLineWithHop(locationComplex, highestZ) 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.repository.firstPerimeterFeedrateOverFeedrate.value, splitG1Line) introX = abs( self.repository.absMaxXIntro.value ) introY = abs( self.repository.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 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(2), location.dropAxis(2), self.aroundPixelTable, None, self.aroundWidth) self.oldLocation = location elif firstWord == 'M101': self.isExtruderActive = True elif firstWord == 'M103': self.isExtruderActive = False elif firstWord == '(<layer>': self.aroundPixelTable = {} self.average.reset() elif firstWord == '(</layer>)': if len(self.boundaryLayers) > self.layerIndex: self.addMillThreads() self.layerIndex += 1 self.distanceFeedRate.addLine(line)
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 getRelativeStretch(self, location, lineIndexRange): "Get relative stretch for a location minus a point." locationComplex = location.dropAxis(2) lastLocationComplex = locationComplex oldTotalLength = 0.0 pointComplex = locationComplex totalLength = 0.0 while 1: try: line = lineIndexRange.getNext() except StopIteration: locationMinusPoint = locationComplex - pointComplex locationMinusPointLength = abs(locationMinusPoint) if locationMinusPointLength > 0.0: return locationMinusPoint / locationMinusPointLength return complex() splitLine = line.split() 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 getDimensionedLinearMovement( self, line, splitLine ): "Get an dimensioned linear movement." distance = 0.0 if self.distanceFeedRate.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." 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(2)) elif firstWord == '(<layer>': boundaryLayer = euclidean.LoopLayer(float(splitLine[1])) self.boundaryLayers.append(boundaryLayer) elif firstWord == '(</extrusion>)': 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, lineIndex): "Parse a gcode line and add it to the inset skein." line = self.lines[lineIndex].lstrip() splitLine = line.split() if len(splitLine) < 1: return firstWord = splitLine[0] if firstWord == '(<boundaryPoint>': location = gcodec.getLocationFromSplitLine(None, splitLine) self.boundary.append(location.dropAxis(2)) elif (firstWord == '(<bridgeDirection>' or firstWord == '<!--bridgeDirection-->'): secondWordWithoutBrackets = splitLine[1].replace('(', '').replace( ')', '') self.rotatedBoundaryLayer.rotation = complex( secondWordWithoutBrackets) elif firstWord == '(<layer>': self.addRotatedLoopLayer(float(splitLine[1])) elif firstWord == '<path': self.addPathData(line) elif firstWord == '(<surroundingLoop>)': self.boundary = [] self.rotatedBoundaryLayer.loops.append(self.boundary) elif firstWord == '<text': self.addTextData(line)
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 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(2)) elif (firstWord == '(<bridgeRotation>' or firstWord == '<!--bridgeRotation-->'): secondWordWithoutBrackets = splitLine[1].replace('(', '').replace( ')', '') self.rotatedBoundaryLayer.rotation = complex( secondWordWithoutBrackets) elif firstWord == '(</extrusion>)': self.distanceFeedRate.addLine(line) if self.repository.turnExtruderHeaterOffAtShutDown.value: self.distanceFeedRate.addLine( 'M104 S0') # Turn extruder heater off. return elif firstWord == '(<layer>': self.rotatedBoundaryLayer = euclidean.RotatedLoopLayer( float(splitLine[1])) self.distanceFeedRate.addLine(line) elif firstWord == '(</layer>)': self.addInset(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 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 linearCorner( self, splitLine ): "Update the bounding corners." location = gcodec.getLocationFromSplitLine( self.oldLocation, splitLine ) if self.extruderActive or self.goAroundExtruderOffTravel: self.cornerHigh = euclidean.getPointMaximum( self.cornerHigh, location ) self.cornerLow = euclidean.getPointMinimum( self.cornerLow, location ) self.oldLocation = location
def getHopLine( self, line ): "Get hopped gcode line." splitLine = line.split( ' ' ) indexOfF = gcodec.indexOfStartingWithSecond( "F", splitLine ) if indexOfF > 0: self.feedrateString = splitLine[ indexOfF ] if self.extruderActive: return line location = gcodec.getLocationFromSplitLine( self.oldLocation, splitLine ) highestZ = location.z if self.oldLocation != None: highestZ = max( highestZ, self.oldLocation.z ) 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.getMovementLineWithHop( locationComplex, highestZ ) alongRatio = min( 0.41666666, self.hopDistance / distance ) oneMinusAlong = 1.0 - alongRatio closeLocation = oldLocationComplex * oneMinusAlong + locationComplex * alongRatio self.addLine( self.getMovementLineWithHop( locationComplex, highestZ ) ) if self.isNextTravel(): return self.getMovementLineWithHop( locationComplex, highestZ ) farLocation = oldLocationComplex * alongRatio + locationComplex * oneMinusAlong self.addLine( self.getMovementLineWithHop( farLocation, highestZ ) ) return line if self.isNextTravel(): return self.getMovementLineWithHop( locationComplex, highestZ ) return 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 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( 2 ) ) elif firstWord == '(<layer>': boundaryLayer = euclidean.LoopLayer( float( splitLine[ 1 ] ) ) self.boundaryLayers.append( boundaryLayer ) elif firstWord == '(</extrusion>)': 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 linearMove( self, line, splitLine ): "Get statistics for a linear move." if self.skeinPane == None: return location = gcodec.getLocationFromSplitLine( self.oldLocation, splitLine ) self.addToPath( line, location ) self.oldLocation = location
def getLocationSetFeedRateToSplitLine(self, splitLine): location = gcodec.getLocationFromSplitLine(self.oldLocation, splitLine) indexOfF = gcodec.indexOfStartingWithSecond("F", splitLine) if indexOfF > 0: self.feedRateMinute = gcodec.getDoubleAfterFirstLetter( splitLine[indexOfF]) return location
def linearMove( self, splitLine ): "Get statistics for a linear move." location = gcodec.getLocationFromSplitLine( self.oldLocation, splitLine ) self.cornerMaximum = euclidean.getPointMaximum( self.cornerMaximum, location ) self.cornerMinimum = euclidean.getPointMinimum( self.cornerMinimum, location ) self.thread.append( location.dropAxis( 2 ) ) self.oldLocation = location
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( 2 ) ) elif ( firstWord == '(<bridgeRotation>' or firstWord == '<!--bridgeRotation-->' ): secondWordWithoutBrackets = splitLine[ 1 ].replace( '(', '' ).replace( ')', '' ) self.rotatedBoundaryLayer.rotation = complex( secondWordWithoutBrackets ) elif firstWord == '(</extrusion>)': self.distanceFeedRate.addLine( line ) if self.repository.turnExtruderHeaterOffAtShutDown.value: self.distanceFeedRate.addLine( 'M104 S0' ) # Turn extruder heater off. return elif firstWord == '(<layer>': self.rotatedBoundaryLayer = euclidean.RotatedLoopLayer( float( splitLine[ 1 ] ) ) self.distanceFeedRate.addLine( line ) elif firstWord == '(</layer>)': self.addInset( 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 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 '' feedRateMinute = self.distanceFeedRate.getZLimitedFeedRate( deltaZ, distance, self.feedRateMinute ) indexOfF = gcodec.indexOfStartingWithSecond( "F", splitLine ) if indexOfF > 0 and feedRateMinute != self.feedRateMinute: feedRateStringOriginal = splitLine[ indexOfF ] feedRateStringReplacement = 'F' + self.distanceFeedRate.getRounded( feedRateMinute ) return line.replace( feedRateStringOriginal, feedRateStringReplacement ) return 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 linearCorner( self, splitLine ): "Update the bounding corners." location = gcodec.getLocationFromSplitLine( self.oldLocation, splitLine ) if self.extruderActive: self.cornerHigh = euclidean.getPointMaximum( self.cornerHigh, location ) self.cornerLow = euclidean.getPointMinimum( self.cornerLow, location ) self.oldLocation = location
def getUnpausedLine(self, splitLine): "Bevel a linear move." location = gcodec.getLocationFromSplitLine(self.oldLocation, splitLine) unpausedFeedrateMinute = self.getUnpausedFeedrateMinute( location, splitLine) self.oldLocation = location return self.getLinearMoveWithFeedrate(unpausedFeedrateMinute, location)
def parseCorner(self, line): "Parse a gcode line and use the location to update the bounding corners." splitLine = line.split() firstWord = gcodec.getFirstWord(splitLine) if firstWord == "(<boundaryPoint>": locationComplex = gcodec.getLocationFromSplitLine(None, splitLine).dropAxis(2) self.cornerMaximum = euclidean.getMaximum(self.cornerMaximum, locationComplex) self.cornerMinimum = euclidean.getMinimum(self.cornerMinimum, locationComplex)
def linearMove( self, splitLine ): "Add a linear move to the loop." location = gcodec.getLocationFromSplitLine( self.oldLocation, splitLine ) self.feedrateMinute = gcodec.getFeedrateMinute( self.feedrateMinute, splitLine ) self.feedrateTable[ location ] = self.feedrateMinute if self.extruderActive: self.addToExtrusion( location ) self.oldLocation = location
def getFeededLine( self, splitLine ): "Get gcode line with feed rate." location = gcodec.getLocationFromSplitLine( self.oldLocation, splitLine ) self.oldLocation = location feedRateMinute = 60.0 * self.feedRatePerSecond if not self.isExtruderActive: feedRateMinute = self.travelFeedRatePerMinute return self.distanceFeedRate.getLinearGcodeMovementWithFeedRate( feedRateMinute, location.dropAxis( 2 ), location.z )
def linearMove( self, splitLine ): "Add a linear move to the loop." location = gcodec.getLocationFromSplitLine( self.oldLocation, splitLine ) self.feedRateMinute = gcodec.getFeedRateMinute( self.feedRateMinute, splitLine ) self.feedRateTable[ location ] = self.feedRateMinute if self.extruderActive: self.addToExtrusion( location ) self.oldLocation = location
def getUnpausedLinearMovement(self, line, splitLine): "Get an unpaused linear movement." location = gcodec.getLocationFromSplitLine(self.oldLocation, splitLine) unpausedFeedRateMinute = self.getUnpausedFeedRateMinute( location, splitLine) self.oldLocation = location return self.distanceFeedRate.getLineWithFeedRate( unpausedFeedRateMinute, line, splitLine)
def setHelicalMoveEndpoint( self, splitLine ): "Get the endpoint of a helical move." if self.oldLocation == None: print( "A helical move is relative and therefore must not be the first move of a gcode file." ) return location = gcodec.getLocationFromSplitLine( self.oldLocation, splitLine ) location += self.oldLocation self.oldLocation = location
def addIfTravel( self, splitLine ): "Add travel move around loops if the extruder is off." location = gcodec.getLocationFromSplitLine( self.oldLocation, splitLine ) if not self.extruderActive and self.oldLocation != None: if len( self.getBoundaries() ) > 0: highestZ = max( location.z, self.oldLocation.z ) self.addGcodePathZ( self.travelFeedRatePerMinute, self.getPathsBetween( self.oldLocation.dropAxis( 2 ), location.dropAxis( 2 ) ), highestZ ) self.oldLocation = location
def getFeededLine(self, splitLine): "Get gcode line with feed rate." location = gcodec.getLocationFromSplitLine(self.oldLocation, splitLine) self.oldLocation = location feedRateMinute = 60.0 * self.feedRatePerSecond if not self.isExtruderActive: feedRateMinute = self.travelFeedRatePerMinute return self.distanceFeedRate.getLinearGcodeMovementWithFeedRate( feedRateMinute, location.dropAxis(2), location.z)
def linearMove( self, splitLine ): "Add line to time spent on layer." self.feedrateMinute = gcodec.getFeedrateMinute( self.feedrateMinute, splitLine ) location = gcodec.getLocationFromSplitLine( self.oldLocation, splitLine ) if self.oldLocation != None: feedrateSecond = self.feedrateMinute / 60.0 self.layerTime += location.distance( self.oldLocation ) / feedrateSecond self.highestZ = max( location.z, self.highestZ ) self.oldLocation = location
def linearMove( self, splitLine ): "Add line to time spent on layer." self.feedRateMinute = gcodec.getFeedRateMinute( self.feedRateMinute, splitLine ) location = gcodec.getLocationFromSplitLine( self.oldLocation, splitLine ) if self.oldLocation != None: feedRateSecond = self.feedRateMinute / 60.0 self.layerTime += location.distance( self.oldLocation ) / feedRateSecond self.highestZ = max( location.z, self.highestZ ) self.oldLocation = location
def getNextLocation( self ): "Get the next linear move. Return none is none is found." for afterIndex in xrange( self.lineIndex + 1, len( self.lines ) ): line = self.lines[ afterIndex ] splitLine = line.split( ' ' ) if gcodec.getFirstWord( splitLine ) == 'G1': nextLocation = gcodec.getLocationFromSplitLine( self.oldLocation, splitLine ) return nextLocation return None
def repeatLines( self ): "Repeat the lines at decreasing altitude." for layerDelta in self.layerDeltas[ 1 : ]: for movementLine in self.movementLines: splitLine = movementLine.split() location = gcodec.getLocationFromSplitLine( self.oldLocation, splitLine ) z = location.z + layerDelta self.distanceFeedRate.addLine( self.distanceFeedRate.getLineWithZ( movementLine, splitLine, z ) ) self.movementLines = []
def repeatLines( self ): "Repeat the lines at decreasing altitude." for layerDelta in self.layerDeltas[ 1 : ]: for movementLine in self.movementLines: splitLine = movementLine.split() location = gcodec.getLocationFromSplitLine( self.oldLocation, splitLine ) z = location.z + layerDelta self.distanceFeedRate.addLine( self.distanceFeedRate.getLineWithZ( movementLine, splitLine, z ) ) self.movementLines = []
def getNextLocation( self ): "Get the next linear move. Return none is none is found." for afterIndex in xrange( self.lineIndex + 1, len( self.lines ) ): line = self.lines[ afterIndex ] splitLine = gcodec.getSplitLineBeforeBracketSemicolon( line ) if gcodec.getFirstWord( splitLine ) == 'G1': nextLocation = gcodec.getLocationFromSplitLine( self.oldLocation, splitLine ) return nextLocation 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