|
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() |