chiark / gitweb /
Merge branch 'SteamEngine' of github.com:daid/Cura into SteamEngine
[cura.git] / Cura / slice / __main__.py
1 from __future__ import absolute_import
2
3 from optparse import OptionParser
4 import sys
5 import re
6 import os
7 import urllib
8 import urllib2
9 import platform
10 import hashlib
11
12 if not hasattr(sys, 'frozen'):
13         cura_sf_path = os.path.normpath(os.path.join(os.path.dirname(os.path.abspath(__file__)), "./cura_sf/"))
14         if cura_sf_path not in sys.path:
15                 sys.path.append(cura_sf_path)
16
17 from Cura.util import profile
18 from Cura.util import version
19 from Cura.slice.cura_sf.skeinforge_application.skeinforge_plugins.craft_plugins import export
20
21 def fixUTF8(input):
22         if input.startswith('#UTF8#'):
23                 return input[6:].decode('utf-8')
24         return input
25
26 def main():
27         parser = OptionParser(usage="usage: %prog [options] <X,Y> <filename>[, <X,Y> <filename>][, ...]")
28         parser.add_option("-p", "--profile", action="store", type="string", dest="profile",
29                                           help="Encoded profile to use for the print")
30         parser.add_option("-o", "--output", action="store", type="string", dest="output",
31                                           help="Output filename")
32         (options, args) = parser.parse_args()
33         if options.output is None:
34                 print 'Missing output filename'
35                 sys.exit(1)
36         if options.profile is not None:
37                 profile.loadGlobalProfileFromString(options.profile)
38         options.output = fixUTF8(options.output)
39
40         clearZ = 0
41         resultFile = open(options.output, "w")
42         for idx in xrange(0, len(args), 2):
43                 position = map(float, args[idx].split(','))
44                 if len(position) < 9 + 2:
45                         position = position[0:2]
46                         position += [1,0,0]
47                         position += [0,1,0]
48                         position += [0,0,1]
49                 filenames = fixUTF8(args[idx + 1]).split('|')
50
51                 profile.setTempOverride('object_center_x', position[0])
52                 profile.setTempOverride('object_center_y', position[1])
53                 if idx == 0:
54                         resultFile.write(';TYPE:CUSTOM\n')
55                         resultFile.write(profile.getAlterationFileContents('start.gcode', len(filenames)).replace('?filename?', ' '.join(filenames).encode('ascii', 'replace')))
56                 else:
57                         resultFile.write(';TYPE:CUSTOM\n')
58                         n = output[-1].rfind('Z')+1
59                         zString = output[-1][n:n+20]
60                         zString = zString[0:zString.find(' ')]
61                         clearZ = max(clearZ, float(zString) + 10)
62                         profile.setTempOverride('clear_z', clearZ)
63                         print position
64                         print profile.getAlterationFileContents('nextobject.gcode')
65                         resultFile.write(profile.getAlterationFileContents('nextobject.gcode').replace('?filename?', ' '.join(filenames).encode('ascii', 'replace')))
66
67                 output = []
68                 for filename in filenames:
69                         extruderNr = filenames.index(filename)
70                         profile.resetTempOverride()
71                         if extruderNr > 0:
72                                 profile.setTempOverride('object_center_x', position[0] - profile.getPreferenceFloat('extruder_offset_x%d' % (extruderNr)))
73                                 profile.setTempOverride('object_center_y', position[1] - profile.getPreferenceFloat('extruder_offset_y%d' % (extruderNr)))
74                                 profile.setTempOverride('fan_enabled', 'False')
75                                 profile.setTempOverride('skirt_line_count', '0')
76                                 profile.setTempOverride('alternative_center', filenames[0])
77                         else:
78                                 profile.setTempOverride('object_center_x', position[0])
79                                 profile.setTempOverride('object_center_y', position[1])
80                         profile.setTempOverride('object_matrix', ','.join(map(str, position[2:11])))
81                         if extruderNr > 0:
82                                 if profile.getProfileSettingFloat('filament_diameter%d' % (extruderNr + 1)) > 0:
83                                         profile.setTempOverride('filament_diameter', profile.getProfileSetting('filament_diameter%d' % (extruderNr + 1)))
84                         print extruderNr, profile.getPreferenceFloat('extruder_offset_x%d' % (extruderNr)), profile.getPreferenceFloat('extruder_offset_y%d' % (extruderNr))
85                         output.append(export.getOutput(filename))
86                         profile.resetTempOverride()
87                 if len(output) == 1:
88                         resultFile.write(output[0])
89                 else:
90                         stitchMultiExtruder(output, resultFile)
91         resultFile.write(';TYPE:CUSTOM\n')
92         resultFile.write(profile.getAlterationFileContents('end.gcode'))
93         resultFile.close()
94
95         print "Running plugins"
96         ret = profile.runPostProcessingPlugins(options.output)
97         if ret is not None:
98                 print ret
99         print "Finalizing %s" % (os.path.basename(options.output))
100         if profile.getPreference('submit_slice_information') == 'True':
101                 filenames = fixUTF8(args[idx + 1]).split('|')
102                 for filename in filenames:
103                         m = hashlib.sha512()
104                         f = open(filename, "rb")
105                         while True:
106                                 chunk = f.read(1024)
107                                 if not chunk:
108                                         break
109                                 m.update(chunk)
110                         f.close()
111                         data = {
112                                 'processor': platform.processor(),
113                                 'machine': platform.machine(),
114                                 'platform': platform.platform(),
115                                 'profile': profile.getGlobalProfileString(),
116                                 'preferences': profile.getGlobalPreferencesString(),
117                                 'modelhash': m.hexdigest(),
118                                 'version': version.getVersion(),
119                         }
120                         try:
121                                 f = urllib2.urlopen("http://platform.ultimaker.com/curastats/", data = urllib.urlencode(data), timeout = 5);
122                                 f.read()
123                                 f.close()
124                         except:
125                                 pass
126
127
128 def isPrintingLine(line):
129         if line.startswith("G1") and ('X' in line or 'Y' in line) and 'E' in line:
130                 return True
131         return False
132
133 def getCodeFloat(line, code, default):
134         n = line.find(code) + 1
135         if n < 1:
136                 return default
137         m = line.find(' ', n)
138         try:
139                 if m < 0:
140                         return float(line[n:])
141                 return float(line[n:m])
142         except:
143                 return default
144
145 def stitchMultiExtruder(outputList, resultFile):
146         print "Stitching %i files for multi-extrusion" % (len(outputList))
147         currentExtruder = 0
148         resultFile.write('T%d\n' % (currentExtruder))
149         layerNr = 0
150         hasLine = True
151         outputList = map(lambda o: o.split('\n'), outputList)
152         outputOrder = range(0, len(outputList))
153         outputSlice = []
154         for n in xrange(0, len(outputList)):
155                 outputSlice.append([0, 0])
156         currentX = 0
157         currentY = 0
158         currentZ = 0
159         currentF = 60
160         while hasLine:
161                 hasLine = layerNr < 1000
162                 for n in xrange(0, len(outputList)):
163                         outputSlice[n][0] = outputSlice[n][1] + 1
164                         outputSlice[n][1] = outputSlice[n][0]
165                         while outputSlice[n][1] < len(outputList[n]) and not outputList[n][outputSlice[n][1]].startswith(';LAYER:'):
166                                 outputSlice[n][1] += 1
167                 outputOrder = range(currentExtruder, len(outputList)) + range(0, currentExtruder)
168                 for n in outputOrder:
169                         if outputSlice[n][1] > outputSlice[n][0] + 1:
170                                 nextExtruder = n
171                                 resultFile.write(';LAYER:%d\n' % (layerNr))
172                                 resultFile.write(';EXTRUDER:%d\n' % (nextExtruder))
173
174                                 startSlice = outputSlice[n][0]
175                                 endSlice = outputSlice[n][1]
176                                 currentE = 0
177                                 while not isPrintingLine(outputList[n][startSlice]):
178                                         currentE = getCodeFloat(outputList[n][startSlice], 'E', currentE)
179                                         currentX = getCodeFloat(outputList[n][startSlice], 'X', currentX)
180                                         currentY = getCodeFloat(outputList[n][startSlice], 'Y', currentY)
181                                         currentZ = getCodeFloat(outputList[n][startSlice], 'Z', currentZ)
182                                         currentF = getCodeFloat(outputList[n][startSlice], 'F', currentF)
183                                         startSlice += 1
184                                 while not isPrintingLine(outputList[n][endSlice-1]):
185                                         endSlice -= 1
186
187                                 if nextExtruder != currentExtruder:
188                                         profile.setTempOverride('extruder', nextExtruder)
189                                         profile.setTempOverride('new_x', currentX)
190                                         profile.setTempOverride('new_y', currentY)
191                                         profile.setTempOverride('new_z', currentZ)
192                                         resultFile.write(profile.getAlterationFileContents('switchExtruder.gcode') + '\n')
193                                         profile.resetTempOverride()
194                                         currentExtruder = nextExtruder
195
196                                 for idx in xrange(outputSlice[n][0], startSlice):
197                                         if not 'G1' in outputList[n][idx]:
198                                                 resultFile.write(outputList[n][idx])
199                                                 resultFile.write('\n')
200
201                                 resultFile.write('G1 X%f Y%f Z%f F%f\n' % (currentX, currentY, currentZ, profile.getProfileSettingFloat('travel_speed') * 60))
202                                 resultFile.write('G1 F%f\n' % (currentF))
203                                 resultFile.write('G92 E%f\n' % (currentE))
204                                 for idx in xrange(startSlice, endSlice):
205                                         resultFile.write(outputList[n][idx])
206                                         resultFile.write('\n')
207                                         currentX = getCodeFloat(outputList[n][idx], 'X', currentX)
208                                         currentY = getCodeFloat(outputList[n][idx], 'Y', currentY)
209                                         currentZ = getCodeFloat(outputList[n][idx], 'Z', currentZ)
210                                         hasLine = True
211                                 resultFile.write('G92 E0\n')
212                 layerNr += 1
213
214 if __name__ == '__main__':
215         main()