printrun-src/printrun/projectlayer.py

changeset 46
cce0af6351f0
parent 15
0bbb006204fc
equal deleted inserted replaced
45:c82943fb205f 46:cce0af6351f0
20 import time 20 import time
21 import zipfile 21 import zipfile
22 import tempfile 22 import tempfile
23 import shutil 23 import shutil
24 from cairosvg.surface import PNGSurface 24 from cairosvg.surface import PNGSurface
25 import cStringIO 25 import io
26 import imghdr 26 import imghdr
27 import copy 27 import copy
28 import re 28 import re
29 from collections import OrderedDict 29 from collections import OrderedDict
30 import itertools
31 import math 30 import math
32 31
33 class DisplayFrame(wx.Frame): 32 class DisplayFrame(wx.Frame):
34 def __init__(self, parent, title, res = (1024, 768), printer = None, scale = 1.0, offset = (0, 0)): 33 def __init__(self, parent, title, res = (1024, 768), printer = None, scale = 1.0, offset = (0, 0)):
35 wx.Frame.__init__(self, parent = parent, title = title, size = res) 34 wx.Frame.__init__(self, parent = parent, title = title, size = res)
36 self.printer = printer 35 self.printer = printer
37 self.control_frame = parent 36 self.control_frame = parent
38 self.pic = wx.StaticBitmap(self) 37 self.pic = wx.StaticBitmap(self)
39 self.bitmap = wx.EmptyBitmap(*res) 38 self.bitmap = wx.Bitmap(*res)
40 self.bbitmap = wx.EmptyBitmap(*res) 39 self.bbitmap = wx.Bitmap(*res)
41 self.slicer = 'bitmap' 40 self.slicer = 'bitmap'
42 self.dpi = 96 41 self.dpi = 96
43 dc = wx.MemoryDC() 42 dc = wx.MemoryDC()
44 dc.SelectObject(self.bbitmap) 43 dc.SelectObject(self.bbitmap)
45 dc.SetBackground(wx.Brush("black")) 44 dc.SetBackground(wx.Brush("black"))
71 except: 70 except:
72 raise 71 raise
73 pass 72 pass
74 73
75 def resize(self, res = (1024, 768)): 74 def resize(self, res = (1024, 768)):
76 self.bitmap = wx.EmptyBitmap(*res) 75 self.bitmap = wx.Bitmap(*res)
77 self.bbitmap = wx.EmptyBitmap(*res) 76 self.bbitmap = wx.Bitmap(*res)
78 dc = wx.MemoryDC() 77 dc = wx.MemoryDC()
79 dc.SelectObject(self.bbitmap) 78 dc.SelectObject(self.bbitmap)
80 dc.SetBackground(wx.Brush("black")) 79 dc.SetBackground(wx.Brush("black"))
81 dc.Clear() 80 dc.Clear()
82 dc.SelectObject(wx.NullBitmap) 81 dc.SelectObject(wx.NullBitmap)
99 layercopy.set('width', str(width * self.scale) + 'mm') 98 layercopy.set('width', str(width * self.scale) + 'mm')
100 layercopy.set('viewBox', '0 0 ' + str(width * self.scale) + ' ' + str(height * self.scale)) 99 layercopy.set('viewBox', '0 0 ' + str(width * self.scale) + ' ' + str(height * self.scale))
101 100
102 g = layercopy.find("{http://www.w3.org/2000/svg}g") 101 g = layercopy.find("{http://www.w3.org/2000/svg}g")
103 g.set('transform', 'scale(' + str(self.scale) + ')') 102 g.set('transform', 'scale(' + str(self.scale) + ')')
104 stream = cStringIO.StringIO(PNGSurface.convert(dpi = self.dpi, bytestring = xml.etree.ElementTree.tostring(layercopy))) 103 stream = io.StringIO(PNGSurface.convert(dpi = self.dpi, bytestring = xml.etree.ElementTree.tostring(layercopy)))
105 else: 104 else:
106 stream = cStringIO.StringIO(PNGSurface.convert(dpi = self.dpi, bytestring = xml.etree.ElementTree.tostring(image))) 105 stream = io.StringIO(PNGSurface.convert(dpi = self.dpi, bytestring = xml.etree.ElementTree.tostring(image)))
107 106
108 pngImage = wx.ImageFromStream(stream) 107 pngImage = wx.ImageFromStream(stream)
109 108
110 # print "w:", pngImage.Width, ", dpi:", self.dpi, ", w (mm): ",(pngImage.Width / self.dpi) * 25.4 109 # print "w:", pngImage.Width, ", dpi:", self.dpi, ", w (mm): ",(pngImage.Width / self.dpi) * 25.4
111 110
130 except: 129 except:
131 raise 130 raise
132 pass 131 pass
133 132
134 def show_img_delay(self, image): 133 def show_img_delay(self, image):
135 print "Showing", str(time.clock()) 134 print("Showing", str(time.clock()))
136 self.control_frame.set_current_layer(self.index) 135 self.control_frame.set_current_layer(self.index)
137 self.draw_layer(image) 136 self.draw_layer(image)
138 wx.FutureCall(1000 * self.interval, self.hide_pic_and_rise) 137 wx.FutureCall(1000 * self.interval, self.hide_pic_and_rise)
139 138
140 def rise(self): 139 def rise(self):
141 if (self.direction == "Top Down"): 140 if (self.direction == "Top Down"):
142 print "Lowering", str(time.clock()) 141 print("Lowering", str(time.clock()))
143 else: 142 else:
144 print "Rising", str(time.clock()) 143 print("Rising", str(time.clock()))
145 144
146 if self.printer is not None and self.printer.online: 145 if self.printer is not None and self.printer.online:
147 self.printer.send_now("G91") 146 self.printer.send_now("G91")
148 147
149 if (self.prelift_gcode): 148 if (self.prelift_gcode):
168 time.sleep(self.pause) 167 time.sleep(self.pause)
169 168
170 wx.FutureCall(1000 * self.pause, self.next_img) 169 wx.FutureCall(1000 * self.pause, self.next_img)
171 170
172 def hide_pic(self): 171 def hide_pic(self):
173 print "Hiding", str(time.clock()) 172 print("Hiding", str(time.clock()))
174 self.pic.Hide() 173 self.pic.Hide()
175 174
176 def hide_pic_and_rise(self): 175 def hide_pic_and_rise(self):
177 wx.CallAfter(self.hide_pic) 176 wx.CallAfter(self.hide_pic)
178 wx.FutureCall(500, self.rise) 177 wx.FutureCall(500, self.rise)
179 178
180 def next_img(self): 179 def next_img(self):
181 if not self.running: 180 if not self.running:
182 return 181 return
183 if self.index < len(self.layers): 182 if self.index < len(self.layers):
184 print self.index 183 print(self.index)
185 wx.CallAfter(self.show_img_delay, self.layers[self.index]) 184 wx.CallAfter(self.show_img_delay, self.layers[self.index])
186 self.index += 1 185 self.index += 1
187 else: 186 else:
188 print "end" 187 print("end")
189 wx.CallAfter(self.pic.Hide) 188 wx.CallAfter(self.pic.Hide)
190 wx.CallAfter(self.Refresh) 189 wx.CallAfter(self.Refresh)
191 190
192 def present(self, 191 def present(self,
193 layers, 192 layers,
276 fieldsizer = wx.GridBagSizer(10, 10) 275 fieldsizer = wx.GridBagSizer(10, 10)
277 276
278 # Left Column 277 # Left Column
279 278
280 fieldsizer.Add(wx.StaticText(self.panel, -1, "Layer (mm):"), pos = (0, 0), flag = wx.ALIGN_CENTER_VERTICAL) 279 fieldsizer.Add(wx.StaticText(self.panel, -1, "Layer (mm):"), pos = (0, 0), flag = wx.ALIGN_CENTER_VERTICAL)
281 self.thickness = wx.TextCtrl(self.panel, -1, str(self._get_setting("project_layer", "0.1")), size = (80, -1)) 280 self.thickness = wx.TextCtrl(self.panel, -1, str(self._get_setting("project_layer", "0.1")), size = (125, -1))
282 self.thickness.Bind(wx.EVT_TEXT, self.update_thickness) 281 self.thickness.Bind(wx.EVT_TEXT, self.update_thickness)
283 self.thickness.SetHelpText("The thickness of each slice. Should match the value used to slice the model. SVG files update this value automatically, 3dlp.zip files have to be manually entered.") 282 self.thickness.SetHelpText("The thickness of each slice. Should match the value used to slice the model. SVG files update this value automatically, 3dlp.zip files have to be manually entered.")
284 fieldsizer.Add(self.thickness, pos = (0, 1)) 283 fieldsizer.Add(self.thickness, pos = (0, 1))
285 284
286 fieldsizer.Add(wx.StaticText(self.panel, -1, "Exposure (s):"), pos = (1, 0), flag = wx.ALIGN_CENTER_VERTICAL) 285 fieldsizer.Add(wx.StaticText(self.panel, -1, "Exposure (s):"), pos = (1, 0), flag = wx.ALIGN_CENTER_VERTICAL)
287 self.interval = wx.TextCtrl(self.panel, -1, str(self._get_setting("project_interval", "0.5")), size = (80, -1)) 286 self.interval = wx.TextCtrl(self.panel, -1, str(self._get_setting("project_interval", "0.5")), size = (125, -1))
288 self.interval.Bind(wx.EVT_TEXT, self.update_interval) 287 self.interval.Bind(wx.EVT_TEXT, self.update_interval)
289 self.interval.SetHelpText("How long each slice should be displayed.") 288 self.interval.SetHelpText("How long each slice should be displayed.")
290 fieldsizer.Add(self.interval, pos = (1, 1)) 289 fieldsizer.Add(self.interval, pos = (1, 1))
291 290
292 fieldsizer.Add(wx.StaticText(self.panel, -1, "Blank (s):"), pos = (2, 0), flag = wx.ALIGN_CENTER_VERTICAL) 291 fieldsizer.Add(wx.StaticText(self.panel, -1, "Blank (s):"), pos = (2, 0), flag = wx.ALIGN_CENTER_VERTICAL)
293 self.pause = wx.TextCtrl(self.panel, -1, str(self._get_setting("project_pause", "0.5")), size = (80, -1)) 292 self.pause = wx.TextCtrl(self.panel, -1, str(self._get_setting("project_pause", "0.5")), size = (125, -1))
294 self.pause.Bind(wx.EVT_TEXT, self.update_pause) 293 self.pause.Bind(wx.EVT_TEXT, self.update_pause)
295 self.pause.SetHelpText("The pause length between slices. This should take into account any movement of the Z axis, plus time to prepare the resin surface (sliding, tilting, sweeping, etc).") 294 self.pause.SetHelpText("The pause length between slices. This should take into account any movement of the Z axis, plus time to prepare the resin surface (sliding, tilting, sweeping, etc).")
296 fieldsizer.Add(self.pause, pos = (2, 1)) 295 fieldsizer.Add(self.pause, pos = (2, 1))
297 296
298 fieldsizer.Add(wx.StaticText(self.panel, -1, "Scale:"), pos = (3, 0), flag = wx.ALIGN_CENTER_VERTICAL) 297 fieldsizer.Add(wx.StaticText(self.panel, -1, "Scale:"), pos = (3, 0), flag = wx.ALIGN_CENTER_VERTICAL)
299 self.scale = floatspin.FloatSpin(self.panel, -1, value = self._get_setting('project_scale', 1.0), increment = 0.1, digits = 3, size = (80, -1)) 298 self.scale = wx.SpinCtrlDouble(self.panel, -1, initial = self._get_setting('project_scale', 1.0), inc = 0.1, size = (125, -1))
300 self.scale.Bind(floatspin.EVT_FLOATSPIN, self.update_scale) 299 self.scale.SetDigits(3)
300 self.scale.Bind(wx.EVT_SPINCTRLDOUBLE, self.update_scale)
301 self.scale.SetHelpText("The additional scaling of each slice.") 301 self.scale.SetHelpText("The additional scaling of each slice.")
302 fieldsizer.Add(self.scale, pos = (3, 1)) 302 fieldsizer.Add(self.scale, pos = (3, 1))
303 303
304 fieldsizer.Add(wx.StaticText(self.panel, -1, "Direction:"), pos = (4, 0), flag = wx.ALIGN_CENTER_VERTICAL) 304 fieldsizer.Add(wx.StaticText(self.panel, -1, "Direction:"), pos = (4, 0), flag = wx.ALIGN_CENTER_VERTICAL)
305 self.direction = wx.ComboBox(self.panel, -1, choices = ["Top Down", "Bottom Up"], value = self._get_setting('project_direction', "Top Down"), size = (80, -1)) 305 self.direction = wx.ComboBox(self.panel, -1, choices = ["Top Down", "Bottom Up"], value = self._get_setting('project_direction', "Top Down"), size = (125, -1))
306 self.direction.Bind(wx.EVT_COMBOBOX, self.update_direction) 306 self.direction.Bind(wx.EVT_COMBOBOX, self.update_direction)
307 self.direction.SetHelpText("The direction the Z axis should move. Top Down is where the projector is above the model, Bottom up is where the projector is below the model.") 307 self.direction.SetHelpText("The direction the Z axis should move. Top Down is where the projector is above the model, Bottom up is where the projector is below the model.")
308 fieldsizer.Add(self.direction, pos = (4, 1), flag = wx.ALIGN_CENTER_VERTICAL) 308 fieldsizer.Add(self.direction, pos = (4, 1), flag = wx.ALIGN_CENTER_VERTICAL)
309 309
310 fieldsizer.Add(wx.StaticText(self.panel, -1, "Overshoot (mm):"), pos = (5, 0), flag = wx.ALIGN_CENTER_VERTICAL) 310 fieldsizer.Add(wx.StaticText(self.panel, -1, "Overshoot (mm):"), pos = (5, 0), flag = wx.ALIGN_CENTER_VERTICAL)
311 self.overshoot = floatspin.FloatSpin(self.panel, -1, value = self._get_setting('project_overshoot', 3.0), increment = 0.1, digits = 1, min_val = 0, size = (80, -1)) 311 self.overshoot = wx.SpinCtrlDouble(self.panel, -1, initial = self._get_setting('project_overshoot', 3.0), inc = 0.1, min = 0, size = (125, -1))
312 self.overshoot.Bind(floatspin.EVT_FLOATSPIN, self.update_overshoot) 312 self.overshoot.SetDigits(1)
313 self.overshoot.Bind(wx.EVT_SPINCTRLDOUBLE, self.update_overshoot)
313 self.overshoot.SetHelpText("How far the axis should move beyond the next slice position for each slice. For Top Down printers this would dunk the model under the resi and then return. For Bottom Up printers this would raise the base away from the vat and then return.") 314 self.overshoot.SetHelpText("How far the axis should move beyond the next slice position for each slice. For Top Down printers this would dunk the model under the resi and then return. For Bottom Up printers this would raise the base away from the vat and then return.")
314 fieldsizer.Add(self.overshoot, pos = (5, 1)) 315 fieldsizer.Add(self.overshoot, pos = (5, 1))
315 316
316 fieldsizer.Add(wx.StaticText(self.panel, -1, "Pre-lift Gcode:"), pos = (6, 0), flag = wx.ALIGN_CENTER_VERTICAL) 317 fieldsizer.Add(wx.StaticText(self.panel, -1, "Pre-lift Gcode:"), pos = (6, 0), flag = wx.ALIGN_CENTER_VERTICAL)
317 self.prelift_gcode = wx.TextCtrl(self.panel, -1, str(self._get_setting("project_prelift_gcode", "").replace("\\n", '\n')), size = (-1, 35), style = wx.TE_MULTILINE) 318 self.prelift_gcode = wx.TextCtrl(self.panel, -1, str(self._get_setting("project_prelift_gcode", "").replace("\\n", '\n')), size = (-1, 35), style = wx.TE_MULTILINE)
327 328
328 # Right Column 329 # Right Column
329 330
330 fieldsizer.Add(wx.StaticText(self.panel, -1, "X (px):"), pos = (0, 2), flag = wx.ALIGN_CENTER_VERTICAL) 331 fieldsizer.Add(wx.StaticText(self.panel, -1, "X (px):"), pos = (0, 2), flag = wx.ALIGN_CENTER_VERTICAL)
331 projectX = int(math.floor(float(self._get_setting("project_x", 1920)))) 332 projectX = int(math.floor(float(self._get_setting("project_x", 1920))))
332 self.X = wx.SpinCtrl(self.panel, -1, str(projectX), max = 999999, size = (80, -1)) 333 self.X = wx.SpinCtrl(self.panel, -1, str(projectX), max = 999999, size = (125, -1))
333 self.X.Bind(wx.EVT_SPINCTRL, self.update_resolution) 334 self.X.Bind(wx.EVT_SPINCTRL, self.update_resolution)
334 self.X.SetHelpText("The projector resolution in the X axis.") 335 self.X.SetHelpText("The projector resolution in the X axis.")
335 fieldsizer.Add(self.X, pos = (0, 3)) 336 fieldsizer.Add(self.X, pos = (0, 3))
336 337
337 fieldsizer.Add(wx.StaticText(self.panel, -1, "Y (px):"), pos = (1, 2), flag = wx.ALIGN_CENTER_VERTICAL) 338 fieldsizer.Add(wx.StaticText(self.panel, -1, "Y (px):"), pos = (1, 2), flag = wx.ALIGN_CENTER_VERTICAL)
338 projectY = int(math.floor(float(self._get_setting("project_y", 1200)))) 339 projectY = int(math.floor(float(self._get_setting("project_y", 1200))))
339 self.Y = wx.SpinCtrl(self.panel, -1, str(projectY), max = 999999, size = (80, -1)) 340 self.Y = wx.SpinCtrl(self.panel, -1, str(projectY), max = 999999, size = (125, -1))
340 self.Y.Bind(wx.EVT_SPINCTRL, self.update_resolution) 341 self.Y.Bind(wx.EVT_SPINCTRL, self.update_resolution)
341 self.Y.SetHelpText("The projector resolution in the Y axis.") 342 self.Y.SetHelpText("The projector resolution in the Y axis.")
342 fieldsizer.Add(self.Y, pos = (1, 3)) 343 fieldsizer.Add(self.Y, pos = (1, 3))
343 344
344 fieldsizer.Add(wx.StaticText(self.panel, -1, "OffsetX (mm):"), pos = (2, 2), flag = wx.ALIGN_CENTER_VERTICAL) 345 fieldsizer.Add(wx.StaticText(self.panel, -1, "OffsetX (mm):"), pos = (2, 2), flag = wx.ALIGN_CENTER_VERTICAL)
345 self.offset_X = floatspin.FloatSpin(self.panel, -1, value = self._get_setting("project_offset_x", 0.0), increment = 1, digits = 1, size = (80, -1)) 346 self.offset_X = wx.SpinCtrlDouble(self.panel, -1, initial = self._get_setting("project_offset_x", 0.0), inc = 1, size = (125, -1))
346 self.offset_X.Bind(floatspin.EVT_FLOATSPIN, self.update_offset) 347 self.offset_X.SetDigits(1)
348 self.offset_X.Bind(wx.EVT_SPINCTRLDOUBLE, self.update_offset)
347 self.offset_X.SetHelpText("How far the slice should be offset from the edge in the X axis.") 349 self.offset_X.SetHelpText("How far the slice should be offset from the edge in the X axis.")
348 fieldsizer.Add(self.offset_X, pos = (2, 3)) 350 fieldsizer.Add(self.offset_X, pos = (2, 3))
349 351
350 fieldsizer.Add(wx.StaticText(self.panel, -1, "OffsetY (mm):"), pos = (3, 2), flag = wx.ALIGN_CENTER_VERTICAL) 352 fieldsizer.Add(wx.StaticText(self.panel, -1, "OffsetY (mm):"), pos = (3, 2), flag = wx.ALIGN_CENTER_VERTICAL)
351 self.offset_Y = floatspin.FloatSpin(self.panel, -1, value = self._get_setting("project_offset_y", 0.0), increment = 1, digits = 1, size = (80, -1)) 353 self.offset_Y = wx.SpinCtrlDouble(self.panel, -1, initial = self._get_setting("project_offset_y", 0.0), inc = 1, size = (125, -1))
352 self.offset_Y.Bind(floatspin.EVT_FLOATSPIN, self.update_offset) 354 self.offset_Y.SetDigits(1)
355 self.offset_Y.Bind(wx.EVT_SPINCTRLDOUBLE, self.update_offset)
353 self.offset_Y.SetHelpText("How far the slice should be offset from the edge in the Y axis.") 356 self.offset_Y.SetHelpText("How far the slice should be offset from the edge in the Y axis.")
354 fieldsizer.Add(self.offset_Y, pos = (3, 3)) 357 fieldsizer.Add(self.offset_Y, pos = (3, 3))
355 358
356 fieldsizer.Add(wx.StaticText(self.panel, -1, "ProjectedX (mm):"), pos = (4, 2), flag = wx.ALIGN_CENTER_VERTICAL) 359 fieldsizer.Add(wx.StaticText(self.panel, -1, "ProjectedX (mm):"), pos = (4, 2), flag = wx.ALIGN_CENTER_VERTICAL)
357 self.projected_X_mm = floatspin.FloatSpin(self.panel, -1, value = self._get_setting("project_projected_x", 505.0), increment = 1, digits = 1, size = (80, -1)) 360 self.projected_X_mm = wx.SpinCtrlDouble(self.panel, -1, initial = self._get_setting("project_projected_x", 505.0), inc = 1, size = (125, -1))
358 self.projected_X_mm.Bind(floatspin.EVT_FLOATSPIN, self.update_projected_Xmm) 361 self.projected_X_mm.SetDigits(1)
362 self.projected_X_mm.Bind(wx.EVT_SPINCTRLDOUBLE, self.update_projected_Xmm)
359 self.projected_X_mm.SetHelpText("The actual width of the entire projected image. Use the Calibrate grid to show the full size of the projected image, and measure the width at the same level where the slice will be projected onto the resin.") 363 self.projected_X_mm.SetHelpText("The actual width of the entire projected image. Use the Calibrate grid to show the full size of the projected image, and measure the width at the same level where the slice will be projected onto the resin.")
360 fieldsizer.Add(self.projected_X_mm, pos = (4, 3)) 364 fieldsizer.Add(self.projected_X_mm, pos = (4, 3))
361 365
362 fieldsizer.Add(wx.StaticText(self.panel, -1, "Z Axis Speed (mm/min):"), pos = (5, 2), flag = wx.ALIGN_CENTER_VERTICAL) 366 fieldsizer.Add(wx.StaticText(self.panel, -1, "Z Axis Speed (mm/min):"), pos = (5, 2), flag = wx.ALIGN_CENTER_VERTICAL)
363 self.z_axis_rate = wx.SpinCtrl(self.panel, -1, str(self._get_setting("project_z_axis_rate", 200)), max = 9999, size = (80, -1)) 367 self.z_axis_rate = wx.SpinCtrl(self.panel, -1, str(self._get_setting("project_z_axis_rate", 200)), max = 9999, size = (125, -1))
364 self.z_axis_rate.Bind(wx.EVT_SPINCTRL, self.update_z_axis_rate) 368 self.z_axis_rate.Bind(wx.EVT_SPINCTRL, self.update_z_axis_rate)
365 self.z_axis_rate.SetHelpText("Speed of the Z axis in mm/minute. Take into account that slower rates may require a longer pause value.") 369 self.z_axis_rate.SetHelpText("Speed of the Z axis in mm/minute. Take into account that slower rates may require a longer pause value.")
366 fieldsizer.Add(self.z_axis_rate, pos = (5, 3)) 370 fieldsizer.Add(self.z_axis_rate, pos = (5, 3))
367 371
368 fieldboxsizer.Add(fieldsizer) 372 fieldboxsizer.Add(fieldsizer)
392 self.first_layer.SetHelpText("Displays the first layer of the model. Use this to project the first layer for longer so it holds to the base. Note: this value does not affect the first layer when the \"Present\" run is started, it should be used manually.") 396 self.first_layer.SetHelpText("Displays the first layer of the model. Use this to project the first layer for longer so it holds to the base. Note: this value does not affect the first layer when the \"Present\" run is started, it should be used manually.")
393 397
394 first_layer_boxer.Add(self.first_layer, flag = wx.ALIGN_CENTER_VERTICAL) 398 first_layer_boxer.Add(self.first_layer, flag = wx.ALIGN_CENTER_VERTICAL)
395 399
396 first_layer_boxer.Add(wx.StaticText(self.panel, -1, " (s):"), flag = wx.ALIGN_CENTER_VERTICAL) 400 first_layer_boxer.Add(wx.StaticText(self.panel, -1, " (s):"), flag = wx.ALIGN_CENTER_VERTICAL)
397 self.show_first_layer_timer = floatspin.FloatSpin(self.panel, -1, value=-1, increment = 1, digits = 1, size = (55, -1)) 401 self.show_first_layer_timer = wx.SpinCtrlDouble(self.panel, -1, initial = -1, inc = 1, size = (125, -1))
402 self.show_first_layer_timer.SetDigits(1)
398 self.show_first_layer_timer.SetHelpText("How long to display the first layer for. -1 = unlimited.") 403 self.show_first_layer_timer.SetHelpText("How long to display the first layer for. -1 = unlimited.")
399 first_layer_boxer.Add(self.show_first_layer_timer, flag = wx.ALIGN_CENTER_VERTICAL) 404 first_layer_boxer.Add(self.show_first_layer_timer, flag = wx.ALIGN_CENTER_VERTICAL)
400 displaysizer.Add(first_layer_boxer, pos = (0, 6), flag = wx.ALIGN_CENTER_VERTICAL) 405 displaysizer.Add(first_layer_boxer, pos = (0, 6), flag = wx.ALIGN_CENTER_VERTICAL)
401 406
402 displaysizer.Add(wx.StaticText(self.panel, -1, "Red:"), pos = (0, 7), flag = wx.ALIGN_CENTER_VERTICAL) 407 displaysizer.Add(wx.StaticText(self.panel, -1, "Red:"), pos = (0, 7), flag = wx.ALIGN_CENTER_VERTICAL)
555 560
556 # Note: the following funky code extracts any numbers from the filenames, matches 561 # Note: the following funky code extracts any numbers from the filenames, matches
557 # them with the original then sorts them. It allows for filenames of the 562 # them with the original then sorts them. It allows for filenames of the
558 # format: abc_1.png, which would be followed by abc_10.png alphabetically. 563 # format: abc_1.png, which would be followed by abc_10.png alphabetically.
559 os.chdir(self.image_dir) 564 os.chdir(self.image_dir)
560 vals = filter(os.path.isfile, os.listdir('.')) 565 vals = [f for f in os.listdir('.') if os.path.isfile(f)]
561 keys = map(lambda p: int(re.search('\d+', p).group()), vals) 566 keys = (int(re.search('\d+', p).group()) for p in vals)
562 imagefilesDict = dict(itertools.izip(keys, vals)) 567 imagefilesDict = dict(zip(keys, vals))
563 imagefilesOrderedDict = OrderedDict(sorted(imagefilesDict.items(), key = lambda t: t[0])) 568 imagefilesOrderedDict = OrderedDict(sorted(imagefilesDict.items(), key = lambda t: t[0]))
564 569
565 for f in imagefilesOrderedDict.values(): 570 for f in imagefilesOrderedDict.values():
566 path = os.path.join(self.image_dir, f) 571 path = os.path.join(self.image_dir, f)
567 if os.path.isfile(path) and imghdr.what(path) in accepted_image_types: 572 if os.path.isfile(path) and imghdr.what(path) in accepted_image_types:
582 layerHeight = float(self.thickness.GetValue()) 587 layerHeight = float(self.thickness.GetValue())
583 else: 588 else:
584 layers = self.parse_svg(name) 589 layers = self.parse_svg(name)
585 layerHeight = layers[1] 590 layerHeight = layers[1]
586 self.thickness.SetValue(str(layers[1])) 591 self.thickness.SetValue(str(layers[1]))
587 print "Layer thickness detected:", layerHeight, "mm" 592 print("Layer thickness detected:", layerHeight, "mm")
588 print len(layers[0]), "layers found, total height", layerHeight * len(layers[0]), "mm" 593 print(len(layers[0]), "layers found, total height", layerHeight * len(layers[0]), "mm")
589 self.layers = layers 594 self.layers = layers
590 self.set_total_layers(len(layers[0])) 595 self.set_total_layers(len(layers[0]))
591 self.set_current_layer(0) 596 self.set_current_layer(0)
592 self.current_filename = os.path.basename(name) 597 self.current_filename = os.path.basename(name)
593 self.display_filename(self.current_filename) 598 self.display_filename(self.current_filename)
622 self.display_frame.offset = (float(self.offset_X.GetValue()), -float(self.offset_Y.GetValue())) 627 self.display_frame.offset = (float(self.offset_X.GetValue()), -float(self.offset_Y.GetValue()))
623 self.display_frame.scale = 1.0 628 self.display_frame.scale = 1.0
624 resolution_x_pixels = int(self.X.GetValue()) 629 resolution_x_pixels = int(self.X.GetValue())
625 resolution_y_pixels = int(self.Y.GetValue()) 630 resolution_y_pixels = int(self.Y.GetValue())
626 631
627 gridBitmap = wx.EmptyBitmap(resolution_x_pixels, resolution_y_pixels) 632 gridBitmap = wx.Bitmap(resolution_x_pixels, resolution_y_pixels)
628 dc = wx.MemoryDC() 633 dc = wx.MemoryDC()
629 dc.SelectObject(gridBitmap) 634 dc.SelectObject(gridBitmap)
630 dc.SetBackground(wx.Brush("black")) 635 dc.SetBackground(wx.Brush("black"))
631 dc.Clear() 636 dc.Clear()
632 637
646 pixelsYPerMM = resolution_y_pixels / projectedYmm 651 pixelsYPerMM = resolution_y_pixels / projectedYmm
647 652
648 gridCountX = int(projectedXmm / 10) 653 gridCountX = int(projectedXmm / 10)
649 gridCountY = int(projectedYmm / 10) 654 gridCountY = int(projectedYmm / 10)
650 655
651 for y in xrange(0, gridCountY + 1): 656 for y in range(0, gridCountY + 1):
652 for x in xrange(0, gridCountX + 1): 657 for x in range(0, gridCountX + 1):
653 dc.DrawLine(0, y * (pixelsYPerMM * 10), resolution_x_pixels, y * (pixelsYPerMM * 10)) 658 dc.DrawLine(0, y * (pixelsYPerMM * 10), resolution_x_pixels, y * (pixelsYPerMM * 10))
654 dc.DrawLine(x * (pixelsXPerMM * 10), 0, x * (pixelsXPerMM * 10), resolution_y_pixels) 659 dc.DrawLine(x * (pixelsXPerMM * 10), 0, x * (pixelsXPerMM * 10), resolution_y_pixels)
655 660
656 self.first_layer.SetValue(False) 661 self.first_layer.SetValue(False)
657 self.display_frame.slicer = 'bitmap' 662 self.display_frame.slicer = 'bitmap'
658 self.display_frame.draw_layer(gridBitmap.ConvertToImage()) 663 self.display_frame.draw_layer(gridBitmap.ConvertToImage())
659 664
660 def present_first_layer(self, event): 665 def present_first_layer(self, event):
661 if (self.first_layer.GetValue()): 666 if (self.first_layer.GetValue()):
662 if not hasattr(self, "layers"): 667 if not hasattr(self, "layers"):
663 print "No model loaded!" 668 print("No model loaded!")
664 self.first_layer.SetValue(False) 669 self.first_layer.SetValue(False)
665 return 670 return
666 self.display_frame.offset = (float(self.offset_X.GetValue()), float(self.offset_Y.GetValue())) 671 self.display_frame.offset = (float(self.offset_X.GetValue()), float(self.offset_Y.GetValue()))
667 self.display_frame.scale = float(self.scale.GetValue()) 672 self.display_frame.scale = float(self.scale.GetValue())
668 673
766 771
767 return resolution_x_pixels / projected_x_inches 772 return resolution_x_pixels / projected_x_inches
768 773
769 def start_present(self, event): 774 def start_present(self, event):
770 if not hasattr(self, "layers"): 775 if not hasattr(self, "layers"):
771 print "No model loaded!" 776 print("No model loaded!")
772 return 777 return
773 778
774 self.pause_button.SetLabel("Pause") 779 self.pause_button.SetLabel("Pause")
775 self.set_current_layer(0) 780 self.set_current_layer(0)
776 self.display_frame.Raise() 781 self.display_frame.Raise()
791 size = (float(self.X.GetValue()), float(self.Y.GetValue())), 796 size = (float(self.X.GetValue()), float(self.Y.GetValue())),
792 offset = (float(self.offset_X.GetValue()), float(self.offset_Y.GetValue())), 797 offset = (float(self.offset_X.GetValue()), float(self.offset_Y.GetValue())),
793 layer_red = self.layer_red.IsChecked()) 798 layer_red = self.layer_red.IsChecked())
794 799
795 def stop_present(self, event): 800 def stop_present(self, event):
796 print "Stop" 801 print("Stop")
797 self.pause_button.SetLabel("Pause") 802 self.pause_button.SetLabel("Pause")
798 self.set_current_layer(0) 803 self.set_current_layer(0)
799 self.display_frame.running = False 804 self.display_frame.running = False
800 805
801 def pause_present(self, event): 806 def pause_present(self, event):
802 if self.pause_button.GetLabel() == 'Pause': 807 if self.pause_button.GetLabel() == 'Pause':
803 print "Pause" 808 print("Pause")
804 self.pause_button.SetLabel("Continue") 809 self.pause_button.SetLabel("Continue")
805 self.display_frame.running = False 810 self.display_frame.running = False
806 else: 811 else:
807 print "Continue" 812 print("Continue")
808 self.pause_button.SetLabel("Pause") 813 self.pause_button.SetLabel("Pause")
809 self.display_frame.running = True 814 self.display_frame.running = True
810 self.display_frame.next_img() 815 self.display_frame.next_img()
811 816
812 if __name__ == "__main__": 817 if __name__ == "__main__":

mercurial