""" Analyze is a script to analyze and comment a gcode file. To run analyze, install python 2.x on your machine, which is avaliable from http://www.python.org/download/ Then in the folder which analyze is in, type 'python' in a shell to run the python interpreter. Finally type 'from analyze import *' to import this program. To get documentation for this program, open a shell in the fill.py directory, then type 'pydoc fill.py'. This example analyzes and comments the gcode file Hollow Square.gcode. This example is run in a terminal in the folder which contains Hollow Square.gcode and analyze.py. >>> import fillet Fillet has been imported. The gcode files in this directory that are not already beveled or filleted are the following: ['Hollow Square.gcode'] >>> fillet.arcPoint() File Hollow Square.gcode is being filleted into arc points. ( GCode generated by March 29,2007 Skeinforge ) ( Extruder Initialization ) .. many lines of gcode .. The arc point file is saved as Hollow Square_arc_point.gcode >>> fillet.arcPointFile("Hollow Square.gcode") File Hollow Square.gcode is being filleted into arc points. .. The arc point file is saved as Hollow Square_arc_point.gcode >>> fillet.arcPointFiles(["Hollow Square.gcode"]) File Hollow Square.gcode is being filleted into arc points. .. The arc point file is saved as Hollow Square_arc_point.gcode >>> fillet.arcRadius() File Hollow Square.gcode is being filleted into arc radiuses. .. The arc radius file is saved as Hollow Square_arc_radius.gcode >>> fillet.arcRadiusFile("Hollow Square.gcode") File Hollow Square.gcode is being filleted into arc radiuses. .. The arc radius file is saved as Hollow Square_arc_radius.gcode >>> fillet.arcRadiusFiles(["Hollow Square.gcode"]) File Hollow Square.gcode is being filleted into arc radiuses. .. The arc radius file is saved as Hollow Square_arc_radius.gcode >>> fillet.arcSegment() File Hollow Square.gcode is being arc segmented. .. The arc segment file is saved as Hollow Square_arc_segment.gcode >>> fillet.arcSegmentFile("Hollow Square.gcode") File Hollow Square.gcode is being arc segmented. .. The arc segment file is saved as Hollow Square_arc_segment.gcode >>> fillet.arcSegmentFiles(["Hollow Square.gcode"]) File Hollow Square.gcode is being arc segmented. .. The arc segment file is saved as Hollow Square_arc_segment.gcode """ from vec3 import Vec3 import cStringIO import euclidean import gcodec import math import preferences __author__ = "Enrique Perez (perez_enrique@yahoo.com)" __credits__ = 'Nophead ' __date__ = "$Date: 2008/21/04 $" __license__ = "GPL 3.0" #add open webbrowser first time file is created choice def getVectorGcode( gcodeText, vectorwritePreferences = None ): "Write a gcode text." if gcodeText == '': return '' if vectorwritePreferences == None: vectorwritePreferences = VectorwritePreferences() preferences.readPreferences( vectorwritePreferences ) skein = VectorwriteSkein() skein.parseGcode( gcodeText, vectorwritePreferences ) return skein.vectorWindow.getVectorFormattedText() def writeSkeinforgeVectorFile( filename ): "Write scalable vector graphics for a skeinforge gcode file, if 'Write Scalable Vector Graphics for Skeinforge Chain' is selected." vectorwritePreferences = VectorwritePreferences() preferences.readPreferences( vectorwritePreferences ) if vectorwritePreferences.writeSkeinforgeSVG.value: writeVectorFile( filename ) def writeVectorFile( filename = '' ): "Write scalable vector graphics for a gcode file. If no filename is specified, write scalable vector graphics for the first gcode file in this folder." if filename == '': unmodified = gcodec.getFilesWithFileTypeWithoutWords( 'gcode' ) if len( unmodified ) == 0: print( "There is no gcode file in this folder." ) return filename = unmodified[ 0 ] vectorwritePreferences = VectorwritePreferences() preferences.readPreferences( vectorwritePreferences ) print( 'Scalable vector graphics are being generated for the file ' + gcodec.getSummarizedFilename( filename ) ) fileText = gcodec.getFileText( filename ) suffixFilename = filename[ : filename.rfind( '.' ) ] + '.svg' suffixFilename = suffixFilename.replace( ' ', '_' ) gcodec.writeFileText( suffixFilename, getVectorGcode( fileText, vectorwritePreferences ) ) print( 'The scalable vector graphics file is saved as ' + gcodec.getSummarizedFilename( suffixFilename ) ) class VectorWindow: "A class to accumulate a scalable vector graphics text." def __init__( self ): self.height = 0 self.leftMargin = 20 self.text = cStringIO.StringIO() self.width = 0 def __repr__( self ): "Get the string representation of this VectorWindow." return str( self.height ) + ' ' + str( self.width ) def addColoredLine( self, pointFirst, pointSecond, colorName ): "Add a colored line to the text." cornerPlusHeight = self.height + self.bottomLeftCorner.imag x1String = str( int( round( pointFirst.real - self.bottomLeftCorner.real + self.leftMargin ) ) ) x2String = str( int( round( pointSecond.real - self.bottomLeftCorner.real + self.leftMargin ) ) ) y1String = str( int( round( cornerPlusHeight - pointFirst.imag ) ) ) y2String = str( int( round( cornerPlusHeight - pointSecond.imag ) ) ) self.addLine( ' ' ) def addFontHeight( self, fontSize ): "Add quadruple the font size to the height." self.height += 4 * fontSize def addLine( self, line ): "Add a line to the text and a newline." self.text.write( line + "\n" ) def addPane( self ): "Add a new window pane for drawing lines." self.height += self.topRightCorner.imag - self.bottomLeftCorner.imag def addText( self, fontSize, line ): "Add a colored line to the text." yString = str( 3 * fontSize + self.height ) self.addLine( ' ' ) self.addLine( ' ' + line ) self.addLine( ' ' ) self.addFontHeight( fontSize ) self.width = max( self.width, fontSize * len( line ) ) def getVectorFormattedText( self ): "Get the text in scalable vector graphics format." textBeginning = '\n\n' textBeginning += '\n' textBeginning += ' \n' return textBeginning + self.text.getvalue() + ' \n\n' def setPaneCorners( self, bottomLeftCorner, topRightCorner ): "Set the corners for the window pane." self.bottomLeftCorner = bottomLeftCorner self.topRightCorner = topRightCorner self.width = self.topRightCorner.real - self.bottomLeftCorner.real class VectorwriteSkein: "A class to write a get a scalable vector graphics text for a gcode skein." def __init__( self ): self.extrusionNumber = 0 self.extrusionWidth = 0.4 self.fontSize = 24 def addToPath( self, location, nextLine ): "Add a point to travel and maybe extrusion." if self.oldLocation == None: return beginningComplex = self.oldLocation.dropAxis( 2 ) endComplex = location.dropAxis( 2 ) colorName = 'gray' if self.extruderActive: colorName = self.colorNames[ self.extrusionNumber % len( self.colorNames ) ] else: splitLine = nextLine.split( ' ' ) firstWord = '' if len( splitLine ) > 0: firstWord = splitLine[ 0 ] if firstWord != 'G1': segment = endComplex - beginningComplex segmentLength = abs( segment ) if segmentLength > 0.0: truncation = 0.3 * min( segmentLength, self.extrusionWidth ) endComplex -= segment / segmentLength * truncation self.vectorWindow.addColoredLine( self.scale * beginningComplex, self.scale * endComplex, colorName ) def initializeActiveLocation( self ): "Set variables to default." self.extruderActive = False self.layerIndex = 0 self.oldLocation = None 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 linearMove( self, splitLine, nextLine ): "Get statistics for a linear move." location = gcodec.getLocationFromSplitLine( self.oldLocation, splitLine ) self.addToPath( location, nextLine ) self.oldLocation = location def parseCorner( self, line ): "Parse a gcode line and use the location to update the bounding corners." splitLine = line.split( ' ' ) if len( splitLine ) < 1: return firstWord = splitLine[ 0 ] if firstWord == 'G1': self.linearCorner( splitLine ) elif firstWord == 'M101': self.extruderActive = True elif firstWord == 'M103': self.extruderActive = False elif firstWord == '(': self.extrusionWidth = gcodec.getDoubleAfterFirstLetter( splitLine[ 1 ] ) def parseGcode( self, gcodeText, vectorwritePreferences ): "Parse gcode text and store the commented gcode." self.initializeActiveLocation() self.cornerHigh = Vec3( - 999999999.0, - 999999999.0, - 999999999.0 ) self.cornerLow = Vec3( 999999999.0, 999999999.0, 999999999.0 ) lines = gcodec.getTextLines( gcodeText ) for line in lines: self.parseCorner( line ) self.initializeActiveLocation() self.colorNames = [ 'brown', 'red', 'orange', 'yellow', 'green', 'blue', 'purple' ] self.scale = vectorwritePreferences.pixelsWidthExtrusion.value / self.extrusionWidth self.vectorWindow = VectorWindow() self.vectorWindow.setPaneCorners( self.scale * self.cornerLow.dropAxis( 2 ), self.scale * self.cornerHigh.dropAxis( 2 ) ) for lineIndex in range( len( lines ) ): line = lines[ lineIndex ] nextLine = '' nextIndex = lineIndex + 1 if nextIndex < len( lines ): nextLine = lines[ nextIndex ] self.parseLine( line, nextLine ) def parseLine( self, line, nextLine ): "Parse a gcode line and add it to the commented gcode." splitLine = line.split( ' ' ) if len( splitLine ) < 1: return firstWord = splitLine[ 0 ] if firstWord == 'G1': self.linearMove( splitLine, nextLine ) elif firstWord == 'M101': self.extruderActive = True self.extrusionNumber += 1 elif firstWord == 'M103': self.extruderActive = False elif firstWord == '(': self.extrusionNumber = 0 if self.layerIndex > 0: self.vectorWindow.addFontHeight( self.fontSize ) self.vectorWindow.addText( self.fontSize, 'Layer index ' + str( self.layerIndex ) + ', z ' + splitLine[ 1 ] ) self.layerIndex += 1 self.vectorWindow.addPane() class VectorwritePreferences: "A class to handle the vectorwrite preferences." def __init__( self ): "Set the default preferences, execute title & preferences filename." #Set the default preferences. self.pixelsWidthExtrusion = preferences.FloatPreference().getFromValue( 'Pixels for the Width of the Extrusion (ratio):', 10.0 ) self.writeSkeinforgeSVG = preferences.BooleanPreference().getFromValue( 'Write Scalable Vector Graphics for Skeinforge Chain:', True ) directoryRadio = [] self.directoryPreference = preferences.RadioLabel().getFromRadioLabel( 'Write Vector Graphics for All Unmodified Files in a Directory', 'File or Directory Choice:', directoryRadio, False ) self.filePreference = preferences.Radio().getFromRadio( 'Write Vector Graphics File', directoryRadio, True ) self.filenameInput = preferences.Filename().getFromFilename( [ ( 'Gcode text files', '*.gcode' ) ], 'Open File to Write Vector Graphics for', '' ) #Create the archive, title of the execute button, title of the dialog & preferences filename. self.archive = [ self.pixelsWidthExtrusion, self.writeSkeinforgeSVG, self.directoryPreference, self.filePreference, self.filenameInput ] self.executeTitle = 'Write Vector Graphics' self.filenamePreferences = preferences.getPreferencesFilePath( 'vectorwrite.csv' ) self.filenameHelp = 'vectorwrite.html' self.title = 'Vectorwrite Preferences' def execute( self ): "Write button has been clicked." filenames = gcodec.getGcodeDirectoryOrFile( self.directoryPreference.value, self.filenameInput.value, self.filenameInput.wasCancelled ) for filename in filenames: writeVectorFile( filename ) def main( hashtable = None ): "Display the vectorwrite dialog." preferences.displayDialog( VectorwritePreferences() ) if __name__ == "__main__": main()