1 from __future__ import absolute_import
10 from gui import util3d
13 def __init__(self, newType, pathType, layerNr, startPoint):
15 self.pathType = pathType
16 self.list = [startPoint]
17 self.layerNr = layerNr
24 self.extrusionAmount = 0
25 self.totalMoveTimeMinute = 0
26 self.progressCallback = None
28 def load(self, filename):
29 fileSize = os.stat(filename).st_size
31 gcodeFile = open(filename, 'r')
32 pos = util3d.Vector3()
33 posOffset = util3d.Vector3()
37 totalMoveTimeMinute = 0.0
43 layerNr = 0; #Note layer 0 will be the start code.
45 currentPath = gcodePath('move', pathType, layerNr, pos.copy())
46 currentPath.list[0].e = totalExtrusion
47 pathList.append(currentPath)
48 for line in gcodeFile:
49 if filePos != gcodeFile.tell():
50 filePos = gcodeFile.tell()
51 if self.progressCallback != None:
52 self.progressCallback(float(filePos) / float(fileSize))
53 if line.startswith(';TYPE:'):
54 pathType = line[6:].strip()
55 if pathType != "CUSTOM":
59 #Slic3r GCode comment parser
60 comment = line[line.find(';')+1:].strip()
63 elif comment == 'perimeter':
64 pathType = 'WALL-INNER'
65 elif comment == 'skirt':
67 if pathType != "CUSTOM":
69 line = line[0:line.find(';')]
71 G = self.getCodeInt(line, 'G')
73 if G == 0 or G == 1: #Move
74 x = self.getCodeFloat(line, 'X')
75 y = self.getCodeFloat(line, 'Y')
76 z = self.getCodeFloat(line, 'Z')
77 e = self.getCodeFloat(line, 'E')
78 f = self.getCodeFloat(line, 'F')
95 if oldPos.z != pos.z and startCodeDone:
99 if x is not None or y is not None or z is not None:
100 totalMoveTimeMinute += (oldPos - pos).vsize() / feedRate
108 totalExtrusion += e - currentE
117 if totalExtrusion > maxExtrusion:
118 maxExtrusion = totalExtrusion
119 if currentPath.type != moveType or currentPath.pathType != pathType:
120 currentPath = gcodePath(moveType, pathType, layerNr, currentPath.list[-1])
121 pathList.append(currentPath)
123 newPos.e = totalExtrusion
124 currentPath.list.append(newPos)
125 elif G == 20: #Units are inches
127 elif G == 21: #Units are mm
130 x = self.getCodeFloat(line, 'X')
131 y = self.getCodeFloat(line, 'Y')
132 z = self.getCodeFloat(line, 'Z')
133 if x is None and y is None and z is None:
134 pos = util3d.Vector3()
142 elif G == 90: #Absolute position
144 elif G == 91: #Relative position
147 x = self.getCodeFloat(line, 'X')
148 y = self.getCodeFloat(line, 'Y')
149 z = self.getCodeFloat(line, 'Z')
150 e = self.getCodeFloat(line, 'E')
154 posOffset.x = pos.x + x
156 posOffset.y = pos.y + y
158 posOffset.z = pos.z + z
160 print "Unknown G code:" + str(G)
162 M = self.getCodeInt(line, 'M')
164 if M == 1: #Message with possible wait (ignored)
166 elif M == 84: #Disable step drivers
168 elif M == 92: #Set steps per unit
170 elif M == 104: #Set temperature, no wait
172 elif M == 105: #Get temperature
174 elif M == 106: #Enable fan
176 elif M == 107: #Disable fan
178 elif M == 108: #Extruder RPM (these should not be in the final GCode, but they are)
180 elif M == 109: #Set temperature, wait
182 elif M == 113: #Extruder PWM (these should not be in the final GCode, but they are)
185 print "Unknown M code:" + str(M)
187 self.layerCount = layerNr
188 self.pathList = pathList
189 self.extrusionAmount = maxExtrusion
190 self.totalMoveTimeMinute = totalMoveTimeMinute
191 print "Extruded a total of: %d mm of filament" % (self.extrusionAmount)
192 print "Estimated print duration: %.2f minutes" % (self.totalMoveTimeMinute)
194 def getCodeInt(self, line, code):
195 if code not in self.regMatch:
196 self.regMatch[code] = re.compile(code + '([^\s]+)')
197 m = self.regMatch[code].search(line)
201 return int(m.group(1))
205 def getCodeFloat(self, line, code):
206 if code not in self.regMatch:
207 self.regMatch[code] = re.compile(code + '([^\s]+)')
208 m = self.regMatch[code].search(line)
212 return float(m.group(1))
216 if __name__ == '__main__':
217 for filename in sys.argv[1:]:
218 gcode().load(filename)