1 from __future__ import absolute_import
9 from util import util3d
12 def __init__(self, newType, pathType, startPoint):
14 self.pathType = pathType
15 self.list = [startPoint]
21 self.extrusionAmount = 0
22 self.totalMoveTimeMinute = 0
23 self.progressCallback = None
25 def load(self, filename):
26 fileSize = os.stat(filename).st_size
28 gcodeFile = open(filename, 'r')
29 pos = util3d.Vector3()
30 posOffset = util3d.Vector3()
34 totalMoveTimeMinute = 0.0
41 currentPath = gcodePath('move', pathType, pos.copy())
42 currentPath.list[0].e = totalExtrusion
43 currentLayer.append(currentPath)
44 for line in gcodeFile:
45 if filePos != gcodeFile.tell():
46 filePos = gcodeFile.tell()
47 if self.progressCallback != None:
48 self.progressCallback(float(filePos) / float(fileSize))
50 #Parse Cura_SF comments
51 if line.startswith(';TYPE:'):
52 pathType = line[6:].strip()
53 if pathType != "CUSTOM":
57 #Slic3r GCode comment parser
58 comment = line[line.find(';')+1:].strip()
61 elif comment == 'perimeter':
62 pathType = 'WALL-INNER'
63 elif comment == 'skirt':
65 if pathType != "CUSTOM":
67 line = line[0:line.find(';')]
69 G = self.getCodeInt(line, 'G')
71 if G == 0 or G == 1: #Move
72 x = self.getCodeFloat(line, 'X')
73 y = self.getCodeFloat(line, 'Y')
74 z = self.getCodeFloat(line, 'Z')
75 e = self.getCodeFloat(line, 'E')
76 f = self.getCodeFloat(line, 'F')
93 #Check if we have a new layer.
94 if oldPos.z != pos.z and startCodeDone:
95 self.layerList.append(currentLayer)
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, currentPath.list[-1])
121 currentLayer.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.layerList.append(currentLayer)
188 self.extrusionAmount = maxExtrusion
189 self.totalMoveTimeMinute = totalMoveTimeMinute
190 print "Extruded a total of: %d mm of filament" % (self.extrusionAmount)
191 print "Estimated print duration: %.2f minutes" % (self.totalMoveTimeMinute)
193 def getCodeInt(self, line, code):
194 if code not in self.regMatch:
195 self.regMatch[code] = re.compile(code + '([^\s]+)')
196 m = self.regMatch[code].search(line)
200 return int(m.group(1))
204 def getCodeFloat(self, line, code):
205 if code not in self.regMatch:
206 self.regMatch[code] = re.compile(code + '([^\s]+)')
207 m = self.regMatch[code].search(line)
211 return float(m.group(1))
215 if __name__ == '__main__':
216 for filename in sys.argv[1:]:
217 gcode().load(filename)