stuff/(Cad.py) Plotting with Z axis movement.py

changeset 0
ee535cb8fb1a
equal deleted inserted replaced
-1:000000000000 0:ee535cb8fb1a
1 #!/usr/bin/env python
2 #
3 # cad.py
4 #
5 # Neil Gershenfeld
6 #
7 # (c) Massachusetts Institute of Technology 2007
8 # Permission granted for experimental and personal use;
9 # license for commercial sale available from MIT.
10 #
11 #Altered by R Parsons (AKA: Capo) to output gcode with the '.gcode' extension as opposed to '.g'.
12 #Also the default variables were changed to metric values
13 DATE = "7/12/010"
14
15 from numpy import *
16 import scipy.signal.signaltools
17 from string import *
18 from Tkinter import *
19 from tkFileDialog import *
20 import Image, ImageTk, ImageDraw, ImageFont, ImageOps
21 import os, struct
22 #import time
23
24 class point:
25 #
26 # an xyz point
27 #
28 def __init__(self,x,y,z=0):
29 self.x = x
30 self.y = y
31 self.z = z
32
33 class cad_variables:
34 #
35 # cad variables
36 #
37 def __init__(self):
38 self.xmin = 0 # minimum x value to render
39 self.xmax = 0 # maximum x value to render
40 self.ymin = 0 # minimum y value to render
41 self.ymax = 0 # maximum y value to render
42 self.zmin = 0 # minimum z value to render
43 self.zmax = 0 # maximum z value to render
44 self.zlist = [] # z values to render
45 self.nx = 0 # number of x points to render
46 self.ny = 0 # number of y points to render
47 self.nz = 1 # number of z points to render
48 self.rz = 0 # perspective view z rotation (degrees)
49 self.rx = 0 # perspective view x rotation (degrees)
50 self.units = 'in' # file units
51 self.function = '0' # cad function
52 self.toolpaths = [] # toolpaths
53 self.x = [] # x triangulation
54 self.y = [] # y triangulation
55 self.z = [] # z triangulation
56 self.labels = [] # display labels
57 self.image_r = array(0) # red array
58 self.image_g = array(0) # green array
59 self.image_b = array(0) # blue array
60 self.image_min = 0 # image min value
61 self.image_max = 0 # image max value
62 self.stop = 0 # stop rendering
63 self.nplot = 200 # plot window size
64 self.inches_per_unit = 1 # file units
65 self.views = 'xyzr'
66 self.cam = '' # CAM export type
67 self.editor_width = 30 # editor width
68 self.editor_height = 10 # editor height
69 def view(self,arg):
70 global canvas_xy,canvas_yz,canvas_xz,canvas_xyz
71 if (arg == 'xy'):
72 view_frame2.grid_forget()
73 view_frame3.grid_forget()
74 canvas_xy.grid_forget()
75 self.views = 'xy'
76 self.nplot = 2*int(string_window_size.get()) # plot window size
77 canvas_xy = Canvas(view_frame2, width=self.nplot, height=self.nplot)
78 imxy = Image.new("RGBX",(self.nplot,self.nplot),'black')
79 image_xy = ImageTk.PhotoImage(imxy)
80 canvas_xy.create_image(self.nplot/2,self.nplot/2,image=image_xy)
81 canvas_xy.bind('<Motion>',msg_xy)
82 canvas_xy.grid(row=0,column=0)
83 view_frame2.grid(row=2,column=0)
84 elif (arg == 'xyzr'):
85 view_frame2.grid_forget()
86 view_frame3.grid_forget()
87 canvas_xy.grid_forget()
88 canvas_yz.grid_forget()
89 canvas_xz.grid_forget()
90 canvas_xyz.grid_forget()
91 self.views = 'xyzr'
92 self.nplot = int(string_window_size.get()) # plot window size
93 canvas_xy = Canvas(view_frame3, width=self.nplot, height=self.nplot)
94 canvas_yz = Canvas(view_frame3, width=self.nplot, height=self.nplot)
95 canvas_xz = Canvas(view_frame3, width=self.nplot, height=self.nplot)
96 canvas_xyz = Canvas(view_frame3, width=self.nplot, height=cad.nplot)
97 imxy = Image.new("RGBX",(self.nplot,self.nplot),'black')
98 image_xy = ImageTk.PhotoImage(imxy)
99 canvas_xy.create_image(self.nplot/2,self.nplot/2,image=image_xy)
100 canvas_xy.bind('<Motion>',msg_xy)
101 canvas_xy.grid(row=0,column=0)
102 imyz = Image.new("RGBX",(self.nplot,self.nplot),'black')
103 image_yz = ImageTk.PhotoImage(imyz)
104 canvas_yz.create_image(self.nplot/2,self.nplot/2,image=image_yz)
105 canvas_yz.bind('<Motion>',msg_yz)
106 canvas_yz.grid(row=0,column=1)
107 imxz = Image.new("RGBX",(self.nplot,self.nplot),'black')
108 image_xz = ImageTk.PhotoImage(imxz)
109 canvas_xz.create_image(self.nplot/2,self.nplot/2,image=image_xz)
110 canvas_xz.bind('<Motion>',msg_xz)
111 canvas_xz.grid(row=1,column=0)
112 imxyz = Image.new("RGBX",(self.nplot,self.nplot),'black')
113 image_xyz = ImageTk.PhotoImage(imxyz)
114 canvas_xyz.create_image(self.nplot/2,self.nplot/2,image=image_xyz)
115 canvas_xyz.bind('<Motion>',msg_nomsg)
116 canvas_xyz.grid(row=1,column=1)
117 view_frame3.grid(row=2,column=0)
118 else:
119 print "view not supported"
120 def nxplot(self):
121 xwidth = self.xmax - self.xmin
122 ywidth = self.ymax - self.ymin
123 zwidth = self.zmax - self.zmin
124 if ((xwidth >= ywidth) & (xwidth >= zwidth)):
125 n = int(self.nplot*xwidth/float(xwidth))
126 elif ((ywidth >= xwidth) & (ywidth >= zwidth)):
127 n = int(self.nplot*xwidth/float(ywidth))
128 else:
129 n = int(self.nplot*xwidth/float(zwidth))
130 return n
131 def nyplot(self):
132 xwidth = self.xmax - self.xmin
133 ywidth = self.ymax - self.ymin
134 zwidth = self.zmax - self.zmin
135 if ((xwidth >= ywidth) & (xwidth >= zwidth)):
136 n = int(self.nplot*ywidth/float(xwidth))
137 elif ((ywidth >= xwidth) & (ywidth >= zwidth)):
138 n = int(self.nplot*ywidth/float(ywidth))
139 else:
140 n = int(self.nplot*ywidth/float(zwidth))
141 return n
142 def nzplot(self):
143 xwidth = self.xmax - self.xmin
144 ywidth = self.ymax - self.ymin
145 zwidth = self.zmax - self.zmin
146 if ((xwidth >= ywidth) & (xwidth >= zwidth)):
147 n = int(self.nplot*zwidth/float(xwidth))
148 elif ((ywidth >= xwidth) & (ywidth >= zwidth)):
149 n = int(self.nplot*zwidth/float(ywidth))
150 else:
151 n = int(self.nplot*zwidth/float(zwidth))
152 return n
153
154 cad = cad_variables()
155
156 class cad_text:
157 def __init__(self,x,y,z=0,text='',size=10,color='#ff0000',anchor=CENTER):
158 self.x = x
159 self.y = y
160 self.z = z
161 self.text = text
162 self.size = size
163 self.color = color
164 self.anchor = anchor
165
166 class im_class:
167 #
168 # for PIL images
169 #
170 def __init__(self):
171 self.xy = 0
172 self.xz = 0
173 self.yz = 0
174 self.xyz = 0
175 self.intensity_xy = 0
176 self.intensity_xz = 0
177 self.intensity_yz = 0
178 self.intensity_xyz = 0
179
180 im = im_class()
181
182 class images_class:
183 #
184 # for PhotoImages
185 #
186 def __init__(self):
187 self.xy = 0
188 self.xz = 0
189 self.yz = 0
190 self.xyz = 0
191
192 images = images_class()
193
194 class CA_states:
195 #
196 # CA state definition class
197 #
198 def __init__(self):
199 self.empty = 0
200 self.interior = 1
201 self.edge = (1 << 1) # 2
202 self.north = (1 << 2) # 4
203 self.west = (2 << 2) # 8
204 self.east = (3 << 2) # 12
205 self.south = (4 << 2) # 16
206 self.stop = (5 << 2) # 20
207 self.corner = (6 << 2) # 24
208
209 class rule_table:
210 #
211 # CA rule table class
212 #
213 # 0 = empty
214 # 1 = interior
215 # 2 = edge
216 # edge+direction = start
217 #
218 def __init__(self):
219 self.table = zeros(2**(9*2),uint32)
220 self.s = CA_states()
221 #
222 # 1 0:
223 #
224 # 011
225 # 111
226 # 111
227 self.add_rule(0,1,1,1,1,1,1,1,1,self.s.north)
228 # 101
229 # 111
230 # 111
231 self.add_rule(1,0,1,1,1,1,1,1,1,self.s.east)
232 #
233 # 2 0's:
234 #
235 # 001
236 # 111
237 # 111
238 self.add_rule(0,0,1,1,1,1,1,1,1,self.s.east)
239 # 100
240 # 111
241 # 111
242 self.add_rule(1,0,0,1,1,1,1,1,1,self.s.east)
243 # 010
244 # 111
245 # 111
246 self.add_rule(0,1,0,1,1,1,1,1,1,self.s.east)
247 # 011
248 # 110
249 # 111
250 self.add_rule(0,1,1,1,1,0,1,1,1,self.s.south)
251 # 110
252 # 011
253 # 111
254 self.add_rule(1,1,0,0,1,1,1,1,1,self.s.east)
255 # 101
256 # 011
257 # 111
258 self.add_rule(1,0,1,0,1,1,1,1,1,self.s.east)
259 # 101
260 # 110
261 # 111
262 self.add_rule(1,0,1,1,1,0,1,1,1,self.s.south)
263 # 011
264 # 111
265 # 110
266 self.add_rule(0,1,1,1,1,1,1,1,0,self.s.corner)
267 # 011
268 # 111
269 # 101
270 self.add_rule(0,1,1,1,1,1,1,0,1,self.s.north)
271 # 110
272 # 111
273 # 101
274 self.add_rule(1,1,0,1,1,1,1,0,1,self.s.west)
275 # 101
276 # 111
277 # 110
278 self.add_rule(1,0,1,1,1,1,1,1,0,self.s.south)
279 # 101
280 # 111
281 # 011
282 self.add_rule(1,0,1,1,1,1,0,1,1,self.s.east)
283 #
284 # 3 0's:
285 #
286 # 001
287 # 011
288 # 111
289 self.add_rule(0,0,1,0,1,1,1,1,1,self.s.east)
290 # 010
291 # 011
292 # 111
293 self.add_rule(0,1,0,0,1,1,1,1,1,self.s.east)
294 # 010
295 # 110
296 # 111
297 self.add_rule(0,1,0,1,1,0,1,1,1,self.s.south)
298 # 010
299 # 111
300 # 011
301 self.add_rule(0,1,0,1,1,1,0,1,1,self.s.east)
302 # 010
303 # 111
304 # 110
305 self.add_rule(0,1,0,1,1,1,1,1,0,self.s.south)
306 # 110
307 # 011
308 # 011
309 self.add_rule(1,1,0,0,1,1,0,1,1,self.s.east)
310 # 011
311 # 110
312 # 110
313 self.add_rule(0,1,1,1,1,0,1,1,0,self.s.south)
314 # 101
315 # 011
316 # 011
317 self.add_rule(1,0,1,0,1,1,0,1,1,self.s.east)
318 # 101
319 # 110
320 # 110
321 self.add_rule(1,0,1,1,1,0,1,1,0,self.s.south)
322 # 011
323 # 011
324 # 011
325 self.add_rule(0,1,1,0,1,1,0,1,1,self.s.north)
326 #
327 # 4 0's:
328 #
329 # 001
330 # 011
331 # 011
332 self.add_rule(0,0,1,0,1,1,0,1,1,self.s.east)
333 # 100
334 # 110
335 # 110
336 self.add_rule(1,0,0,1,1,0,1,1,0,self.s.south)
337 # 010
338 # 011
339 # 011
340 self.add_rule(0,1,0,0,1,1,0,1,1,self.s.east)
341 # 010
342 # 110
343 # 110
344 self.add_rule(0,1,0,1,1,0,1,1,0,self.s.south)
345 # 001
346 # 110
347 # 110
348 self.add_rule(0,0,1,1,1,0,1,1,0,self.s.south)
349 # 100
350 # 011
351 # 011
352 self.add_rule(1,0,0,0,1,1,0,1,1,self.s.east)
353 #
354 # 5 0's:
355 #
356 # 000
357 # 011
358 # 011
359 self.add_rule(0,0,0,0,1,1,0,1,1,self.s.east)
360 #
361 # edge states
362 #
363 # 200
364 # 211
365 # 211
366 self.add_rule(2,0,0,2,1,1,2,1,1,self.s.east+self.s.edge)
367 # 201
368 # 211
369 # 211
370 self.add_rule(2,0,1,2,1,1,2,1,1,self.s.east+self.s.edge)
371 # 210
372 # 211
373 # 211
374 self.add_rule(2,1,0,2,1,1,2,1,1,self.s.east+self.s.edge)
375 # 002
376 # 112
377 # 112
378 self.add_rule(0,0,2,1,1,2,1,1,2,self.s.stop)
379 # 102
380 # 112
381 # 112
382 self.add_rule(1,0,2,1,1,2,1,1,2,self.s.stop)
383 # 002
384 # 112
385 # 102
386 self.add_rule(0,0,2,1,1,2,1,0,2,self.s.stop)
387 # 012
388 # 112
389 # 112
390 self.add_rule(0,1,2,1,1,2,1,1,2,self.s.stop)
391 # 012
392 # 112
393 # 102
394 self.add_rule(0,1,2,1,1,2,1,0,2,self.s.stop)
395
396 def add_rule(self,nw,nn,ne,ww,cc,ee,sw,ss,se,rule):
397 #
398 # add a CA rule, with rotations
399 #
400 s = CA_states()
401 #
402 # add the rule
403 #
404 state = \
405 (nw << 0) + (nn << 2) + (ne << 4) + \
406 (ww << 6) + (cc << 8) + (ee << 10) + \
407 (sw << 12) + (ss << 14) + (se << 16)
408 self.table[state] = rule
409 #
410 # rotate 90 degrees
411 #
412 state = \
413 (sw << 0) + (ww << 2) + (nw << 4) + \
414 (ss << 6) + (cc << 8) + (nn << 10) + \
415 (se << 12) + (ee << 14) + (ne << 16)
416 if (rule == s.east):
417 self.table[state] = s.south
418 elif (rule == s.south):
419 self.table[state] = s.west
420 elif (rule == s.west):
421 self.table[state] = s.north
422 elif (rule == s.north):
423 self.table[state] = s.east
424 elif (rule == (s.east+s.edge)):
425 self.table[state] = s.south+s.edge
426 elif (rule == (s.south+s.edge)):
427 self.table[state] = s.west+s.edge
428 elif (rule == (s.west+s.edge)):
429 self.table[state] = s.north+s.edge
430 elif (rule == (s.north+s.edge)):
431 self.table[state] = s.east+s.edge
432 elif (rule == s.corner):
433 self.table[state] = s.corner
434 elif (rule == s.stop):
435 self.table[state] = s.stop
436 #
437 # rotate 180 degrees
438 #
439 state = \
440 (se << 0) + (ss << 2) + (sw << 4) + \
441 (ee << 6) + (cc << 8) + (ww << 10) + \
442 (ne << 12) + (nn << 14) + (nw << 16)
443 if (rule == s.east):
444 self.table[state] = s.west
445 elif (rule == s.south):
446 self.table[state] = s.north
447 elif (rule == s.west):
448 self.table[state] = s.east
449 elif (rule == s.north):
450 self.table[state] = s.south
451 elif (rule == (s.east+s.edge)):
452 self.table[state] = s.west+s.edge
453 elif (rule == (s.south+s.edge)):
454 self.table[state] = s.north+s.edge
455 elif (rule == (s.west+s.edge)):
456 self.table[state] = s.east+s.edge
457 elif (rule == (s.north+s.edge)):
458 self.table[state] = s.south+s.edge
459 elif (rule == s.corner):
460 self.table[state] = s.corner
461 elif (rule == s.stop):
462 self.table[state] = s.stop
463 #
464 # rotate 270 degrees
465 #
466 state = \
467 (ne << 0) + (ee << 2) + (se << 4) + \
468 (nn << 6) + (cc << 8) + (ss << 10) + \
469 (nw << 12) + (ww << 14) + (sw << 16)
470 if (rule == s.east):
471 self.table[state] = s.north
472 elif (rule == s.south):
473 self.table[state] = s.east
474 elif (rule == s.west):
475 self.table[state] = s.south
476 elif (rule == s.north):
477 self.table[state] = s.west
478 elif (rule == (s.east+s.edge)):
479 self.table[state] = s.north+s.edge
480 elif (rule == (s.south+s.edge)):
481 self.table[state] = s.east+s.edge
482 elif (rule == (s.west+s.edge)):
483 self.table[state] = s.south+s.edge
484 elif (rule == (s.north+s.edge)):
485 self.table[state] = s.west+s.edge
486 elif (rule == s.corner):
487 self.table[state] = s.corner
488 elif (rule == s.stop):
489 self.table[state] = s.stop
490
491 def evaluate_state(arr):
492 #
493 # assemble the state bit strings
494 #
495 (ny, nx) = shape(arr)
496 s = CA_states()
497 nn = concatenate(([s.edge+zeros(nx,uint32)],arr[:(ny-1)]))
498 ss = concatenate((arr[1:],[s.edge+zeros(nx,uint32)]))
499 ww = concatenate((reshape(s.edge+zeros(ny,uint32),(ny,1)),arr[:,:(nx-1)]),1)
500 ee = concatenate((arr[:,1:],reshape(s.edge+zeros(ny,uint32),(ny,1))),1)
501 cc = arr
502 nw = concatenate(([s.edge+zeros(nx,uint32)],ww[:(ny-1)]))
503 ne = concatenate(([s.edge+zeros(nx,uint32)],ee[:(ny-1)]))
504 sw = concatenate((ww[1:],[s.edge+zeros(nx,uint32)]))
505 se = concatenate((ee[1:],[s.edge+zeros(nx,uint32)]))
506 state = (nw << 0) + (nn << 2) + (ne << 4) + \
507 (ww << 6) + (cc << 8) + (ee << 10) + \
508 (sw << 12) + (ss << 14) + (se << 16)
509 return state
510
511 def vectorize_toolpaths(arr):
512 #
513 # convert lattice toolpath directions to vectors
514 #
515 s = CA_states()
516 toolpaths = []
517 max_dist = float(string_vector_error.get())
518 start_sites = (arr == (s.north+s.edge)) | (arr == (s.south+s.edge)) | \
519 (arr == (s.east+s.edge)) | (arr == (s.west+s.edge))
520 num_start_sites = sum(sum(1.0*start_sites))
521 path_sites = (arr == s.north) | (arr == s.south) | (arr == s.east) | \
522 (arr == s.west)
523 num_path_sites = sum(sum(1.0*path_sites))
524 remaining_sites = num_start_sites + num_path_sites
525 while (remaining_sites != 0):
526 #print remaining_sites
527 if (num_start_sites > 0):
528 #
529 # begin segment on a start state
530 #
531 if (argmax(start_sites[0,:],axis=0) != 0):
532 x = argmax(start_sites[0,:],axis=0)
533 y = 0
534 elif (argmax(start_sites[:,0],axis=0) != 0):
535 x = 0
536 y = argmax(start_sites[:,0],axis=0)
537 elif (argmax(start_sites[-1,:],axis=0) != 0):
538 x = argmax(start_sites[-1,:],axis=0)
539 y = cad.ny-1
540 elif (argmax(start_sites[:,-1],axis=0) != 0):
541 x = cad.nx-1
542 y = argmax(start_sites[:,-1],axis=0)
543 else:
544 print "error: internal start"
545 sys.exit()
546 #print "start from ",x,y
547 else:
548 #
549 # no start states; begin segment on upper-left boundary point
550 #
551 maxcols = argmax(path_sites,axis=1)
552 y = argmax(argmax(path_sites,axis=1))
553 x = maxcols[y]
554 arr[y][x] += s.edge
555 #print "segment from ",x,y
556 segment = [point(x,y)]
557 vector = [point(x,y)]
558 while 1:
559 #
560 # follow path
561 #
562 y = vector[-1].y
563 x = vector[-1].x
564 state = arr[y][x]
565 #
566 # if start state, set stop
567 #
568 if (state == (s.north + s.edge)):
569 state = s.north
570 arr[y][x] = s.stop
571 elif (state == (s.south + s.edge)):
572 state = s.south
573 arr[y][x] = s.stop
574 elif (state == (s.east + s.edge)):
575 state = s.east
576 arr[y][x] = s.stop
577 elif (state == (s.west + s.edge)):
578 state = s.west
579 arr[y][x] = s.stop
580 #print "x,y,state,arr: ",x,y,state,arr[y][x]
581 #
582 # move if a valid direction
583 #
584 if (state == s.north):
585 direction = "north"
586 #print "north"
587 ynew = y - 1
588 xnew = x
589 elif (state == s.south):
590 direction = "south"
591 #print "south"
592 ynew = y + 1
593 xnew = x
594 elif (state == s.east):
595 direction = "east"
596 #print "east"
597 ynew = y
598 xnew = x + 1
599 elif (state == s.west):
600 direction = "west"
601 #print "west"
602 ynew = y
603 xnew = x - 1
604 elif (state == s.corner):
605 #print "corner"
606 if (direction == "east"):
607 #print "south"
608 xnew = x
609 ynew = y + 1
610 elif (direction == "west"):
611 #print "north"
612 xnew = x
613 ynew = y - 1
614 elif (direction == "north"):
615 #print "east"
616 ynew = y
617 xnew = x + 1
618 elif (direction == "south"):
619 #print "west"
620 ynew = y
621 xnew = x - 1
622 else:
623 #
624 # not a valid direction, terminate segment on previous point
625 #
626 print "unexpected path termination at",x,y
627 #sys.exit()
628 segment.append(point(x,y))
629 toolpaths.append(segment)
630 arr[y][x] = s.interior
631 break
632 #print "xnew,ynew,snew",xnew,ynew,arr[ynew][xnew]
633 #
634 # check if stop reached
635 #
636 if (arr[ynew][xnew] == s.stop):
637 #print "stop at ",xnew,ynew
638 segment.append(point(xnew,ynew))
639 toolpaths.extend([segment])
640 if (state != s.corner):
641 arr[y][x] = s.interior
642 arr[ynew][xnew] = s.interior
643 break
644 #
645 # find max transverse distance from vector to new point
646 #
647 dmax = 0
648 dx = xnew - vector[0].x
649 dy = ynew - vector[0].y
650 norm = sqrt(dx**2 + dy**2)
651 nx = dy / norm
652 ny = -dx / norm
653 for i in range(len(vector)):
654 dx = vector[i].x - vector[0].x
655 dy = vector[i].y - vector[0].y
656 d = abs(nx*dx + ny*dy)
657 if (d > dmax):
658 dmax = d
659 #
660 # start new vector if transverse distance > max_dist
661 #
662 if (dmax >= max_dist):
663 #print "max at ",x,y
664 segment.append(point(x,y))
665 vector = [point(x,y)]
666 #
667 # otherwise add point to vector
668 #
669 else:
670 #print "add ",xnew,ynew
671 vector.append(point(xnew,ynew))
672 if ((arr[y][x] != s.corner) & (arr[y][x] != s.stop)):
673 arr[y][x] = s.interior
674 start_sites = (arr == (s.north+s.edge)) | (arr == (s.south+s.edge)) | \
675 (arr == (s.east+s.edge)) | (arr == (s.west+s.edge))
676 num_start_sites = sum(sum(1.0*start_sites))
677 path_sites = (arr == s.north) | (arr == s.south) | (arr == s.east) | \
678 (arr == s.west)
679 num_path_sites = sum(sum(1.0*path_sites))
680 remaining_sites = num_start_sites + num_path_sites
681 #
682 # reverse segment order, to start from inside to out
683 #
684 newpaths = []
685 for segment in range(len(toolpaths)):
686 newpaths.append(toolpaths[-1-segment])
687 root.update()
688 return newpaths
689
690 def evaluate():
691 #
692 # evaluate .cad program/image
693 #
694 if (len(widget_cad_text.get("1.0",END)) > 1):
695 #
696 # .cad
697 #
698 cad.zlist = []
699 cad_text_string = widget_cad_text.get("1.0",END)
700 exec cad_text_string in globals()
701 widget_function_text.config(state=NORMAL)
702 widget_function_text.delete("1.0",END)
703 widget_function_text.insert("1.0",cad.function)
704 widget_function_text.config(state=DISABLED)
705 if (cad.image_r.size > 1):
706 #
707 # image
708 #
709 cad.xmin = float(string_image_xmin.get())
710 xwidth = float(string_image_xwidth.get())
711 cad.xmax = cad.xmin + xwidth
712 cad.ymin = float(string_image_ymin.get())
713 yheight = float(string_image_yheight.get())
714 cad.ymax = cad.ymin + yheight
715 cad.image_min = float(string_image_min.get())
716 cad.image_max = float(string_image_max.get())
717 cad.zmin = float(string_image_zmin.get())
718 cad.zmax = float(string_image_zmax.get())
719 cad.nz = int(string_image_nz.get())
720 cad.inches_per_unit = float(string_image_units.get())
721
722 def render(view='xyzr'):
723 render_stop_flag = 0
724 cad.stop = 0
725 #
726 # if .cad doesn't call render, delete windows and add stop button
727 #
728 if (find(widget_cad_text.get("1.0",END),"render(") == -1):
729 string_msg.set("render ...")
730 widget_stop.pack()
731 delete_windows()
732 #
733 # initialize variables
734 #
735 cad.toolpaths = []
736 rx = pi*cad.rx/180.
737 rz = pi*cad.rz/180.
738 r = rule_table()
739 s = CA_states()
740 #
741 # evaluate coordinate arrays
742 #
743 Xarray = outer(ones((cad.ny,1)),cad.xmin+(cad.xmax-cad.xmin)*arange(cad.nx)/(cad.nx-1.0))
744 Yarray = outer(cad.ymin+(cad.ymax-cad.ymin)*arange(cad.ny-1,-1,-1)/(cad.ny-1.0),ones((1,cad.nx)))
745 if (cad.zlist == []):
746 if ((cad.nz == 1) & (cad.image_r.size != 1)):
747 cad.zlist = [cad.zmax]
748 cad.view('xy')
749 elif (cad.nz == 1):
750 cad.zlist = [cad.zmin]
751 cad.view('xy')
752 else:
753 cad.zlist = cad.zmin + (cad.zmax-cad.zmin)*arange(cad.nz)/(cad.nz-1.0)
754 cad.view('xyzr')
755 else:
756 cad.nz = len(cad.zlist)
757 cad.zmin = cad.zlist[0]
758 cad.zmax = cad.zlist[-1]
759 #
760 # draw orthogonal views
761 #
762 X = Xarray
763 Y = Yarray
764 accum_r = zeros((cad.ny,cad.nx),uint32)
765 accum_g = zeros((cad.ny,cad.nx),uint32)
766 accum_b = zeros((cad.ny,cad.nx),uint32)
767 im.intensity_yz = zeros((cad.ny,cad.nz),uint32)
768 im.intensity_xz = zeros((cad.nz,cad.nx),uint32)
769 im.intensity_xyz = zeros((cad.nz,cad.nx),uint32)
770 for layer in range(cad.nz):
771 #
772 # check render stop button
773 #
774 if (cad.stop == 1):
775 break
776 #
777 # xy view
778 #
779 Z = cad.zlist[layer]
780 string_msg.set("render z = %.3f"%Z)
781 # root.update()
782 if (cad.image_r.size == 1):
783 #
784 # .cad
785 #
786 array_r = eval(cad.function)
787 array_g = array_r
788 array_b = array_r
789 if ((cad.zmax == cad.zmin) | (cad.nz == 1)):
790 zi = array([255],uint32)
791 else:
792 zi = array([55.0 + 200.0*layer/(cad.nz-1.0)],uint32)
793 accum_r = where(((zi*array_r) > accum_r),(zi*array_r),accum_r)
794 accum_g = where(((zi*array_g) > accum_g),(zi*array_g),accum_g)
795 accum_b = where(((zi*array_b) > accum_b),(zi*array_b),accum_b)
796 im.intensity_xy = (1 << 16)*accum_b + (1 << 8)*accum_g + (1 << 0)*accum_r
797 else:
798 #
799 # bitmap
800 #
801 array_r = (cad.image_r[0,] >= (cad.image_min + (cad.image_max-cad.image_min)*(Z-cad.zmin)/float(cad.zmax-cad.zmin)))
802 array_g = (cad.image_g[0,] >= (cad.image_min + (cad.image_max-cad.image_min)*(Z-cad.zmin)/float(cad.zmax-cad.zmin)))
803 array_b = (cad.image_b[0,] >= (cad.image_min + (cad.image_max-cad.image_min)*(Z-cad.zmin)/float(cad.zmax-cad.zmin)))
804 image_z = int(cad.image_min + (cad.image_max-cad.image_min)*(Z-cad.zmin)/float(cad.zmax-cad.zmin))
805 intensity_r = where((cad.image_r[0,] <= image_z),cad.image_r[0,],image_z)
806 intensity_g = where((cad.image_g[0,] <= image_z),cad.image_g[0,],image_z)
807 intensity_b = where((cad.image_b[0,] <= image_z),cad.image_b[0,],image_z)
808 im.intensity_xy = (1 << 16)*intensity_b + (1 << 8)*intensity_g + (1 << 0)*intensity_r
809 im.xy = Image.fromarray(im.intensity_xy,mode="RGBX")
810 im.xy_draw = ImageDraw.Draw(im.xy)
811 im.xy = im.xy.resize((cad.nxplot(),cad.nyplot()))
812 images.xy = ImageTk.PhotoImage(im.xy)
813 canvas_xy.create_image(cad.nplot/2,cad.nplot/2,image=images.xy)
814 # root.update()
815 #
816 # find toolpaths if needed
817 #
818 ncontours = int(string_num_contours.get())
819 if (ncontours == -1):
820 ncontours = 2**20 # a big number
821 cad.toolpaths.append([])
822 """
823 if (ncontours != 0):
824 #
825 # grassfire convolve (to come)
826 #
827 interior = (array_r | array_g | array_b)
828 print shape(X[interior])
829 conv_array = interior
830 """
831 for contour in range(ncontours):
832 #
833 # check render stop button
834 #
835 if (cad.stop == 1):
836 break
837 #
838 # convolve tool for contour
839 #
840 string_msg.set(" convolve tool ... ")
841 #
842 # FFT convolve
843 #
844 # root.update()
845 tool_rad = float(string_tool_dia.get())/2.0
846 tool_dia = float(string_tool_dia.get())
847 tool_overlap = float(string_tool_overlap.get())
848 kernel_rad = tool_rad + contour*tool_overlap*tool_dia
849 ikernel_rad = 1 + int(cad.nx*kernel_rad/(cad.xmax-cad.xmin))
850 if (ikernel_rad > (((cad.nx/2),(cad.ny/2))[(cad.ny/2) > (cad.nx/2)])):
851 break
852 kx = 1+outer(ones((2*ikernel_rad,1)),arange(2*ikernel_rad))
853 ky = 1+outer(arange(2*ikernel_rad),ones((1,2*ikernel_rad)))
854 k = (((kx-ikernel_rad)**2 + (ky-ikernel_rad)**2) < ikernel_rad**2).astype('uint32')
855 interior = (array_r == s.interior).astype('uint32')
856 #tstart = time.time()
857 conv = scipy.signal.signaltools.fftconvolve(interior,k,mode='same')
858 conv = where(conv > 0.01,s.interior,0)
859 conv_array = conv + (conv != s.interior)*array_r
860 #tend = time.time()
861 #print 'convolve:',tend-tstart
862 #
863 # use CA rule table to find edge directions
864 #
865 string_msg.set(" follow edges ... ")
866 # root.update()
867 state = evaluate_state(conv_array)
868 toolpath = r.table[state]
869 tool_array = toolpath + (toolpath == s.empty)*conv_array
870 tool_intensity = \
871 ((0 << 16) + (0 << 8) + (0 << 0))*(tool_array == s.empty).astype('uint32') +\
872 ((255 << 16) + (255 << 8) + (255 << 0))*(tool_array == s.interior).astype('uint32') +\
873 (( 0 << 16) + ( 0 << 8) + (255 << 0))*(tool_array == s.north).astype('uint32') +\
874 (( 0 << 16) + (255 << 8) + ( 0 << 0))*(tool_array == s.south).astype('uint32') +\
875 ((255 << 16) + ( 0 << 8) + ( 0 << 0))*(tool_array == s.east).astype('uint32') +\
876 (( 0 << 16) + (255 << 8) + (255 << 0))*(tool_array == s.west ).astype('uint32') +\
877 ((128 << 16) + ( 0 << 8) + (128 << 0))*(tool_array == s.stop).astype('uint32')
878
879 #
880 # show CA
881 #
882 """
883 im.xy = Image.fromarray(tool_intensity,mode="RGBX")
884 im.xy = im.xy.resize((cad.nplot,cad.nplot))
885 images.xy = ImageTk.PhotoImage(im.xy)
886 canvas_xy.create_image(cad.nplot/2,cad.nplot/2,image=images.xy)
887 """
888 #
889 # vectorize contour
890 #
891 #tstart = time.time()
892 string_msg.set(" vectorize ... ")
893 # root.update()
894 new_paths = vectorize_toolpaths(tool_array)
895 if (len(new_paths) == 0):
896 break
897 cad.toolpaths[layer].extend(new_paths)
898 #tend = time.time()
899 #print 'vector:',tend-tstart
900 #
901 # draw toolpath
902 #
903 im.xy_draw = ImageDraw.Draw(im.xy)
904 for segment in range(len(cad.toolpaths[layer])):
905 x = cad.nxplot()*(cad.toolpaths[layer][segment][0].x+0.5)/float(cad.nx)
906 y = cad.nyplot()*(cad.toolpaths[layer][segment][0].y+0.5)/float(cad.ny)
907 for vertex in range(1,len(cad.toolpaths[layer][segment])):
908 xnew = cad.nxplot()*(cad.toolpaths[layer][segment][vertex].x+0.5)/float(cad.nx)
909 ynew = cad.nyplot()*(cad.toolpaths[layer][segment][vertex].y+0.5)/float(cad.ny)
910 im.xy_draw.line([x,y,xnew,ynew],fill="#ffa0a0",width=1)
911 x = xnew
912 y = ynew
913 #
914 # show xy toolpath view
915 #
916 images.xy = ImageTk.PhotoImage(im.xy)
917 canvas_xy.create_image(cad.nplot/2,cad.nplot/2,image=images.xy)
918 #
919 # add send_to button
920 #
921 string_send_to_time.set("")
922 send_to_frame.pack()
923 # root.update()
924 #
925 # draw labels
926 #
927 for label in range(len(cad.labels)):
928 x = cad.nplot/2. + cad.nxplot()*(cad.labels[label].x-(cad.xmax+cad.xmin)/2.0)/(cad.xmax-cad.xmin)
929 y = cad.nplot/2. - cad.nyplot()*(cad.labels[label].y-(cad.ymax+cad.ymin)/2.0)/(cad.ymax-cad.ymin)
930 string = cad.labels[label].text
931 size = cad.labels[label].size
932 color = cad.labels[label].color
933 anch = cad.labels[label].anchor
934 canvas_xy.create_text(x,y,text=string,font=('arial',size,'bold'),fill=color,anchor=anch,justify=CENTER)
935 #
936 # draw origin
937 #
938 x0 = cad.nplot/2. + cad.nxplot()*(0-(cad.xmax+cad.xmin)/2.)/(cad.xmax-cad.xmin)
939 y0 = cad.nplot/2. - cad.nyplot()*(0-(cad.ymax+cad.ymin)/2.)/(cad.ymax-cad.ymin)
940 dxy = .025*cad.nplot
941 canvas_xy.create_line([x0-dxy,y0,x0+dxy,y0],fill="green")
942 canvas_xy.create_line([x0,y0-dxy,x0,y0+dxy],fill="green")
943 #
944 # yz view
945 #
946 if (cad.views == 'xyzr'):
947 accum_yz_r = zeros(cad.ny,uint32)
948 accum_yz_g = zeros(cad.ny,uint32)
949 accum_yz_b = zeros(cad.ny,uint32)
950 for vertex in range(cad.nx):
951 xi = array([55.0 + 200.0*vertex/(cad.nx-1.0)],uint32)
952 slice_r = array_r[:,vertex]
953 slice_g = array_g[:,vertex]
954 slice_b = array_b[:,vertex]
955 accum_yz_r = where(((xi*slice_r) >= accum_yz_r),(xi*slice_r),accum_yz_r)
956 accum_yz_g = where(((xi*slice_g) >= accum_yz_g),(xi*slice_g),accum_yz_g)
957 accum_yz_b = where(((xi*slice_b) >= accum_yz_b),(xi*slice_b),accum_yz_b)
958 im.intensity_yz[:,layer] = (1 << 16)*accum_yz_b + (1 << 8)*accum_yz_g + (1 << 0)*accum_yz_r
959 im.yz = Image.fromarray(im.intensity_yz,mode="RGBX")
960 im.yz = im.yz.transpose(Image.FLIP_LEFT_RIGHT)
961 im.yz = im.yz.resize((cad.nzplot(),cad.nyplot()))
962 images.yz = ImageTk.PhotoImage(im.yz)
963 canvas_yz.create_image(cad.nplot/2,cad.nplot/2,image=images.yz)
964 #
965 # draw origin
966 #
967 z0 = cad.nplot/2. - cad.nzplot()*(0-(cad.zmax+cad.zmin)/2.)/(cad.zmax-cad.zmin)
968 y0 = cad.nplot/2. - cad.nyplot()*(0-(cad.ymax+cad.ymin)/2.)/(cad.ymax-cad.ymin)
969 canvas_yz.create_line([z0-dxy,y0,z0+dxy,y0],fill="green")
970 canvas_yz.create_line([z0,y0-dxy,z0,y0+dxy],fill="green")
971 #
972 # xz view
973 #
974 if (cad.views == 'xyzr'):
975 accum_xz_r = zeros(cad.nx,uint32)
976 accum_xz_g = zeros(cad.nx,uint32)
977 accum_xz_b = zeros(cad.nx,uint32)
978 for vertex in range(cad.ny):
979 yi = array([55.0+200.0*vertex/(cad.ny-1.0)],uint32)
980 slice_r = array_r[vertex,:]
981 slice_g = array_g[vertex,:]
982 slice_b = array_b[vertex,:]
983 accum_xz_r = where(((yi*slice_r) >= accum_xz_r),(yi*slice_r),accum_xz_r)
984 accum_xz_g = where(((yi*slice_g) >= accum_xz_g),(yi*slice_g),accum_xz_g)
985 accum_xz_b = where(((yi*slice_b) >= accum_xz_b),(yi*slice_b),accum_xz_b)
986 im.intensity_xz[(cad.nz-1-layer),:] = (1 << 16)*accum_xz_b + (1 << 8)*accum_xz_g + (1 << 0)*accum_xz_r
987 im.xz = Image.fromarray(im.intensity_xz,mode="RGBX")
988 im.xz = im.xz.resize((cad.nxplot(),cad.nzplot()))
989 images.xz = ImageTk.PhotoImage(im.xz)
990 canvas_xz.create_image(cad.nplot/2,cad.nplot/2,image=images.xz)
991 #
992 # draw origin
993 #
994 x0 = cad.nplot/2. + cad.nxplot()*(0-(cad.xmax+cad.xmin)/2.)/(cad.xmax-cad.xmin)
995 z0 = cad.nplot/2. - cad.nzplot()*(0-(cad.zmax+cad.zmin)/2.)/(cad.zmax-cad.zmin)
996 canvas_xz.create_line([x0-dxy,z0,x0+dxy,z0],fill="green")
997 canvas_xz.create_line([x0,z0-dxy,x0,z0+dxy],fill="green")
998 #
999 # draw it
1000 #
1001 root.update()
1002 #
1003 # rotated view
1004 #
1005 if ((cad.views == 'xyzr') & (cad.image_r.size == 1)):
1006 accum = zeros((cad.ny,cad.nx),uint32)
1007 for z in cad.zlist:
1008 #
1009 # check render stop button
1010 #
1011 if (cad.stop == 1):
1012 break
1013 string_msg.set("render z = %.3f"%z)
1014 dY = cos(rx)*(Yarray-(cad.ymax+cad.ymin)/2.0) - sin(rx)*(z-(cad.zmax+cad.zmin)/2.0)
1015 Z = (cad.zmax+cad.zmin)/2.0 + sin(rx)*(Yarray-(cad.ymax+cad.ymin)/2.0) + cos(rx)*(z-(cad.zmax+cad.zmin)/2.0)
1016 X = (cad.xmax+cad.xmin)/2.0 + cos(rz)*(Xarray-(cad.xmax+cad.xmin)/2.0) - sin(rz)*dY
1017 Y = (cad.ymax+cad.ymin)/2.0 + sin(rz)*(Xarray-(cad.xmax+cad.xmin)/2.0) + cos(rz)*dY
1018 arr = eval(cad.function)
1019 if (cad.zmax == cad.zmin):
1020 zi = array([255],uint32)
1021 else:
1022 zi = array([55.0 + 200.0*(z-cad.zmin)/(cad.zmax-cad.zmin)],uint32)
1023 accum = where(((zi*arr) > accum),(zi*arr),accum)
1024 im.intensity_xyz = ((1 << 16) + (1 << 8) + (1 << 0)) * accum
1025 im.xyz = Image.fromarray(im.intensity_xyz,mode="RGBX")
1026 im.xyz = im.xyz.resize((cad.nxplot(),cad.nyplot()))
1027 images.xyz = ImageTk.PhotoImage(im.xyz)
1028 canvas_xyz.create_image(cad.nplot/2,cad.nplot/2,image=images.xyz)
1029 root.update()
1030 #
1031 # return
1032 #
1033 cad.zwrite = cad.zlist
1034 cad.zlist = []
1035 widget_stop.pack_forget()
1036 string_msg.set("done")
1037 root.update()
1038 return
1039
1040 def draw_toolpath():
1041 im.xy = Image.new("RGBX",(cad.nxplot(),cad.nyplot()),'white')
1042 im.xy_draw = ImageDraw.Draw(im.xy)
1043 for layer in range(len(cad.toolpaths)):
1044 for segment in range(len(cad.toolpaths[layer])):
1045 x = cad.nxplot()*(cad.toolpaths[layer][segment][0].x+0.5)/float(cad.nx)
1046 y = cad.nyplot()*(cad.toolpaths[layer][segment][0].y+0.5)/float(cad.ny)
1047 for vertex in range(1,len(cad.toolpaths[layer][segment])):
1048 xnew = cad.nxplot()*(cad.toolpaths[layer][segment][vertex].x+0.5)/float(cad.nx)
1049 ynew = cad.nyplot()*(cad.toolpaths[layer][segment][vertex].y+0.5)/float(cad.ny)
1050 im.xy_draw.line([x,y,xnew,ynew],fill="black")
1051 x = xnew
1052 y = ynew
1053 images.xy = ImageTk.PhotoImage(im.xy)
1054 canvas_xy.create_image(cad.nplot/2,cad.nplot/2,image=images.xy)
1055
1056 def delete_windows():
1057 im.xy = Image.new("RGBX",(cad.nplot,cad.nplot),'black')
1058 images.xy = ImageTk.PhotoImage(im.xy)
1059 canvas_xy.create_image(cad.nplot/2,cad.nplot/2,image=images.xy)
1060 im.yz = Image.new("RGBX",(cad.nplot,cad.nplot),'black')
1061 images.yz = ImageTk.PhotoImage(im.yz)
1062 canvas_yz.create_image(cad.nplot/2,cad.nplot/2,image=images.yz)
1063 im.xz = Image.new("RGBX",(cad.nplot,cad.nplot),'black')
1064 images.xz = ImageTk.PhotoImage(im.xz)
1065 canvas_xz.create_image(cad.nplot/2,cad.nplot/2,image=images.xz)
1066 im.xyz = Image.new("RGBX",(cad.nplot,cad.nplot),'black')
1067 images.xyz = ImageTk.PhotoImage(im.xyz)
1068 canvas_xyz.create_image(cad.nplot/2,cad.nplot/2,image=images.xyz)
1069 root.update()
1070
1071 def select_cad():
1072 image_x_frame.pack_forget()
1073 image_y_frame.pack_forget()
1074 image_z_frame.pack_forget()
1075 image_intensity_frame.pack_forget()
1076 image_units_frame.pack_forget()
1077 image_invert_frame.pack_forget()
1078 cad_input_frame.pack_forget()
1079 widget_cad_text.delete("1.0",END)
1080 widget_cad_text.insert("1.0",cad_template)
1081 editor_frame.pack()
1082 cad.image = array(0)
1083 cad_input_frame.pack()
1084 cad.toolpaths = []
1085 string_num_contours.set('0')
1086 widget_cad_save.pack(side='left')
1087 delete_windows()
1088
1089 def select_image():
1090 editor_frame.pack_forget()
1091 cad_input_frame.pack_forget()
1092 image_x_frame.pack()
1093 image_y_frame.pack()
1094 image_z_frame.pack()
1095 image_intensity_frame.pack()
1096 image_units_frame.pack()
1097 image_invert_frame.pack()
1098 cad_input_frame.pack()
1099 cad.toolpaths = []
1100 string_num_contours.set('0')
1101 widget_cad_save.pack_forget()
1102 delete_windows()
1103
1104 def input_open():
1105 filename = askopenfilename()
1106 string_input_file.set(filename)
1107 if (find(filename,'.cad') != -1):
1108 cad_load(0)
1109 elif ((find(filename,'.jpg') != -1) | (find(filename,'.JPG') != -1) |
1110 (find(filename,'.png') != -1) | (find(filename,'.PNG') != -1) |
1111 (find(filename,'.gif') != -1) | (find(filename,'.GIF') != -1)):
1112 widget_cad_text.delete("1.0",END)
1113 image_load(0)
1114 else:
1115 string_msg.set("unsupported input file format")
1116 root.update()
1117
1118 def cad_load(event):
1119 global cad
1120 cad = cad_variables()
1121 cam_pack_forget()
1122 select_cad()
1123 input_file_name = string_input_file.get()
1124 input_file = open(input_file_name,'rb')
1125 cad_text_string = input_file.read()
1126 widget_cad_text.delete("1.0",END)
1127 widget_cad_text.insert("1.0",cad_text_string)
1128 input_file.close()
1129 cad.toolpaths = []
1130 cad.image = array(0)
1131 cad.nz = 1
1132 string_num_contours.set('0')
1133 evaluate()
1134 if (find(widget_cad_text.get("1.0",END),"render(") == -1):
1135 render()
1136
1137 def image_load(event):
1138 global cad
1139 cad = cad_variables()
1140 cam_pack_forget()
1141 select_image()
1142 function_string_frame.pack_forget()
1143 input_file_name = string_input_file.get()
1144 input_file = open(input_file_name,'rb')
1145 input_file.close()
1146 cad.toolpaths = []
1147 string_num_contours.set('0')
1148 image = Image.open(input_file_name)
1149 num_layers = 1
1150 while 1: # check number of layers
1151 try:
1152 image.seek(image.tell()+1)
1153 num_layers += 1
1154 except:
1155 break
1156 image = Image.open(input_file_name)
1157 if image.mode != "RGBX":
1158 image = image.convert("RGBX")
1159 (cad.nx,cad.ny) = image.size
1160 info = image.info
1161 if ('dpi' in info):
1162 (xdpi,ydpi) = info['dpi']
1163 else:
1164 xdpi = cad.nx
1165 ydpi = xdpi
1166 string_image_nx.set(" nx = "+str(cad.nx))
1167 string_image_ny.set(" ny = "+str(cad.ny))
1168 cad.nz = 1
1169 string_image_nz.set(str(cad.nz))
1170 cad.xmin = 0
1171 string_image_xmin.set('0')
1172 cad.xmax = cad.nx/float(xdpi)
1173 string_image_xwidth.set(str(cad.xmax-cad.xmin))
1174 cad.ymin = 0
1175 string_image_ymin.set('0')
1176 cad.ymax = cad.ny/float(ydpi)
1177 string_image_yheight.set(str(cad.ymax-cad.ymin))
1178 cad.zmin = -.005
1179 string_image_zmin.set('-0.05')
1180 cad.zmax = 0.05
1181 string_image_zmax.set('0.05')
1182 cad.inches_per_unit = 1.0
1183 string_image_units.set('25.4')
1184 data = zeros((num_layers,cad.nx*cad.ny,3),uint32)
1185 data[0,] = array(image.convert("RGB").getdata(),uint32)
1186 for layer in range(1,num_layers):
1187 image.seek(image.tell()+1)
1188 data[layer,] = array(image.convert("RGB").getdata(),uint32)
1189 cad.image_r = array(data[:,:,0],uint32)
1190 cad.image_r = cad.image_r.reshape((num_layers,cad.ny,cad.nx))
1191 cad.image_g = array(data[:,:,1],uint32)
1192 cad.image_g = cad.image_g.reshape((num_layers,cad.ny,cad.nx))
1193 cad.image_b = array(data[:,:,2],uint32)
1194 cad.image_b = cad.image_b.reshape((num_layers,cad.ny,cad.nx))
1195 cad.image_min = 1
1196 string_image_min.set(str(cad.image_min))
1197 cad.image_max = 255
1198 string_image_max.set(str(cad.image_max))
1199 evaluate()
1200 render()
1201
1202 def invert_image(event):
1203 cad.image_r = 255 - cad.image_r
1204 cad.image_g = 255 - cad.image_g
1205 cad.image_b = 255 - cad.image_b
1206 evaluate()
1207 render()
1208
1209 def cad_save(event):
1210 input_file_name = string_input_file.get()
1211 input_file = open(input_file_name,'wb')
1212 cad_text_string = widget_cad_text.get("1.0",END)
1213 input_file.write(cad_text_string)
1214 input_file.close()
1215 string_msg.set(input_file_name+" saved")
1216 root.update()
1217
1218 def render_button(event):
1219 cam_pack_forget()
1220 cad.cam = ''
1221 if (cad.image_r.size == 1):
1222 function_string_frame.pack()
1223 cad.toolpaths = []
1224 string_num_contours.set('0')
1225 evaluate()
1226 if (find(widget_cad_text.get("1.0",END),"render(") == -1):
1227 render()
1228
1229 def render_stop(event):
1230 cad.stop = 1
1231 widget_stop.pack_forget()
1232
1233 def cam(event):
1234 function_string_frame.pack_forget()
1235 cam_file_frame.pack()
1236 string_num_contours.set('1')
1237 root.update()
1238
1239 def contour(event):
1240 evaluate()
1241 if (find(widget_cad_text.get("1.0",END),"render(") == -1):
1242 render()
1243
1244 def triangulate(event):
1245 #
1246 # triangulate for STL
1247 #
1248 # evaluate .cad
1249 #
1250 evaluate()
1251 #
1252 # initialize variables
1253 #
1254 render_stop_flag = 0
1255 cad.stop = 0
1256 widget_stop.pack()
1257 delete_windows()
1258 cad.toolpaths = []
1259 cad.zwrite = []
1260 cad.x = zeros(0)
1261 cad.y = zeros(0)
1262 cad.z = zeros(0)
1263 ixlr = array([])
1264 iylrs = array([])
1265 iylre = array([])
1266 izlr = array([])
1267 ixfbs = array([])
1268 ixfbe = array([])
1269 iyfb = array([])
1270 izfb = array([])
1271 ixtbs = array([])
1272 ixtbe = array([])
1273 iytb = array([])
1274 iztb = array([])
1275 #
1276 # evaluate coordinate arrays
1277 #
1278 (IY,IX) = indices((cad.ny,cad.nx))
1279 IY = IY[::-1,:]
1280 X = cad.xmin+(cad.xmax-cad.xmin)*IX/(cad.nx-1.0)
1281 Y = cad.ymin+(cad.ymax-cad.ymin)*IY/(cad.ny-1.0)
1282 cad.zwrite = cad.zmin + (cad.zmax-cad.zmin)*arange(cad.nz)/(cad.nz-1.0)
1283 #
1284 # set up drawing images
1285 #
1286 im.xy = Image.new("RGBX",(cad.nxplot(),cad.nyplot()),'white')
1287 im.xy_draw = ImageDraw.Draw(im.xy)
1288 im.xz = Image.new("RGBX",(cad.nxplot(),cad.nzplot()),'white')
1289 im.xz_draw = ImageDraw.Draw(im.xz)
1290 im.yz = Image.new("RGBX",(cad.nzplot(),cad.nyplot()),'white')
1291 im.yz_draw = ImageDraw.Draw(im.yz)
1292 #
1293 # loop over layers
1294 #
1295 Z = cad.zwrite[0]
1296 array0 = eval(cad.function)
1297 Z = cad.zwrite[1]
1298 array1 = eval(cad.function)
1299 for layer in range(2,len(cad.zwrite)):
1300 #
1301 # check render stop button
1302 #
1303 if (cad.stop == 1):
1304 break
1305 #
1306 # evaluate new layer
1307 #
1308 Z = cad.zwrite[layer]
1309 string_msg.set("triangulate z = %.3f"%Z)
1310 root.update()
1311 array2 = eval(cad.function)
1312 #
1313 # find left faces and merge y
1314 #
1315 elements = hstack((reshape((array1[:,0] == True),(cad.ny,1)),((array1[:,1:] == True) & (array1[:,:-1] == False))))
1316 starts = vstack((((elements[:-1,:] == True) & (elements[1:,:] == False)),reshape((elements[-1,:] == True),(1,cad.nx))))
1317 ends = vstack((reshape((elements[0,:] == True),(1,cad.nx)),((elements[1:,:] == True) & (elements[:-1,:] == False))))
1318 IY_t = transpose(IY) # for starts and ends to be read in same row
1319 IX_t = transpose(IX)
1320 starts_t = transpose(starts)
1321 ends_t = transpose(ends)
1322 ixlr = append(ixlr,IX_t[starts_t])
1323 iylrs = append(iylrs,IY_t[starts_t])
1324 iylre = append(iylre,1+IY_t[ends_t])
1325 izlr = append(izlr,(layer-1)*ones(len(IX_t[starts_t])))
1326 #
1327 # find right faces and merge y
1328 #
1329 elements = hstack((((array1[:,1:] == False) & (array1[:,:-1] == True)),reshape((array1[:,1] == True),(cad.ny,1))))
1330 starts = vstack((((elements[:-1,:] == True) & (elements[1:,:] == False)),reshape((elements[-1,:] == True),(1,cad.nx))))
1331 ends = vstack((reshape((elements[0,:] == True),(1,cad.nx)),((elements[1:,:] == True) & (elements[:-1,:] == False))))
1332 IY_t = transpose(IY) # for starts and ends to be read in same row
1333 IX_t = transpose(IX)
1334 starts_t = transpose(starts)
1335 ends_t = transpose(ends)
1336 ixlr = append(ixlr,1+IX_t[starts_t])
1337 iylre = append(iylre,IY_t[starts_t])
1338 iylrs = append(iylrs,1+IY_t[ends_t])
1339 izlr = append(izlr,(layer-1)*ones(len(IX_t[starts_t])))
1340 #
1341 # find front faces and merge x
1342 #
1343 elements = vstack((((array1[:-1,:] == True) & (array1[1:,:] == False)),reshape((array1[0,:] == True),(1,cad.nx))))
1344 starts = hstack((reshape((elements[:,0] == True),(cad.ny,1)),((elements[:,1:] == True) & (elements[:,:-1] == False))))
1345 ends = hstack((((elements[:,:-1] == True) & (elements[:,1:] == False)),reshape((elements[:,-1] == True),(cad.ny,1))))
1346 ixfbs = append(ixfbs,IX[starts])
1347 ixfbe = append(ixfbe,1+IX[ends])
1348 iyfb = append(iyfb,IY[starts])
1349 izfb = append(izfb,(layer-1)*ones(len(IX[starts])))
1350 #
1351 # find back faces and merge x
1352 #
1353 elements = vstack((reshape((array1[-1,:] == True),(1,cad.nx)),((array1[1:,:] == True) & (array1[:-1,:] == False))))
1354 starts = hstack((reshape((elements[:,0] == True),(cad.ny,1)),((elements[:,1:] == True) & (elements[:,:-1] == False))))
1355 ends = hstack((((elements[:,:-1] == True) & (elements[:,1:] == False)),reshape((elements[:,-1] == True),(cad.ny,1))))
1356 ixfbe = append(ixfbe,IX[starts])
1357 ixfbs = append(ixfbs,1+IX[ends])
1358 iyfb = append(iyfb,1+IY[starts])
1359 izfb = append(izfb,(layer-1)*ones(len(IX[starts])))
1360 #
1361 # find top faces and merge x
1362 #
1363 elements = ((array2 == False) & (array1 == True))
1364 starts = hstack((reshape((elements[:,0] == True),(cad.ny,1)),((elements[:,1:] == True) & (elements[:,:-1] == False))))
1365 ends = hstack((((elements[:,:-1] == True) & (elements[:,1:] == False)),reshape((elements[:,-1] == True),(cad.ny,1))))
1366 ixtbs = append(ixtbs,IX[starts])
1367 ixtbe = append(ixtbe,1+IX[ends])
1368 iytb = append(iytb,IY[starts])
1369 iztb = append(iztb,layer*ones(len(IX[starts])))
1370 #
1371 # find bottom faces and merge x
1372 #
1373 elements = ((array0 == False) & (array1 == True))
1374 starts = hstack((reshape((elements[:,0] == True),(cad.ny,1)),((elements[:,1:] == True) & (elements[:,:-1] == False))))
1375 ends = hstack((((elements[:,:-1] == True) & (elements[:,1:] == False)),reshape((elements[:,-1] == True),(cad.ny,1))))
1376 ixtbe = append(ixtbe,IX[starts])
1377 ixtbs = append(ixtbs,1+IX[ends])
1378 iytb = append(iytb,IY[starts])
1379 iztb = append(iztb,(layer-1)*ones(len(IX[starts])))
1380 #
1381 # push array stack
1382 #
1383 array0 = array1
1384 array1 = array2
1385 #
1386 # z merge front/back faces
1387 #
1388 index = lexsort(keys=(izfb,ixfbe,ixfbs,iyfb))
1389 merge = (iyfb[index[1:]] == iyfb[index[:-1]]) & \
1390 (ixfbe[index[1:]] == ixfbe[index[:-1]]) & \
1391 (ixfbs[index[1:]] == ixfbs[index[:-1]]) & \
1392 ((izfb[index[1:]] - izfb[index[:-1]]) == 1)
1393 merge = append(False,merge).astype(bool_)
1394 starts = ((merge[1:] == True) & (merge[:-1] == False))
1395 starts = append(starts,False).astype(bool_)
1396 ends = ((merge[1:] == False) & (merge[:-1] == True))
1397 if (merge[-1] == True):
1398 ends = append(ends,True)
1399 else:
1400 ends = append(ends,False)
1401 ends = ends.astype(bool_)
1402 xs = ixfbs[index][starts | ~merge]
1403 xe = ixfbe[index][starts | ~merge]
1404 y = iyfb[index][starts | ~merge]
1405 zs = izfb[index][starts | ~merge]
1406 ze = izfb[index][ends | ~(merge | starts)]+1
1407 cad.x = ravel(transpose(vstack((xs,xe,xs,xs,xe,xe))))
1408 cad.y = ravel(transpose(vstack((y,y,y,y,y,y))))
1409 cad.z = ravel(transpose(vstack((zs,ze,ze,zs,zs,ze))))
1410 #
1411 # z merge left/right faces
1412 #
1413 index = lexsort(keys=(izlr,iylre,iylrs,ixlr))
1414 merge = (ixlr[index[1:]] == ixlr[index[:-1]]) & \
1415 (iylre[index[1:]] == iylre[index[:-1]]) & \
1416 (iylrs[index[1:]] == iylrs[index[:-1]]) & \
1417 ((izlr[index[1:]] - izlr[index[:-1]]) == 1)
1418 merge = append(False,merge).astype(bool_)
1419 starts = ((merge[1:] == True) & (merge[:-1] == False))
1420 starts = append(starts,False).astype(bool_)
1421 ends = ((merge[1:] == False) & (merge[:-1] == True))
1422 if (merge[-1] == True):
1423 ends = append(ends,True)
1424 else:
1425 ends = append(ends,False)
1426 ends = ends.astype(bool_)
1427 x = ixlr[index][starts | ~merge]
1428 ys = iylrs[index][starts | ~merge]
1429 ye = iylre[index][starts | ~merge]
1430 zs = izlr[index][starts | ~merge]
1431 ze = izlr[index][ends | ~(merge | starts)]+1
1432 cad.x = append(cad.x,ravel(transpose(vstack((x,x,x,x,x,x)))))
1433 cad.y = append(cad.y,ravel(transpose(vstack((ys,ye,ys,ys,ye,ye)))))
1434 cad.z = append(cad.z,ravel(transpose(vstack((zs,ze,ze,zs,zs,ze)))))
1435 #
1436 # y merge top/bottom faces
1437 #
1438 index = lexsort(keys=(iytb,ixtbe,ixtbs,iztb))
1439 merge = (iztb[index[1:]] == iztb[index[:-1]]) & \
1440 (ixtbe[index[1:]] == ixtbe[index[:-1]]) & \
1441 (ixtbs[index[1:]] == ixtbs[index[:-1]]) & \
1442 ((iytb[index[1:]] - iytb[index[:-1]]) == 1)
1443 merge = append(False,merge).astype(bool_)
1444 starts = ((merge[1:] == True) & (merge[:-1] == False))
1445 starts = append(starts,False).astype(bool_)
1446 ends = ((merge[1:] == False) & (merge[:-1] == True))
1447 if (merge[-1] == True):
1448 ends = append(ends,True)
1449 else:
1450 ends = append(ends,False)
1451 ends = ends.astype(bool_)
1452 xs = ixtbs[index][starts | ~merge]
1453 xe = ixtbe[index][starts | ~merge]
1454 ys = iytb[index][starts | ~merge]
1455 ye = iytb[index][ends | ~(merge | starts)]+1
1456 z = iztb[index][starts | ~merge]
1457 cad.x = append(cad.x,ravel(transpose(vstack((xs,xe,xs,xs,xe,xe)))))
1458 cad.y = append(cad.y,ravel(transpose(vstack((ys,ye,ye,ys,ys,ye)))))
1459 cad.z = append(cad.z,ravel(transpose(vstack((z,z,z,z,z,z)))))
1460 #
1461 # draw triangulation
1462 #
1463 widget_stop.pack_forget()
1464 string_msg.set("draw ...")
1465 root.update()
1466 N = len(cad.x)
1467 for i in range(0,N,3):
1468 string_msg.set("draw triangle %d/%d"%(i/3,N/3))
1469 root.update()
1470 x0 = cad.nxplot()*(cad.x[i]+0.5)/float(cad.nx)
1471 y0 = cad.nyplot()*(cad.ny-cad.y[i]+0.5)/float(cad.ny)
1472 z0 = cad.nzplot()*(cad.nz-cad.z[i]+0.5)/float(cad.nz)
1473 x1 = cad.nxplot()*(cad.x[i+1]+0.5)/float(cad.nx)
1474 y1 = cad.nyplot()*(cad.ny-cad.y[i+1]+0.5)/float(cad.ny)
1475 z1 = cad.nzplot()*(cad.nz-cad.z[i+1]+0.5)/float(cad.nz)
1476 x2 = cad.nxplot()*(cad.x[i+2]+0.5)/float(cad.nx)
1477 y2 = cad.nyplot()*(cad.ny-cad.y[i+2]+0.5)/float(cad.ny)
1478 z2 = cad.nzplot()*(cad.nz-cad.z[i+2]+0.5)/float(cad.nz)
1479 im.xy_draw.line([x0,y0,x1,y1,x2,y2,x0,y0],fill="black")
1480 im.xz_draw.line([x0,z0,x1,z1,x2,z2,x0,z0],fill="black")
1481 im.yz_draw.line([z0,y0,z1,y1,z2,y2,z0,y0],fill="black")
1482 images.xy = ImageTk.PhotoImage(im.xy)
1483 images.xz = ImageTk.PhotoImage(im.xz)
1484 images.yz = ImageTk.PhotoImage(im.yz)
1485 canvas_xy.create_image(cad.nplot/2,cad.nplot/2,image=images.xy)
1486 canvas_xz.create_image(cad.nplot/2,cad.nplot/2,image=images.xz)
1487 canvas_yz.create_image(cad.nplot/2,cad.nplot/2,image=images.yz)
1488 im.xyz = Image.new("RGBX",(cad.nplot,cad.nplot),'white')
1489 images.xyz = ImageTk.PhotoImage(im.xyz)
1490 canvas_xyz.create_image(cad.nplot/2,cad.nplot/2,image=images.xyz)
1491 string_msg.set("done")
1492 root.update()
1493
1494 def flash(event):
1495 #
1496 # convert to Gerber flashes
1497 #
1498 # evaluate .cad
1499 #
1500 evaluate()
1501 #
1502 # initialize variables
1503 #
1504 render_stop_flag = 0
1505 cad.stop = 0
1506 widget_stop.pack()
1507 delete_windows()
1508 cad.toolpaths = []
1509 cad.zwrite = []
1510 cad.x = zeros(0)
1511 cad.y = zeros(0)
1512 cad.z = zeros(0)
1513 ixs = array([])
1514 ixe = array([])
1515 iy = array([])
1516 iz = array([])
1517 #
1518 # evaluate coordinate arrays
1519 #
1520 (IY,IX) = indices((cad.ny,cad.nx))
1521 IY = IY[::-1,:]
1522 IZ = arange(cad.nz)
1523 X = cad.xmin+(cad.xmax-cad.xmin)*IX/(cad.nx-1.0)
1524 Y = cad.ymin+(cad.ymax-cad.ymin)*IY/(cad.ny-1.0)
1525 if (cad.zwrite == []):
1526 if (cad.nz > 1):
1527 cad.zwrite = cad.zmin + (cad.zmax-cad.zmin)*arange(cad.nz)/(cad.nz-1.0)
1528 else:
1529 cad.zwrite = [cad.zmin]
1530 #
1531 # set up drawing image
1532 #
1533 im.xy = Image.new("RGBX",(cad.nxplot(),cad.nyplot()),'white')
1534 im.xy_draw = ImageDraw.Draw(im.xy)
1535 #
1536 # loop over layers
1537 #
1538 for layer in range(len(cad.zwrite)):
1539 #
1540 # check render stop button
1541 #
1542 if (cad.stop == 1):
1543 break
1544 #
1545 # evaluate layer
1546 #
1547 Z = cad.zwrite[layer]
1548 string_msg.set("convert z = %.3f"%Z)
1549 root.update()
1550 elements = eval(cad.function)
1551 #
1552 # merge x
1553 #
1554 starts = hstack((reshape((elements[:,0] == TRUE),(cad.ny,1)),((elements[:,1:] == TRUE) & (elements[:,:-1] == FALSE))))
1555 ends = hstack((((elements[:,:-1] == TRUE) & (elements[:,1:] == FALSE)),reshape((elements[:,-1] == TRUE),(cad.ny,1))))
1556 ixs = append(ixs,IX[starts])
1557 ixe = append(ixe,1+IX[ends])
1558 iy = append(iy,IY[starts])
1559 iz = append(iz,IZ[layer-1]*ones(len(IX[starts])))
1560 #
1561 # merge y
1562 #
1563 index = lexsort(keys=(iy,ixe,ixs,iz))
1564 merge = (iz[index[1:]] == iz[index[:-1]]) & \
1565 (ixe[index[1:]] == ixe[index[:-1]]) & \
1566 (ixs[index[1:]] == ixs[index[:-1]]) & \
1567 ((iy[index[1:]] - iy[index[:-1]]) == 1)
1568 merge = append(FALSE,merge).astype(bool_)
1569 starts = ((merge[1:] == TRUE) & (merge[:-1] == FALSE))
1570 starts = append(starts,FALSE).astype(bool_)
1571 ends = ((merge[1:] == FALSE) & (merge[:-1] == TRUE))
1572 if (merge[-1] == TRUE):
1573 ends = append(ends,TRUE)
1574 else:
1575 ends = append(ends,FALSE)
1576 ends = ends.astype(bool_)
1577 xs = ixs[index][starts | ~merge]
1578 xe = ixe[index][starts | ~merge]
1579 ys = iy[index][starts | ~merge]
1580 ye = iy[index][ends | ~(merge | starts)]+1
1581 cad.x = ravel(transpose(vstack((xs,xe))))
1582 cad.y = ravel(transpose(vstack((ys,ye))))
1583 #
1584 # draw flashes
1585 #
1586 widget_stop.pack_forget()
1587 cad.view('xy')
1588 string_msg.set("draw ...")
1589 root.update()
1590 N = len(cad.x)
1591 for i in range(0,N,2):
1592 string_msg.set("draw flash %d/%d"%(i/4,N/4))
1593 root.update()
1594 x0 = cad.nxplot()*(cad.x[i]+0.5)/float(cad.nx)
1595 y0 = cad.nyplot()*(cad.ny-cad.y[i]+0.5)/float(cad.ny)
1596 x1 = cad.nxplot()*(cad.x[i]+0.5)/float(cad.nx)
1597 y1 = cad.nyplot()*(cad.ny-cad.y[i+1]+0.5)/float(cad.ny)
1598 x2 = cad.nxplot()*(cad.x[i+1]+0.5)/float(cad.nx)
1599 y2 = cad.nyplot()*(cad.ny-cad.y[i+1]+0.5)/float(cad.ny)
1600 x3 = cad.nxplot()*(cad.x[i+1]+0.5)/float(cad.nx)
1601 y3 = cad.nyplot()*(cad.ny-cad.y[i]+0.5)/float(cad.ny)
1602 im.xy_draw.line([x0,y0,x1,y1,x2,y2,x3,y3,x0,y0],fill="black")
1603 images.xy = ImageTk.PhotoImage(im.xy)
1604 canvas_xy.create_image(cad.nplot/2,cad.nplot/2,image=images.xy)
1605 string_msg.set("done")
1606 root.update()
1607
1608 def select_epi():
1609 input_file_name = string_input_file.get()
1610 string_cam_file.set(input_file_name[0:-4]+'.epi')
1611 cad.cam = 'epi'
1612 cam_pack_forget()
1613 cam_file_frame.pack()
1614 cam_vector_frame.pack()
1615 cam_dia_frame.pack()
1616 cam_contour_frame.pack()
1617 laser_frame1.pack()
1618 if ((cad.nz > 1) | (cad.image_r.size > 1)):
1619 laser_frame2.pack()
1620 laser_frame3.pack()
1621 string_laser_rate.set("2500")
1622 string_laser_power.set("90")
1623 string_laser_speed.set("50")
1624 string_laser_min_power.set("10")
1625 string_laser_max_power.set("100")
1626 string_tool_dia.set("0.01")
1627 root.update()
1628
1629 def select_camm():
1630 input_file_name = string_input_file.get()
1631 string_cam_file.set(input_file_name[0:-4]+'.camm')
1632 cad.cam = 'camm'
1633 cam_pack_forget()
1634 cam_file_frame.pack()
1635 cam_vector_frame.pack()
1636 cam_dia_frame.pack()
1637 cam_contour_frame.pack()
1638 cut_frame.pack()
1639 string_cut_force.set("45")
1640 string_cut_velocity.set("2")
1641 string_tool_dia.set("0.01")
1642 root.update()
1643
1644 def select_ps():
1645 input_file_name = string_input_file.get()
1646 string_cam_file.set(input_file_name[0:-4]+'.ps')
1647 cad.cam = 'ps'
1648 cam_pack_forget()
1649 cam_file_frame.pack()
1650 cam_vector_frame.pack()
1651 cam_dia_frame.pack()
1652 cam_contour_frame.pack()
1653 fill_frame.pack()
1654 string_tool_dia.set("0.0")
1655 root.update()
1656
1657 def select_ord():
1658 input_file_name = string_input_file.get()
1659 string_cam_file.set(input_file_name[0:-4]+'.ord')
1660 cad.cam = 'ord'
1661 cam_pack_forget()
1662 cam_file_frame.pack()
1663 cam_vector_frame.pack()
1664 cam_dia_frame.pack()
1665 cam_contour_frame.pack()
1666 string_tool_dia.set("0.01")
1667 waterjet_frame.pack()
1668 string_lead_in.set("0.05")
1669 string_quality.set("-3")
1670 root.update()
1671
1672 def select_g():
1673 input_file_name = string_input_file.get()
1674 string_cam_file.set(input_file_name[0:-4]+'.gcode')
1675 cad.cam = 'g'
1676 cam_pack_forget()
1677 cam_file_frame.pack()
1678 cam_vector_frame.pack()
1679 string_tool_dia.set("0.0156")
1680 cam_dia_frame.pack()
1681 cam_contour_frame.pack()
1682 string_g_feed_rate.set("20")
1683 string_g_spindle_speed.set("5000")
1684 string_g_tool.set("1")
1685 integer_g_cool.set("0")
1686 g_frame.pack()
1687 root.update()
1688
1689 def select_rml():
1690 input_file_name = string_input_file.get()
1691 string_cam_file.set(input_file_name[0:-4]+'.rml')
1692 cad.cam = 'rml'
1693 cam_pack_forget()
1694 cam_file_frame.pack()
1695 cam_vector_frame.pack()
1696 cam_dia_frame.pack()
1697 cam_contour_frame.pack()
1698 speed_frame.pack()
1699 rml_move_frame.pack()
1700 string_tool_dia.set("0.0156")
1701 string_xy_speed.set("4")
1702 string_z_speed.set("4")
1703 string_rml_x_move.set("1")
1704 string_rml_y_move.set("1")
1705 root.update()
1706
1707 def select_sbp():
1708 input_file_name = string_input_file.get()
1709 string_cam_file.set(input_file_name[0:-4]+'.sbp')
1710 cad.cam = 'sbp'
1711 cam_pack_forget()
1712 cam_file_frame.pack()
1713 cam_vector_frame.pack()
1714 cam_dia_frame.pack()
1715 cam_contour_frame.pack()
1716 jog_frame.pack()
1717 speed_frame.pack()
1718 string_tool_dia.set("0.125")
1719 string_xy_speed.set("1.1")
1720 string_z_speed.set("1.1")
1721 string_jog_xy_speed.set("7")
1722 string_jog_z_speed.set("7")
1723 string_jog_z.set(".25")
1724 root.update()
1725
1726 def select_oms():
1727 input_file_name = string_input_file.get()
1728 string_cam_file.set(input_file_name[0:-4]+'.oms')
1729 cad.cam = 'oms'
1730 cam_pack_forget()
1731 cam_file_frame.pack()
1732 cam_vector_frame.pack()
1733 cam_dia_frame.pack()
1734 cam_contour_frame.pack()
1735 excimer_frame.pack()
1736 string_pulse_period.set("10000")
1737 string_tool_dia.set("0.001")
1738 string_cut_vel.set("0.1")
1739 string_cut_accel.set("5.0")
1740 root.update()
1741
1742 def select_dxf():
1743 input_file_name = string_input_file.get()
1744 string_cam_file.set(input_file_name[0:-4]+'.dxf')
1745 cad.cam = 'dxf'
1746 cam_pack_forget()
1747 cam_file_frame.pack()
1748 cam_vector_frame.pack()
1749 cam_dia_frame.pack()
1750 cam_contour_frame.pack()
1751 string_tool_dia.set("0.0")
1752 root.update()
1753
1754 def select_uni():
1755 input_file_name = string_input_file.get()
1756 string_cam_file.set(input_file_name[0:-4]+'.uni')
1757 cad.cam = 'uni'
1758 cam_pack_forget()
1759 cam_file_frame.pack()
1760 cam_vector_frame.pack()
1761 cam_dia_frame.pack()
1762 cam_contour_frame.pack()
1763 laser_frame1.pack()
1764 if ((cad.nz > 1) | (cad.image_r.size > 1)):
1765 laser_frame2.pack()
1766 string_laser_rate.set("500")
1767 string_laser_power.set("60")
1768 string_laser_speed.set("15")
1769 string_tool_dia.set("0.01")
1770 string_laser_min_power.set("10")
1771 string_laser_max_power.set("100")
1772 string_vector_error.set('1.1')
1773 root.update()
1774
1775 def select_jpg():
1776 input_file_name = string_input_file.get()
1777 string_cam_file.set(input_file_name[0:-4]+'.jpg')
1778 cad.cam = 'jpg'
1779 cam_pack_forget()
1780 cam_file_frame.pack()
1781 root.update()
1782
1783 def select_png():
1784 input_file_name = string_input_file.get()
1785 string_cam_file.set(input_file_name[0:-4]+'.png')
1786 cad.cam = 'png'
1787 cam_pack_forget()
1788 cam_file_frame.pack()
1789 root.update()
1790
1791 def select_stl():
1792 input_file_name = string_input_file.get()
1793 string_cam_file.set(input_file_name[0:-4]+'.stl')
1794 cad.cam = 'stl'
1795 cam_pack_forget()
1796 cam_file_frame.pack()
1797 STL_frame.pack()
1798 root.update()
1799
1800 def select_gerber():
1801 input_file_name = string_input_file.get()
1802 string_cam_file.set(input_file_name[0:-4]+'.grb')
1803 cad.cam = 'grb'
1804 cam_pack_forget()
1805 cam_file_frame.pack()
1806 Gerber_frame.pack()
1807 root.update()
1808
1809 def select_excellon():
1810 input_file_name = string_input_file.get()
1811 string_cam_file.set(input_file_name[0:-4]+'.drl')
1812 cad.cam = 'drl'
1813 cam_pack_forget()
1814 cam_file_frame.pack()
1815 Excellon_frame.pack()
1816 root.update()
1817
1818 def select_ca():
1819 input_file_name = string_input_file.get()
1820 string_cam_file.set(input_file_name[0:-4]+'.ca')
1821 cad.cam = 'ca'
1822 cam_pack_forget()
1823 cam_file_frame.pack()
1824 root.update()
1825
1826 def cam_pack_forget():
1827 cam_file_frame.pack_forget()
1828 cam_vector_frame.pack_forget()
1829 cam_dia_frame.pack_forget()
1830 cam_contour_frame.pack_forget()
1831 laser_frame1.pack_forget()
1832 laser_frame2.pack_forget()
1833 laser_frame3.pack_forget()
1834 cut_frame.pack_forget()
1835 speed_frame.pack_forget()
1836 jog_frame.pack_forget()
1837 rml_move_frame.pack_forget()
1838 waterjet_frame.pack_forget()
1839 excimer_frame.pack_forget()
1840 STL_frame.pack_forget()
1841 Gerber_frame.pack_forget()
1842 Excellon_frame.pack_forget()
1843 fill_frame.pack_forget()
1844 g_frame.pack_forget()
1845 send_to_frame.pack_forget()
1846
1847 def save_cam(event):
1848 #
1849 # write toolpath
1850 #
1851 if (cad.cam == "epi"):
1852 write_epi()
1853 elif (cad.cam == "camm"):
1854 write_camm()
1855 elif (cad.cam == "ps"):
1856 write_ps()
1857 elif (cad.cam == "ord"):
1858 write_ord()
1859 elif (cad.cam == "g"):
1860 write_G()
1861 elif (cad.cam == "rml"):
1862 write_rml()
1863 elif (cad.cam == "sbp"):
1864 write_sbp()
1865 elif (cad.cam == "oms"):
1866 write_oms()
1867 elif (cad.cam == "dxf"):
1868 write_dxf()
1869 elif (cad.cam == "uni"):
1870 write_uni()
1871 elif (cad.cam == "jpg"):
1872 write_jpg()
1873 elif (cad.cam == "png"):
1874 write_png()
1875 elif (cad.cam == "stl"):
1876 write_stl()
1877 elif (cad.cam == "grb"):
1878 write_gerber()
1879 elif (cad.cam == "drl"):
1880 write_excellon()
1881 elif (cad.cam == "ca"):
1882 write_ca()
1883 else:
1884 string_msg.set("unsupported output file format")
1885 root.update()
1886
1887 def write_epi():
1888 #
1889 # Epilog lasercutter output
1890 # todo: try 1200 DPI
1891 #
1892 units = 600*cad.inches_per_unit
1893 filename = string_cam_file.get()
1894 file = open(filename, 'wb')
1895 if (integer_laser_autofocus.get() == 0):
1896 #
1897 # init with autofocus off
1898 #
1899 file.write("%-12345X@PJL JOB NAME="+string_cam_file.get()+"\r\nE@PJL ENTER LANGUAGE=PCL\r\n&y0A&l0U&l0Z&u600D*p0X*p0Y*t600R*r0F&y50P&z50S*r6600T*r5100S*r1A*rC%1BIN;XR"+string_laser_rate.get()+";YP"+string_laser_power.get()+";ZS"+string_laser_speed.get()+";")
1900 else:
1901 #
1902 # init with autofocus on
1903 #
1904 file.write("%-12345X@PJL JOB NAME="+string_cam_file.get()+"\r\nE@PJL ENTER LANGUAGE=PCL\r\n&y1A&l0U&l0Z&u600D*p0X*p0Y*t600R*r0F&y50P&z50S*r6600T*r5100S*r1A*rC%1BIN;XR"+string_laser_rate.get()+";YP"+string_laser_power.get()+";ZS"+string_laser_speed.get()+";")
1905 power = float(string_laser_power.get())
1906 min_power = float(string_laser_min_power.get())
1907 max_power = float(string_laser_max_power.get())
1908 for layer in range(len(cad.toolpaths)):
1909 if ((len(cad.zwrite) > 1) & (len(cad.toolpaths[layer]) > 0)):
1910 fraction = (cad.zwrite[layer]-cad.zwrite[0])/(cad.zwrite[-1]-cad.zwrite[0])
1911 layer_power = min_power + fraction*(max_power-min_power)
1912 file.write("YP%f;"%layer_power)
1913 for segment in range(len(cad.toolpaths[layer])):
1914 x = int(units*(cad.xmin + (cad.xmax-cad.xmin)*(cad.toolpaths[layer][segment][0].x+0.5)/float(cad.nx)))
1915 y = int(units*(-cad.ymin - ((cad.ymax-cad.ymin)*((cad.ny-cad.toolpaths[layer][segment][0].y)+0.5)/float(cad.ny))))
1916 file.write("PU"+str(x)+","+str(y)+";")
1917 for vertex in range(1,len(cad.toolpaths[layer][segment])):
1918 x = int(units*(cad.xmin + (cad.xmax-cad.xmin)*(cad.toolpaths[layer][segment][vertex].x+0.5)/float(cad.nx)))
1919 y = int(units*(-cad.ymin - ((cad.ymax-cad.ymin)*((cad.ny-cad.toolpaths[layer][segment][vertex].y)+0.5)/float(cad.ny))))
1920 file.write("PD"+str(x)+","+str(y)+";")
1921 file.write("%0B%1BPUE%-12345X@PJL EOJ \r\n")
1922 file.close()
1923 draw_toolpath()
1924 string_msg.set("wrote %s"%filename)
1925 root.update()
1926
1927 def write_camm():
1928 filename = string_cam_file.get()
1929 file = open(filename, 'wb')
1930 units = 1016*cad.inches_per_unit
1931 file.write("PA;PA;!ST1;!FS"+string_cut_force.get()+";VS"+string_cut_velocity.get()+";")
1932 for layer in range(len(cad.toolpaths)):
1933 for segment in range(len(cad.toolpaths[layer])):
1934 x = int(units*(cad.xmin + (cad.xmax-cad.xmin)*(cad.toolpaths[layer][segment][0].x+0.5)/float(cad.nx)))
1935 y = int(units*(cad.ymin + (cad.ymax-cad.ymin)*((cad.ny-cad.toolpaths[layer][segment][0].y)+0.5)/float(cad.ny)))
1936 file.write("PU"+str(x)+","+str(y)+";")
1937 for vertex in range(1,len(cad.toolpaths[layer][segment])):
1938 x = int(units*(cad.xmin + (cad.xmax-cad.xmin)*(cad.toolpaths[layer][segment][vertex].x+0.5)/float(cad.nx)))
1939 y = int(units*(cad.ymin + (cad.ymax-cad.ymin)*((cad.ny-cad.toolpaths[layer][segment][vertex].y)+0.5)/float(cad.ny)))
1940 file.write("PD"+str(x)+","+str(y)+";")
1941 file.write("PU0,0;")
1942 file.close()
1943 draw_toolpath()
1944 string_msg.set("wrote %s"%filename)
1945 root.update()
1946
1947 def write_ps():
1948 #
1949 # Postscript output
1950 #
1951 units = cad.inches_per_unit
1952 filename = string_cam_file.get()
1953 file = open(filename, 'wb')
1954 file.write("%! cad.py output\n")
1955 file.write("%%%%BoundingBox: 0 0 %.3f %.3f\n"%
1956 (72.0*(cad.xmax-cad.xmin),72.0*(cad.ymax-cad.ymin)))
1957 file.write("/m {moveto} def\n")
1958 file.write("/l {lineto} def\n")
1959 file.write("72 72 scale\n")
1960 file.write(".005 setlinewidth\n")
1961 file.write("%f %f translate\n"%(0.5,0.5))
1962 for layer in range(len(cad.toolpaths)):
1963 for segment in range(len(cad.toolpaths[layer])):
1964 x = units*(cad.xmin + (cad.xmax-cad.xmin)*(cad.toolpaths[layer][segment][0].x+0.5)/float(cad.nx))
1965 y = units*(cad.ymin + (cad.ymax-cad.ymin)*((cad.ny-cad.toolpaths[layer][segment][0].y)+0.5)/float(cad.ny))
1966 file.write("%f %f m\n"%(x,y))
1967 for vertex in range(1,len(cad.toolpaths[layer][segment])):
1968 x = units*(cad.xmin + (cad.xmax-cad.xmin)*(cad.toolpaths[layer][segment][vertex].x+0.5)/float(cad.nx))
1969 y = units*(cad.ymin + (cad.ymax-cad.ymin)*((cad.ny-cad.toolpaths[layer][segment][vertex].y)+0.5)/float(cad.ny))
1970 file.write("%f %f l\n"%(x,y))
1971 if (integer_fill.get() == 0):
1972 file.write("stroke\n")
1973 else:
1974 file.write("fill\n")
1975 file.write("showpage\n")
1976 file.close()
1977 draw_toolpath()
1978 string_msg.set("wrote %s"%filename)
1979 root.update()
1980
1981 def write_ord():
1982 #
1983 # OMAX waterjet output
1984 #
1985 units = cad.inches_per_unit
1986 lead_in = float(string_lead_in.get())
1987 quality = int(string_quality.get())
1988 filename = string_cam_file.get()
1989 file = open(filename, 'wb')
1990 xlead = []
1991 ylead = []
1992 for layer in range(len(cad.toolpaths)):
1993 for segment in range(len(cad.toolpaths[layer])):
1994 #
1995 # calculate and write lead-in
1996 #
1997 x0 = units*(cad.xmin + (cad.xmax-cad.xmin)*(cad.toolpaths[layer][segment][0].x+0.5)/float(cad.nx))
1998 y0 = units*(cad.ymin + (cad.ymax-cad.ymin)*((cad.ny-cad.toolpaths[layer][segment][0].y)+0.5)/float(cad.ny))
1999 x1 = units*(cad.xmin + (cad.xmax-cad.xmin)*(cad.toolpaths[layer][segment][1].x+0.5)/float(cad.nx))
2000 y1 = units*(cad.ymin + (cad.ymax-cad.ymin)*((cad.ny-cad.toolpaths[layer][segment][1].y)+0.5)/float(cad.ny))
2001 dx = x1 - x0
2002 dy = y1 - y0
2003 norm_x = -dy
2004 norm_y = dx
2005 norm = sqrt(norm_x**2 + norm_y**2)
2006 norm_x = norm_x/norm
2007 norm_y = norm_y/norm
2008 xlead.append(x0 + norm_x*lead_in)
2009 ylead.append(y0 + norm_y*lead_in)
2010 file.write("%f, %f, 0, %d\n"%(xlead[segment],ylead[segment],quality))
2011 #
2012 # loop over segment
2013 #
2014 for vertex in range(len(cad.toolpaths[layer][segment])):
2015 x = units*(cad.xmin + (cad.xmax-cad.xmin)*(cad.toolpaths[layer][segment][vertex].x+0.5)/float(cad.nx))
2016 y = units*(cad.ymin + (cad.ymax-cad.ymin)*((cad.ny-cad.toolpaths[layer][segment][vertex].y)+0.5)/float(cad.ny))
2017 file.write("%f, %f, 0, %d\n"%(x,y,quality))
2018 #
2019 # write lead-out
2020 #
2021 file.write("%f, %f, 0, 0\n"%(x0,y0))
2022 file.write("%f, %f, 0, 0\n"%(xlead[segment],ylead[segment]))
2023 file.close()
2024 #
2025 # draw toolpath with lead-in/out
2026 #
2027 im.xy = Image.new("RGBX",(cad.nxplot(),cad.nyplot()),'white')
2028 im.xy_draw = ImageDraw.Draw(im.xy)
2029 for layer in range(len(cad.toolpaths)):
2030 for segment in range(len(cad.toolpaths[layer])):
2031 x = cad.nxplot()*(cad.toolpaths[layer][segment][0].x+0.5)/float(cad.nx)
2032 y = cad.nyplot()*(cad.toolpaths[layer][segment][0].y+0.5)/float(cad.ny)
2033 xl = cad.nxplot()*(xlead[segment]-cad.xmin)/(cad.xmax-cad.xmin)
2034 yl = cad.nyplot()-cad.nyplot()*(ylead[segment]-cad.ymin)/(cad.ymax-cad.ymin)
2035 im.xy_draw.line([xl,yl,x,y],fill="black")
2036 for vertex in range(1,len(cad.toolpaths[layer][segment])):
2037 xnew = cad.nxplot()*(cad.toolpaths[layer][segment][vertex].x+0.5)/float(cad.nx)
2038 ynew = cad.nyplot()*(cad.toolpaths[layer][segment][vertex].y+0.5)/float(cad.ny)
2039 im.xy_draw.line([x,y,xnew,ynew],fill="black")
2040 x = xnew
2041 y = ynew
2042 images.xy = ImageTk.PhotoImage(im.xy)
2043 canvas_xy.create_image(cad.nplot/2,cad.nplot/2,image=images.xy)
2044 string_msg.set("wrote %s"%filename)
2045 root.update()
2046
2047 def distance(x1, y1, x2, y2):
2048 return sqrt((x1-x2)**2+(y1-y2)**2)
2049
2050 def write_G():
2051 #
2052 # G code output
2053 #
2054 units = cad.inches_per_unit
2055 zup = units*cad.zmax
2056 feed_rate = float(string_g_feed_rate.get())
2057 spindle_speed = float(string_g_spindle_speed.get())
2058 coolant = integer_g_cool.get()
2059 tool = int(string_g_tool.get())
2060 if (cad.nz == 1):
2061 cad.zwrite = [cad.zmin]
2062 filename = string_cam_file.get()
2063 file = open(filename, 'wb')
2064 file.write("""(---------------------------------------------------------------)
2065 (---------------------------------------------------------------)
2066 (Start of sheet header)
2067 G21 (metric ftw)
2068 G90 (absolute mode)
2069 G92 X0 Y0 Z0 (zero all axes)
2070 G92 Z0.00 F150.00 (go up to printing level)
2071 M106 (pen down)
2072 G4 P120 (wait 120ms)
2073 M300 S50 (pen up)
2074 G4 P120 (wait 120ms)
2075 M18 (disengage drives)
2076 M01 (Was registration test successful?)
2077 (while drives are disengaged, adjustments can be made to position)
2078 M17 (engage drives if YES, and continue)
2079 (End of sheet header)\n""")
2080 dxy = 0
2081 dz = 0
2082 xold = 0
2083 yold = 0
2084 for layer in range(len(cad.zwrite)-1,-1,-1):
2085 zdown = units*cad.zwrite[layer]
2086 #
2087 # follow toolpaths CCW, for CW tool motion
2088 #
2089 unsorted_segments = cad.toolpaths[layer]
2090 sorted_segments = []
2091 if len(unsorted_segments) > 0:
2092 sorted_segments.append(unsorted_segments.pop(0)) #starts with the first path in the list
2093 else:
2094 print "empty path --- strange"
2095
2096 while len(unsorted_segments) > 0:
2097 #find closest start to the the last sorted segment start
2098 min_dist = 99999
2099 min_dist_index = None
2100 for i in range(len(unsorted_segments)):
2101 dist = distance(sorted_segments[-1][0].x, sorted_segments[-1][0].y,
2102 unsorted_segments[i][0].x, unsorted_segments[i][0].y)
2103 if dist < min_dist:
2104 min_dist = dist
2105 min_dist_index = i
2106
2107 #print "min_dist: %d index: %d" % (min_dist, min_dist_index)
2108 sorted_segments.append(unsorted_segments.pop(min_dist_index))
2109
2110 for segment in range(len(sorted_segments)):
2111
2112 x = units*(cad.xmin + (cad.xmax-cad.xmin)*(sorted_segments[segment][0].x+0.5)/float(cad.nx))
2113 y = units*(cad.ymin + (cad.ymax-cad.ymin)*((cad.ny-sorted_segments[segment][0].y)+0.5)/float(cad.ny))
2114 file.write("G1 X%0.4f "%x+"Y%0.4f "%y+"Z%0.4f"%zup+" F2000.00\n") # rapid motion
2115 file.write("G1 Z%0.4f "%zdown+" F300.00\n") # linear motion
2116 dxy += sqrt((xold-x)**2+(yold-y)**2)
2117 xold = x
2118 yold = y
2119 dz += zup-zdown
2120 for vertex in range(1,len(sorted_segments[segment])):
2121 x = units*(cad.xmin + (cad.xmax-cad.xmin)*(sorted_segments[segment][vertex].x+0.5)/float(cad.nx))
2122 y = units*(cad.ymin + (cad.ymax-cad.ymin)*((cad.ny-sorted_segments[segment][vertex].y)+0.5)/float(cad.ny))
2123 file.write("G1 X%0.4f "%x+"Y%0.4f"%y+" F2000.00\n")
2124 dxy += sqrt((xold-x)**2+(yold-y)**2)
2125 xold = x
2126 yold = y
2127 file.write("""(Start of sheet footer.)
2128 M107
2129 G4 P120 (wait 120ms)
2130 G0 X0 Y0 Z15 F3500.00 (go to position for retrieving platform -- increase Z to Z25 or similar if you have trouble avoiding tool)
2131 G4 P300 (wait 300ms)
2132 M01 (Have you retrieved the print?)
2133 (machine halts until 'okay')
2134 G4 P120 (if yes continue, pause 120ms before ... )
2135 G0 Z0 F3500.00 (return to start position of current sheet)
2136 G4 P300 (wait 300ms)
2137 M18 (disengage drives)
2138 (End of sheet footer)
2139
2140 M01 (Printing on the next sheet?)
2141 (yes, if dropping the default .1 mm to next sheet; no, if you will print again on same sheet)
2142 G0 Z-0.10 F3500.00 (drop 0.1mm to next sheet)
2143
2144 (Paste in further sheets below)
2145 (---------------------------------------------------------------)
2146 (---------------------------------------------------------------)
2147 """)
2148 file.close()
2149 print "Path length: %f" % dxy
2150 time = (dxy/feed_rate + dz/feed_rate)
2151 string_send_to_time.set(" estimated time: %.1f minutes"%time)
2152 draw_toolpath()
2153 string_msg.set("wrote %s"%filename)
2154 root.update()
2155
2156 def write_rml():
2157 #
2158 # Roland Modela output
2159 #
2160 units = 1016*cad.inches_per_unit # 40/mm
2161 filename = string_cam_file.get()
2162 file = open(filename, 'wb')
2163 file.write("PA;PA;VS"+string_xy_speed.get()+";!VZ"+string_z_speed.get()+";!MC1;")
2164 zup = cad.zmax
2165 izup = int(units*zup)
2166 if (cad.nz == 1):
2167 cad.zwrite = [cad.zmin]
2168 xy_speed = float(string_xy_speed.get()) # mm/s
2169 z_speed = float(string_z_speed.get()) # mm/s
2170 dxy = 0
2171 dz = 0
2172 xold = 0
2173 yold = 0
2174 for layer in range(len(cad.zwrite)-1,-1,-1):
2175 zdown = cad.zwrite[layer]
2176 izdown = int(units*zdown)
2177 file.write("!PZ"+str(izdown)+","+str(izup)+";")
2178 #
2179 # follow toolpaths CCW, for CW tool motion
2180 #
2181 for segment in range(len(cad.toolpaths[layer])):
2182 x = int(units*(cad.xmin + (cad.xmax-cad.xmin)*(cad.toolpaths[layer][segment][0].x+0.5)/float(cad.nx)))
2183 y = int(units*(cad.ymin + (cad.ymax-cad.ymin)*((cad.ny-cad.toolpaths[layer][segment][0].y)+0.5)/float(cad.ny)))
2184 file.write("PU"+str(x)+","+str(y)+";")
2185 dxy += sqrt((xold-x)**2+(yold-y)**2)
2186 xold = x
2187 yold = y
2188 dz += izup-izdown
2189 for vertex in range(1,len(cad.toolpaths[layer][segment])):
2190 x = int(units*(cad.xmin + (cad.xmax-cad.xmin)*(cad.toolpaths[layer][segment][vertex].x+0.5)/float(cad.nx)))
2191 y = int(units*(cad.ymin + (cad.ymax-cad.ymin)*((cad.ny-cad.toolpaths[layer][segment][vertex].y)+0.5)/float(cad.ny)))
2192 file.write("PD"+str(x)+","+str(y)+";")
2193 dxy += sqrt((xold-x)**2+(yold-y)**2)
2194 xold = x
2195 yold = y
2196 file.write("PU"+str(x)+","+str(y)+";!MC0;")
2197 #
2198 # file padding hack for end-of-file buffering problems
2199 #
2200 for i in range(1000):
2201 file.write("!MC0;")
2202 file.close()
2203 time = ((dxy/40.0)/xy_speed + (dz/40.0)/z_speed)/60.0
2204 string_send_to_time.set(" estimated time: %.1f minutes"%time)
2205 draw_toolpath()
2206 string_msg.set("wrote %s"%filename)
2207 root.update()
2208
2209 def rml_move(event):
2210 #
2211 # move Roland Modela
2212 #
2213 units = 1016*cad.inches_per_unit # 40/mm
2214 x = float(string_rml_x_move.get())
2215 y = float(string_rml_y_move.get())
2216 ix = int(units*x)
2217 iy = int(units*y)
2218 filename = "move.rml"
2219 file = open(filename, 'wb')
2220 file.write("PA;PA;!PZ0,400;VS10;!VZ10;!MC0;PU%d,%d;!MC0;"%(ix,iy))
2221 file.close()
2222 send_to_file("move.rml")
2223 os.remove("move.rml")
2224
2225 def write_sbp():
2226 #
2227 # ShopBot output
2228 #
2229 units = cad.inches_per_unit
2230 filename = string_cam_file.get()
2231 file = open(filename, 'wb')
2232 file.write("SA\r\n") # set to absolute distances
2233 file.write("SO,1,1\r\n") # set output number 1 to on
2234 file.write("pause 2\r\n") # let spindle come up to speed
2235 xy_speed = units*float(string_xy_speed.get())
2236 z_speed = units*float(string_z_speed.get())
2237 file.write("MS %f,%f\r\n"%(xy_speed,z_speed)) # set xy,z speed
2238 jog_xy_speed = units*float(string_jog_xy_speed.get())
2239 jog_z_speed = units*float(string_jog_z_speed.get())
2240 file.write("JS %f,%f\r\n"%(jog_xy_speed,jog_z_speed)) # set jog xy,z speed
2241 zup = units*float(string_jog_z.get())
2242 dxy = 0
2243 dz = 0
2244 xold = 0
2245 yold = 0
2246 for layer in range(len(cad.zwrite)-1,-1,-1):
2247 zdown = cad.zwrite[layer]
2248 #
2249 # follow toolpaths CCW, for CW tool motion
2250 #
2251 for segment in range(len(cad.toolpaths[layer])):
2252 x = units*(cad.xmin + (cad.xmax-cad.xmin)*(cad.toolpaths[layer][segment][0].x+0.5)/float(cad.nx))
2253 y = units*(cad.ymin + (cad.ymax-cad.ymin)*((cad.ny-cad.toolpaths[layer][segment][0].y)+0.5)/float(cad.ny))
2254 file.write("JZ %f\r\n"%zup)
2255 file.write("J2 %f,%f\r\n"%(x,y))
2256 file.write("MZ %f\r\n"%zdown)
2257 dxy += sqrt((xold-x)**2+(yold-y)**2)
2258 xold = x
2259 yold = y
2260 dz += zup-zdown
2261 for vertex in range(1,len(cad.toolpaths[layer][segment])):
2262 x = units*(cad.xmin + (cad.xmax-cad.xmin)*(cad.toolpaths[layer][segment][vertex].x+0.5)/float(cad.nx))
2263 y = units*(cad.ymin + (cad.ymax-cad.ymin)*((cad.ny-cad.toolpaths[layer][segment][vertex].y)+0.5)/float(cad.ny))
2264 file.write("M2 %f,%f\r\n"%(x,y))
2265 dxy += sqrt((xold-x)**2+(yold-y)**2)
2266 xold = x
2267 yold = y
2268 file.write("JZ %f\r\n"%zup)
2269 file.close()
2270 time = (dxy/xy_speed + dz/z_speed)/60.0
2271 string_send_to_time.set(" estimated time: %.1f minutes"%time)
2272 draw_toolpath()
2273 string_msg.set("wrote %s"%filename)
2274 root.update()
2275
2276 def write_oms():
2277 #
2278 # Resonetics excimer micromachining center output
2279 #
2280 units = 25.4*cad.inches_per_unit
2281 pulseperiod = float(string_pulse_period.get())
2282 cutvel = float(string_cut_vel.get())
2283 cutaccel = float(string_cut_accel.get())
2284 slewvel = 1
2285 slewaccel = 5
2286 settle = 100
2287 filename = string_cam_file.get()
2288 file = open(filename, 'wb')
2289 file.write("AA LP0,0,0,0,0\n") # set origin
2290 file.write("PP%d\n"%pulseperiod) # set pulse period
2291 for layer in range(len(cad.toolpaths)):
2292 for segment in range(len(cad.toolpaths[layer])):
2293 x = units*(cad.xmin + (cad.xmax-cad.xmin)*(cad.toolpaths[layer][segment][0].x+0.5)/float(cad.nx))
2294 y = units*(cad.ymin + (cad.ymax-cad.ymin)*((cad.ny-cad.toolpaths[layer][segment][0].y)+0.5)/float(cad.ny))
2295 file.write("VL%.1f,%.1f\n"%(slewvel,slewvel))
2296 file.write("AC%.1f,%.1f\n"%(slewaccel,slewaccel))
2297 file.write("MA%f,%f\n"%(x,y))
2298 file.write("VL%.1f,%.1f\n"%(cutvel,cutvel))
2299 file.write("AC%.1f,%.1f\n"%(cutaccel,cutaccel))
2300 file.write("WT%d\n"%settle) # wait to settle
2301 for vertex in range(1,len(cad.toolpaths[layer][segment])):
2302 x = units*(cad.xmin + (cad.xmax-cad.xmin)*(cad.toolpaths[layer][segment][vertex].x+0.5)/float(cad.nx))
2303 y = units*(cad.ymin + (cad.ymax-cad.ymin)*((cad.ny-cad.toolpaths[layer][segment][vertex].y)+0.5)/float(cad.ny))
2304 file.write("CutAbs %f,%f\n"%(x,y))
2305 file.write("END\n")
2306 file.close()
2307 draw_toolpath()
2308 string_msg.set("wrote %s"%filename)
2309 root.update()
2310
2311 def write_dxf():
2312 #
2313 # DXF output
2314 #
2315 units = cad.inches_per_unit
2316 filename = string_cam_file.get()
2317 file = open(filename, 'wb')
2318 file.write("999\nDXF written by cad.py\n")
2319 file.write("0\nSECTION\n")
2320 file.write("2\nHEADER\n")
2321 file.write("9\n$EXTMIN\n")
2322 file.write("10\n%f\n"%cad.xmin)
2323 file.write("20\n%f\n"%cad.ymin)
2324 file.write("9\n$EXTMAX\n")
2325 file.write("10\n%f\n"%cad.xmax)
2326 file.write("20\n%f\n"%cad.ymax)
2327 file.write("0\nENDSEC\n")
2328 file.write("0\nSECTION\n")
2329 file.write("2\nTABLES\n")
2330 file.write("0\nTABLE\n")
2331 file.write("2\nLTYPE\n70\n1\n")
2332 file.write("0\nLTYPE\n")
2333 file.write("2\nCONTINUOUS\n")
2334 file.write("70\n64\n3\n")
2335 file.write("Solid line\n")
2336 file.write("72\n65\n73\n0\n40\n0.000000\n")
2337 file.write("0\nENDTAB\n")
2338 file.write("0\nTABLE\n2\nLAYER\n70\n1\n")
2339 file.write("0\nLAYER\n2\ndefault\n70\n64\n62\n7\n6\n")
2340 file.write("CONTINUOUS\n0\nENDTAB\n")
2341 file.write("0\nENDSEC\n")
2342 file.write("0\nSECTION\n")
2343 file.write("2\nBLOCKS\n")
2344 file.write("0\nENDSEC\n")
2345 file.write("0\nSECTION\n")
2346 file.write("2\nENTITIES\n")
2347 for layer in range(len(cad.toolpaths)):
2348 for segment in range(len(cad.toolpaths[layer])):
2349 for vertex in range(1,len(cad.toolpaths[layer][segment])):
2350 x0 = units*(cad.xmin + (cad.xmax-cad.xmin)*(cad.toolpaths[layer][segment][vertex-1].x+0.5)/float(cad.nx))
2351 y0 = units*(cad.ymin + (cad.ymax-cad.ymin)*((cad.ny-cad.toolpaths[layer][segment][vertex-1].y)+0.5)/float(cad.ny))
2352 x1 = units*(cad.xmin + (cad.xmax-cad.xmin)*(cad.toolpaths[layer][segment][vertex].x+0.5)/float(cad.nx))
2353 y1 = units*(cad.ymin + (cad.ymax-cad.ymin)*((cad.ny-cad.toolpaths[layer][segment][vertex].y)+0.5)/float(cad.ny))
2354 file.write("0\nLINE\n")
2355 file.write("10\n%f\n"%x0)
2356 file.write("20\n%f\n"%y0)
2357 file.write("11\n%f\n"%x1)
2358 file.write("21\n%f\n"%y1)
2359 file.write("0\nENDSEC\n")
2360 file.write("0\nEOF\n")
2361 file.close()
2362 draw_toolpath()
2363 string_msg.set("wrote %s"%filename)
2364 root.update()
2365
2366 def write_uni():
2367 #
2368 # Universal lasercutter output
2369 #
2370 units = 1000*cad.inches_per_unit
2371 filename = string_cam_file.get()
2372 file = open(filename, 'wb')
2373 file.write("Z") # initialize
2374 file.write("t%s~;"%filename) # title
2375 file.write("IN;DF;PS0;DT~") # initialize
2376 ppibyte = int(float(string_laser_rate.get())/10)
2377 file.write("s%c"%ppibyte) # PPI
2378 speed_hibyte = int(648*float(string_laser_speed.get()))/256
2379 speed_lobyte = int(648*float(string_laser_speed.get()))%256
2380 file.write("v%c%c"%(speed_hibyte,speed_lobyte)) # speed
2381 power = float(string_laser_power.get())
2382 min_power = float(string_laser_min_power.get())
2383 max_power = float(string_laser_max_power.get())
2384 power_hibyte = (320*int(power))/256
2385 power_lobyte = (320*int(power))%256
2386 file.write("p%c%c"%(power_hibyte,power_lobyte)) # power
2387 file.write("a%c"%2) # air assist on high
2388 for layer in range(len(cad.toolpaths)):
2389 if ((len(cad.zwrite) > 1) & (len(cad.toolpaths[layer]) > 0)):
2390 fraction = (cad.zwrite[layer]-cad.zwrite[0])/(cad.zwrite[-1]-cad.zwrite[0])
2391 layer_power = min_power + fraction*(max_power-min_power)
2392 power_hibyte = (320*int(layer_power))/256
2393 power_lobyte = (320*int(layer_power))%256
2394 file.write("p%c%c"%(power_hibyte,power_lobyte)) # power
2395 for segment in range(len(cad.toolpaths[layer])):
2396 x = int(units*(cad.xmin + (cad.xmax-cad.xmin)*(cad.toolpaths[layer][segment][0].x+0.5)/float(cad.nx)))
2397 y = int(units*(cad.ymin + ((cad.ymax-cad.ymin)*((cad.ny-cad.toolpaths[layer][segment][0].y)+0.5)/float(cad.ny))))
2398 file.write("PU;PA"+str(x)+","+str(y)+";PD;")
2399 for vertex in range(1,len(cad.toolpaths[layer][segment])):
2400 x = int(units*(cad.xmin + (cad.xmax-cad.xmin)*(cad.toolpaths[layer][segment][vertex].x+0.5)/float(cad.nx)))
2401 y = int(units*(cad.ymin + ((cad.ymax-cad.ymin)*((cad.ny-cad.toolpaths[layer][segment][vertex].y)+0.5)/float(cad.ny))))
2402 file.write("PA"+str(x)+","+str(y)+";")
2403 file.write("e") # end of file
2404 file.close()
2405 draw_toolpath()
2406 string_msg.set("wrote %s"%filename)
2407 root.update()
2408
2409 def write_jpg():
2410 #
2411 # JPG image output
2412 #
2413 if (cad.views == "xy"):
2414 filename = string_cam_file.get()
2415 im.xy = Image.fromarray(im.intensity_xy,mode="RGBX")
2416 im_rgb_xy = im.xy.convert("RGB")
2417 dpi = int(cad.nx/float(cad.xmax-cad.xmin))
2418 im_rgb_xy.save(filename,dpi=(dpi,dpi))
2419 string_msg.set("wrote %s"%filename)
2420 elif (cad.views == "xyzr"):
2421 border = 5
2422 filename = string_cam_file.get()
2423 im.xy = Image.fromarray(im.intensity_xy,mode="RGBX")
2424 im.xz = Image.fromarray(im.intensity_xz,mode="RGBX")
2425 im.yz = Image.fromarray(im.intensity_yz,mode="RGBX")
2426 im.yz = im.yz.transpose(Image.FLIP_LEFT_RIGHT)
2427 im.xyz = Image.fromarray(im.intensity_xyz,mode="RGBX")
2428 (nx,ny) = im.xy.size
2429 ny = (nx*cad.nyplot())/cad.nxplot()
2430 nz = (nx*cad.nzplot())/cad.nxplot()
2431 im.xy = im.xy.resize((nx,ny))
2432 im.yz = im.yz.resize((nz,ny))
2433 im.xz = im.xz.resize((nx,nz))
2434 im.xyz = im.xyz.resize((nx,ny))
2435 im_rgb_xy = im.xy.convert("RGB")
2436 im_rgb_xz = im.xz.convert("RGB")
2437 im_rgb_yz = im.yz.convert("RGB")
2438 im_rgb_xyz = im.xyz.convert("RGB")
2439 img = Image.new("RGB",(nx+border+nx,ny+border+ny),"white")
2440 img.paste(im_rgb_xy,(0,0))
2441 img.paste(im_rgb_xz,(0,border+ny))
2442 img.paste(im_rgb_yz,(border+nx,0))
2443 img.paste(im_rgb_xyz,(border+nx,border+ny))
2444 img.save(filename)
2445 string_msg.set("wrote %s"%filename)
2446 else:
2447 string_msg.set("unknown view")
2448
2449 def write_png():
2450 #
2451 # PNG image output
2452 #
2453 if (cad.views == "xy"):
2454 filename = string_cam_file.get()
2455 im.xy = Image.fromarray(im.intensity_xy,mode="RGBX")
2456 im_rgb_xy = im.xy.convert("RGB")
2457 dpi = int(cad.nx/float(cad.xmax-cad.xmin))
2458 im_rgb_xy.save(filename,dpi=(dpi,dpi))
2459 string_msg.set("wrote %s"%filename)
2460 elif (cad.views == "xyzr"):
2461 border = 5
2462 filename = string_cam_file.get()
2463 im.xy = Image.fromarray(im.intensity_xy,mode="RGBX")
2464 im.xz = Image.fromarray(im.intensity_xz,mode="RGBX")
2465 im.yz = Image.fromarray(im.intensity_yz,mode="RGBX")
2466 im.yz = im.yz.transpose(Image.FLIP_LEFT_RIGHT)
2467 im.xyz = Image.fromarray(im.intensity_xyz,mode="RGBX")
2468 (nx,ny) = im.xy.size
2469 ny = (nx*cad.nyplot())/cad.nxplot()
2470 nz = (nx*cad.nzplot())/cad.nxplot()
2471 im.xy = im.xy.resize((nx,ny))
2472 im.yz = im.yz.resize((nz,ny))
2473 im.xz = im.xz.resize((nx,nz))
2474 im.xyz = im.xyz.resize((nx,ny))
2475 im_rgb_xy = im.xy.convert("RGB")
2476 im_rgb_xz = im.xz.convert("RGB")
2477 im_rgb_yz = im.yz.convert("RGB")
2478 im_rgb_xyz = im.xyz.convert("RGB")
2479 img = Image.new("RGB",(nx+border+nx,ny+border+ny),"white")
2480 img.paste(im_rgb_xy,(0,0))
2481 img.paste(im_rgb_xz,(0,border+ny))
2482 img.paste(im_rgb_yz,(border+nx,0))
2483 img.paste(im_rgb_xyz,(border+nx,border+ny))
2484 img.save(filename)
2485 string_msg.set("wrote %s"%filename)
2486 else:
2487 string_msg.set("unknown view")
2488
2489 def write_stl():
2490 #
2491 # STL output
2492 #
2493 filename = string_cam_file.get()
2494 file = open(filename, 'wb')
2495 units = cad.inches_per_unit
2496 x = cad.xmin+(cad.xmax-cad.xmin)*(cad.x+0.5)/float(cad.nx)
2497 y = cad.ymin+(cad.ymax-cad.ymin)*(cad.y+0.5)/float(cad.ny)
2498 z = cad.zmin+(cad.zmax-cad.zmin)*(cad.z+0.5)/float(cad.nz)
2499 #
2500 # header
2501 #
2502 file.write('cad.py')
2503 file.write('a'*74)
2504 #
2505 # length
2506 #
2507 N = len(cad.x)
2508 file.write(struct.pack('L',N/3))
2509 #
2510 # triangles
2511 #
2512 for i in range(0,N,3):
2513 string_msg.set("write triangle %d/%d"%(i/3,N/3))
2514 root.update()
2515 #
2516 # normals
2517 #
2518 file.write(struct.pack('f',0))
2519 file.write(struct.pack('f',0))
2520 file.write(struct.pack('f',0))
2521 #
2522 # vertices
2523 #
2524 file.write(struct.pack('f',x[i]*units))
2525 file.write(struct.pack('f',y[i]*units))
2526 file.write(struct.pack('f',z[i]*units))
2527 file.write(struct.pack('f',x[i+1]*units))
2528 file.write(struct.pack('f',y[i+1]*units))
2529 file.write(struct.pack('f',z[i+1]*units))
2530 file.write(struct.pack('f',x[i+2]*units))
2531 file.write(struct.pack('f',y[i+2]*units))
2532 file.write(struct.pack('f',z[i+2]*units))
2533 #
2534 # padding
2535 #
2536 file.write(struct.pack('xx'))
2537 file.close()
2538 string_msg.set("wrote %s"%filename)
2539 root.update()
2540
2541 def write_gerber():
2542 #
2543 # Gerber (RS-274X) output
2544 #
2545 filename = string_cam_file.get()
2546 file = open(filename, 'wb')
2547 units = cad.inches_per_unit
2548 #
2549 # write parameters
2550 #
2551 file.write("%FSLAX24Y24*%\n") # leading zeros omitted, absolute coordinates, 2.4
2552 file.write("%MOIN*%\n") # inches units
2553 file.write("%OFA0B0*%\n") # no offset
2554 #
2555 # find and write apertures
2556 #
2557 ixs = cad.x[::2]
2558 xs = cad.xmin+(cad.xmax-cad.xmin)*(ixs+0.5)/float(cad.nx)
2559 ixe = cad.x[1::2]
2560 xe = cad.xmin+(cad.xmax-cad.xmin)*(ixe+0.5)/float(cad.nx)
2561 idx = ixe - ixs
2562 dx = xe - xs
2563 iys = cad.y[::2]
2564 ys = cad.ymin+(cad.ymax-cad.ymin)*(iys+0.5)/float(cad.ny)
2565 iye = cad.y[1::2]
2566 ye = cad.ymin+(cad.ymax-cad.ymin)*(iye+0.5)/float(cad.ny)
2567 idy = iye - iys
2568 dy = ye - ys
2569 mins = where((idx < idy),idx,idy)
2570 uniques = unique(mins)
2571 apertures = (cad.xmax-cad.xmin)*uniques/float(cad.nx)
2572 index = searchsorted(uniques,mins)
2573 for i in range(len(uniques)):
2574 file.write("%%ADD%dR,%.4fX%.4f*%%\n"%(i+10,apertures[i],apertures[i]))
2575 #
2576 # write flashes
2577 #
2578 coords = arange(len(mins))
2579 for i in range(len(uniques)):
2580 file.write("D%d*\n"%(i+10))
2581 coord = coords[index == i]
2582 delta = apertures[i]/2.
2583 ixs = (10000*(xs+delta)).astype(int32)
2584 ixe = (10000*(xe-delta)).astype(int32)
2585 iys = (10000*(ys+delta)).astype(int32)
2586 iye = (10000*(ye-delta)).astype(int32)
2587 for j in range(len(coord)):
2588 n = coord[j]
2589 if (idx[n] == idy[n]):
2590 #
2591 # flash
2592 #
2593 file.write('X%dY%dD03*\n'%(ixs[n],iys[n]))
2594 elif (idx[n] > idy[n]):
2595 #
2596 # stroke horizontal
2597 #
2598 file.write('X%dY%dD02*\n'%(ixs[n],iys[n]))
2599 file.write('X%dY%dD01*\n'%(ixe[n],iys[n]))
2600 else:
2601 #
2602 # stroke vertical
2603 #
2604 file.write('X%dY%dD02*\n'%(ixs[n],iys[n]))
2605 file.write('X%dY%dD01*\n'%(ixs[n],iye[n]))
2606 file.write("M02*\n") # end of file
2607 file.close()
2608 string_msg.set("wrote %s (RS-274X)"%filename)
2609 root.update()
2610
2611 def write_excellon():
2612 #
2613 # Excellon (RS-) output
2614 #
2615 """
2616 % Rewind and Stop
2617 X#Y# Move and Drill
2618 T# Tool Selection
2619 M30 End of Program
2620 M00 End of Program
2621 R#X#Y# Repeat Hole
2622 G05, G81 Select Drill Mode
2623 G90 Absolute Mode
2624 G91 Incremental Mode
2625 G92 X#Y# Set Zero
2626 G93 X#Y# Set Zero
2627 M48 Program Header to first "%"
2628 M72 English-Imperial Mode
2629
2630 """
2631 filename = string_cam_file.get()
2632 file = open(filename, 'wb')
2633 units = cad.inches_per_unit
2634 #
2635 # write parameters
2636 #
2637 file.write("%FSLAX24Y24*%\n") # leading zeros omitted, absolute coordinates, 2.4
2638 file.write("%MOIN*%\n") # inches units
2639 file.write("%OFA0B0*%\n") # no offset
2640 #
2641 # find and write apertures
2642 #
2643 ixs = cad.x[::2]
2644 xs = cad.xmin+(cad.xmax-cad.xmin)*(ixs+0.5)/float(cad.nx)
2645 ixe = cad.x[1::2]
2646 xe = cad.xmin+(cad.xmax-cad.xmin)*(ixe+0.5)/float(cad.nx)
2647 idx = ixe - ixs
2648 dx = xe - xs
2649 iys = cad.y[::2]
2650 ys = cad.ymin+(cad.ymax-cad.ymin)*(iys+0.5)/float(cad.ny)
2651 iye = cad.y[1::2]
2652 ye = cad.ymin+(cad.ymax-cad.ymin)*(iye+0.5)/float(cad.ny)
2653 idy = iye - iys
2654 dy = ye - ys
2655 mins = where((idx < idy),idx,idy)
2656 uniques = unique(mins)
2657 apertures = (cad.xmax-cad.xmin)*uniques/float(cad.nx)
2658 index = searchsorted(uniques,mins)
2659 for i in range(len(uniques)):
2660 file.write("%%ADD%dR,%.4fX%.4f*%%\n"%(i+10,apertures[i],apertures[i]))
2661 #
2662 # write flashes
2663 #
2664 coords = arange(len(mins))
2665 for i in range(len(uniques)):
2666 file.write("D%d*\n"%(i+10))
2667 coord = coords[index == i]
2668 delta = apertures[i]/2.
2669 ixs = (10000*(xs+delta)).astype(int32)
2670 ixe = (10000*(xe-delta)).astype(int32)
2671 iys = (10000*(ys+delta)).astype(int32)
2672 iye = (10000*(ye-delta)).astype(int32)
2673 for j in range(len(coord)):
2674 n = coord[j]
2675 if (idx[n] == idy[n]):
2676 #
2677 # flash
2678 #
2679 file.write('X%dY%dD03*\n'%(ixs[n],iys[n]))
2680 elif (idx[n] > idy[n]):
2681 #
2682 # stroke horizontal
2683 #
2684 file.write('X%dY%dD02*\n'%(ixs[n],iys[n]))
2685 file.write('X%dY%dD01*\n'%(ixe[n],iys[n]))
2686 else:
2687 #
2688 # stroke vertical
2689 #
2690 file.write('X%dY%dD02*\n'%(ixs[n],iys[n]))
2691 file.write('X%dY%dD01*\n'%(ixs[n],iye[n]))
2692 file.write("M02*\n") # end of file
2693 file.close()
2694 string_msg.set("wrote %s (RS-274X)"%filename)
2695 root.update()
2696
2697 def write_ca():
2698 #
2699 # CA output
2700 #
2701 filename = string_cam_file.get()
2702 file = open(filename, 'wb')
2703 file.write(chr(0xB9)) # magic number 0xB9
2704 file.write(chr(ca.nx/256)) # x size
2705 file.write(chr(ca.nx%256)) #
2706 file.write(chr(ca.ny/256)) # y size
2707 file.write(chr(ca.ny%256)) #
2708 file.write(chr(4)) # LED sub-array x
2709 file.write(chr(2)) # LED sub-array y
2710 for y in range(ca.nx):
2711 for x in range(ca.nx):
2712 if (ca.in1[y,x] == ca.E):
2713 config = 0
2714 elif (ca.in1[y,x] == ca.NE):
2715 config = 1
2716 elif (ca.in1[y,x] == ca.N):
2717 config = 2
2718 elif (ca.in1[y,x] == ca.NW):
2719 config = 3
2720 elif (ca.in1[y,x] == ca.W):
2721 config = 4
2722 elif (ca.in1[y,x] == ca.SW):
2723 config = 5
2724 elif (ca.in1[y,x] == ca.S):
2725 config = 6
2726 elif (ca.in1[y,x] == ca.SE):
2727 config = 7
2728 elif (ca.in1[y,x] == ca.empty): # XOR W W for empty
2729 config = 4
2730 if (ca.in2[y,x] == ca.E):
2731 config += 0
2732 elif (ca.in2[y,x] == ca.NE):
2733 config += (1 << 3)
2734 elif (ca.in2[y,x] == ca.N):
2735 config += (2 << 3)
2736 elif (ca.in2[y,x] == ca.NW):
2737 config += (3 << 3)
2738 elif (ca.in2[y,x] == ca.W):
2739 config += (4 << 3)
2740 elif (ca.in2[y,x] == ca.SW):
2741 config += (5 << 3)
2742 elif (ca.in2[y,x] == ca.S):
2743 config += (6 << 3)
2744 elif (ca.in2[y,x] == ca.SE):
2745 config += (7 << 3)
2746 elif (ca.in2[y,x] == ca.empty): # XOR W W for empty
2747 config += (4 << 3)
2748 if (ca.gates[y,x] == ca.AND):
2749 config += 0
2750 elif (ca.gates[y,x] == ca.OR):
2751 config += (1 << 6)
2752 elif (ca.gates[y,x] == ca.XOR):
2753 config += (2 << 6)
2754 elif (ca.gates[y,x] == ca.NAND):
2755 config += (3 << 6)
2756 elif (ca.gates[y,x] == ca.empty): # XOR W W for empty
2757 config += (2 << 6)
2758 file.write(chr(config))
2759 for y in range(ca.ny):
2760 for x in range((ca.nx/8)):
2761 state = \
2762 (ca.states[y,8*x+0] << 7) \
2763 + (ca.states[y,8*x+1] << 6) \
2764 + (ca.states[y,8*x+2] << 5) \
2765 + (ca.states[y,8*x+3] << 4) \
2766 + (ca.states[y,8*x+4] << 3) \
2767 + (ca.states[y,8*x+5] << 2) \
2768 + (ca.states[y,8*x+6] << 1) \
2769 + (ca.states[y,8*x+7] << 0)
2770 file.write(chr(state))
2771 if ((ca.nx%8) != 0):
2772 x = cad.nx/8
2773 state = 0
2774 for i in range((ca.nx%8)):
2775 state += (ca.states[y,8*x+i] << (7-i))
2776 file.write(chr(state))
2777 file.close()
2778 string_msg.set("wrote %s"%filename)
2779 root.update()
2780
2781 def msg_xy(event):
2782 x = (cad.xmin+cad.xmax)/2. + (cad.xmax-cad.xmin)*(1+event.x-cad.nplot/2.)/float(cad.nxplot())
2783 y = (cad.ymin+cad.ymax)/2. + (cad.ymin-cad.ymax)*(1+event.y-cad.nplot/2.)/float(cad.nyplot())
2784 string_msg.set("x = %.2f y = %.2f"%(x,y))
2785
2786 def msg_yz(event):
2787 if (cad.nz > 1):
2788 y = (cad.ymin+cad.ymax)/2. + (cad.ymin-cad.ymax)*(1+event.y-cad.nplot/2.)/float(cad.nyplot())
2789 z = (cad.zmin+cad.zmax)/2. + (cad.zmin-cad.zmax)*(1+event.x-cad.nplot/2.)/float(cad.nzplot())
2790 string_msg.set("y = %.2f z = %.2f"%(y,z))
2791 else:
2792 string_msg.set("")
2793
2794 def msg_xz(event):
2795 if (cad.nz > 1):
2796 x = (cad.xmin+cad.xmax)/2. + (cad.xmax-cad.xmin)*(1+event.x-cad.nplot/2.)/float(cad.nxplot())
2797 z = (cad.zmin+cad.zmax)/2. + (cad.zmin-cad.zmax)*(1+event.y-cad.nplot/2.)/float(cad.nzplot())
2798 string_msg.set("x = %.2f z = %.2f"%(x,z))
2799 else:
2800 string_msg.set("")
2801
2802 def msg_nomsg(event):
2803 string_msg.set("")
2804
2805 def image_min_x(event):
2806 cad.xmin = float(string_image_xmin.get())
2807 xwidth = float(string_image_xwidth.get())
2808 cad.xmax = cad.xmin + xwidth
2809 root.update()
2810
2811 def image_min_y(event):
2812 cad.ymin = float(string_image_ymin.get())
2813 yheight = float(string_image_yheight.get())
2814 cad.ymax = cad.ymin + yheight
2815 root.update()
2816
2817 def image_scale_x(event):
2818 yheight = float(string_image_yheight.get())
2819 xwidth = yheight*cad.nx/float(cad.ny)
2820 cad.xmax = cad.xmin + xwidth
2821 string_image_xwidth.set(str(xwidth))
2822 root.update()
2823
2824 def image_scale_y(event):
2825 xwidth = float(string_image_xwidth.get())
2826 yheight = xwidth*cad.ny/float(cad.nx)
2827 cad.ymax = cad.ymin + yheight
2828 string_image_yheight.set(str(yheight))
2829 root.update()
2830
2831 def send_to(event):
2832 save_cam(0)
2833 cam_file_name = string_cam_file.get()
2834 send_to_file(cam_file_name)
2835
2836 def send_to_file(cam_file_name):
2837 cad_path = os.path.dirname(sys.argv[0])
2838 if (sys.argv[0] == "cad.py"):
2839 cfg_path = "cad.cfg"
2840 else:
2841 cfg_path = os.path.dirname(sys.argv[0])+"/cad.cfg"
2842 try:
2843 config_file = open(cfg_path, 'r')
2844 except:
2845 string_msg.set(cfg_path+" not found")
2846 root.update()
2847 return()
2848 dot = find(cam_file_name,".")
2849 while 1:
2850 new_dot = find(cam_file_name,".",dot+1)
2851 if (new_dot == -1):
2852 break
2853 else:
2854 dot = new_dot
2855 suffix = cam_file_name[dot+1:]
2856 while 1:
2857 line = config_file.readline()
2858 if (find(line,suffix) == 0):
2859 string_msg.set("sending "+cam_file_name+" ...")
2860 root.update()
2861 quote1 = find(line,"'")
2862 quote2 = find(line,"'",quote1+1)
2863 cmd = line[(quote1+1):quote2]
2864 if (os.name == 'nt'):
2865 cam_file_name = replace(cam_file_name,'/','\\')
2866 cmd = replace(cmd,'file','"'+cam_file_name+'"')
2867 os.system(cmd)
2868 string_msg.set(cam_file_name+" sent")
2869 root.update()
2870 config_file.close()
2871 root.update()
2872 return()
2873 elif (line == ""):
2874 string_msg.set(suffix+" driver not defined in "+cfg_path)
2875 config_file.close()
2876 root.update()
2877 return()
2878
2879 def resize_window(event):
2880 #
2881 # resize drawing windows
2882 #
2883 cad.nplot = int(string_window_size.get())
2884 cad.view(cad.views)
2885 render()
2886
2887 def resize_editor(event):
2888 #
2889 # resize editing windows
2890 #
2891 cad.editor_height = int(string_editor_height.get())
2892 widget_cad_text.config(height=cad.editor_height)
2893 cad.editor_width = int(string_editor_width.get())
2894 widget_cad_text.config(width=cad.editor_width)
2895 widget_function_text.config(width=cad.editor_width)
2896 root.update()
2897
2898 def reload():
2899 #
2900 # reload input file
2901 #
2902 filename = string_input_file.get()
2903 if (find(filename,'.cad') != -1):
2904 cad_load(0)
2905 elif ((find(filename,'.jpg') != -1) | (find(filename,'.JPG') != -1) |
2906 (find(filename,'.png') != -1) | (find(filename,'.PNG') != -1) |
2907 (find(filename,'.gif') != -1) | (find(filename,'.GIF') != -1)):
2908 widget_cad_text.delete("1.0",END)
2909 image_load(0)
2910 else:
2911 string_msg.set("unsupported input file format")
2912 root.update()
2913
2914 #
2915 # set up GUI
2916 #
2917 root = Tk()
2918 root.title('cad.py')
2919 #
2920 # message frame
2921 #
2922 msg_frame = Frame(root)
2923 string_msg = StringVar()
2924 widget_msg = Label(msg_frame, textvariable = string_msg)
2925 widget_msg.pack(side='right')
2926 Label(msg_frame, text=" ").pack(side='right')
2927 widget_stop = Button(msg_frame, text='stop', borderwidth=2)
2928 widget_stop.bind('<Button-1>',render_stop)
2929 msg_frame.grid(row=0,column=0)
2930 #
2931 # size frame
2932 #
2933 size_frame = Frame(root)
2934 Label(size_frame, text="window size: ").pack(side='left')
2935 string_window_size = StringVar()
2936 string_window_size.set(str(cad.nplot))
2937 widget_window_size = Entry(size_frame, width=4, bg='white', textvariable=string_window_size)
2938 widget_window_size.bind('<Return>',resize_window)
2939 widget_window_size.pack(side='left')
2940 Label(size_frame, text=" editor width: ").pack(side='left')
2941 string_editor_width = StringVar()
2942 string_editor_width.set(str(cad.editor_width))
2943 widget_editor_width = Entry(size_frame, width=3, bg='white', textvariable=string_editor_width)
2944 widget_editor_width.bind('<Return>',resize_editor)
2945 widget_editor_width.pack(side='left')
2946 Label(size_frame, text=" height: ").pack(side='left')
2947 string_editor_height = StringVar()
2948 string_editor_height.set(str(cad.editor_height))
2949 widget_editor_height = Entry(size_frame, width=3, bg='white', textvariable=string_editor_height)
2950 widget_editor_height.bind('<Return>',resize_editor)
2951 widget_editor_height.pack(side='left')
2952 size_frame.grid(row=0,column=1)
2953 #
2954 # view frame
2955 #
2956 view_frame2 = Frame(root)
2957 view_frame3 = Frame(root)
2958 canvas_xy = Canvas(view_frame3)
2959 canvas_xz = Canvas(view_frame3)
2960 canvas_yz = Canvas(view_frame3)
2961 canvas_xyz = Canvas(view_frame3)
2962 cad.view('xyzr')
2963 #
2964 # I/O frame
2965 #
2966 io_frame = Frame(root)
2967 io_frame.grid(row=2,column=1,sticky=N)
2968 #cad_frame.bind('<Motion>',msg_nomsg)
2969 #
2970 # input frame
2971 #
2972 input_frame = Frame(io_frame)
2973 input_frame.pack()
2974 #
2975 # .cad editor
2976 #
2977 editor_frame = Frame(input_frame)
2978 widget_text_yscrollbar = Scrollbar(editor_frame)
2979 widget_cad_text = Text(editor_frame, bg='white', bd=5, width=cad.editor_width, height=cad.editor_height, yscrollcommand=widget_text_yscrollbar.set)
2980 widget_cad_text.grid(row=1,column=1)
2981 widget_text_yscrollbar.grid(row=1,column=2,sticky=N+S)
2982 widget_text_yscrollbar.config(command=widget_cad_text.yview)
2983 widget_cad_text.bind('<Motion>',msg_nomsg)
2984 editor_frame.pack()
2985 #
2986 # input file
2987 #
2988 cad_input_frame = Frame(input_frame)
2989 widget_input_file = Button(cad_input_frame, text="input:",command=input_open)
2990 widget_input_file.pack(side='left')
2991 string_input_file = StringVar()
2992 string_input_file.set('out.cad')
2993 widget_cad = Entry(cad_input_frame, width=17, bg='white', textvariable=string_input_file)
2994 widget_cad.pack(side='left')
2995 Label(cad_input_frame, text=" ").pack(side='left')
2996 widget_cad_save = Button(cad_input_frame, text="save")
2997 widget_cad_save.bind('<Button-1>',cad_save)
2998 widget_cad_save.pack(side='left')
2999 Label(cad_input_frame, text=" ").pack(side='left')
3000 widget_reload = Button(cad_input_frame, text="reload",command=reload)
3001 widget_reload.pack(side='left')
3002 cad_input_frame.pack()
3003 #
3004 # image x
3005 #
3006 image_x_frame = Frame(input_frame)
3007 Label(image_x_frame, text="x min: ").pack(side='left')
3008 string_image_xmin = StringVar()
3009 widget_image_xmin = Entry(image_x_frame, width=6, bg='white', textvariable=string_image_xmin)
3010 widget_image_xmin.bind('<Return>',image_min_x)
3011 widget_image_xmin.pack(side='left')
3012 Label(image_x_frame, text=" x width: ").pack(side='left')
3013 string_image_xwidth = StringVar()
3014 widget_image_xwidth = Entry(image_x_frame, width=6, bg='white', textvariable=string_image_xwidth)
3015 widget_image_xwidth.bind('<Return>',image_scale_y)
3016 widget_image_xwidth.pack(side='left')
3017 string_image_nx = StringVar()
3018 Label(image_x_frame, textvariable = string_image_nx).pack(side='left')
3019 #
3020 # image y
3021 #
3022 image_y_frame = Frame(input_frame)
3023 Label(image_y_frame, text="y min: ").pack(side='left')
3024 string_image_ymin = StringVar()
3025 widget_image_ymin = Entry(image_y_frame, width=6, bg='white', textvariable=string_image_ymin)
3026 widget_image_ymin.bind('<Return>',image_min_y)
3027 widget_image_ymin.pack(side='left')
3028 Label(image_y_frame, text=" y height: ").pack(side='left')
3029 string_image_yheight = StringVar()
3030 widget_image_yheight = Entry(image_y_frame, width=6, bg='white', textvariable=string_image_yheight)
3031 widget_image_yheight.bind('<Return>',image_scale_x)
3032 widget_image_yheight.pack(side='left')
3033 string_image_ny = StringVar()
3034 Label(image_y_frame, textvariable = string_image_ny).pack(side='left')
3035 #
3036 # image z
3037 #
3038 image_z_frame = Frame(input_frame)
3039 Label(image_z_frame, text="z min: ").pack(side='left')
3040 string_image_zmin = StringVar()
3041 widget_image_zmin = Entry(image_z_frame, width=6, bg='white', textvariable=string_image_zmin)
3042 widget_image_zmin.pack(side='left')
3043 Label(image_z_frame, text=" z max: ").pack(side='left')
3044 string_image_zmax = StringVar()
3045 widget_image_zmax = Entry(image_z_frame, width=6, bg='white', textvariable=string_image_zmax)
3046 widget_image_zmax.pack(side='left')
3047 Label(image_z_frame, text=" nz: ").pack(side='left')
3048 string_image_nz = StringVar()
3049 widget_image_nz = Entry(image_z_frame, width=6, bg='white', textvariable=string_image_nz)
3050 widget_image_nz.pack(side='left')
3051 #
3052 # image intensity
3053 #
3054 image_intensity_frame = Frame(input_frame)
3055 Label(image_intensity_frame, text="intensity min: ").pack(side='left')
3056 string_image_min = StringVar()
3057 widget_image_min = Entry(image_intensity_frame, width=6, bg='white', textvariable=string_image_min)
3058 widget_image_min.pack(side='left')
3059 Label(image_intensity_frame, text=" intensity max: ").pack(side='left')
3060 string_image_max = StringVar()
3061 widget_image_max = Entry(image_intensity_frame, width=6, bg='white', textvariable=string_image_max)
3062 widget_image_max.pack(side='left')
3063 #
3064 # image units
3065 #
3066 image_units_frame = Frame(input_frame)
3067 Label(image_units_frame, text="inches per unit: ").pack(side='left')
3068 string_image_units = StringVar()
3069 widget_image_units = Entry(image_units_frame, width=6, bg='white', textvariable=string_image_units)
3070 widget_image_units.pack(side='left')
3071 #
3072 # image invert
3073 #
3074 image_invert_frame = Frame(input_frame)
3075 Label(image_invert_frame, text=" ").pack(side='left')
3076 widget_image_invert = Button(image_invert_frame, text="invert image")
3077 widget_image_invert.pack(side='left')
3078 widget_image_invert.bind('<Button-1>',invert_image)
3079 #
3080 # output frame
3081 #
3082 output_frame = Frame(io_frame)
3083 output_frame.pack()
3084 #
3085 # controls
3086 #
3087 control_frame = Frame(output_frame)
3088 widget_render = Button(control_frame, text="render")
3089 widget_render.bind('<Button-1>',render_button)
3090 widget_render.pack(side='left')
3091 Label(control_frame, text=" ").pack(side='left')
3092 canvas_logo = Canvas(control_frame, width=26, height=26, background="white")
3093 canvas_logo.create_oval(2,2,8,8,fill="red",outline="")
3094 canvas_logo.create_rectangle(11,2,17,8,fill="blue",outline="")
3095 canvas_logo.create_rectangle(20,2,26,8,fill="blue",outline="")
3096 canvas_logo.create_rectangle(2,11,8,17,fill="blue",outline="")
3097 canvas_logo.create_oval(10,10,16,16,fill="red",outline="")
3098 canvas_logo.create_rectangle(20,11,26,17,fill="blue",outline="")
3099 canvas_logo.create_rectangle(2,20,8,26,fill="blue",outline="")
3100 canvas_logo.create_rectangle(11,20,17,26,fill="blue",outline="")
3101 canvas_logo.create_rectangle(20,20,26,26,fill="blue",outline="")
3102 canvas_logo.pack(side='left')
3103 control_text = " cad.py (%s) "%DATE
3104 Label(control_frame, text=control_text).pack(side='left')
3105 widget_cam = Button(control_frame, text="cam")
3106 widget_cam.bind('<Button-1>',cam)
3107 widget_cam.pack(side='left')
3108 Label(control_frame, text=" ").pack(side='left')
3109 widget_quit = Button(control_frame, text="quit", command='exit')
3110 widget_quit.pack(side='left')
3111 control_frame.pack()
3112 #
3113 # function string
3114 #
3115 function_string_frame = Frame(output_frame)
3116 Label(function_string_frame, text="function:").grid(row=1,column=1)
3117 widget_function_yscrollbar = Scrollbar(function_string_frame)
3118 widget_function_text = Text(function_string_frame, bg='white', bd=5, width=cad.editor_width, height=12, yscrollcommand=widget_function_yscrollbar.set, state=DISABLED)
3119 widget_function_text.grid(row=2,column=1)
3120 widget_function_yscrollbar.grid(row=2,column=2,sticky=N+S)
3121 widget_function_yscrollbar.config(command=widget_function_text.yview)
3122 function_string_frame.pack()
3123 #
3124 # CAM file
3125 #
3126 cam_file_frame = Frame(output_frame)
3127 widget_cam_menu_button = Menubutton(cam_file_frame,text="output format", relief=RAISED)
3128 widget_cam_menu_button.pack(side='left')
3129 widget_cam_menu = Menu(widget_cam_menu_button)
3130 widget_cam_menu.add_command(label='.epi (Epilog)',command=select_epi)
3131 widget_cam_menu.add_command(label='.camm (CAMM)',command=select_camm)
3132 widget_cam_menu.add_command(label='.rml (Modela)',command=select_rml)
3133 widget_cam_menu.add_command(label='.sbp (ShopBot)',command=select_sbp)
3134 widget_cam_menu.add_command(label='.gcode (Gcode)',command=select_g)
3135 widget_cam_menu.add_command(label='.ps (Postscript)',command=select_ps)
3136 widget_cam_menu.add_command(label='.ord (OMAX)',command=select_ord)
3137 widget_cam_menu.add_command(label='.oms (Resonetics)',command=select_oms)
3138 widget_cam_menu.add_command(label='.grb (Gerber)',command=select_gerber)
3139 widget_cam_menu.add_command(label='.drl (Excellon)',command=select_excellon)
3140 widget_cam_menu.add_command(label='.stl (STL)',command=select_stl)
3141 widget_cam_menu.add_command(label='.dxf (DXF)',command=select_dxf)
3142 widget_cam_menu.add_command(label='.jpg (JPG)',command=select_jpg)
3143 widget_cam_menu.add_command(label='.png (PNG)',command=select_png)
3144 widget_cam_menu.add_command(label='.ca (CA)',command=select_ca)
3145 widget_cam_menu.add_command(label='.uni (Universal)',command=select_uni)
3146 widget_cam_menu.add_command(label='.epb (Epilog bitmap)',state=DISABLED)
3147 widget_cam_menu_button['menu'] = widget_cam_menu
3148 Label(cam_file_frame, text=" output file: ").pack(side='left')
3149 string_cam_file = StringVar()
3150 widget_cam_file = Entry(cam_file_frame, width=12, bg='white', textvariable=string_cam_file)
3151 widget_cam_file.pack(side='left')
3152 Label(cam_file_frame, text=" ").pack(side='left')
3153 widget_cam_save = Button(cam_file_frame, text="save")
3154 widget_cam_save.bind('<Button-1>',save_cam)
3155 widget_cam_save.pack(side='left')
3156 #
3157 # vectorization
3158 #
3159 cam_vector_frame = Frame(output_frame)
3160 Label(cam_vector_frame, text="maximum vector fit error (lattice units): ").pack(side='left')
3161 string_vector_error = StringVar()
3162 string_vector_error.set('.75')
3163 widget_vector_error = Entry(cam_vector_frame, width=6, bg='white', textvariable=string_vector_error)
3164 widget_vector_error.pack(side='left')
3165 #
3166 # tool
3167 #
3168 cam_dia_frame = Frame(output_frame)
3169 Label(cam_dia_frame, text="tool diameter: ").pack(side='left')
3170 string_tool_dia = StringVar()
3171 string_tool_dia.set('0')
3172 widget_tool_dia = Entry(cam_dia_frame, width=6, bg='white', textvariable=string_tool_dia)
3173 widget_tool_dia.pack(side='left')
3174 Label(cam_dia_frame, text=" tool overlap: ").pack(side='left')
3175 string_tool_overlap = StringVar()
3176 string_tool_overlap.set('0.5')
3177 widget_tool_overlap = Entry(cam_dia_frame, width=6, bg='white', textvariable=string_tool_overlap)
3178 widget_tool_overlap.pack(side='left')
3179 #
3180 # contour
3181 #
3182 cam_contour_frame = Frame(output_frame)
3183 Label(cam_contour_frame, text=" # contours (-1 for max): ").pack(side='left')
3184 string_num_contours = StringVar()
3185 string_num_contours.set('0')
3186 widget_num_contours = Entry(cam_contour_frame, width=6, bg='white', textvariable=string_num_contours)
3187 widget_num_contours.pack(side='left')
3188 Label(cam_contour_frame, text=" ").pack(side='left')
3189 widget_cam_contour = Button(cam_contour_frame, text="contour")
3190 widget_cam_contour.pack(side='left')
3191 widget_cam_contour.bind('<Button-1>',contour)
3192 #
3193 # laser power
3194 #
3195 laser_frame1 = Frame(output_frame)
3196 Label(laser_frame1, text=" power:").pack(side='left')
3197 string_laser_power = StringVar()
3198 Entry(laser_frame1, width=6, bg='white', textvariable=string_laser_power).pack(side='left')
3199 Label(laser_frame1, text=" speed:").pack(side='left')
3200 string_laser_speed = StringVar()
3201 Entry(laser_frame1, width=6, bg='white', textvariable=string_laser_speed).pack(side='left')
3202 Label(laser_frame1, text=" rate: ").pack(side='left')
3203 string_laser_rate = StringVar()
3204 Entry(laser_frame1, width=6, bg='white', textvariable=string_laser_rate).pack(side='left')
3205 #
3206 # power range
3207 #
3208 laser_frame2 = Frame(output_frame)
3209 Label(laser_frame2, text=" min power:").pack(side='left')
3210 string_laser_min_power = StringVar()
3211 Entry(laser_frame2, width=6, bg='white', textvariable=string_laser_min_power).pack(side='left')
3212 Label(laser_frame2, text="% max power:").pack(side='left')
3213 string_laser_max_power = StringVar()
3214 Entry(laser_frame2, width=6, bg='white', textvariable=string_laser_max_power).pack(side='left')
3215 Label(laser_frame2, text="%").pack(side='left')
3216 #
3217 # autofocus
3218 #
3219 laser_frame3 = Frame(output_frame)
3220 integer_laser_autofocus = IntVar()
3221 widget_autofocus = Checkbutton(laser_frame3, text="Auto Focus", variable=integer_laser_autofocus).pack(side='left')
3222 #
3223 # cutting
3224 #
3225 cut_frame = Frame(output_frame)
3226 Label(cut_frame, text="force: ").pack(side='left')
3227 string_cut_force = StringVar()
3228 Entry(cut_frame, width=6, bg='white', textvariable=string_cut_force).pack(side='left')
3229 Label(cut_frame, text=" velocity:").pack(side='left')
3230 string_cut_velocity = StringVar()
3231 Entry(cut_frame, width=6, bg='white', textvariable=string_cut_velocity).pack(side='left')
3232 #
3233 # speed
3234 #
3235 speed_frame = Frame(output_frame)
3236 Label(speed_frame, text="xy speed:").pack(side='left')
3237 string_xy_speed = StringVar()
3238 Entry(speed_frame, width=4, bg='white', textvariable=string_xy_speed).pack(side='left')
3239 Label(speed_frame, text=" z speed:").pack(side='left')
3240 string_z_speed = StringVar()
3241 Entry(speed_frame, width=4, bg='white', textvariable=string_z_speed).pack(side='left')
3242 #
3243 # jog
3244 #
3245 jog_frame = Frame(output_frame)
3246 Label(jog_frame, text="jog xy speed:").pack(side='left')
3247 string_jog_xy_speed = StringVar()
3248 Entry(jog_frame, width=4, bg='white', textvariable=string_jog_xy_speed).pack(side='left')
3249 Label(jog_frame, text=" z speed:").pack(side='left')
3250 string_jog_z_speed = StringVar()
3251 Entry(jog_frame, width=4, bg='white', textvariable=string_jog_z_speed).pack(side='left')
3252 Label(jog_frame, text=" z:").pack(side='left')
3253 string_jog_z = StringVar()
3254 Entry(jog_frame, width=4, bg='white', textvariable=string_jog_z).pack(side='left')
3255 #
3256 # RML move
3257 #
3258 rml_move_frame = Frame(output_frame)
3259 Label(rml_move_frame, text="x: ").pack(side='left')
3260 string_rml_x_move = StringVar()
3261 Entry(rml_move_frame, width=6, bg='white', textvariable=string_rml_x_move).pack(side='left')
3262 Label(rml_move_frame, text=" y: ").pack(side='left')
3263 string_rml_y_move = StringVar()
3264 Entry(rml_move_frame, width=6, bg='white', textvariable=string_rml_y_move).pack(side='left')
3265 Label(rml_move_frame, text=" ").pack(side='left')
3266 widget_rml_move = Button(rml_move_frame, text="move")
3267 widget_rml_move.pack(side='left')
3268 widget_rml_move.bind('<Button-1>',rml_move)
3269 #
3270 # G codes
3271 #
3272 g_frame = Frame(output_frame)
3273 Label(g_frame, text=" feed rate:").pack(side="left")
3274 string_g_feed_rate = StringVar()
3275 Entry(g_frame, width=6, textvariable=string_g_feed_rate).pack(side="left")
3276 Label(g_frame, text=" spindle speed:").pack(side="left")
3277 string_g_spindle_speed = StringVar()
3278 Entry(g_frame, width=6, textvariable=string_g_spindle_speed).pack(side="left")
3279 Label(g_frame, text=" tool:").pack(side="left")
3280 string_g_tool = StringVar()
3281 Entry(g_frame, width=3, textvariable=string_g_tool).pack(side="left")
3282 integer_g_cool = IntVar()
3283 widget_g_cool = Checkbutton(g_frame, text="coolant", variable=integer_g_cool)
3284 widget_g_cool.pack(side="left")
3285 #
3286 # waterjet
3287 #
3288 waterjet_frame = Frame(output_frame)
3289 Label(waterjet_frame,text="lead-in/out: ").pack(side='left')
3290 string_lead_in = StringVar()
3291 widget_lead_in = Entry(waterjet_frame, width=4, bg='white', textvariable=string_lead_in)
3292 widget_lead_in.pack(side='left')
3293 Label(waterjet_frame,text="quality: ").pack(side='left')
3294 string_quality = StringVar()
3295 widget_quality = Entry(waterjet_frame, width=4, bg='white', textvariable=string_quality)
3296 widget_quality.pack(side='left')
3297 #
3298 # excimer
3299 #
3300 excimer_frame = Frame(output_frame)
3301 Label(excimer_frame,text="period (usec): ").pack(side='left')
3302 string_pulse_period = StringVar()
3303 widget_pulse_period = Entry(excimer_frame, width=5, bg='white', textvariable=string_pulse_period)
3304 widget_pulse_period.pack(side='left')
3305 Label(excimer_frame,text="velocity: ").pack(side='left')
3306 string_cut_vel = StringVar()
3307 widget_cut_vel = Entry(excimer_frame, width=4, bg='white', textvariable=string_cut_vel)
3308 widget_cut_vel.pack(side='left')
3309 Label(excimer_frame,text="acceleration: ").pack(side='left')
3310 string_cut_accel = StringVar()
3311 widget_cut_accel = Entry(excimer_frame, width=4, bg='white', textvariable=string_cut_accel)
3312 widget_cut_accel.pack(side='left')
3313 #
3314 # STL
3315 #
3316 STL_frame = Frame(output_frame)
3317 widget_STL_triangulate = Button(STL_frame, text="triangulate")
3318 widget_STL_triangulate.pack(side='left')
3319 widget_STL_triangulate.bind('<Button-1>',triangulate)
3320 #
3321 # Gerber
3322 #
3323 Gerber_frame = Frame(output_frame)
3324 widget_Gerber_convert = Button(Gerber_frame, text="convert")
3325 widget_Gerber_convert.pack(side='left')
3326 widget_Gerber_convert.bind('<Button-1>',flash)
3327 #
3328 # Excellon
3329 #
3330 Excellon_frame = Frame(output_frame)
3331 widget_Excellon_convert = Button(Excellon_frame, text="convert")
3332 widget_Excellon_convert.pack(side='left')
3333 widget_Excellon_convert.bind('<Button-1>',flash)
3334 #
3335 # filling
3336 #
3337 fill_frame = Frame(output_frame)
3338 integer_fill = IntVar()
3339 widget_fill = Checkbutton(fill_frame, text="fill polygons", variable=integer_fill).pack(side='left')
3340 #
3341 # send to
3342 #
3343 send_to_frame = Frame(output_frame)
3344 widget_send_to = Button(send_to_frame, text="send to machine")
3345 widget_send_to.bind('<Button-1>',send_to)
3346 widget_send_to.pack(side='left')
3347 string_send_to_time = StringVar()
3348 string_send_to_time.set("")
3349 Label(send_to_frame,textvariable=string_send_to_time).pack(side='left')
3350
3351 #
3352 # define .cad template
3353 #
3354 cad_template = """#
3355 # .cad template
3356 #
3357
3358 #
3359 # define shapes and transformation
3360 #
3361 # circle(x0, y0, r)
3362 # cylinder(x0, y0, z0, z1, r)
3363 # cone(x0, y0, z0, z1, r0)
3364 # sphere(x0, y0, z0, r)
3365 # torus(x0, y0, z0, r0, r1)
3366 # rectangle(x0, x1, y0, y1)
3367 # cube(x0, x1, y0, y1, z0, z1)
3368 # right_triangle(x0, y0, h)
3369 # triangle(x0, y0, x1, y1, x2, y2) (points in clockwise order)
3370 # pyramid(x0, x1, y0, y1, z0, z1)
3371 # function(Z_of_XY)
3372 # functions(upper_Z_of_XY,lower_Z_of_XY)
3373 # add(part1, part2)
3374 # subtract(part1, part2)
3375 # intersect(part1, part2)
3376 # move(part,dx,dy)
3377 # translate(part,dx,dy,dz)
3378 # rotate(part, angle)
3379 # rotate_x(part, angle)
3380 # rotate_y(part, angle)
3381 # rotate_z(part, angle)
3382 # rotate_90(part)
3383 # rotate_180(part)
3384 # rotate_270(part)
3385 # reflect_x(part)
3386 # reflect_y(part)
3387 # reflect_z(part)
3388 # reflect_xy(part)
3389 # reflect_xz(part)
3390 # reflect_yz(part)
3391 # scale_x(part, x0, sx)
3392 # scale_y(part, y0, sy)
3393 # scale_z(part, z0, sz)
3394 # scale_xy(part, x0, y0, sxy)
3395 # scale_xyz(part, x0, y0, z0, sxyz)
3396 # coscale_x_y(part, x0, y0, y1, angle0, angle1, amplitude, offset)
3397 # coscale_x_z(part, x0, z0, z1, angle0, angle1, amplitude, offset)
3398 # coscale_xy_z(part, x0, y0, z0, z1, angle0, angle1, amplitude, offset)
3399 # taper_x_y(part, x0, y0, y1, s0, s1)
3400 # taper_x_z(part, x0, z0, z1, s0, s1)
3401 # taper_xy_z(part, x0, y0, z0, z1, s0, s1)
3402 # shear_x_y(part, y0, y1, dx0, dx1)
3403 # shear_x_z(part, z0, z1, dx0, dx1)
3404 # (more to come)
3405
3406 def circle(x0, y0, r):
3407 part = "(((X-x0)**2 + (Y-y0)**2) <= r**2)"
3408 part = replace(part,'x0',str(x0))
3409 part = replace(part,'y0',str(y0))
3410 part = replace(part,'r',str(r))
3411 return part
3412
3413 def cylinder(x0, y0, z0, z1, r):
3414 part = "(((X-x0)**2 + (Y-y0)**2 <= r**2) & (Z >= z0) & (Z <= z1))"
3415 part = replace(part,'x0',str(x0))
3416 part = replace(part,'y0',str(y0))
3417 part = replace(part,'z0',str(z0))
3418 part = replace(part,'z1',str(z1))
3419 part = replace(part,'r',str(r))
3420 return part
3421
3422 def cone(x0, y0, z0, z1, r0):
3423 part = cylinder(x0, y0, z0, z1, r0)
3424 part = taper_xy_z(part, x0, y0, z0, z1, 1.0, 0.0)
3425 return part
3426
3427 def sphere(x0, y0, z0, r):
3428 part = "(((X-x0)**2 + (Y-y0)**2 + (Z-z0)**2) <= r**2)"
3429 part = replace(part,'x0',str(x0))
3430 part = replace(part,'y0',str(y0))
3431 part = replace(part,'z0',str(z0))
3432 part = replace(part,'r',str(r))
3433 return part
3434
3435 def torus(x0, y0, z0, r0, r1):
3436 part = "(((r0 - sqrt((X-x0)**2 + (Y-y0)**2))**2 + (Z-z0)**2) <= r1**2)"
3437 part = replace(part,'x0',str(x0))
3438 part = replace(part,'y0',str(y0))
3439 part = replace(part,'z0',str(z0))
3440 part = replace(part,'r0',str(r0))
3441 part = replace(part,'r1',str(r1))
3442 return part
3443
3444 def rectangle(x0, x1, y0, y1):
3445 part = "((X >= x0) & (X <= x1) & (Y >= y0) & (Y <= y1))"
3446 part = replace(part,'x0',str(x0))
3447 part = replace(part,'x1',str(x1))
3448 part = replace(part,'y0',str(y0))
3449 part = replace(part,'y1',str(y1))
3450 return part
3451
3452 def cube(x0, x1, y0, y1, z0, z1):
3453 part = "((X >= x0) & (X <= x1) & (Y >= y0) & (Y <= y1) & (Z >= z0) & (Z <= z1))"
3454 part = replace(part,'x0',str(x0))
3455 part = replace(part,'x1',str(x1))
3456 part = replace(part,'y0',str(y0))
3457 part = replace(part,'y1',str(y1))
3458 part = replace(part,'z0',str(z0))
3459 part = replace(part,'z1',str(z1))
3460 return part
3461
3462 def right_triangle(x0, y0, h):
3463 part = "((X > x0) & (X < x0 + h - (Y-y0)) & (Y > y0))"
3464 part = replace(part,'x0',str(x0))
3465 part = replace(part,'y0',str(y0))
3466 part = replace(part,'h',str(h))
3467 return part
3468
3469 def triangle(x0, y0, x1, y1, x2, y2): # points in clockwise order
3470 part = "((((y1-y0)*(X-x0)-(x1-x0)*(Y-y0)) >= 0) & (((y2-y1)*(X-x1)-(x2-x1)*(Y-y1)) >= 0) & (((y0-y2)*(X-x2)-(x0-x2)*(Y-y2)) >= 0))"
3471 part = replace(part,'x0',str(x0))
3472 part = replace(part,'y0',str(y0))
3473 part = replace(part,'x1',str(x1))
3474 part = replace(part,'y1',str(y1))
3475 part = replace(part,'x2',str(x2))
3476 part = replace(part,'y2',str(y2))
3477 return part
3478
3479 def pyramid(x0, x1, y0, y1, z0, z1):
3480 part = cube(x0, x1, y0, y1, z0, z1)
3481 part = taper_xy_z(part, (x0+x1)/2., (y0+y1)/2., z0, z1, 1.0, 0.0)
3482 return part
3483
3484 def function(Z_of_XY):
3485 part = '(Z <= '+Z_of_XY+')'
3486 return part
3487
3488 def functions(upper_Z_of_XY,lower_Z_of_XY):
3489 part = '(Z <= '+upper_Z_of_XY+') & (Z >= '+lower_Z_of_XY+')'
3490 return part
3491
3492 def add(part1, part2):
3493 part = "part1 | part2"
3494 part = replace(part,'part1',part1)
3495 part = replace(part,'part2',part2)
3496 return part
3497
3498 def subtract(part1, part2):
3499 part = "(part1) & ~(part2)"
3500 part = replace(part,'part1',part1)
3501 part = replace(part,'part2',part2)
3502 return part
3503
3504 def intersect(part1, part2):
3505 part = "(part1) & (part2)"
3506 part = replace(part,'part1',part1)
3507 part = replace(part,'part2',part2)
3508 return part
3509
3510 def move(part,dx,dy):
3511 part = replace(part,'X','(X-'+str(dx)+')')
3512 part = replace(part,'Y','(Y-'+str(dy)+')')
3513 return part
3514
3515 def translate(part,dx,dy,dz):
3516 part = replace(part,'X','(X-'+str(dx)+')')
3517 part = replace(part,'Y','(Y-'+str(dy)+')')
3518 part = replace(part,'Z','(Z-'+str(dz)+')')
3519 return part
3520
3521 def rotate(part, angle):
3522 angle = angle*pi/180
3523 part = replace(part,'X','(cos(angle)*X+sin(angle)*y)')
3524 part = replace(part,'Y','(-sin(angle)*X+cos(angle)*y)')
3525 part = replace(part,'y','Y')
3526 part = replace(part,'angle',str(angle))
3527 return part
3528
3529 def rotate_x(part, angle):
3530 angle = angle*pi/180
3531 part = replace(part,'Y','(cos(angle)*Y+sin(angle)*z)')
3532 part = replace(part,'Z','(-sin(angle)*Y+cos(angle)*z)')
3533 part = replace(part,'z','Z')
3534 part = replace(part,'angle',str(angle))
3535 return part
3536
3537 def rotate_y(part, angle):
3538 angle = angle*pi/180
3539 part = replace(part,'X','(cos(angle)*X+sin(angle)*z)')
3540 part = replace(part,'Z','(-sin(angle)*X+cos(angle)*z)')
3541 part = replace(part,'z','Z')
3542 part = replace(part,'angle',str(angle))
3543 return part
3544
3545 def rotate_z(part, angle):
3546 angle = angle*pi/180
3547 part = replace(part,'X','(cos(angle)*X+sin(angle)*y)')
3548 part = replace(part,'Y','(-sin(angle)*X+cos(angle)*y)')
3549 part = replace(part,'y','Y')
3550 part = replace(part,'angle',str(angle))
3551 return part
3552
3553 def rotate_90(part):
3554 part = reflect_xy(part)
3555 part = reflect_y(part)
3556 return part
3557
3558 def rotate_180(part):
3559 part = reflect_xy(part)
3560 part = reflect_y(part)
3561 part = reflect_xy(part)
3562 part = reflect_y(part)
3563 return part
3564
3565 def rotate_270(part):
3566 part = reflect_xy(part)
3567 part = reflect_y(part)
3568 part = reflect_xy(part)
3569 part = reflect_y(part)
3570 part = reflect_xy(part)
3571 part = reflect_y(part)
3572 return part
3573
3574 def reflect_x(part):
3575 part = replace(part,'X','(-X)')
3576 return part
3577
3578 def reflect_y(part):
3579 part = replace(part,'Y','(-Y)')
3580 return part
3581
3582 def reflect_z(part):
3583 part = replace(part,'Z','(-Z)')
3584 return part
3585
3586 def reflect_xy(part):
3587 part = replace(part,'X','temp')
3588 part = replace(part,'Y','X')
3589 part = replace(part,'temp','Y')
3590 return part
3591
3592 def reflect_xz(part):
3593 part = replace(part,'X','temp')
3594 part = replace(part,'Z','X')
3595 part = replace(part,'temp','Z')
3596 return part
3597
3598 def reflect_yz(part):
3599 part = replace(part,'Y','temp')
3600 part = replace(part,'Z','Y')
3601 part = replace(part,'temp','Z')
3602 return part
3603
3604 def scale_x(part, x0, sx):
3605 part = replace(part,'X','(x0 + (X-x0)/sx)')
3606 part = replace(part,'x0',str(x0))
3607 part = replace(part,'sx',str(sx))
3608 return part
3609
3610 def scale_y(part, y0, sy):
3611 part = replace(part,'Y','(y0 + (Y-y0)/sy)')
3612 part = replace(part,'y0',str(y0))
3613 part = replace(part,'sy',str(sy))
3614 return part
3615
3616 def scale_z(part, z0, sz):
3617 part = replace(part,'Z','(z0 + (Z-z0)/sz)')
3618 part = replace(part,'z0',str(z0))
3619 part = replace(part,'sz',str(sz))
3620 return part
3621
3622 def scale_xy(part, x0, y0, sxy):
3623 part = replace(part,'X','(x0 + (X-x0)/sxy)')
3624 part = replace(part,'Y','(y0 + (Y-y0)/sxy)')
3625 part = replace(part,'x0',str(x0))
3626 part = replace(part,'y0',str(y0))
3627 part = replace(part,'sxy',str(sxy))
3628 return part
3629
3630 def scale_xyz(part, x0, y0, z0, sxyz):
3631 part = replace(part,'X','(x0 + (X-x0)/sxyz)')
3632 part = replace(part,'Y','(y0 + (Y-y0)/sxyz)')
3633 part = replace(part,'Z','(z0 + (Z-z0)/sxyz)')
3634 part = replace(part,'x0',str(x0))
3635 part = replace(part,'y0',str(y0))
3636 part = replace(part,'z0',str(z0))
3637 part = replace(part,'sxyz',str(sxyz))
3638 return part
3639
3640 def coscale_x_y(part, x0, y0, y1, angle0, angle1, amplitude, offset):
3641 phase0 = pi*angle0/180.
3642 phase1 = pi*angle1/180.
3643 part = replace(part,'X','(x0 + (X-x0)/(offset + amplitude*cos(phase0 + (phase1-phase0)*(Y-y0)/(y1-y0))))')
3644 part = replace(part,'x0',str(x0))
3645 part = replace(part,'y0',str(y0))
3646 part = replace(part,'y1',str(y1))
3647 part = replace(part,'phase0',str(phase0))
3648 part = replace(part,'phase1',str(phase1))
3649 part = replace(part,'amplitude',str(amplitude))
3650 part = replace(part,'offset',str(offset))
3651 return part
3652
3653 def coscale_x_z(part, x0, z0, z1, angle0, angle1, amplitude, offset):
3654 phase0 = pi*angle0/180.
3655 phase1 = pi*angle1/180.
3656 part = replace(part,'X','(x0 + (X-x0)/(offset + amplitude*cos(phase0 + (phase1-phase0)*(Z-z0)/(z1-z0))))')
3657 part = replace(part,'x0',str(x0))
3658 part = replace(part,'z0',str(z0))
3659 part = replace(part,'z1',str(z1))
3660 part = replace(part,'phase0',str(phase0))
3661 part = replace(part,'phase1',str(phase1))
3662 part = replace(part,'amplitude',str(amplitude))
3663 part = replace(part,'offset',str(offset))
3664 return part
3665
3666 def coscale_xy_z(part, x0, y0, z0, z1, angle0, angle1, amplitude, offset):
3667 phase0 = pi*angle0/180.
3668 phase1 = pi*angle1/180.
3669 part = replace(part,'X','(x0 + (X-x0)/(offset + amplitude*cos(phase0 + (phase1-phase0)*(Z-z0)/(z1-z0))))')
3670 part = replace(part,'Y','(y0 + (Y-y0)/(offset + amplitude*cos(phase0 + (phase1-phase0)*(Z-z0)/(z1-z0))))')
3671 part = replace(part,'x0',str(x0))
3672 part = replace(part,'y0',str(y0))
3673 part = replace(part,'z0',str(z0))
3674 part = replace(part,'z1',str(z1))
3675 part = replace(part,'phase0',str(phase0))
3676 part = replace(part,'phase1',str(phase1))
3677 part = replace(part,'amplitude',str(amplitude))
3678 part = replace(part,'offset',str(offset))
3679 return part
3680
3681 def taper_x_y(part, x0, y0, y1, s0, s1):
3682 part = replace(part,'X','(x0 + (X-x0)*(y1-y0)/(s1*(Y-y0) + s0*(y1-Y)))')
3683 part = replace(part,'x0',str(x0))
3684 part = replace(part,'y0',str(y0))
3685 part = replace(part,'y1',str(y1))
3686 part = replace(part,'s0',str(s0))
3687 part = replace(part,'s1',str(s1))
3688 return part
3689
3690 def taper_x_z(part, x0, z0, z1, s0, s1):
3691 part = replace(part,'X','(x0 + (X-x0)*(z1-z0)/(s1*(Z-z0) + s0*(z1-Z)))')
3692 part = replace(part,'x0',str(x0))
3693 part = replace(part,'z0',str(z0))
3694 part = replace(part,'z1',str(z1))
3695 part = replace(part,'s0',str(s0))
3696 part = replace(part,'s1',str(s1))
3697 return part
3698
3699 def taper_xy_z(part, x0, y0, z0, z1, s0, s1):
3700 part = replace(part,'X','(x0 + (X-x0)*(z1-z0)/(s1*(Z-z0) + s0*(z1-Z)))')
3701 part = replace(part,'Y','(y0 + (Y-y0)*(z1-z0)/(s1*(Z-z0) + s0*(z1-Z)))')
3702 part = replace(part,'x0',str(x0))
3703 part = replace(part,'y0',str(y0))
3704 part = replace(part,'z0',str(z0))
3705 part = replace(part,'z1',str(z1))
3706 part = replace(part,'s0',str(s0))
3707 part = replace(part,'s1',str(s1))
3708 return part
3709
3710 def shear_x_y(part, y0, y1, dx0, dx1):
3711 part = replace(part,'X','(X - dx0 - (dx1-dx0)*(Y-y0)/(y1-y0))')
3712 part = replace(part,'y0',str(y0))
3713 part = replace(part,'y1',str(y1))
3714 part = replace(part,'dx0',str(dx0))
3715 part = replace(part,'dx1',str(dx1))
3716 return part
3717
3718 def shear_x_z(part, z0, z1, dx0, dx1):
3719 part = replace(part,'X','(X - dx0 - (dx1-dx0)*(Z-z0)/(z1-z0))')
3720 part = replace(part,'z0',str(z0))
3721 part = replace(part,'z1',str(z1))
3722 part = replace(part,'dx0',str(dx0))
3723 part = replace(part,'dx1',str(dx1))
3724 return part
3725
3726 def coshear_x_z(part, z0, z1, angle0, angle1, amplitude, offset):
3727 phase0 = pi*angle0/180.
3728 phase1 = pi*angle1/180.
3729 part = replace(part,'X','(X - offset - amplitude*cos(phase0 + (phase1-phase0)*(Z-z0)/(z1-z0)))')
3730 part = replace(part,'z0',str(z0))
3731 part = replace(part,'z1',str(z1))
3732 part = replace(part,'phase0',str(phase0))
3733 part = replace(part,'phase1',str(phase1))
3734 part = replace(part,'amplitude',str(amplitude))
3735 part = replace(part,'offset',str(offset))
3736 return part
3737
3738 #
3739 # define part
3740 #
3741
3742 d = .5
3743 teapot = cylinder(0,0,-d,d,d)
3744 teapot = coscale_xy_z(teapot,0,0,-d,d,-90,90,.5,.75)
3745
3746 handle = torus(0,0,0,3.5*d/5.,d/10.)
3747 handle = reflect_xz(handle)
3748 handle = reflect_xy(handle)
3749 handle = scale_x(handle,0,.75)
3750 handle = scale_y(handle,0,3)
3751 handle = translate(handle,-6*d/5.,0,0)
3752 teapot = add(teapot,handle)
3753
3754 spout = torus(2.1*d,-.2*d,0,1.1*d,.2*d)
3755 spout = reflect_yz(spout)
3756 spout = intersect(spout,cube(-3*d,1.8*d,-3*d,3*d,0,3*d))
3757 teapot = add(teapot,spout)
3758
3759 interior = cylinder(0,0,.1-d,.1+d,d-.1)
3760 interior = coscale_xy_z(interior,0,0,-d,d,-90,90,.5,.75)
3761 teapot = subtract(teapot,interior)
3762
3763 spout_interior = torus(2.1*d,-.2*d,0,1.1*d,.15*d)
3764 spout_interior = reflect_yz(spout_interior)
3765 spout_interior = intersect(spout_interior,cube(-3*d,1.8*d,-3*d,3*d,0,3*d))
3766 teapot = subtract(teapot,spout_interior)
3767
3768 part = teapot
3769
3770 part = subtract(part,cube(0,3*d,-3*d,0,-3*d,3*d))
3771
3772 #
3773 # define limits and parameters
3774 #
3775
3776 width = 2.5
3777 x0 = 0
3778 y0 = 0
3779 z0 = 0
3780 cad.xmin = x0-width/2. # min x to render
3781 cad.xmax = x0+width/2. # max x to render
3782 cad.ymin = y0-width/2. # min y to render
3783 cad.ymax = y0+width/2. # max y to render
3784 #cad.zmin = z0-width/4. # min z to render
3785 #cad.zmax = z0+width/4. # max x to render
3786 cad.zmin = z0-width/4. # min z to render
3787 cad.zmax = z0+width/4. # max x to render
3788 cad.rx = 30 # x view rotation (degrees)
3789 cad.rz = 20 # z view rotation (degrees)
3790 dpi = 100 # rendering resolution
3791 cad.nx = int(dpi*(cad.xmax-cad.xmin)) # x points to render
3792 cad.ny = int(dpi*(cad.ymax-cad.ymin)) # y points to render
3793 cad.nz = int(dpi*(cad.zmax-cad.zmin)) # z points to render
3794 cad.inches_per_unit = 1.0 # use inch units
3795
3796 #
3797 # assign part to cad.function
3798 #
3799
3800 cad.function = part
3801
3802 """
3803
3804 #
3805 # check config file for window parameters
3806 #
3807
3808 cad_path = os.path.dirname(sys.argv[0])
3809 if (sys.argv[0] == "cad.py"):
3810 cfg_path = "cad.cfg"
3811 else:
3812 cfg_path = os.path.dirname(sys.argv[0])+"/cad.cfg"
3813 try:
3814 config_file = open(cfg_path, 'r')
3815 string_msg.set("found "+cfg_path)
3816 while 1:
3817 line = config_file.readline()
3818 if (find(line,"window size:") == 0):
3819 string_window_size.set(int(line[12:]))
3820 elif (find(line,"editor width:") == 0):
3821 string_editor_width.set(int(line[13:]))
3822 elif (find(line,"editor height:") == 0):
3823 string_editor_height.set(int(line[14:]))
3824 elif (line == ""):
3825 break
3826 config_file.close()
3827 resize_editor(0)
3828 except:
3829 string_msg.set(cfg_path+" not found")
3830
3831 #
3832 # read input file if on command line, otherwise use template
3833 #
3834
3835 if len(sys.argv) == 2:
3836 filename = sys.argv[1]
3837 string_input_file.set(filename)
3838 if (find(filename,'.cad') != -1):
3839 cad_load(0)
3840 elif ((find(filename,'.jpg') != -1) | (find(filename,'.JPG') != -1) |
3841 (find(filename,'.png') != -1) | (find(filename,'.PNG') != -1) |
3842 (find(filename,'.gif') != -1) | (find(filename,'.GIF') != -1)):
3843 widget_cad_text.delete("1.0",END)
3844 image_load(0)
3845 else:
3846 string_msg.set("unsupported input file format")
3847 root.update()
3848 else:
3849 widget_cad_text.insert("1.0",cad_template)
3850
3851 #
3852 # start GUI
3853 #
3854
3855 root.mainloop()

mercurial