# HG changeset patch # User mbayer # Date 1446899415 -3600 # Node ID ee535cb8fb1abca665a48b927fd8356756426136 added some stuff for reference diff -r 000000000000 -r ee535cb8fb1a stuff/(Cad.py) Plotting with Z axis movement.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/stuff/(Cad.py) Plotting with Z axis movement.py Sat Nov 07 13:30:15 2015 +0100 @@ -0,0 +1,3855 @@ +#!/usr/bin/env python +# +# cad.py +# +# Neil Gershenfeld +# +# (c) Massachusetts Institute of Technology 2007 +# Permission granted for experimental and personal use; +# license for commercial sale available from MIT. +# +#Altered by R Parsons (AKA: Capo) to output gcode with the '.gcode' extension as opposed to '.g'. +#Also the default variables were changed to metric values +DATE = "7/12/010" + +from numpy import * +import scipy.signal.signaltools +from string import * +from Tkinter import * +from tkFileDialog import * +import Image, ImageTk, ImageDraw, ImageFont, ImageOps +import os, struct +#import time + +class point: + # + # an xyz point + # + def __init__(self,x,y,z=0): + self.x = x + self.y = y + self.z = z + +class cad_variables: + # + # cad variables + # + def __init__(self): + self.xmin = 0 # minimum x value to render + self.xmax = 0 # maximum x value to render + self.ymin = 0 # minimum y value to render + self.ymax = 0 # maximum y value to render + self.zmin = 0 # minimum z value to render + self.zmax = 0 # maximum z value to render + self.zlist = [] # z values to render + self.nx = 0 # number of x points to render + self.ny = 0 # number of y points to render + self.nz = 1 # number of z points to render + self.rz = 0 # perspective view z rotation (degrees) + self.rx = 0 # perspective view x rotation (degrees) + self.units = 'in' # file units + self.function = '0' # cad function + self.toolpaths = [] # toolpaths + self.x = [] # x triangulation + self.y = [] # y triangulation + self.z = [] # z triangulation + self.labels = [] # display labels + self.image_r = array(0) # red array + self.image_g = array(0) # green array + self.image_b = array(0) # blue array + self.image_min = 0 # image min value + self.image_max = 0 # image max value + self.stop = 0 # stop rendering + self.nplot = 200 # plot window size + self.inches_per_unit = 1 # file units + self.views = 'xyzr' + self.cam = '' # CAM export type + self.editor_width = 30 # editor width + self.editor_height = 10 # editor height + def view(self,arg): + global canvas_xy,canvas_yz,canvas_xz,canvas_xyz + if (arg == 'xy'): + view_frame2.grid_forget() + view_frame3.grid_forget() + canvas_xy.grid_forget() + self.views = 'xy' + self.nplot = 2*int(string_window_size.get()) # plot window size + canvas_xy = Canvas(view_frame2, width=self.nplot, height=self.nplot) + imxy = Image.new("RGBX",(self.nplot,self.nplot),'black') + image_xy = ImageTk.PhotoImage(imxy) + canvas_xy.create_image(self.nplot/2,self.nplot/2,image=image_xy) + canvas_xy.bind('',msg_xy) + canvas_xy.grid(row=0,column=0) + view_frame2.grid(row=2,column=0) + elif (arg == 'xyzr'): + view_frame2.grid_forget() + view_frame3.grid_forget() + canvas_xy.grid_forget() + canvas_yz.grid_forget() + canvas_xz.grid_forget() + canvas_xyz.grid_forget() + self.views = 'xyzr' + self.nplot = int(string_window_size.get()) # plot window size + canvas_xy = Canvas(view_frame3, width=self.nplot, height=self.nplot) + canvas_yz = Canvas(view_frame3, width=self.nplot, height=self.nplot) + canvas_xz = Canvas(view_frame3, width=self.nplot, height=self.nplot) + canvas_xyz = Canvas(view_frame3, width=self.nplot, height=cad.nplot) + imxy = Image.new("RGBX",(self.nplot,self.nplot),'black') + image_xy = ImageTk.PhotoImage(imxy) + canvas_xy.create_image(self.nplot/2,self.nplot/2,image=image_xy) + canvas_xy.bind('',msg_xy) + canvas_xy.grid(row=0,column=0) + imyz = Image.new("RGBX",(self.nplot,self.nplot),'black') + image_yz = ImageTk.PhotoImage(imyz) + canvas_yz.create_image(self.nplot/2,self.nplot/2,image=image_yz) + canvas_yz.bind('',msg_yz) + canvas_yz.grid(row=0,column=1) + imxz = Image.new("RGBX",(self.nplot,self.nplot),'black') + image_xz = ImageTk.PhotoImage(imxz) + canvas_xz.create_image(self.nplot/2,self.nplot/2,image=image_xz) + canvas_xz.bind('',msg_xz) + canvas_xz.grid(row=1,column=0) + imxyz = Image.new("RGBX",(self.nplot,self.nplot),'black') + image_xyz = ImageTk.PhotoImage(imxyz) + canvas_xyz.create_image(self.nplot/2,self.nplot/2,image=image_xyz) + canvas_xyz.bind('',msg_nomsg) + canvas_xyz.grid(row=1,column=1) + view_frame3.grid(row=2,column=0) + else: + print "view not supported" + def nxplot(self): + xwidth = self.xmax - self.xmin + ywidth = self.ymax - self.ymin + zwidth = self.zmax - self.zmin + if ((xwidth >= ywidth) & (xwidth >= zwidth)): + n = int(self.nplot*xwidth/float(xwidth)) + elif ((ywidth >= xwidth) & (ywidth >= zwidth)): + n = int(self.nplot*xwidth/float(ywidth)) + else: + n = int(self.nplot*xwidth/float(zwidth)) + return n + def nyplot(self): + xwidth = self.xmax - self.xmin + ywidth = self.ymax - self.ymin + zwidth = self.zmax - self.zmin + if ((xwidth >= ywidth) & (xwidth >= zwidth)): + n = int(self.nplot*ywidth/float(xwidth)) + elif ((ywidth >= xwidth) & (ywidth >= zwidth)): + n = int(self.nplot*ywidth/float(ywidth)) + else: + n = int(self.nplot*ywidth/float(zwidth)) + return n + def nzplot(self): + xwidth = self.xmax - self.xmin + ywidth = self.ymax - self.ymin + zwidth = self.zmax - self.zmin + if ((xwidth >= ywidth) & (xwidth >= zwidth)): + n = int(self.nplot*zwidth/float(xwidth)) + elif ((ywidth >= xwidth) & (ywidth >= zwidth)): + n = int(self.nplot*zwidth/float(ywidth)) + else: + n = int(self.nplot*zwidth/float(zwidth)) + return n + +cad = cad_variables() + +class cad_text: + def __init__(self,x,y,z=0,text='',size=10,color='#ff0000',anchor=CENTER): + self.x = x + self.y = y + self.z = z + self.text = text + self.size = size + self.color = color + self.anchor = anchor + +class im_class: + # + # for PIL images + # + def __init__(self): + self.xy = 0 + self.xz = 0 + self.yz = 0 + self.xyz = 0 + self.intensity_xy = 0 + self.intensity_xz = 0 + self.intensity_yz = 0 + self.intensity_xyz = 0 + +im = im_class() + +class images_class: + # + # for PhotoImages + # + def __init__(self): + self.xy = 0 + self.xz = 0 + self.yz = 0 + self.xyz = 0 + +images = images_class() + +class CA_states: + # + # CA state definition class + # + def __init__(self): + self.empty = 0 + self.interior = 1 + self.edge = (1 << 1) # 2 + self.north = (1 << 2) # 4 + self.west = (2 << 2) # 8 + self.east = (3 << 2) # 12 + self.south = (4 << 2) # 16 + self.stop = (5 << 2) # 20 + self.corner = (6 << 2) # 24 + +class rule_table: + # + # CA rule table class + # + # 0 = empty + # 1 = interior + # 2 = edge + # edge+direction = start + # + def __init__(self): + self.table = zeros(2**(9*2),uint32) + self.s = CA_states() + # + # 1 0: + # + # 011 + # 111 + # 111 + self.add_rule(0,1,1,1,1,1,1,1,1,self.s.north) + # 101 + # 111 + # 111 + self.add_rule(1,0,1,1,1,1,1,1,1,self.s.east) + # + # 2 0's: + # + # 001 + # 111 + # 111 + self.add_rule(0,0,1,1,1,1,1,1,1,self.s.east) + # 100 + # 111 + # 111 + self.add_rule(1,0,0,1,1,1,1,1,1,self.s.east) + # 010 + # 111 + # 111 + self.add_rule(0,1,0,1,1,1,1,1,1,self.s.east) + # 011 + # 110 + # 111 + self.add_rule(0,1,1,1,1,0,1,1,1,self.s.south) + # 110 + # 011 + # 111 + self.add_rule(1,1,0,0,1,1,1,1,1,self.s.east) + # 101 + # 011 + # 111 + self.add_rule(1,0,1,0,1,1,1,1,1,self.s.east) + # 101 + # 110 + # 111 + self.add_rule(1,0,1,1,1,0,1,1,1,self.s.south) + # 011 + # 111 + # 110 + self.add_rule(0,1,1,1,1,1,1,1,0,self.s.corner) + # 011 + # 111 + # 101 + self.add_rule(0,1,1,1,1,1,1,0,1,self.s.north) + # 110 + # 111 + # 101 + self.add_rule(1,1,0,1,1,1,1,0,1,self.s.west) + # 101 + # 111 + # 110 + self.add_rule(1,0,1,1,1,1,1,1,0,self.s.south) + # 101 + # 111 + # 011 + self.add_rule(1,0,1,1,1,1,0,1,1,self.s.east) + # + # 3 0's: + # + # 001 + # 011 + # 111 + self.add_rule(0,0,1,0,1,1,1,1,1,self.s.east) + # 010 + # 011 + # 111 + self.add_rule(0,1,0,0,1,1,1,1,1,self.s.east) + # 010 + # 110 + # 111 + self.add_rule(0,1,0,1,1,0,1,1,1,self.s.south) + # 010 + # 111 + # 011 + self.add_rule(0,1,0,1,1,1,0,1,1,self.s.east) + # 010 + # 111 + # 110 + self.add_rule(0,1,0,1,1,1,1,1,0,self.s.south) + # 110 + # 011 + # 011 + self.add_rule(1,1,0,0,1,1,0,1,1,self.s.east) + # 011 + # 110 + # 110 + self.add_rule(0,1,1,1,1,0,1,1,0,self.s.south) + # 101 + # 011 + # 011 + self.add_rule(1,0,1,0,1,1,0,1,1,self.s.east) + # 101 + # 110 + # 110 + self.add_rule(1,0,1,1,1,0,1,1,0,self.s.south) + # 011 + # 011 + # 011 + self.add_rule(0,1,1,0,1,1,0,1,1,self.s.north) + # + # 4 0's: + # + # 001 + # 011 + # 011 + self.add_rule(0,0,1,0,1,1,0,1,1,self.s.east) + # 100 + # 110 + # 110 + self.add_rule(1,0,0,1,1,0,1,1,0,self.s.south) + # 010 + # 011 + # 011 + self.add_rule(0,1,0,0,1,1,0,1,1,self.s.east) + # 010 + # 110 + # 110 + self.add_rule(0,1,0,1,1,0,1,1,0,self.s.south) + # 001 + # 110 + # 110 + self.add_rule(0,0,1,1,1,0,1,1,0,self.s.south) + # 100 + # 011 + # 011 + self.add_rule(1,0,0,0,1,1,0,1,1,self.s.east) + # + # 5 0's: + # + # 000 + # 011 + # 011 + self.add_rule(0,0,0,0,1,1,0,1,1,self.s.east) + # + # edge states + # + # 200 + # 211 + # 211 + self.add_rule(2,0,0,2,1,1,2,1,1,self.s.east+self.s.edge) + # 201 + # 211 + # 211 + self.add_rule(2,0,1,2,1,1,2,1,1,self.s.east+self.s.edge) + # 210 + # 211 + # 211 + self.add_rule(2,1,0,2,1,1,2,1,1,self.s.east+self.s.edge) + # 002 + # 112 + # 112 + self.add_rule(0,0,2,1,1,2,1,1,2,self.s.stop) + # 102 + # 112 + # 112 + self.add_rule(1,0,2,1,1,2,1,1,2,self.s.stop) + # 002 + # 112 + # 102 + self.add_rule(0,0,2,1,1,2,1,0,2,self.s.stop) + # 012 + # 112 + # 112 + self.add_rule(0,1,2,1,1,2,1,1,2,self.s.stop) + # 012 + # 112 + # 102 + self.add_rule(0,1,2,1,1,2,1,0,2,self.s.stop) + + def add_rule(self,nw,nn,ne,ww,cc,ee,sw,ss,se,rule): + # + # add a CA rule, with rotations + # + s = CA_states() + # + # add the rule + # + state = \ + (nw << 0) + (nn << 2) + (ne << 4) + \ + (ww << 6) + (cc << 8) + (ee << 10) + \ + (sw << 12) + (ss << 14) + (se << 16) + self.table[state] = rule + # + # rotate 90 degrees + # + state = \ + (sw << 0) + (ww << 2) + (nw << 4) + \ + (ss << 6) + (cc << 8) + (nn << 10) + \ + (se << 12) + (ee << 14) + (ne << 16) + if (rule == s.east): + self.table[state] = s.south + elif (rule == s.south): + self.table[state] = s.west + elif (rule == s.west): + self.table[state] = s.north + elif (rule == s.north): + self.table[state] = s.east + elif (rule == (s.east+s.edge)): + self.table[state] = s.south+s.edge + elif (rule == (s.south+s.edge)): + self.table[state] = s.west+s.edge + elif (rule == (s.west+s.edge)): + self.table[state] = s.north+s.edge + elif (rule == (s.north+s.edge)): + self.table[state] = s.east+s.edge + elif (rule == s.corner): + self.table[state] = s.corner + elif (rule == s.stop): + self.table[state] = s.stop + # + # rotate 180 degrees + # + state = \ + (se << 0) + (ss << 2) + (sw << 4) + \ + (ee << 6) + (cc << 8) + (ww << 10) + \ + (ne << 12) + (nn << 14) + (nw << 16) + if (rule == s.east): + self.table[state] = s.west + elif (rule == s.south): + self.table[state] = s.north + elif (rule == s.west): + self.table[state] = s.east + elif (rule == s.north): + self.table[state] = s.south + elif (rule == (s.east+s.edge)): + self.table[state] = s.west+s.edge + elif (rule == (s.south+s.edge)): + self.table[state] = s.north+s.edge + elif (rule == (s.west+s.edge)): + self.table[state] = s.east+s.edge + elif (rule == (s.north+s.edge)): + self.table[state] = s.south+s.edge + elif (rule == s.corner): + self.table[state] = s.corner + elif (rule == s.stop): + self.table[state] = s.stop + # + # rotate 270 degrees + # + state = \ + (ne << 0) + (ee << 2) + (se << 4) + \ + (nn << 6) + (cc << 8) + (ss << 10) + \ + (nw << 12) + (ww << 14) + (sw << 16) + if (rule == s.east): + self.table[state] = s.north + elif (rule == s.south): + self.table[state] = s.east + elif (rule == s.west): + self.table[state] = s.south + elif (rule == s.north): + self.table[state] = s.west + elif (rule == (s.east+s.edge)): + self.table[state] = s.north+s.edge + elif (rule == (s.south+s.edge)): + self.table[state] = s.east+s.edge + elif (rule == (s.west+s.edge)): + self.table[state] = s.south+s.edge + elif (rule == (s.north+s.edge)): + self.table[state] = s.west+s.edge + elif (rule == s.corner): + self.table[state] = s.corner + elif (rule == s.stop): + self.table[state] = s.stop + +def evaluate_state(arr): + # + # assemble the state bit strings + # + (ny, nx) = shape(arr) + s = CA_states() + nn = concatenate(([s.edge+zeros(nx,uint32)],arr[:(ny-1)])) + ss = concatenate((arr[1:],[s.edge+zeros(nx,uint32)])) + ww = concatenate((reshape(s.edge+zeros(ny,uint32),(ny,1)),arr[:,:(nx-1)]),1) + ee = concatenate((arr[:,1:],reshape(s.edge+zeros(ny,uint32),(ny,1))),1) + cc = arr + nw = concatenate(([s.edge+zeros(nx,uint32)],ww[:(ny-1)])) + ne = concatenate(([s.edge+zeros(nx,uint32)],ee[:(ny-1)])) + sw = concatenate((ww[1:],[s.edge+zeros(nx,uint32)])) + se = concatenate((ee[1:],[s.edge+zeros(nx,uint32)])) + state = (nw << 0) + (nn << 2) + (ne << 4) + \ + (ww << 6) + (cc << 8) + (ee << 10) + \ + (sw << 12) + (ss << 14) + (se << 16) + return state + +def vectorize_toolpaths(arr): + # + # convert lattice toolpath directions to vectors + # + s = CA_states() + toolpaths = [] + max_dist = float(string_vector_error.get()) + start_sites = (arr == (s.north+s.edge)) | (arr == (s.south+s.edge)) | \ + (arr == (s.east+s.edge)) | (arr == (s.west+s.edge)) + num_start_sites = sum(sum(1.0*start_sites)) + path_sites = (arr == s.north) | (arr == s.south) | (arr == s.east) | \ + (arr == s.west) + num_path_sites = sum(sum(1.0*path_sites)) + remaining_sites = num_start_sites + num_path_sites + while (remaining_sites != 0): + #print remaining_sites + if (num_start_sites > 0): + # + # begin segment on a start state + # + if (argmax(start_sites[0,:],axis=0) != 0): + x = argmax(start_sites[0,:],axis=0) + y = 0 + elif (argmax(start_sites[:,0],axis=0) != 0): + x = 0 + y = argmax(start_sites[:,0],axis=0) + elif (argmax(start_sites[-1,:],axis=0) != 0): + x = argmax(start_sites[-1,:],axis=0) + y = cad.ny-1 + elif (argmax(start_sites[:,-1],axis=0) != 0): + x = cad.nx-1 + y = argmax(start_sites[:,-1],axis=0) + else: + print "error: internal start" + sys.exit() + #print "start from ",x,y + else: + # + # no start states; begin segment on upper-left boundary point + # + maxcols = argmax(path_sites,axis=1) + y = argmax(argmax(path_sites,axis=1)) + x = maxcols[y] + arr[y][x] += s.edge + #print "segment from ",x,y + segment = [point(x,y)] + vector = [point(x,y)] + while 1: + # + # follow path + # + y = vector[-1].y + x = vector[-1].x + state = arr[y][x] + # + # if start state, set stop + # + if (state == (s.north + s.edge)): + state = s.north + arr[y][x] = s.stop + elif (state == (s.south + s.edge)): + state = s.south + arr[y][x] = s.stop + elif (state == (s.east + s.edge)): + state = s.east + arr[y][x] = s.stop + elif (state == (s.west + s.edge)): + state = s.west + arr[y][x] = s.stop + #print "x,y,state,arr: ",x,y,state,arr[y][x] + # + # move if a valid direction + # + if (state == s.north): + direction = "north" + #print "north" + ynew = y - 1 + xnew = x + elif (state == s.south): + direction = "south" + #print "south" + ynew = y + 1 + xnew = x + elif (state == s.east): + direction = "east" + #print "east" + ynew = y + xnew = x + 1 + elif (state == s.west): + direction = "west" + #print "west" + ynew = y + xnew = x - 1 + elif (state == s.corner): + #print "corner" + if (direction == "east"): + #print "south" + xnew = x + ynew = y + 1 + elif (direction == "west"): + #print "north" + xnew = x + ynew = y - 1 + elif (direction == "north"): + #print "east" + ynew = y + xnew = x + 1 + elif (direction == "south"): + #print "west" + ynew = y + xnew = x - 1 + else: + # + # not a valid direction, terminate segment on previous point + # + print "unexpected path termination at",x,y + #sys.exit() + segment.append(point(x,y)) + toolpaths.append(segment) + arr[y][x] = s.interior + break + #print "xnew,ynew,snew",xnew,ynew,arr[ynew][xnew] + # + # check if stop reached + # + if (arr[ynew][xnew] == s.stop): + #print "stop at ",xnew,ynew + segment.append(point(xnew,ynew)) + toolpaths.extend([segment]) + if (state != s.corner): + arr[y][x] = s.interior + arr[ynew][xnew] = s.interior + break + # + # find max transverse distance from vector to new point + # + dmax = 0 + dx = xnew - vector[0].x + dy = ynew - vector[0].y + norm = sqrt(dx**2 + dy**2) + nx = dy / norm + ny = -dx / norm + for i in range(len(vector)): + dx = vector[i].x - vector[0].x + dy = vector[i].y - vector[0].y + d = abs(nx*dx + ny*dy) + if (d > dmax): + dmax = d + # + # start new vector if transverse distance > max_dist + # + if (dmax >= max_dist): + #print "max at ",x,y + segment.append(point(x,y)) + vector = [point(x,y)] + # + # otherwise add point to vector + # + else: + #print "add ",xnew,ynew + vector.append(point(xnew,ynew)) + if ((arr[y][x] != s.corner) & (arr[y][x] != s.stop)): + arr[y][x] = s.interior + start_sites = (arr == (s.north+s.edge)) | (arr == (s.south+s.edge)) | \ + (arr == (s.east+s.edge)) | (arr == (s.west+s.edge)) + num_start_sites = sum(sum(1.0*start_sites)) + path_sites = (arr == s.north) | (arr == s.south) | (arr == s.east) | \ + (arr == s.west) + num_path_sites = sum(sum(1.0*path_sites)) + remaining_sites = num_start_sites + num_path_sites + # + # reverse segment order, to start from inside to out + # + newpaths = [] + for segment in range(len(toolpaths)): + newpaths.append(toolpaths[-1-segment]) + root.update() + return newpaths + +def evaluate(): + # + # evaluate .cad program/image + # + if (len(widget_cad_text.get("1.0",END)) > 1): + # + # .cad + # + cad.zlist = [] + cad_text_string = widget_cad_text.get("1.0",END) + exec cad_text_string in globals() + widget_function_text.config(state=NORMAL) + widget_function_text.delete("1.0",END) + widget_function_text.insert("1.0",cad.function) + widget_function_text.config(state=DISABLED) + if (cad.image_r.size > 1): + # + # image + # + cad.xmin = float(string_image_xmin.get()) + xwidth = float(string_image_xwidth.get()) + cad.xmax = cad.xmin + xwidth + cad.ymin = float(string_image_ymin.get()) + yheight = float(string_image_yheight.get()) + cad.ymax = cad.ymin + yheight + cad.image_min = float(string_image_min.get()) + cad.image_max = float(string_image_max.get()) + cad.zmin = float(string_image_zmin.get()) + cad.zmax = float(string_image_zmax.get()) + cad.nz = int(string_image_nz.get()) + cad.inches_per_unit = float(string_image_units.get()) + +def render(view='xyzr'): + render_stop_flag = 0 + cad.stop = 0 + # + # if .cad doesn't call render, delete windows and add stop button + # + if (find(widget_cad_text.get("1.0",END),"render(") == -1): + string_msg.set("render ...") + widget_stop.pack() + delete_windows() + # + # initialize variables + # + cad.toolpaths = [] + rx = pi*cad.rx/180. + rz = pi*cad.rz/180. + r = rule_table() + s = CA_states() + # + # evaluate coordinate arrays + # + Xarray = outer(ones((cad.ny,1)),cad.xmin+(cad.xmax-cad.xmin)*arange(cad.nx)/(cad.nx-1.0)) + Yarray = outer(cad.ymin+(cad.ymax-cad.ymin)*arange(cad.ny-1,-1,-1)/(cad.ny-1.0),ones((1,cad.nx))) + if (cad.zlist == []): + if ((cad.nz == 1) & (cad.image_r.size != 1)): + cad.zlist = [cad.zmax] + cad.view('xy') + elif (cad.nz == 1): + cad.zlist = [cad.zmin] + cad.view('xy') + else: + cad.zlist = cad.zmin + (cad.zmax-cad.zmin)*arange(cad.nz)/(cad.nz-1.0) + cad.view('xyzr') + else: + cad.nz = len(cad.zlist) + cad.zmin = cad.zlist[0] + cad.zmax = cad.zlist[-1] + # + # draw orthogonal views + # + X = Xarray + Y = Yarray + accum_r = zeros((cad.ny,cad.nx),uint32) + accum_g = zeros((cad.ny,cad.nx),uint32) + accum_b = zeros((cad.ny,cad.nx),uint32) + im.intensity_yz = zeros((cad.ny,cad.nz),uint32) + im.intensity_xz = zeros((cad.nz,cad.nx),uint32) + im.intensity_xyz = zeros((cad.nz,cad.nx),uint32) + for layer in range(cad.nz): + # + # check render stop button + # + if (cad.stop == 1): + break + # + # xy view + # + Z = cad.zlist[layer] + string_msg.set("render z = %.3f"%Z) + # root.update() + if (cad.image_r.size == 1): + # + # .cad + # + array_r = eval(cad.function) + array_g = array_r + array_b = array_r + if ((cad.zmax == cad.zmin) | (cad.nz == 1)): + zi = array([255],uint32) + else: + zi = array([55.0 + 200.0*layer/(cad.nz-1.0)],uint32) + accum_r = where(((zi*array_r) > accum_r),(zi*array_r),accum_r) + accum_g = where(((zi*array_g) > accum_g),(zi*array_g),accum_g) + accum_b = where(((zi*array_b) > accum_b),(zi*array_b),accum_b) + im.intensity_xy = (1 << 16)*accum_b + (1 << 8)*accum_g + (1 << 0)*accum_r + else: + # + # bitmap + # + array_r = (cad.image_r[0,] >= (cad.image_min + (cad.image_max-cad.image_min)*(Z-cad.zmin)/float(cad.zmax-cad.zmin))) + array_g = (cad.image_g[0,] >= (cad.image_min + (cad.image_max-cad.image_min)*(Z-cad.zmin)/float(cad.zmax-cad.zmin))) + array_b = (cad.image_b[0,] >= (cad.image_min + (cad.image_max-cad.image_min)*(Z-cad.zmin)/float(cad.zmax-cad.zmin))) + image_z = int(cad.image_min + (cad.image_max-cad.image_min)*(Z-cad.zmin)/float(cad.zmax-cad.zmin)) + intensity_r = where((cad.image_r[0,] <= image_z),cad.image_r[0,],image_z) + intensity_g = where((cad.image_g[0,] <= image_z),cad.image_g[0,],image_z) + intensity_b = where((cad.image_b[0,] <= image_z),cad.image_b[0,],image_z) + im.intensity_xy = (1 << 16)*intensity_b + (1 << 8)*intensity_g + (1 << 0)*intensity_r + im.xy = Image.fromarray(im.intensity_xy,mode="RGBX") + im.xy_draw = ImageDraw.Draw(im.xy) + im.xy = im.xy.resize((cad.nxplot(),cad.nyplot())) + images.xy = ImageTk.PhotoImage(im.xy) + canvas_xy.create_image(cad.nplot/2,cad.nplot/2,image=images.xy) + # root.update() + # + # find toolpaths if needed + # + ncontours = int(string_num_contours.get()) + if (ncontours == -1): + ncontours = 2**20 # a big number + cad.toolpaths.append([]) + """ + if (ncontours != 0): + # + # grassfire convolve (to come) + # + interior = (array_r | array_g | array_b) + print shape(X[interior]) + conv_array = interior + """ + for contour in range(ncontours): + # + # check render stop button + # + if (cad.stop == 1): + break + # + # convolve tool for contour + # + string_msg.set(" convolve tool ... ") + # + # FFT convolve + # + # root.update() + tool_rad = float(string_tool_dia.get())/2.0 + tool_dia = float(string_tool_dia.get()) + tool_overlap = float(string_tool_overlap.get()) + kernel_rad = tool_rad + contour*tool_overlap*tool_dia + ikernel_rad = 1 + int(cad.nx*kernel_rad/(cad.xmax-cad.xmin)) + if (ikernel_rad > (((cad.nx/2),(cad.ny/2))[(cad.ny/2) > (cad.nx/2)])): + break + kx = 1+outer(ones((2*ikernel_rad,1)),arange(2*ikernel_rad)) + ky = 1+outer(arange(2*ikernel_rad),ones((1,2*ikernel_rad))) + k = (((kx-ikernel_rad)**2 + (ky-ikernel_rad)**2) < ikernel_rad**2).astype('uint32') + interior = (array_r == s.interior).astype('uint32') + #tstart = time.time() + conv = scipy.signal.signaltools.fftconvolve(interior,k,mode='same') + conv = where(conv > 0.01,s.interior,0) + conv_array = conv + (conv != s.interior)*array_r + #tend = time.time() + #print 'convolve:',tend-tstart + # + # use CA rule table to find edge directions + # + string_msg.set(" follow edges ... ") + # root.update() + state = evaluate_state(conv_array) + toolpath = r.table[state] + tool_array = toolpath + (toolpath == s.empty)*conv_array + tool_intensity = \ + ((0 << 16) + (0 << 8) + (0 << 0))*(tool_array == s.empty).astype('uint32') +\ + ((255 << 16) + (255 << 8) + (255 << 0))*(tool_array == s.interior).astype('uint32') +\ + (( 0 << 16) + ( 0 << 8) + (255 << 0))*(tool_array == s.north).astype('uint32') +\ + (( 0 << 16) + (255 << 8) + ( 0 << 0))*(tool_array == s.south).astype('uint32') +\ + ((255 << 16) + ( 0 << 8) + ( 0 << 0))*(tool_array == s.east).astype('uint32') +\ + (( 0 << 16) + (255 << 8) + (255 << 0))*(tool_array == s.west ).astype('uint32') +\ + ((128 << 16) + ( 0 << 8) + (128 << 0))*(tool_array == s.stop).astype('uint32') + + # + # show CA + # + """ + im.xy = Image.fromarray(tool_intensity,mode="RGBX") + im.xy = im.xy.resize((cad.nplot,cad.nplot)) + images.xy = ImageTk.PhotoImage(im.xy) + canvas_xy.create_image(cad.nplot/2,cad.nplot/2,image=images.xy) + """ + # + # vectorize contour + # + #tstart = time.time() + string_msg.set(" vectorize ... ") + # root.update() + new_paths = vectorize_toolpaths(tool_array) + if (len(new_paths) == 0): + break + cad.toolpaths[layer].extend(new_paths) + #tend = time.time() + #print 'vector:',tend-tstart + # + # draw toolpath + # + im.xy_draw = ImageDraw.Draw(im.xy) + for segment in range(len(cad.toolpaths[layer])): + x = cad.nxplot()*(cad.toolpaths[layer][segment][0].x+0.5)/float(cad.nx) + y = cad.nyplot()*(cad.toolpaths[layer][segment][0].y+0.5)/float(cad.ny) + for vertex in range(1,len(cad.toolpaths[layer][segment])): + xnew = cad.nxplot()*(cad.toolpaths[layer][segment][vertex].x+0.5)/float(cad.nx) + ynew = cad.nyplot()*(cad.toolpaths[layer][segment][vertex].y+0.5)/float(cad.ny) + im.xy_draw.line([x,y,xnew,ynew],fill="#ffa0a0",width=1) + x = xnew + y = ynew + # + # show xy toolpath view + # + images.xy = ImageTk.PhotoImage(im.xy) + canvas_xy.create_image(cad.nplot/2,cad.nplot/2,image=images.xy) + # + # add send_to button + # + string_send_to_time.set("") + send_to_frame.pack() + # root.update() + # + # draw labels + # + for label in range(len(cad.labels)): + x = cad.nplot/2. + cad.nxplot()*(cad.labels[label].x-(cad.xmax+cad.xmin)/2.0)/(cad.xmax-cad.xmin) + y = cad.nplot/2. - cad.nyplot()*(cad.labels[label].y-(cad.ymax+cad.ymin)/2.0)/(cad.ymax-cad.ymin) + string = cad.labels[label].text + size = cad.labels[label].size + color = cad.labels[label].color + anch = cad.labels[label].anchor + canvas_xy.create_text(x,y,text=string,font=('arial',size,'bold'),fill=color,anchor=anch,justify=CENTER) + # + # draw origin + # + x0 = cad.nplot/2. + cad.nxplot()*(0-(cad.xmax+cad.xmin)/2.)/(cad.xmax-cad.xmin) + y0 = cad.nplot/2. - cad.nyplot()*(0-(cad.ymax+cad.ymin)/2.)/(cad.ymax-cad.ymin) + dxy = .025*cad.nplot + canvas_xy.create_line([x0-dxy,y0,x0+dxy,y0],fill="green") + canvas_xy.create_line([x0,y0-dxy,x0,y0+dxy],fill="green") + # + # yz view + # + if (cad.views == 'xyzr'): + accum_yz_r = zeros(cad.ny,uint32) + accum_yz_g = zeros(cad.ny,uint32) + accum_yz_b = zeros(cad.ny,uint32) + for vertex in range(cad.nx): + xi = array([55.0 + 200.0*vertex/(cad.nx-1.0)],uint32) + slice_r = array_r[:,vertex] + slice_g = array_g[:,vertex] + slice_b = array_b[:,vertex] + accum_yz_r = where(((xi*slice_r) >= accum_yz_r),(xi*slice_r),accum_yz_r) + accum_yz_g = where(((xi*slice_g) >= accum_yz_g),(xi*slice_g),accum_yz_g) + accum_yz_b = where(((xi*slice_b) >= accum_yz_b),(xi*slice_b),accum_yz_b) + im.intensity_yz[:,layer] = (1 << 16)*accum_yz_b + (1 << 8)*accum_yz_g + (1 << 0)*accum_yz_r + im.yz = Image.fromarray(im.intensity_yz,mode="RGBX") + im.yz = im.yz.transpose(Image.FLIP_LEFT_RIGHT) + im.yz = im.yz.resize((cad.nzplot(),cad.nyplot())) + images.yz = ImageTk.PhotoImage(im.yz) + canvas_yz.create_image(cad.nplot/2,cad.nplot/2,image=images.yz) + # + # draw origin + # + z0 = cad.nplot/2. - cad.nzplot()*(0-(cad.zmax+cad.zmin)/2.)/(cad.zmax-cad.zmin) + y0 = cad.nplot/2. - cad.nyplot()*(0-(cad.ymax+cad.ymin)/2.)/(cad.ymax-cad.ymin) + canvas_yz.create_line([z0-dxy,y0,z0+dxy,y0],fill="green") + canvas_yz.create_line([z0,y0-dxy,z0,y0+dxy],fill="green") + # + # xz view + # + if (cad.views == 'xyzr'): + accum_xz_r = zeros(cad.nx,uint32) + accum_xz_g = zeros(cad.nx,uint32) + accum_xz_b = zeros(cad.nx,uint32) + for vertex in range(cad.ny): + yi = array([55.0+200.0*vertex/(cad.ny-1.0)],uint32) + slice_r = array_r[vertex,:] + slice_g = array_g[vertex,:] + slice_b = array_b[vertex,:] + accum_xz_r = where(((yi*slice_r) >= accum_xz_r),(yi*slice_r),accum_xz_r) + accum_xz_g = where(((yi*slice_g) >= accum_xz_g),(yi*slice_g),accum_xz_g) + accum_xz_b = where(((yi*slice_b) >= accum_xz_b),(yi*slice_b),accum_xz_b) + im.intensity_xz[(cad.nz-1-layer),:] = (1 << 16)*accum_xz_b + (1 << 8)*accum_xz_g + (1 << 0)*accum_xz_r + im.xz = Image.fromarray(im.intensity_xz,mode="RGBX") + im.xz = im.xz.resize((cad.nxplot(),cad.nzplot())) + images.xz = ImageTk.PhotoImage(im.xz) + canvas_xz.create_image(cad.nplot/2,cad.nplot/2,image=images.xz) + # + # draw origin + # + x0 = cad.nplot/2. + cad.nxplot()*(0-(cad.xmax+cad.xmin)/2.)/(cad.xmax-cad.xmin) + z0 = cad.nplot/2. - cad.nzplot()*(0-(cad.zmax+cad.zmin)/2.)/(cad.zmax-cad.zmin) + canvas_xz.create_line([x0-dxy,z0,x0+dxy,z0],fill="green") + canvas_xz.create_line([x0,z0-dxy,x0,z0+dxy],fill="green") + # + # draw it + # + root.update() + # + # rotated view + # + if ((cad.views == 'xyzr') & (cad.image_r.size == 1)): + accum = zeros((cad.ny,cad.nx),uint32) + for z in cad.zlist: + # + # check render stop button + # + if (cad.stop == 1): + break + string_msg.set("render z = %.3f"%z) + dY = cos(rx)*(Yarray-(cad.ymax+cad.ymin)/2.0) - sin(rx)*(z-(cad.zmax+cad.zmin)/2.0) + 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) + X = (cad.xmax+cad.xmin)/2.0 + cos(rz)*(Xarray-(cad.xmax+cad.xmin)/2.0) - sin(rz)*dY + Y = (cad.ymax+cad.ymin)/2.0 + sin(rz)*(Xarray-(cad.xmax+cad.xmin)/2.0) + cos(rz)*dY + arr = eval(cad.function) + if (cad.zmax == cad.zmin): + zi = array([255],uint32) + else: + zi = array([55.0 + 200.0*(z-cad.zmin)/(cad.zmax-cad.zmin)],uint32) + accum = where(((zi*arr) > accum),(zi*arr),accum) + im.intensity_xyz = ((1 << 16) + (1 << 8) + (1 << 0)) * accum + im.xyz = Image.fromarray(im.intensity_xyz,mode="RGBX") + im.xyz = im.xyz.resize((cad.nxplot(),cad.nyplot())) + images.xyz = ImageTk.PhotoImage(im.xyz) + canvas_xyz.create_image(cad.nplot/2,cad.nplot/2,image=images.xyz) + root.update() + # + # return + # + cad.zwrite = cad.zlist + cad.zlist = [] + widget_stop.pack_forget() + string_msg.set("done") + root.update() + return + +def draw_toolpath(): + im.xy = Image.new("RGBX",(cad.nxplot(),cad.nyplot()),'white') + im.xy_draw = ImageDraw.Draw(im.xy) + for layer in range(len(cad.toolpaths)): + for segment in range(len(cad.toolpaths[layer])): + x = cad.nxplot()*(cad.toolpaths[layer][segment][0].x+0.5)/float(cad.nx) + y = cad.nyplot()*(cad.toolpaths[layer][segment][0].y+0.5)/float(cad.ny) + for vertex in range(1,len(cad.toolpaths[layer][segment])): + xnew = cad.nxplot()*(cad.toolpaths[layer][segment][vertex].x+0.5)/float(cad.nx) + ynew = cad.nyplot()*(cad.toolpaths[layer][segment][vertex].y+0.5)/float(cad.ny) + im.xy_draw.line([x,y,xnew,ynew],fill="black") + x = xnew + y = ynew + images.xy = ImageTk.PhotoImage(im.xy) + canvas_xy.create_image(cad.nplot/2,cad.nplot/2,image=images.xy) + +def delete_windows(): + im.xy = Image.new("RGBX",(cad.nplot,cad.nplot),'black') + images.xy = ImageTk.PhotoImage(im.xy) + canvas_xy.create_image(cad.nplot/2,cad.nplot/2,image=images.xy) + im.yz = Image.new("RGBX",(cad.nplot,cad.nplot),'black') + images.yz = ImageTk.PhotoImage(im.yz) + canvas_yz.create_image(cad.nplot/2,cad.nplot/2,image=images.yz) + im.xz = Image.new("RGBX",(cad.nplot,cad.nplot),'black') + images.xz = ImageTk.PhotoImage(im.xz) + canvas_xz.create_image(cad.nplot/2,cad.nplot/2,image=images.xz) + im.xyz = Image.new("RGBX",(cad.nplot,cad.nplot),'black') + images.xyz = ImageTk.PhotoImage(im.xyz) + canvas_xyz.create_image(cad.nplot/2,cad.nplot/2,image=images.xyz) + root.update() + +def select_cad(): + image_x_frame.pack_forget() + image_y_frame.pack_forget() + image_z_frame.pack_forget() + image_intensity_frame.pack_forget() + image_units_frame.pack_forget() + image_invert_frame.pack_forget() + cad_input_frame.pack_forget() + widget_cad_text.delete("1.0",END) + widget_cad_text.insert("1.0",cad_template) + editor_frame.pack() + cad.image = array(0) + cad_input_frame.pack() + cad.toolpaths = [] + string_num_contours.set('0') + widget_cad_save.pack(side='left') + delete_windows() + +def select_image(): + editor_frame.pack_forget() + cad_input_frame.pack_forget() + image_x_frame.pack() + image_y_frame.pack() + image_z_frame.pack() + image_intensity_frame.pack() + image_units_frame.pack() + image_invert_frame.pack() + cad_input_frame.pack() + cad.toolpaths = [] + string_num_contours.set('0') + widget_cad_save.pack_forget() + delete_windows() + +def input_open(): + filename = askopenfilename() + string_input_file.set(filename) + if (find(filename,'.cad') != -1): + cad_load(0) + elif ((find(filename,'.jpg') != -1) | (find(filename,'.JPG') != -1) | + (find(filename,'.png') != -1) | (find(filename,'.PNG') != -1) | + (find(filename,'.gif') != -1) | (find(filename,'.GIF') != -1)): + widget_cad_text.delete("1.0",END) + image_load(0) + else: + string_msg.set("unsupported input file format") + root.update() + +def cad_load(event): + global cad + cad = cad_variables() + cam_pack_forget() + select_cad() + input_file_name = string_input_file.get() + input_file = open(input_file_name,'rb') + cad_text_string = input_file.read() + widget_cad_text.delete("1.0",END) + widget_cad_text.insert("1.0",cad_text_string) + input_file.close() + cad.toolpaths = [] + cad.image = array(0) + cad.nz = 1 + string_num_contours.set('0') + evaluate() + if (find(widget_cad_text.get("1.0",END),"render(") == -1): + render() + +def image_load(event): + global cad + cad = cad_variables() + cam_pack_forget() + select_image() + function_string_frame.pack_forget() + input_file_name = string_input_file.get() + input_file = open(input_file_name,'rb') + input_file.close() + cad.toolpaths = [] + string_num_contours.set('0') + image = Image.open(input_file_name) + num_layers = 1 + while 1: # check number of layers + try: + image.seek(image.tell()+1) + num_layers += 1 + except: + break + image = Image.open(input_file_name) + if image.mode != "RGBX": + image = image.convert("RGBX") + (cad.nx,cad.ny) = image.size + info = image.info + if ('dpi' in info): + (xdpi,ydpi) = info['dpi'] + else: + xdpi = cad.nx + ydpi = xdpi + string_image_nx.set(" nx = "+str(cad.nx)) + string_image_ny.set(" ny = "+str(cad.ny)) + cad.nz = 1 + string_image_nz.set(str(cad.nz)) + cad.xmin = 0 + string_image_xmin.set('0') + cad.xmax = cad.nx/float(xdpi) + string_image_xwidth.set(str(cad.xmax-cad.xmin)) + cad.ymin = 0 + string_image_ymin.set('0') + cad.ymax = cad.ny/float(ydpi) + string_image_yheight.set(str(cad.ymax-cad.ymin)) + cad.zmin = -.005 + string_image_zmin.set('-0.05') + cad.zmax = 0.05 + string_image_zmax.set('0.05') + cad.inches_per_unit = 1.0 + string_image_units.set('25.4') + data = zeros((num_layers,cad.nx*cad.ny,3),uint32) + data[0,] = array(image.convert("RGB").getdata(),uint32) + for layer in range(1,num_layers): + image.seek(image.tell()+1) + data[layer,] = array(image.convert("RGB").getdata(),uint32) + cad.image_r = array(data[:,:,0],uint32) + cad.image_r = cad.image_r.reshape((num_layers,cad.ny,cad.nx)) + cad.image_g = array(data[:,:,1],uint32) + cad.image_g = cad.image_g.reshape((num_layers,cad.ny,cad.nx)) + cad.image_b = array(data[:,:,2],uint32) + cad.image_b = cad.image_b.reshape((num_layers,cad.ny,cad.nx)) + cad.image_min = 1 + string_image_min.set(str(cad.image_min)) + cad.image_max = 255 + string_image_max.set(str(cad.image_max)) + evaluate() + render() + +def invert_image(event): + cad.image_r = 255 - cad.image_r + cad.image_g = 255 - cad.image_g + cad.image_b = 255 - cad.image_b + evaluate() + render() + +def cad_save(event): + input_file_name = string_input_file.get() + input_file = open(input_file_name,'wb') + cad_text_string = widget_cad_text.get("1.0",END) + input_file.write(cad_text_string) + input_file.close() + string_msg.set(input_file_name+" saved") + root.update() + +def render_button(event): + cam_pack_forget() + cad.cam = '' + if (cad.image_r.size == 1): + function_string_frame.pack() + cad.toolpaths = [] + string_num_contours.set('0') + evaluate() + if (find(widget_cad_text.get("1.0",END),"render(") == -1): + render() + +def render_stop(event): + cad.stop = 1 + widget_stop.pack_forget() + +def cam(event): + function_string_frame.pack_forget() + cam_file_frame.pack() + string_num_contours.set('1') + root.update() + +def contour(event): + evaluate() + if (find(widget_cad_text.get("1.0",END),"render(") == -1): + render() + +def triangulate(event): + # + # triangulate for STL + # + # evaluate .cad + # + evaluate() + # + # initialize variables + # + render_stop_flag = 0 + cad.stop = 0 + widget_stop.pack() + delete_windows() + cad.toolpaths = [] + cad.zwrite = [] + cad.x = zeros(0) + cad.y = zeros(0) + cad.z = zeros(0) + ixlr = array([]) + iylrs = array([]) + iylre = array([]) + izlr = array([]) + ixfbs = array([]) + ixfbe = array([]) + iyfb = array([]) + izfb = array([]) + ixtbs = array([]) + ixtbe = array([]) + iytb = array([]) + iztb = array([]) + # + # evaluate coordinate arrays + # + (IY,IX) = indices((cad.ny,cad.nx)) + IY = IY[::-1,:] + X = cad.xmin+(cad.xmax-cad.xmin)*IX/(cad.nx-1.0) + Y = cad.ymin+(cad.ymax-cad.ymin)*IY/(cad.ny-1.0) + cad.zwrite = cad.zmin + (cad.zmax-cad.zmin)*arange(cad.nz)/(cad.nz-1.0) + # + # set up drawing images + # + im.xy = Image.new("RGBX",(cad.nxplot(),cad.nyplot()),'white') + im.xy_draw = ImageDraw.Draw(im.xy) + im.xz = Image.new("RGBX",(cad.nxplot(),cad.nzplot()),'white') + im.xz_draw = ImageDraw.Draw(im.xz) + im.yz = Image.new("RGBX",(cad.nzplot(),cad.nyplot()),'white') + im.yz_draw = ImageDraw.Draw(im.yz) + # + # loop over layers + # + Z = cad.zwrite[0] + array0 = eval(cad.function) + Z = cad.zwrite[1] + array1 = eval(cad.function) + for layer in range(2,len(cad.zwrite)): + # + # check render stop button + # + if (cad.stop == 1): + break + # + # evaluate new layer + # + Z = cad.zwrite[layer] + string_msg.set("triangulate z = %.3f"%Z) + root.update() + array2 = eval(cad.function) + # + # find left faces and merge y + # + elements = hstack((reshape((array1[:,0] == True),(cad.ny,1)),((array1[:,1:] == True) & (array1[:,:-1] == False)))) + starts = vstack((((elements[:-1,:] == True) & (elements[1:,:] == False)),reshape((elements[-1,:] == True),(1,cad.nx)))) + ends = vstack((reshape((elements[0,:] == True),(1,cad.nx)),((elements[1:,:] == True) & (elements[:-1,:] == False)))) + IY_t = transpose(IY) # for starts and ends to be read in same row + IX_t = transpose(IX) + starts_t = transpose(starts) + ends_t = transpose(ends) + ixlr = append(ixlr,IX_t[starts_t]) + iylrs = append(iylrs,IY_t[starts_t]) + iylre = append(iylre,1+IY_t[ends_t]) + izlr = append(izlr,(layer-1)*ones(len(IX_t[starts_t]))) + # + # find right faces and merge y + # + elements = hstack((((array1[:,1:] == False) & (array1[:,:-1] == True)),reshape((array1[:,1] == True),(cad.ny,1)))) + starts = vstack((((elements[:-1,:] == True) & (elements[1:,:] == False)),reshape((elements[-1,:] == True),(1,cad.nx)))) + ends = vstack((reshape((elements[0,:] == True),(1,cad.nx)),((elements[1:,:] == True) & (elements[:-1,:] == False)))) + IY_t = transpose(IY) # for starts and ends to be read in same row + IX_t = transpose(IX) + starts_t = transpose(starts) + ends_t = transpose(ends) + ixlr = append(ixlr,1+IX_t[starts_t]) + iylre = append(iylre,IY_t[starts_t]) + iylrs = append(iylrs,1+IY_t[ends_t]) + izlr = append(izlr,(layer-1)*ones(len(IX_t[starts_t]))) + # + # find front faces and merge x + # + elements = vstack((((array1[:-1,:] == True) & (array1[1:,:] == False)),reshape((array1[0,:] == True),(1,cad.nx)))) + starts = hstack((reshape((elements[:,0] == True),(cad.ny,1)),((elements[:,1:] == True) & (elements[:,:-1] == False)))) + ends = hstack((((elements[:,:-1] == True) & (elements[:,1:] == False)),reshape((elements[:,-1] == True),(cad.ny,1)))) + ixfbs = append(ixfbs,IX[starts]) + ixfbe = append(ixfbe,1+IX[ends]) + iyfb = append(iyfb,IY[starts]) + izfb = append(izfb,(layer-1)*ones(len(IX[starts]))) + # + # find back faces and merge x + # + elements = vstack((reshape((array1[-1,:] == True),(1,cad.nx)),((array1[1:,:] == True) & (array1[:-1,:] == False)))) + starts = hstack((reshape((elements[:,0] == True),(cad.ny,1)),((elements[:,1:] == True) & (elements[:,:-1] == False)))) + ends = hstack((((elements[:,:-1] == True) & (elements[:,1:] == False)),reshape((elements[:,-1] == True),(cad.ny,1)))) + ixfbe = append(ixfbe,IX[starts]) + ixfbs = append(ixfbs,1+IX[ends]) + iyfb = append(iyfb,1+IY[starts]) + izfb = append(izfb,(layer-1)*ones(len(IX[starts]))) + # + # find top faces and merge x + # + elements = ((array2 == False) & (array1 == True)) + starts = hstack((reshape((elements[:,0] == True),(cad.ny,1)),((elements[:,1:] == True) & (elements[:,:-1] == False)))) + ends = hstack((((elements[:,:-1] == True) & (elements[:,1:] == False)),reshape((elements[:,-1] == True),(cad.ny,1)))) + ixtbs = append(ixtbs,IX[starts]) + ixtbe = append(ixtbe,1+IX[ends]) + iytb = append(iytb,IY[starts]) + iztb = append(iztb,layer*ones(len(IX[starts]))) + # + # find bottom faces and merge x + # + elements = ((array0 == False) & (array1 == True)) + starts = hstack((reshape((elements[:,0] == True),(cad.ny,1)),((elements[:,1:] == True) & (elements[:,:-1] == False)))) + ends = hstack((((elements[:,:-1] == True) & (elements[:,1:] == False)),reshape((elements[:,-1] == True),(cad.ny,1)))) + ixtbe = append(ixtbe,IX[starts]) + ixtbs = append(ixtbs,1+IX[ends]) + iytb = append(iytb,IY[starts]) + iztb = append(iztb,(layer-1)*ones(len(IX[starts]))) + # + # push array stack + # + array0 = array1 + array1 = array2 + # + # z merge front/back faces + # + index = lexsort(keys=(izfb,ixfbe,ixfbs,iyfb)) + merge = (iyfb[index[1:]] == iyfb[index[:-1]]) & \ + (ixfbe[index[1:]] == ixfbe[index[:-1]]) & \ + (ixfbs[index[1:]] == ixfbs[index[:-1]]) & \ + ((izfb[index[1:]] - izfb[index[:-1]]) == 1) + merge = append(False,merge).astype(bool_) + starts = ((merge[1:] == True) & (merge[:-1] == False)) + starts = append(starts,False).astype(bool_) + ends = ((merge[1:] == False) & (merge[:-1] == True)) + if (merge[-1] == True): + ends = append(ends,True) + else: + ends = append(ends,False) + ends = ends.astype(bool_) + xs = ixfbs[index][starts | ~merge] + xe = ixfbe[index][starts | ~merge] + y = iyfb[index][starts | ~merge] + zs = izfb[index][starts | ~merge] + ze = izfb[index][ends | ~(merge | starts)]+1 + cad.x = ravel(transpose(vstack((xs,xe,xs,xs,xe,xe)))) + cad.y = ravel(transpose(vstack((y,y,y,y,y,y)))) + cad.z = ravel(transpose(vstack((zs,ze,ze,zs,zs,ze)))) + # + # z merge left/right faces + # + index = lexsort(keys=(izlr,iylre,iylrs,ixlr)) + merge = (ixlr[index[1:]] == ixlr[index[:-1]]) & \ + (iylre[index[1:]] == iylre[index[:-1]]) & \ + (iylrs[index[1:]] == iylrs[index[:-1]]) & \ + ((izlr[index[1:]] - izlr[index[:-1]]) == 1) + merge = append(False,merge).astype(bool_) + starts = ((merge[1:] == True) & (merge[:-1] == False)) + starts = append(starts,False).astype(bool_) + ends = ((merge[1:] == False) & (merge[:-1] == True)) + if (merge[-1] == True): + ends = append(ends,True) + else: + ends = append(ends,False) + ends = ends.astype(bool_) + x = ixlr[index][starts | ~merge] + ys = iylrs[index][starts | ~merge] + ye = iylre[index][starts | ~merge] + zs = izlr[index][starts | ~merge] + ze = izlr[index][ends | ~(merge | starts)]+1 + cad.x = append(cad.x,ravel(transpose(vstack((x,x,x,x,x,x))))) + cad.y = append(cad.y,ravel(transpose(vstack((ys,ye,ys,ys,ye,ye))))) + cad.z = append(cad.z,ravel(transpose(vstack((zs,ze,ze,zs,zs,ze))))) + # + # y merge top/bottom faces + # + index = lexsort(keys=(iytb,ixtbe,ixtbs,iztb)) + merge = (iztb[index[1:]] == iztb[index[:-1]]) & \ + (ixtbe[index[1:]] == ixtbe[index[:-1]]) & \ + (ixtbs[index[1:]] == ixtbs[index[:-1]]) & \ + ((iytb[index[1:]] - iytb[index[:-1]]) == 1) + merge = append(False,merge).astype(bool_) + starts = ((merge[1:] == True) & (merge[:-1] == False)) + starts = append(starts,False).astype(bool_) + ends = ((merge[1:] == False) & (merge[:-1] == True)) + if (merge[-1] == True): + ends = append(ends,True) + else: + ends = append(ends,False) + ends = ends.astype(bool_) + xs = ixtbs[index][starts | ~merge] + xe = ixtbe[index][starts | ~merge] + ys = iytb[index][starts | ~merge] + ye = iytb[index][ends | ~(merge | starts)]+1 + z = iztb[index][starts | ~merge] + cad.x = append(cad.x,ravel(transpose(vstack((xs,xe,xs,xs,xe,xe))))) + cad.y = append(cad.y,ravel(transpose(vstack((ys,ye,ye,ys,ys,ye))))) + cad.z = append(cad.z,ravel(transpose(vstack((z,z,z,z,z,z))))) + # + # draw triangulation + # + widget_stop.pack_forget() + string_msg.set("draw ...") + root.update() + N = len(cad.x) + for i in range(0,N,3): + string_msg.set("draw triangle %d/%d"%(i/3,N/3)) + root.update() + x0 = cad.nxplot()*(cad.x[i]+0.5)/float(cad.nx) + y0 = cad.nyplot()*(cad.ny-cad.y[i]+0.5)/float(cad.ny) + z0 = cad.nzplot()*(cad.nz-cad.z[i]+0.5)/float(cad.nz) + x1 = cad.nxplot()*(cad.x[i+1]+0.5)/float(cad.nx) + y1 = cad.nyplot()*(cad.ny-cad.y[i+1]+0.5)/float(cad.ny) + z1 = cad.nzplot()*(cad.nz-cad.z[i+1]+0.5)/float(cad.nz) + x2 = cad.nxplot()*(cad.x[i+2]+0.5)/float(cad.nx) + y2 = cad.nyplot()*(cad.ny-cad.y[i+2]+0.5)/float(cad.ny) + z2 = cad.nzplot()*(cad.nz-cad.z[i+2]+0.5)/float(cad.nz) + im.xy_draw.line([x0,y0,x1,y1,x2,y2,x0,y0],fill="black") + im.xz_draw.line([x0,z0,x1,z1,x2,z2,x0,z0],fill="black") + im.yz_draw.line([z0,y0,z1,y1,z2,y2,z0,y0],fill="black") + images.xy = ImageTk.PhotoImage(im.xy) + images.xz = ImageTk.PhotoImage(im.xz) + images.yz = ImageTk.PhotoImage(im.yz) + canvas_xy.create_image(cad.nplot/2,cad.nplot/2,image=images.xy) + canvas_xz.create_image(cad.nplot/2,cad.nplot/2,image=images.xz) + canvas_yz.create_image(cad.nplot/2,cad.nplot/2,image=images.yz) + im.xyz = Image.new("RGBX",(cad.nplot,cad.nplot),'white') + images.xyz = ImageTk.PhotoImage(im.xyz) + canvas_xyz.create_image(cad.nplot/2,cad.nplot/2,image=images.xyz) + string_msg.set("done") + root.update() + +def flash(event): + # + # convert to Gerber flashes + # + # evaluate .cad + # + evaluate() + # + # initialize variables + # + render_stop_flag = 0 + cad.stop = 0 + widget_stop.pack() + delete_windows() + cad.toolpaths = [] + cad.zwrite = [] + cad.x = zeros(0) + cad.y = zeros(0) + cad.z = zeros(0) + ixs = array([]) + ixe = array([]) + iy = array([]) + iz = array([]) + # + # evaluate coordinate arrays + # + (IY,IX) = indices((cad.ny,cad.nx)) + IY = IY[::-1,:] + IZ = arange(cad.nz) + X = cad.xmin+(cad.xmax-cad.xmin)*IX/(cad.nx-1.0) + Y = cad.ymin+(cad.ymax-cad.ymin)*IY/(cad.ny-1.0) + if (cad.zwrite == []): + if (cad.nz > 1): + cad.zwrite = cad.zmin + (cad.zmax-cad.zmin)*arange(cad.nz)/(cad.nz-1.0) + else: + cad.zwrite = [cad.zmin] + # + # set up drawing image + # + im.xy = Image.new("RGBX",(cad.nxplot(),cad.nyplot()),'white') + im.xy_draw = ImageDraw.Draw(im.xy) + # + # loop over layers + # + for layer in range(len(cad.zwrite)): + # + # check render stop button + # + if (cad.stop == 1): + break + # + # evaluate layer + # + Z = cad.zwrite[layer] + string_msg.set("convert z = %.3f"%Z) + root.update() + elements = eval(cad.function) + # + # merge x + # + starts = hstack((reshape((elements[:,0] == TRUE),(cad.ny,1)),((elements[:,1:] == TRUE) & (elements[:,:-1] == FALSE)))) + ends = hstack((((elements[:,:-1] == TRUE) & (elements[:,1:] == FALSE)),reshape((elements[:,-1] == TRUE),(cad.ny,1)))) + ixs = append(ixs,IX[starts]) + ixe = append(ixe,1+IX[ends]) + iy = append(iy,IY[starts]) + iz = append(iz,IZ[layer-1]*ones(len(IX[starts]))) + # + # merge y + # + index = lexsort(keys=(iy,ixe,ixs,iz)) + merge = (iz[index[1:]] == iz[index[:-1]]) & \ + (ixe[index[1:]] == ixe[index[:-1]]) & \ + (ixs[index[1:]] == ixs[index[:-1]]) & \ + ((iy[index[1:]] - iy[index[:-1]]) == 1) + merge = append(FALSE,merge).astype(bool_) + starts = ((merge[1:] == TRUE) & (merge[:-1] == FALSE)) + starts = append(starts,FALSE).astype(bool_) + ends = ((merge[1:] == FALSE) & (merge[:-1] == TRUE)) + if (merge[-1] == TRUE): + ends = append(ends,TRUE) + else: + ends = append(ends,FALSE) + ends = ends.astype(bool_) + xs = ixs[index][starts | ~merge] + xe = ixe[index][starts | ~merge] + ys = iy[index][starts | ~merge] + ye = iy[index][ends | ~(merge | starts)]+1 + cad.x = ravel(transpose(vstack((xs,xe)))) + cad.y = ravel(transpose(vstack((ys,ye)))) + # + # draw flashes + # + widget_stop.pack_forget() + cad.view('xy') + string_msg.set("draw ...") + root.update() + N = len(cad.x) + for i in range(0,N,2): + string_msg.set("draw flash %d/%d"%(i/4,N/4)) + root.update() + x0 = cad.nxplot()*(cad.x[i]+0.5)/float(cad.nx) + y0 = cad.nyplot()*(cad.ny-cad.y[i]+0.5)/float(cad.ny) + x1 = cad.nxplot()*(cad.x[i]+0.5)/float(cad.nx) + y1 = cad.nyplot()*(cad.ny-cad.y[i+1]+0.5)/float(cad.ny) + x2 = cad.nxplot()*(cad.x[i+1]+0.5)/float(cad.nx) + y2 = cad.nyplot()*(cad.ny-cad.y[i+1]+0.5)/float(cad.ny) + x3 = cad.nxplot()*(cad.x[i+1]+0.5)/float(cad.nx) + y3 = cad.nyplot()*(cad.ny-cad.y[i]+0.5)/float(cad.ny) + im.xy_draw.line([x0,y0,x1,y1,x2,y2,x3,y3,x0,y0],fill="black") + images.xy = ImageTk.PhotoImage(im.xy) + canvas_xy.create_image(cad.nplot/2,cad.nplot/2,image=images.xy) + string_msg.set("done") + root.update() + +def select_epi(): + input_file_name = string_input_file.get() + string_cam_file.set(input_file_name[0:-4]+'.epi') + cad.cam = 'epi' + cam_pack_forget() + cam_file_frame.pack() + cam_vector_frame.pack() + cam_dia_frame.pack() + cam_contour_frame.pack() + laser_frame1.pack() + if ((cad.nz > 1) | (cad.image_r.size > 1)): + laser_frame2.pack() + laser_frame3.pack() + string_laser_rate.set("2500") + string_laser_power.set("90") + string_laser_speed.set("50") + string_laser_min_power.set("10") + string_laser_max_power.set("100") + string_tool_dia.set("0.01") + root.update() + +def select_camm(): + input_file_name = string_input_file.get() + string_cam_file.set(input_file_name[0:-4]+'.camm') + cad.cam = 'camm' + cam_pack_forget() + cam_file_frame.pack() + cam_vector_frame.pack() + cam_dia_frame.pack() + cam_contour_frame.pack() + cut_frame.pack() + string_cut_force.set("45") + string_cut_velocity.set("2") + string_tool_dia.set("0.01") + root.update() + +def select_ps(): + input_file_name = string_input_file.get() + string_cam_file.set(input_file_name[0:-4]+'.ps') + cad.cam = 'ps' + cam_pack_forget() + cam_file_frame.pack() + cam_vector_frame.pack() + cam_dia_frame.pack() + cam_contour_frame.pack() + fill_frame.pack() + string_tool_dia.set("0.0") + root.update() + +def select_ord(): + input_file_name = string_input_file.get() + string_cam_file.set(input_file_name[0:-4]+'.ord') + cad.cam = 'ord' + cam_pack_forget() + cam_file_frame.pack() + cam_vector_frame.pack() + cam_dia_frame.pack() + cam_contour_frame.pack() + string_tool_dia.set("0.01") + waterjet_frame.pack() + string_lead_in.set("0.05") + string_quality.set("-3") + root.update() + +def select_g(): + input_file_name = string_input_file.get() + string_cam_file.set(input_file_name[0:-4]+'.gcode') + cad.cam = 'g' + cam_pack_forget() + cam_file_frame.pack() + cam_vector_frame.pack() + string_tool_dia.set("0.0156") + cam_dia_frame.pack() + cam_contour_frame.pack() + string_g_feed_rate.set("20") + string_g_spindle_speed.set("5000") + string_g_tool.set("1") + integer_g_cool.set("0") + g_frame.pack() + root.update() + +def select_rml(): + input_file_name = string_input_file.get() + string_cam_file.set(input_file_name[0:-4]+'.rml') + cad.cam = 'rml' + cam_pack_forget() + cam_file_frame.pack() + cam_vector_frame.pack() + cam_dia_frame.pack() + cam_contour_frame.pack() + speed_frame.pack() + rml_move_frame.pack() + string_tool_dia.set("0.0156") + string_xy_speed.set("4") + string_z_speed.set("4") + string_rml_x_move.set("1") + string_rml_y_move.set("1") + root.update() + +def select_sbp(): + input_file_name = string_input_file.get() + string_cam_file.set(input_file_name[0:-4]+'.sbp') + cad.cam = 'sbp' + cam_pack_forget() + cam_file_frame.pack() + cam_vector_frame.pack() + cam_dia_frame.pack() + cam_contour_frame.pack() + jog_frame.pack() + speed_frame.pack() + string_tool_dia.set("0.125") + string_xy_speed.set("1.1") + string_z_speed.set("1.1") + string_jog_xy_speed.set("7") + string_jog_z_speed.set("7") + string_jog_z.set(".25") + root.update() + +def select_oms(): + input_file_name = string_input_file.get() + string_cam_file.set(input_file_name[0:-4]+'.oms') + cad.cam = 'oms' + cam_pack_forget() + cam_file_frame.pack() + cam_vector_frame.pack() + cam_dia_frame.pack() + cam_contour_frame.pack() + excimer_frame.pack() + string_pulse_period.set("10000") + string_tool_dia.set("0.001") + string_cut_vel.set("0.1") + string_cut_accel.set("5.0") + root.update() + +def select_dxf(): + input_file_name = string_input_file.get() + string_cam_file.set(input_file_name[0:-4]+'.dxf') + cad.cam = 'dxf' + cam_pack_forget() + cam_file_frame.pack() + cam_vector_frame.pack() + cam_dia_frame.pack() + cam_contour_frame.pack() + string_tool_dia.set("0.0") + root.update() + +def select_uni(): + input_file_name = string_input_file.get() + string_cam_file.set(input_file_name[0:-4]+'.uni') + cad.cam = 'uni' + cam_pack_forget() + cam_file_frame.pack() + cam_vector_frame.pack() + cam_dia_frame.pack() + cam_contour_frame.pack() + laser_frame1.pack() + if ((cad.nz > 1) | (cad.image_r.size > 1)): + laser_frame2.pack() + string_laser_rate.set("500") + string_laser_power.set("60") + string_laser_speed.set("15") + string_tool_dia.set("0.01") + string_laser_min_power.set("10") + string_laser_max_power.set("100") + string_vector_error.set('1.1') + root.update() + +def select_jpg(): + input_file_name = string_input_file.get() + string_cam_file.set(input_file_name[0:-4]+'.jpg') + cad.cam = 'jpg' + cam_pack_forget() + cam_file_frame.pack() + root.update() + +def select_png(): + input_file_name = string_input_file.get() + string_cam_file.set(input_file_name[0:-4]+'.png') + cad.cam = 'png' + cam_pack_forget() + cam_file_frame.pack() + root.update() + +def select_stl(): + input_file_name = string_input_file.get() + string_cam_file.set(input_file_name[0:-4]+'.stl') + cad.cam = 'stl' + cam_pack_forget() + cam_file_frame.pack() + STL_frame.pack() + root.update() + +def select_gerber(): + input_file_name = string_input_file.get() + string_cam_file.set(input_file_name[0:-4]+'.grb') + cad.cam = 'grb' + cam_pack_forget() + cam_file_frame.pack() + Gerber_frame.pack() + root.update() + +def select_excellon(): + input_file_name = string_input_file.get() + string_cam_file.set(input_file_name[0:-4]+'.drl') + cad.cam = 'drl' + cam_pack_forget() + cam_file_frame.pack() + Excellon_frame.pack() + root.update() + +def select_ca(): + input_file_name = string_input_file.get() + string_cam_file.set(input_file_name[0:-4]+'.ca') + cad.cam = 'ca' + cam_pack_forget() + cam_file_frame.pack() + root.update() + +def cam_pack_forget(): + cam_file_frame.pack_forget() + cam_vector_frame.pack_forget() + cam_dia_frame.pack_forget() + cam_contour_frame.pack_forget() + laser_frame1.pack_forget() + laser_frame2.pack_forget() + laser_frame3.pack_forget() + cut_frame.pack_forget() + speed_frame.pack_forget() + jog_frame.pack_forget() + rml_move_frame.pack_forget() + waterjet_frame.pack_forget() + excimer_frame.pack_forget() + STL_frame.pack_forget() + Gerber_frame.pack_forget() + Excellon_frame.pack_forget() + fill_frame.pack_forget() + g_frame.pack_forget() + send_to_frame.pack_forget() + +def save_cam(event): + # + # write toolpath + # + if (cad.cam == "epi"): + write_epi() + elif (cad.cam == "camm"): + write_camm() + elif (cad.cam == "ps"): + write_ps() + elif (cad.cam == "ord"): + write_ord() + elif (cad.cam == "g"): + write_G() + elif (cad.cam == "rml"): + write_rml() + elif (cad.cam == "sbp"): + write_sbp() + elif (cad.cam == "oms"): + write_oms() + elif (cad.cam == "dxf"): + write_dxf() + elif (cad.cam == "uni"): + write_uni() + elif (cad.cam == "jpg"): + write_jpg() + elif (cad.cam == "png"): + write_png() + elif (cad.cam == "stl"): + write_stl() + elif (cad.cam == "grb"): + write_gerber() + elif (cad.cam == "drl"): + write_excellon() + elif (cad.cam == "ca"): + write_ca() + else: + string_msg.set("unsupported output file format") + root.update() + +def write_epi(): + # + # Epilog lasercutter output + # todo: try 1200 DPI + # + units = 600*cad.inches_per_unit + filename = string_cam_file.get() + file = open(filename, 'wb') + if (integer_laser_autofocus.get() == 0): + # + # init with autofocus off + # + 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()+";") + else: + # + # init with autofocus on + # + 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()+";") + power = float(string_laser_power.get()) + min_power = float(string_laser_min_power.get()) + max_power = float(string_laser_max_power.get()) + for layer in range(len(cad.toolpaths)): + if ((len(cad.zwrite) > 1) & (len(cad.toolpaths[layer]) > 0)): + fraction = (cad.zwrite[layer]-cad.zwrite[0])/(cad.zwrite[-1]-cad.zwrite[0]) + layer_power = min_power + fraction*(max_power-min_power) + file.write("YP%f;"%layer_power) + for segment in range(len(cad.toolpaths[layer])): + x = int(units*(cad.xmin + (cad.xmax-cad.xmin)*(cad.toolpaths[layer][segment][0].x+0.5)/float(cad.nx))) + y = int(units*(-cad.ymin - ((cad.ymax-cad.ymin)*((cad.ny-cad.toolpaths[layer][segment][0].y)+0.5)/float(cad.ny)))) + file.write("PU"+str(x)+","+str(y)+";") + for vertex in range(1,len(cad.toolpaths[layer][segment])): + x = int(units*(cad.xmin + (cad.xmax-cad.xmin)*(cad.toolpaths[layer][segment][vertex].x+0.5)/float(cad.nx))) + y = int(units*(-cad.ymin - ((cad.ymax-cad.ymin)*((cad.ny-cad.toolpaths[layer][segment][vertex].y)+0.5)/float(cad.ny)))) + file.write("PD"+str(x)+","+str(y)+";") + file.write("%0B%1BPUE%-12345X@PJL EOJ \r\n") + file.close() + draw_toolpath() + string_msg.set("wrote %s"%filename) + root.update() + +def write_camm(): + filename = string_cam_file.get() + file = open(filename, 'wb') + units = 1016*cad.inches_per_unit + file.write("PA;PA;!ST1;!FS"+string_cut_force.get()+";VS"+string_cut_velocity.get()+";") + for layer in range(len(cad.toolpaths)): + for segment in range(len(cad.toolpaths[layer])): + x = int(units*(cad.xmin + (cad.xmax-cad.xmin)*(cad.toolpaths[layer][segment][0].x+0.5)/float(cad.nx))) + y = int(units*(cad.ymin + (cad.ymax-cad.ymin)*((cad.ny-cad.toolpaths[layer][segment][0].y)+0.5)/float(cad.ny))) + file.write("PU"+str(x)+","+str(y)+";") + for vertex in range(1,len(cad.toolpaths[layer][segment])): + x = int(units*(cad.xmin + (cad.xmax-cad.xmin)*(cad.toolpaths[layer][segment][vertex].x+0.5)/float(cad.nx))) + y = int(units*(cad.ymin + (cad.ymax-cad.ymin)*((cad.ny-cad.toolpaths[layer][segment][vertex].y)+0.5)/float(cad.ny))) + file.write("PD"+str(x)+","+str(y)+";") + file.write("PU0,0;") + file.close() + draw_toolpath() + string_msg.set("wrote %s"%filename) + root.update() + +def write_ps(): + # + # Postscript output + # + units = cad.inches_per_unit + filename = string_cam_file.get() + file = open(filename, 'wb') + file.write("%! cad.py output\n") + file.write("%%%%BoundingBox: 0 0 %.3f %.3f\n"% + (72.0*(cad.xmax-cad.xmin),72.0*(cad.ymax-cad.ymin))) + file.write("/m {moveto} def\n") + file.write("/l {lineto} def\n") + file.write("72 72 scale\n") + file.write(".005 setlinewidth\n") + file.write("%f %f translate\n"%(0.5,0.5)) + for layer in range(len(cad.toolpaths)): + for segment in range(len(cad.toolpaths[layer])): + x = units*(cad.xmin + (cad.xmax-cad.xmin)*(cad.toolpaths[layer][segment][0].x+0.5)/float(cad.nx)) + y = units*(cad.ymin + (cad.ymax-cad.ymin)*((cad.ny-cad.toolpaths[layer][segment][0].y)+0.5)/float(cad.ny)) + file.write("%f %f m\n"%(x,y)) + for vertex in range(1,len(cad.toolpaths[layer][segment])): + x = units*(cad.xmin + (cad.xmax-cad.xmin)*(cad.toolpaths[layer][segment][vertex].x+0.5)/float(cad.nx)) + y = units*(cad.ymin + (cad.ymax-cad.ymin)*((cad.ny-cad.toolpaths[layer][segment][vertex].y)+0.5)/float(cad.ny)) + file.write("%f %f l\n"%(x,y)) + if (integer_fill.get() == 0): + file.write("stroke\n") + else: + file.write("fill\n") + file.write("showpage\n") + file.close() + draw_toolpath() + string_msg.set("wrote %s"%filename) + root.update() + +def write_ord(): + # + # OMAX waterjet output + # + units = cad.inches_per_unit + lead_in = float(string_lead_in.get()) + quality = int(string_quality.get()) + filename = string_cam_file.get() + file = open(filename, 'wb') + xlead = [] + ylead = [] + for layer in range(len(cad.toolpaths)): + for segment in range(len(cad.toolpaths[layer])): + # + # calculate and write lead-in + # + x0 = units*(cad.xmin + (cad.xmax-cad.xmin)*(cad.toolpaths[layer][segment][0].x+0.5)/float(cad.nx)) + y0 = units*(cad.ymin + (cad.ymax-cad.ymin)*((cad.ny-cad.toolpaths[layer][segment][0].y)+0.5)/float(cad.ny)) + x1 = units*(cad.xmin + (cad.xmax-cad.xmin)*(cad.toolpaths[layer][segment][1].x+0.5)/float(cad.nx)) + y1 = units*(cad.ymin + (cad.ymax-cad.ymin)*((cad.ny-cad.toolpaths[layer][segment][1].y)+0.5)/float(cad.ny)) + dx = x1 - x0 + dy = y1 - y0 + norm_x = -dy + norm_y = dx + norm = sqrt(norm_x**2 + norm_y**2) + norm_x = norm_x/norm + norm_y = norm_y/norm + xlead.append(x0 + norm_x*lead_in) + ylead.append(y0 + norm_y*lead_in) + file.write("%f, %f, 0, %d\n"%(xlead[segment],ylead[segment],quality)) + # + # loop over segment + # + for vertex in range(len(cad.toolpaths[layer][segment])): + x = units*(cad.xmin + (cad.xmax-cad.xmin)*(cad.toolpaths[layer][segment][vertex].x+0.5)/float(cad.nx)) + y = units*(cad.ymin + (cad.ymax-cad.ymin)*((cad.ny-cad.toolpaths[layer][segment][vertex].y)+0.5)/float(cad.ny)) + file.write("%f, %f, 0, %d\n"%(x,y,quality)) + # + # write lead-out + # + file.write("%f, %f, 0, 0\n"%(x0,y0)) + file.write("%f, %f, 0, 0\n"%(xlead[segment],ylead[segment])) + file.close() + # + # draw toolpath with lead-in/out + # + im.xy = Image.new("RGBX",(cad.nxplot(),cad.nyplot()),'white') + im.xy_draw = ImageDraw.Draw(im.xy) + for layer in range(len(cad.toolpaths)): + for segment in range(len(cad.toolpaths[layer])): + x = cad.nxplot()*(cad.toolpaths[layer][segment][0].x+0.5)/float(cad.nx) + y = cad.nyplot()*(cad.toolpaths[layer][segment][0].y+0.5)/float(cad.ny) + xl = cad.nxplot()*(xlead[segment]-cad.xmin)/(cad.xmax-cad.xmin) + yl = cad.nyplot()-cad.nyplot()*(ylead[segment]-cad.ymin)/(cad.ymax-cad.ymin) + im.xy_draw.line([xl,yl,x,y],fill="black") + for vertex in range(1,len(cad.toolpaths[layer][segment])): + xnew = cad.nxplot()*(cad.toolpaths[layer][segment][vertex].x+0.5)/float(cad.nx) + ynew = cad.nyplot()*(cad.toolpaths[layer][segment][vertex].y+0.5)/float(cad.ny) + im.xy_draw.line([x,y,xnew,ynew],fill="black") + x = xnew + y = ynew + images.xy = ImageTk.PhotoImage(im.xy) + canvas_xy.create_image(cad.nplot/2,cad.nplot/2,image=images.xy) + string_msg.set("wrote %s"%filename) + root.update() + +def distance(x1, y1, x2, y2): + return sqrt((x1-x2)**2+(y1-y2)**2) + +def write_G(): + # + # G code output + # + units = cad.inches_per_unit + zup = units*cad.zmax + feed_rate = float(string_g_feed_rate.get()) + spindle_speed = float(string_g_spindle_speed.get()) + coolant = integer_g_cool.get() + tool = int(string_g_tool.get()) + if (cad.nz == 1): + cad.zwrite = [cad.zmin] + filename = string_cam_file.get() + file = open(filename, 'wb') + file.write("""(---------------------------------------------------------------) +(---------------------------------------------------------------) +(Start of sheet header) +G21 (metric ftw) +G90 (absolute mode) +G92 X0 Y0 Z0 (zero all axes) +G92 Z0.00 F150.00 (go up to printing level) +M106 (pen down) +G4 P120 (wait 120ms) +M300 S50 (pen up) +G4 P120 (wait 120ms) +M18 (disengage drives) +M01 (Was registration test successful?) +(while drives are disengaged, adjustments can be made to position) +M17 (engage drives if YES, and continue) +(End of sheet header)\n""") + dxy = 0 + dz = 0 + xold = 0 + yold = 0 + for layer in range(len(cad.zwrite)-1,-1,-1): + zdown = units*cad.zwrite[layer] + # + # follow toolpaths CCW, for CW tool motion + # + unsorted_segments = cad.toolpaths[layer] + sorted_segments = [] + if len(unsorted_segments) > 0: + sorted_segments.append(unsorted_segments.pop(0)) #starts with the first path in the list + else: + print "empty path --- strange" + + while len(unsorted_segments) > 0: + #find closest start to the the last sorted segment start + min_dist = 99999 + min_dist_index = None + for i in range(len(unsorted_segments)): + dist = distance(sorted_segments[-1][0].x, sorted_segments[-1][0].y, + unsorted_segments[i][0].x, unsorted_segments[i][0].y) + if dist < min_dist: + min_dist = dist + min_dist_index = i + + #print "min_dist: %d index: %d" % (min_dist, min_dist_index) + sorted_segments.append(unsorted_segments.pop(min_dist_index)) + + for segment in range(len(sorted_segments)): + + x = units*(cad.xmin + (cad.xmax-cad.xmin)*(sorted_segments[segment][0].x+0.5)/float(cad.nx)) + y = units*(cad.ymin + (cad.ymax-cad.ymin)*((cad.ny-sorted_segments[segment][0].y)+0.5)/float(cad.ny)) + file.write("G1 X%0.4f "%x+"Y%0.4f "%y+"Z%0.4f"%zup+" F2000.00\n") # rapid motion + file.write("G1 Z%0.4f "%zdown+" F300.00\n") # linear motion + dxy += sqrt((xold-x)**2+(yold-y)**2) + xold = x + yold = y + dz += zup-zdown + for vertex in range(1,len(sorted_segments[segment])): + x = units*(cad.xmin + (cad.xmax-cad.xmin)*(sorted_segments[segment][vertex].x+0.5)/float(cad.nx)) + y = units*(cad.ymin + (cad.ymax-cad.ymin)*((cad.ny-sorted_segments[segment][vertex].y)+0.5)/float(cad.ny)) + file.write("G1 X%0.4f "%x+"Y%0.4f"%y+" F2000.00\n") + dxy += sqrt((xold-x)**2+(yold-y)**2) + xold = x + yold = y + file.write("""(Start of sheet footer.) +M107 +G4 P120 (wait 120ms) +G0 X0 Y0 Z15 F3500.00 (go to position for retrieving platform -- increase Z to Z25 or similar if you have trouble avoiding tool) +G4 P300 (wait 300ms) +M01 (Have you retrieved the print?) +(machine halts until 'okay') +G4 P120 (if yes continue, pause 120ms before ... ) +G0 Z0 F3500.00 (return to start position of current sheet) +G4 P300 (wait 300ms) +M18 (disengage drives) +(End of sheet footer) + +M01 (Printing on the next sheet?) +(yes, if dropping the default .1 mm to next sheet; no, if you will print again on same sheet) +G0 Z-0.10 F3500.00 (drop 0.1mm to next sheet) + +(Paste in further sheets below) +(---------------------------------------------------------------) +(---------------------------------------------------------------) +""") + file.close() + print "Path length: %f" % dxy + time = (dxy/feed_rate + dz/feed_rate) + string_send_to_time.set(" estimated time: %.1f minutes"%time) + draw_toolpath() + string_msg.set("wrote %s"%filename) + root.update() + +def write_rml(): + # + # Roland Modela output + # + units = 1016*cad.inches_per_unit # 40/mm + filename = string_cam_file.get() + file = open(filename, 'wb') + file.write("PA;PA;VS"+string_xy_speed.get()+";!VZ"+string_z_speed.get()+";!MC1;") + zup = cad.zmax + izup = int(units*zup) + if (cad.nz == 1): + cad.zwrite = [cad.zmin] + xy_speed = float(string_xy_speed.get()) # mm/s + z_speed = float(string_z_speed.get()) # mm/s + dxy = 0 + dz = 0 + xold = 0 + yold = 0 + for layer in range(len(cad.zwrite)-1,-1,-1): + zdown = cad.zwrite[layer] + izdown = int(units*zdown) + file.write("!PZ"+str(izdown)+","+str(izup)+";") + # + # follow toolpaths CCW, for CW tool motion + # + for segment in range(len(cad.toolpaths[layer])): + x = int(units*(cad.xmin + (cad.xmax-cad.xmin)*(cad.toolpaths[layer][segment][0].x+0.5)/float(cad.nx))) + y = int(units*(cad.ymin + (cad.ymax-cad.ymin)*((cad.ny-cad.toolpaths[layer][segment][0].y)+0.5)/float(cad.ny))) + file.write("PU"+str(x)+","+str(y)+";") + dxy += sqrt((xold-x)**2+(yold-y)**2) + xold = x + yold = y + dz += izup-izdown + for vertex in range(1,len(cad.toolpaths[layer][segment])): + x = int(units*(cad.xmin + (cad.xmax-cad.xmin)*(cad.toolpaths[layer][segment][vertex].x+0.5)/float(cad.nx))) + y = int(units*(cad.ymin + (cad.ymax-cad.ymin)*((cad.ny-cad.toolpaths[layer][segment][vertex].y)+0.5)/float(cad.ny))) + file.write("PD"+str(x)+","+str(y)+";") + dxy += sqrt((xold-x)**2+(yold-y)**2) + xold = x + yold = y + file.write("PU"+str(x)+","+str(y)+";!MC0;") + # + # file padding hack for end-of-file buffering problems + # + for i in range(1000): + file.write("!MC0;") + file.close() + time = ((dxy/40.0)/xy_speed + (dz/40.0)/z_speed)/60.0 + string_send_to_time.set(" estimated time: %.1f minutes"%time) + draw_toolpath() + string_msg.set("wrote %s"%filename) + root.update() + +def rml_move(event): + # + # move Roland Modela + # + units = 1016*cad.inches_per_unit # 40/mm + x = float(string_rml_x_move.get()) + y = float(string_rml_y_move.get()) + ix = int(units*x) + iy = int(units*y) + filename = "move.rml" + file = open(filename, 'wb') + file.write("PA;PA;!PZ0,400;VS10;!VZ10;!MC0;PU%d,%d;!MC0;"%(ix,iy)) + file.close() + send_to_file("move.rml") + os.remove("move.rml") + +def write_sbp(): + # + # ShopBot output + # + units = cad.inches_per_unit + filename = string_cam_file.get() + file = open(filename, 'wb') + file.write("SA\r\n") # set to absolute distances + file.write("SO,1,1\r\n") # set output number 1 to on + file.write("pause 2\r\n") # let spindle come up to speed + xy_speed = units*float(string_xy_speed.get()) + z_speed = units*float(string_z_speed.get()) + file.write("MS %f,%f\r\n"%(xy_speed,z_speed)) # set xy,z speed + jog_xy_speed = units*float(string_jog_xy_speed.get()) + jog_z_speed = units*float(string_jog_z_speed.get()) + file.write("JS %f,%f\r\n"%(jog_xy_speed,jog_z_speed)) # set jog xy,z speed + zup = units*float(string_jog_z.get()) + dxy = 0 + dz = 0 + xold = 0 + yold = 0 + for layer in range(len(cad.zwrite)-1,-1,-1): + zdown = cad.zwrite[layer] + # + # follow toolpaths CCW, for CW tool motion + # + for segment in range(len(cad.toolpaths[layer])): + x = units*(cad.xmin + (cad.xmax-cad.xmin)*(cad.toolpaths[layer][segment][0].x+0.5)/float(cad.nx)) + y = units*(cad.ymin + (cad.ymax-cad.ymin)*((cad.ny-cad.toolpaths[layer][segment][0].y)+0.5)/float(cad.ny)) + file.write("JZ %f\r\n"%zup) + file.write("J2 %f,%f\r\n"%(x,y)) + file.write("MZ %f\r\n"%zdown) + dxy += sqrt((xold-x)**2+(yold-y)**2) + xold = x + yold = y + dz += zup-zdown + for vertex in range(1,len(cad.toolpaths[layer][segment])): + x = units*(cad.xmin + (cad.xmax-cad.xmin)*(cad.toolpaths[layer][segment][vertex].x+0.5)/float(cad.nx)) + y = units*(cad.ymin + (cad.ymax-cad.ymin)*((cad.ny-cad.toolpaths[layer][segment][vertex].y)+0.5)/float(cad.ny)) + file.write("M2 %f,%f\r\n"%(x,y)) + dxy += sqrt((xold-x)**2+(yold-y)**2) + xold = x + yold = y + file.write("JZ %f\r\n"%zup) + file.close() + time = (dxy/xy_speed + dz/z_speed)/60.0 + string_send_to_time.set(" estimated time: %.1f minutes"%time) + draw_toolpath() + string_msg.set("wrote %s"%filename) + root.update() + +def write_oms(): + # + # Resonetics excimer micromachining center output + # + units = 25.4*cad.inches_per_unit + pulseperiod = float(string_pulse_period.get()) + cutvel = float(string_cut_vel.get()) + cutaccel = float(string_cut_accel.get()) + slewvel = 1 + slewaccel = 5 + settle = 100 + filename = string_cam_file.get() + file = open(filename, 'wb') + file.write("AA LP0,0,0,0,0\n") # set origin + file.write("PP%d\n"%pulseperiod) # set pulse period + for layer in range(len(cad.toolpaths)): + for segment in range(len(cad.toolpaths[layer])): + x = units*(cad.xmin + (cad.xmax-cad.xmin)*(cad.toolpaths[layer][segment][0].x+0.5)/float(cad.nx)) + y = units*(cad.ymin + (cad.ymax-cad.ymin)*((cad.ny-cad.toolpaths[layer][segment][0].y)+0.5)/float(cad.ny)) + file.write("VL%.1f,%.1f\n"%(slewvel,slewvel)) + file.write("AC%.1f,%.1f\n"%(slewaccel,slewaccel)) + file.write("MA%f,%f\n"%(x,y)) + file.write("VL%.1f,%.1f\n"%(cutvel,cutvel)) + file.write("AC%.1f,%.1f\n"%(cutaccel,cutaccel)) + file.write("WT%d\n"%settle) # wait to settle + for vertex in range(1,len(cad.toolpaths[layer][segment])): + x = units*(cad.xmin + (cad.xmax-cad.xmin)*(cad.toolpaths[layer][segment][vertex].x+0.5)/float(cad.nx)) + y = units*(cad.ymin + (cad.ymax-cad.ymin)*((cad.ny-cad.toolpaths[layer][segment][vertex].y)+0.5)/float(cad.ny)) + file.write("CutAbs %f,%f\n"%(x,y)) + file.write("END\n") + file.close() + draw_toolpath() + string_msg.set("wrote %s"%filename) + root.update() + +def write_dxf(): + # + # DXF output + # + units = cad.inches_per_unit + filename = string_cam_file.get() + file = open(filename, 'wb') + file.write("999\nDXF written by cad.py\n") + file.write("0\nSECTION\n") + file.write("2\nHEADER\n") + file.write("9\n$EXTMIN\n") + file.write("10\n%f\n"%cad.xmin) + file.write("20\n%f\n"%cad.ymin) + file.write("9\n$EXTMAX\n") + file.write("10\n%f\n"%cad.xmax) + file.write("20\n%f\n"%cad.ymax) + file.write("0\nENDSEC\n") + file.write("0\nSECTION\n") + file.write("2\nTABLES\n") + file.write("0\nTABLE\n") + file.write("2\nLTYPE\n70\n1\n") + file.write("0\nLTYPE\n") + file.write("2\nCONTINUOUS\n") + file.write("70\n64\n3\n") + file.write("Solid line\n") + file.write("72\n65\n73\n0\n40\n0.000000\n") + file.write("0\nENDTAB\n") + file.write("0\nTABLE\n2\nLAYER\n70\n1\n") + file.write("0\nLAYER\n2\ndefault\n70\n64\n62\n7\n6\n") + file.write("CONTINUOUS\n0\nENDTAB\n") + file.write("0\nENDSEC\n") + file.write("0\nSECTION\n") + file.write("2\nBLOCKS\n") + file.write("0\nENDSEC\n") + file.write("0\nSECTION\n") + file.write("2\nENTITIES\n") + for layer in range(len(cad.toolpaths)): + for segment in range(len(cad.toolpaths[layer])): + for vertex in range(1,len(cad.toolpaths[layer][segment])): + x0 = units*(cad.xmin + (cad.xmax-cad.xmin)*(cad.toolpaths[layer][segment][vertex-1].x+0.5)/float(cad.nx)) + y0 = units*(cad.ymin + (cad.ymax-cad.ymin)*((cad.ny-cad.toolpaths[layer][segment][vertex-1].y)+0.5)/float(cad.ny)) + x1 = units*(cad.xmin + (cad.xmax-cad.xmin)*(cad.toolpaths[layer][segment][vertex].x+0.5)/float(cad.nx)) + y1 = units*(cad.ymin + (cad.ymax-cad.ymin)*((cad.ny-cad.toolpaths[layer][segment][vertex].y)+0.5)/float(cad.ny)) + file.write("0\nLINE\n") + file.write("10\n%f\n"%x0) + file.write("20\n%f\n"%y0) + file.write("11\n%f\n"%x1) + file.write("21\n%f\n"%y1) + file.write("0\nENDSEC\n") + file.write("0\nEOF\n") + file.close() + draw_toolpath() + string_msg.set("wrote %s"%filename) + root.update() + +def write_uni(): + # + # Universal lasercutter output + # + units = 1000*cad.inches_per_unit + filename = string_cam_file.get() + file = open(filename, 'wb') + file.write("Z") # initialize + file.write("t%s~;"%filename) # title + file.write("IN;DF;PS0;DT~") # initialize + ppibyte = int(float(string_laser_rate.get())/10) + file.write("s%c"%ppibyte) # PPI + speed_hibyte = int(648*float(string_laser_speed.get()))/256 + speed_lobyte = int(648*float(string_laser_speed.get()))%256 + file.write("v%c%c"%(speed_hibyte,speed_lobyte)) # speed + power = float(string_laser_power.get()) + min_power = float(string_laser_min_power.get()) + max_power = float(string_laser_max_power.get()) + power_hibyte = (320*int(power))/256 + power_lobyte = (320*int(power))%256 + file.write("p%c%c"%(power_hibyte,power_lobyte)) # power + file.write("a%c"%2) # air assist on high + for layer in range(len(cad.toolpaths)): + if ((len(cad.zwrite) > 1) & (len(cad.toolpaths[layer]) > 0)): + fraction = (cad.zwrite[layer]-cad.zwrite[0])/(cad.zwrite[-1]-cad.zwrite[0]) + layer_power = min_power + fraction*(max_power-min_power) + power_hibyte = (320*int(layer_power))/256 + power_lobyte = (320*int(layer_power))%256 + file.write("p%c%c"%(power_hibyte,power_lobyte)) # power + for segment in range(len(cad.toolpaths[layer])): + x = int(units*(cad.xmin + (cad.xmax-cad.xmin)*(cad.toolpaths[layer][segment][0].x+0.5)/float(cad.nx))) + y = int(units*(cad.ymin + ((cad.ymax-cad.ymin)*((cad.ny-cad.toolpaths[layer][segment][0].y)+0.5)/float(cad.ny)))) + file.write("PU;PA"+str(x)+","+str(y)+";PD;") + for vertex in range(1,len(cad.toolpaths[layer][segment])): + x = int(units*(cad.xmin + (cad.xmax-cad.xmin)*(cad.toolpaths[layer][segment][vertex].x+0.5)/float(cad.nx))) + y = int(units*(cad.ymin + ((cad.ymax-cad.ymin)*((cad.ny-cad.toolpaths[layer][segment][vertex].y)+0.5)/float(cad.ny)))) + file.write("PA"+str(x)+","+str(y)+";") + file.write("e") # end of file + file.close() + draw_toolpath() + string_msg.set("wrote %s"%filename) + root.update() + +def write_jpg(): + # + # JPG image output + # + if (cad.views == "xy"): + filename = string_cam_file.get() + im.xy = Image.fromarray(im.intensity_xy,mode="RGBX") + im_rgb_xy = im.xy.convert("RGB") + dpi = int(cad.nx/float(cad.xmax-cad.xmin)) + im_rgb_xy.save(filename,dpi=(dpi,dpi)) + string_msg.set("wrote %s"%filename) + elif (cad.views == "xyzr"): + border = 5 + filename = string_cam_file.get() + im.xy = Image.fromarray(im.intensity_xy,mode="RGBX") + im.xz = Image.fromarray(im.intensity_xz,mode="RGBX") + im.yz = Image.fromarray(im.intensity_yz,mode="RGBX") + im.yz = im.yz.transpose(Image.FLIP_LEFT_RIGHT) + im.xyz = Image.fromarray(im.intensity_xyz,mode="RGBX") + (nx,ny) = im.xy.size + ny = (nx*cad.nyplot())/cad.nxplot() + nz = (nx*cad.nzplot())/cad.nxplot() + im.xy = im.xy.resize((nx,ny)) + im.yz = im.yz.resize((nz,ny)) + im.xz = im.xz.resize((nx,nz)) + im.xyz = im.xyz.resize((nx,ny)) + im_rgb_xy = im.xy.convert("RGB") + im_rgb_xz = im.xz.convert("RGB") + im_rgb_yz = im.yz.convert("RGB") + im_rgb_xyz = im.xyz.convert("RGB") + img = Image.new("RGB",(nx+border+nx,ny+border+ny),"white") + img.paste(im_rgb_xy,(0,0)) + img.paste(im_rgb_xz,(0,border+ny)) + img.paste(im_rgb_yz,(border+nx,0)) + img.paste(im_rgb_xyz,(border+nx,border+ny)) + img.save(filename) + string_msg.set("wrote %s"%filename) + else: + string_msg.set("unknown view") + +def write_png(): + # + # PNG image output + # + if (cad.views == "xy"): + filename = string_cam_file.get() + im.xy = Image.fromarray(im.intensity_xy,mode="RGBX") + im_rgb_xy = im.xy.convert("RGB") + dpi = int(cad.nx/float(cad.xmax-cad.xmin)) + im_rgb_xy.save(filename,dpi=(dpi,dpi)) + string_msg.set("wrote %s"%filename) + elif (cad.views == "xyzr"): + border = 5 + filename = string_cam_file.get() + im.xy = Image.fromarray(im.intensity_xy,mode="RGBX") + im.xz = Image.fromarray(im.intensity_xz,mode="RGBX") + im.yz = Image.fromarray(im.intensity_yz,mode="RGBX") + im.yz = im.yz.transpose(Image.FLIP_LEFT_RIGHT) + im.xyz = Image.fromarray(im.intensity_xyz,mode="RGBX") + (nx,ny) = im.xy.size + ny = (nx*cad.nyplot())/cad.nxplot() + nz = (nx*cad.nzplot())/cad.nxplot() + im.xy = im.xy.resize((nx,ny)) + im.yz = im.yz.resize((nz,ny)) + im.xz = im.xz.resize((nx,nz)) + im.xyz = im.xyz.resize((nx,ny)) + im_rgb_xy = im.xy.convert("RGB") + im_rgb_xz = im.xz.convert("RGB") + im_rgb_yz = im.yz.convert("RGB") + im_rgb_xyz = im.xyz.convert("RGB") + img = Image.new("RGB",(nx+border+nx,ny+border+ny),"white") + img.paste(im_rgb_xy,(0,0)) + img.paste(im_rgb_xz,(0,border+ny)) + img.paste(im_rgb_yz,(border+nx,0)) + img.paste(im_rgb_xyz,(border+nx,border+ny)) + img.save(filename) + string_msg.set("wrote %s"%filename) + else: + string_msg.set("unknown view") + +def write_stl(): + # + # STL output + # + filename = string_cam_file.get() + file = open(filename, 'wb') + units = cad.inches_per_unit + x = cad.xmin+(cad.xmax-cad.xmin)*(cad.x+0.5)/float(cad.nx) + y = cad.ymin+(cad.ymax-cad.ymin)*(cad.y+0.5)/float(cad.ny) + z = cad.zmin+(cad.zmax-cad.zmin)*(cad.z+0.5)/float(cad.nz) + # + # header + # + file.write('cad.py') + file.write('a'*74) + # + # length + # + N = len(cad.x) + file.write(struct.pack('L',N/3)) + # + # triangles + # + for i in range(0,N,3): + string_msg.set("write triangle %d/%d"%(i/3,N/3)) + root.update() + # + # normals + # + file.write(struct.pack('f',0)) + file.write(struct.pack('f',0)) + file.write(struct.pack('f',0)) + # + # vertices + # + file.write(struct.pack('f',x[i]*units)) + file.write(struct.pack('f',y[i]*units)) + file.write(struct.pack('f',z[i]*units)) + file.write(struct.pack('f',x[i+1]*units)) + file.write(struct.pack('f',y[i+1]*units)) + file.write(struct.pack('f',z[i+1]*units)) + file.write(struct.pack('f',x[i+2]*units)) + file.write(struct.pack('f',y[i+2]*units)) + file.write(struct.pack('f',z[i+2]*units)) + # + # padding + # + file.write(struct.pack('xx')) + file.close() + string_msg.set("wrote %s"%filename) + root.update() + +def write_gerber(): + # + # Gerber (RS-274X) output + # + filename = string_cam_file.get() + file = open(filename, 'wb') + units = cad.inches_per_unit + # + # write parameters + # + file.write("%FSLAX24Y24*%\n") # leading zeros omitted, absolute coordinates, 2.4 + file.write("%MOIN*%\n") # inches units + file.write("%OFA0B0*%\n") # no offset + # + # find and write apertures + # + ixs = cad.x[::2] + xs = cad.xmin+(cad.xmax-cad.xmin)*(ixs+0.5)/float(cad.nx) + ixe = cad.x[1::2] + xe = cad.xmin+(cad.xmax-cad.xmin)*(ixe+0.5)/float(cad.nx) + idx = ixe - ixs + dx = xe - xs + iys = cad.y[::2] + ys = cad.ymin+(cad.ymax-cad.ymin)*(iys+0.5)/float(cad.ny) + iye = cad.y[1::2] + ye = cad.ymin+(cad.ymax-cad.ymin)*(iye+0.5)/float(cad.ny) + idy = iye - iys + dy = ye - ys + mins = where((idx < idy),idx,idy) + uniques = unique(mins) + apertures = (cad.xmax-cad.xmin)*uniques/float(cad.nx) + index = searchsorted(uniques,mins) + for i in range(len(uniques)): + file.write("%%ADD%dR,%.4fX%.4f*%%\n"%(i+10,apertures[i],apertures[i])) + # + # write flashes + # + coords = arange(len(mins)) + for i in range(len(uniques)): + file.write("D%d*\n"%(i+10)) + coord = coords[index == i] + delta = apertures[i]/2. + ixs = (10000*(xs+delta)).astype(int32) + ixe = (10000*(xe-delta)).astype(int32) + iys = (10000*(ys+delta)).astype(int32) + iye = (10000*(ye-delta)).astype(int32) + for j in range(len(coord)): + n = coord[j] + if (idx[n] == idy[n]): + # + # flash + # + file.write('X%dY%dD03*\n'%(ixs[n],iys[n])) + elif (idx[n] > idy[n]): + # + # stroke horizontal + # + file.write('X%dY%dD02*\n'%(ixs[n],iys[n])) + file.write('X%dY%dD01*\n'%(ixe[n],iys[n])) + else: + # + # stroke vertical + # + file.write('X%dY%dD02*\n'%(ixs[n],iys[n])) + file.write('X%dY%dD01*\n'%(ixs[n],iye[n])) + file.write("M02*\n") # end of file + file.close() + string_msg.set("wrote %s (RS-274X)"%filename) + root.update() + +def write_excellon(): + # + # Excellon (RS-) output + # + """ +% Rewind and Stop +X#Y# Move and Drill +T# Tool Selection +M30 End of Program +M00 End of Program +R#X#Y# Repeat Hole +G05, G81 Select Drill Mode +G90 Absolute Mode +G91 Incremental Mode +G92 X#Y# Set Zero +G93 X#Y# Set Zero +M48 Program Header to first "%" +M72 English-Imperial Mode + + """ + filename = string_cam_file.get() + file = open(filename, 'wb') + units = cad.inches_per_unit + # + # write parameters + # + file.write("%FSLAX24Y24*%\n") # leading zeros omitted, absolute coordinates, 2.4 + file.write("%MOIN*%\n") # inches units + file.write("%OFA0B0*%\n") # no offset + # + # find and write apertures + # + ixs = cad.x[::2] + xs = cad.xmin+(cad.xmax-cad.xmin)*(ixs+0.5)/float(cad.nx) + ixe = cad.x[1::2] + xe = cad.xmin+(cad.xmax-cad.xmin)*(ixe+0.5)/float(cad.nx) + idx = ixe - ixs + dx = xe - xs + iys = cad.y[::2] + ys = cad.ymin+(cad.ymax-cad.ymin)*(iys+0.5)/float(cad.ny) + iye = cad.y[1::2] + ye = cad.ymin+(cad.ymax-cad.ymin)*(iye+0.5)/float(cad.ny) + idy = iye - iys + dy = ye - ys + mins = where((idx < idy),idx,idy) + uniques = unique(mins) + apertures = (cad.xmax-cad.xmin)*uniques/float(cad.nx) + index = searchsorted(uniques,mins) + for i in range(len(uniques)): + file.write("%%ADD%dR,%.4fX%.4f*%%\n"%(i+10,apertures[i],apertures[i])) + # + # write flashes + # + coords = arange(len(mins)) + for i in range(len(uniques)): + file.write("D%d*\n"%(i+10)) + coord = coords[index == i] + delta = apertures[i]/2. + ixs = (10000*(xs+delta)).astype(int32) + ixe = (10000*(xe-delta)).astype(int32) + iys = (10000*(ys+delta)).astype(int32) + iye = (10000*(ye-delta)).astype(int32) + for j in range(len(coord)): + n = coord[j] + if (idx[n] == idy[n]): + # + # flash + # + file.write('X%dY%dD03*\n'%(ixs[n],iys[n])) + elif (idx[n] > idy[n]): + # + # stroke horizontal + # + file.write('X%dY%dD02*\n'%(ixs[n],iys[n])) + file.write('X%dY%dD01*\n'%(ixe[n],iys[n])) + else: + # + # stroke vertical + # + file.write('X%dY%dD02*\n'%(ixs[n],iys[n])) + file.write('X%dY%dD01*\n'%(ixs[n],iye[n])) + file.write("M02*\n") # end of file + file.close() + string_msg.set("wrote %s (RS-274X)"%filename) + root.update() + +def write_ca(): + # + # CA output + # + filename = string_cam_file.get() + file = open(filename, 'wb') + file.write(chr(0xB9)) # magic number 0xB9 + file.write(chr(ca.nx/256)) # x size + file.write(chr(ca.nx%256)) # + file.write(chr(ca.ny/256)) # y size + file.write(chr(ca.ny%256)) # + file.write(chr(4)) # LED sub-array x + file.write(chr(2)) # LED sub-array y + for y in range(ca.nx): + for x in range(ca.nx): + if (ca.in1[y,x] == ca.E): + config = 0 + elif (ca.in1[y,x] == ca.NE): + config = 1 + elif (ca.in1[y,x] == ca.N): + config = 2 + elif (ca.in1[y,x] == ca.NW): + config = 3 + elif (ca.in1[y,x] == ca.W): + config = 4 + elif (ca.in1[y,x] == ca.SW): + config = 5 + elif (ca.in1[y,x] == ca.S): + config = 6 + elif (ca.in1[y,x] == ca.SE): + config = 7 + elif (ca.in1[y,x] == ca.empty): # XOR W W for empty + config = 4 + if (ca.in2[y,x] == ca.E): + config += 0 + elif (ca.in2[y,x] == ca.NE): + config += (1 << 3) + elif (ca.in2[y,x] == ca.N): + config += (2 << 3) + elif (ca.in2[y,x] == ca.NW): + config += (3 << 3) + elif (ca.in2[y,x] == ca.W): + config += (4 << 3) + elif (ca.in2[y,x] == ca.SW): + config += (5 << 3) + elif (ca.in2[y,x] == ca.S): + config += (6 << 3) + elif (ca.in2[y,x] == ca.SE): + config += (7 << 3) + elif (ca.in2[y,x] == ca.empty): # XOR W W for empty + config += (4 << 3) + if (ca.gates[y,x] == ca.AND): + config += 0 + elif (ca.gates[y,x] == ca.OR): + config += (1 << 6) + elif (ca.gates[y,x] == ca.XOR): + config += (2 << 6) + elif (ca.gates[y,x] == ca.NAND): + config += (3 << 6) + elif (ca.gates[y,x] == ca.empty): # XOR W W for empty + config += (2 << 6) + file.write(chr(config)) + for y in range(ca.ny): + for x in range((ca.nx/8)): + state = \ + (ca.states[y,8*x+0] << 7) \ + + (ca.states[y,8*x+1] << 6) \ + + (ca.states[y,8*x+2] << 5) \ + + (ca.states[y,8*x+3] << 4) \ + + (ca.states[y,8*x+4] << 3) \ + + (ca.states[y,8*x+5] << 2) \ + + (ca.states[y,8*x+6] << 1) \ + + (ca.states[y,8*x+7] << 0) + file.write(chr(state)) + if ((ca.nx%8) != 0): + x = cad.nx/8 + state = 0 + for i in range((ca.nx%8)): + state += (ca.states[y,8*x+i] << (7-i)) + file.write(chr(state)) + file.close() + string_msg.set("wrote %s"%filename) + root.update() + +def msg_xy(event): + x = (cad.xmin+cad.xmax)/2. + (cad.xmax-cad.xmin)*(1+event.x-cad.nplot/2.)/float(cad.nxplot()) + y = (cad.ymin+cad.ymax)/2. + (cad.ymin-cad.ymax)*(1+event.y-cad.nplot/2.)/float(cad.nyplot()) + string_msg.set("x = %.2f y = %.2f"%(x,y)) + +def msg_yz(event): + if (cad.nz > 1): + y = (cad.ymin+cad.ymax)/2. + (cad.ymin-cad.ymax)*(1+event.y-cad.nplot/2.)/float(cad.nyplot()) + z = (cad.zmin+cad.zmax)/2. + (cad.zmin-cad.zmax)*(1+event.x-cad.nplot/2.)/float(cad.nzplot()) + string_msg.set("y = %.2f z = %.2f"%(y,z)) + else: + string_msg.set("") + +def msg_xz(event): + if (cad.nz > 1): + x = (cad.xmin+cad.xmax)/2. + (cad.xmax-cad.xmin)*(1+event.x-cad.nplot/2.)/float(cad.nxplot()) + z = (cad.zmin+cad.zmax)/2. + (cad.zmin-cad.zmax)*(1+event.y-cad.nplot/2.)/float(cad.nzplot()) + string_msg.set("x = %.2f z = %.2f"%(x,z)) + else: + string_msg.set("") + +def msg_nomsg(event): + string_msg.set("") + +def image_min_x(event): + cad.xmin = float(string_image_xmin.get()) + xwidth = float(string_image_xwidth.get()) + cad.xmax = cad.xmin + xwidth + root.update() + +def image_min_y(event): + cad.ymin = float(string_image_ymin.get()) + yheight = float(string_image_yheight.get()) + cad.ymax = cad.ymin + yheight + root.update() + +def image_scale_x(event): + yheight = float(string_image_yheight.get()) + xwidth = yheight*cad.nx/float(cad.ny) + cad.xmax = cad.xmin + xwidth + string_image_xwidth.set(str(xwidth)) + root.update() + +def image_scale_y(event): + xwidth = float(string_image_xwidth.get()) + yheight = xwidth*cad.ny/float(cad.nx) + cad.ymax = cad.ymin + yheight + string_image_yheight.set(str(yheight)) + root.update() + +def send_to(event): + save_cam(0) + cam_file_name = string_cam_file.get() + send_to_file(cam_file_name) + +def send_to_file(cam_file_name): + cad_path = os.path.dirname(sys.argv[0]) + if (sys.argv[0] == "cad.py"): + cfg_path = "cad.cfg" + else: + cfg_path = os.path.dirname(sys.argv[0])+"/cad.cfg" + try: + config_file = open(cfg_path, 'r') + except: + string_msg.set(cfg_path+" not found") + root.update() + return() + dot = find(cam_file_name,".") + while 1: + new_dot = find(cam_file_name,".",dot+1) + if (new_dot == -1): + break + else: + dot = new_dot + suffix = cam_file_name[dot+1:] + while 1: + line = config_file.readline() + if (find(line,suffix) == 0): + string_msg.set("sending "+cam_file_name+" ...") + root.update() + quote1 = find(line,"'") + quote2 = find(line,"'",quote1+1) + cmd = line[(quote1+1):quote2] + if (os.name == 'nt'): + cam_file_name = replace(cam_file_name,'/','\\') + cmd = replace(cmd,'file','"'+cam_file_name+'"') + os.system(cmd) + string_msg.set(cam_file_name+" sent") + root.update() + config_file.close() + root.update() + return() + elif (line == ""): + string_msg.set(suffix+" driver not defined in "+cfg_path) + config_file.close() + root.update() + return() + +def resize_window(event): + # + # resize drawing windows + # + cad.nplot = int(string_window_size.get()) + cad.view(cad.views) + render() + +def resize_editor(event): + # + # resize editing windows + # + cad.editor_height = int(string_editor_height.get()) + widget_cad_text.config(height=cad.editor_height) + cad.editor_width = int(string_editor_width.get()) + widget_cad_text.config(width=cad.editor_width) + widget_function_text.config(width=cad.editor_width) + root.update() + +def reload(): + # + # reload input file + # + filename = string_input_file.get() + if (find(filename,'.cad') != -1): + cad_load(0) + elif ((find(filename,'.jpg') != -1) | (find(filename,'.JPG') != -1) | + (find(filename,'.png') != -1) | (find(filename,'.PNG') != -1) | + (find(filename,'.gif') != -1) | (find(filename,'.GIF') != -1)): + widget_cad_text.delete("1.0",END) + image_load(0) + else: + string_msg.set("unsupported input file format") + root.update() + +# +# set up GUI +# +root = Tk() +root.title('cad.py') +# +# message frame +# +msg_frame = Frame(root) +string_msg = StringVar() +widget_msg = Label(msg_frame, textvariable = string_msg) +widget_msg.pack(side='right') +Label(msg_frame, text=" ").pack(side='right') +widget_stop = Button(msg_frame, text='stop', borderwidth=2) +widget_stop.bind('',render_stop) +msg_frame.grid(row=0,column=0) +# +# size frame +# +size_frame = Frame(root) +Label(size_frame, text="window size: ").pack(side='left') +string_window_size = StringVar() +string_window_size.set(str(cad.nplot)) +widget_window_size = Entry(size_frame, width=4, bg='white', textvariable=string_window_size) +widget_window_size.bind('',resize_window) +widget_window_size.pack(side='left') +Label(size_frame, text=" editor width: ").pack(side='left') +string_editor_width = StringVar() +string_editor_width.set(str(cad.editor_width)) +widget_editor_width = Entry(size_frame, width=3, bg='white', textvariable=string_editor_width) +widget_editor_width.bind('',resize_editor) +widget_editor_width.pack(side='left') +Label(size_frame, text=" height: ").pack(side='left') +string_editor_height = StringVar() +string_editor_height.set(str(cad.editor_height)) +widget_editor_height = Entry(size_frame, width=3, bg='white', textvariable=string_editor_height) +widget_editor_height.bind('',resize_editor) +widget_editor_height.pack(side='left') +size_frame.grid(row=0,column=1) +# +# view frame +# +view_frame2 = Frame(root) +view_frame3 = Frame(root) +canvas_xy = Canvas(view_frame3) +canvas_xz = Canvas(view_frame3) +canvas_yz = Canvas(view_frame3) +canvas_xyz = Canvas(view_frame3) +cad.view('xyzr') +# +# I/O frame +# +io_frame = Frame(root) +io_frame.grid(row=2,column=1,sticky=N) +#cad_frame.bind('',msg_nomsg) + # + # input frame + # +input_frame = Frame(io_frame) +input_frame.pack() + # + # .cad editor + # +editor_frame = Frame(input_frame) +widget_text_yscrollbar = Scrollbar(editor_frame) +widget_cad_text = Text(editor_frame, bg='white', bd=5, width=cad.editor_width, height=cad.editor_height, yscrollcommand=widget_text_yscrollbar.set) +widget_cad_text.grid(row=1,column=1) +widget_text_yscrollbar.grid(row=1,column=2,sticky=N+S) +widget_text_yscrollbar.config(command=widget_cad_text.yview) +widget_cad_text.bind('',msg_nomsg) +editor_frame.pack() + # + # input file + # +cad_input_frame = Frame(input_frame) +widget_input_file = Button(cad_input_frame, text="input:",command=input_open) +widget_input_file.pack(side='left') +string_input_file = StringVar() +string_input_file.set('out.cad') +widget_cad = Entry(cad_input_frame, width=17, bg='white', textvariable=string_input_file) +widget_cad.pack(side='left') +Label(cad_input_frame, text=" ").pack(side='left') +widget_cad_save = Button(cad_input_frame, text="save") +widget_cad_save.bind('',cad_save) +widget_cad_save.pack(side='left') +Label(cad_input_frame, text=" ").pack(side='left') +widget_reload = Button(cad_input_frame, text="reload",command=reload) +widget_reload.pack(side='left') +cad_input_frame.pack() + # + # image x + # +image_x_frame = Frame(input_frame) +Label(image_x_frame, text="x min: ").pack(side='left') +string_image_xmin = StringVar() +widget_image_xmin = Entry(image_x_frame, width=6, bg='white', textvariable=string_image_xmin) +widget_image_xmin.bind('',image_min_x) +widget_image_xmin.pack(side='left') +Label(image_x_frame, text=" x width: ").pack(side='left') +string_image_xwidth = StringVar() +widget_image_xwidth = Entry(image_x_frame, width=6, bg='white', textvariable=string_image_xwidth) +widget_image_xwidth.bind('',image_scale_y) +widget_image_xwidth.pack(side='left') +string_image_nx = StringVar() +Label(image_x_frame, textvariable = string_image_nx).pack(side='left') + # + # image y + # +image_y_frame = Frame(input_frame) +Label(image_y_frame, text="y min: ").pack(side='left') +string_image_ymin = StringVar() +widget_image_ymin = Entry(image_y_frame, width=6, bg='white', textvariable=string_image_ymin) +widget_image_ymin.bind('',image_min_y) +widget_image_ymin.pack(side='left') +Label(image_y_frame, text=" y height: ").pack(side='left') +string_image_yheight = StringVar() +widget_image_yheight = Entry(image_y_frame, width=6, bg='white', textvariable=string_image_yheight) +widget_image_yheight.bind('',image_scale_x) +widget_image_yheight.pack(side='left') +string_image_ny = StringVar() +Label(image_y_frame, textvariable = string_image_ny).pack(side='left') + # + # image z + # +image_z_frame = Frame(input_frame) +Label(image_z_frame, text="z min: ").pack(side='left') +string_image_zmin = StringVar() +widget_image_zmin = Entry(image_z_frame, width=6, bg='white', textvariable=string_image_zmin) +widget_image_zmin.pack(side='left') +Label(image_z_frame, text=" z max: ").pack(side='left') +string_image_zmax = StringVar() +widget_image_zmax = Entry(image_z_frame, width=6, bg='white', textvariable=string_image_zmax) +widget_image_zmax.pack(side='left') +Label(image_z_frame, text=" nz: ").pack(side='left') +string_image_nz = StringVar() +widget_image_nz = Entry(image_z_frame, width=6, bg='white', textvariable=string_image_nz) +widget_image_nz.pack(side='left') + # + # image intensity + # +image_intensity_frame = Frame(input_frame) +Label(image_intensity_frame, text="intensity min: ").pack(side='left') +string_image_min = StringVar() +widget_image_min = Entry(image_intensity_frame, width=6, bg='white', textvariable=string_image_min) +widget_image_min.pack(side='left') +Label(image_intensity_frame, text=" intensity max: ").pack(side='left') +string_image_max = StringVar() +widget_image_max = Entry(image_intensity_frame, width=6, bg='white', textvariable=string_image_max) +widget_image_max.pack(side='left') + # + # image units + # +image_units_frame = Frame(input_frame) +Label(image_units_frame, text="inches per unit: ").pack(side='left') +string_image_units = StringVar() +widget_image_units = Entry(image_units_frame, width=6, bg='white', textvariable=string_image_units) +widget_image_units.pack(side='left') + # + # image invert + # +image_invert_frame = Frame(input_frame) +Label(image_invert_frame, text=" ").pack(side='left') +widget_image_invert = Button(image_invert_frame, text="invert image") +widget_image_invert.pack(side='left') +widget_image_invert.bind('',invert_image) + # + # output frame + # +output_frame = Frame(io_frame) +output_frame.pack() + # + # controls + # +control_frame = Frame(output_frame) +widget_render = Button(control_frame, text="render") +widget_render.bind('',render_button) +widget_render.pack(side='left') +Label(control_frame, text=" ").pack(side='left') +canvas_logo = Canvas(control_frame, width=26, height=26, background="white") +canvas_logo.create_oval(2,2,8,8,fill="red",outline="") +canvas_logo.create_rectangle(11,2,17,8,fill="blue",outline="") +canvas_logo.create_rectangle(20,2,26,8,fill="blue",outline="") +canvas_logo.create_rectangle(2,11,8,17,fill="blue",outline="") +canvas_logo.create_oval(10,10,16,16,fill="red",outline="") +canvas_logo.create_rectangle(20,11,26,17,fill="blue",outline="") +canvas_logo.create_rectangle(2,20,8,26,fill="blue",outline="") +canvas_logo.create_rectangle(11,20,17,26,fill="blue",outline="") +canvas_logo.create_rectangle(20,20,26,26,fill="blue",outline="") +canvas_logo.pack(side='left') +control_text = " cad.py (%s) "%DATE +Label(control_frame, text=control_text).pack(side='left') +widget_cam = Button(control_frame, text="cam") +widget_cam.bind('',cam) +widget_cam.pack(side='left') +Label(control_frame, text=" ").pack(side='left') +widget_quit = Button(control_frame, text="quit", command='exit') +widget_quit.pack(side='left') +control_frame.pack() + # + # function string + # +function_string_frame = Frame(output_frame) +Label(function_string_frame, text="function:").grid(row=1,column=1) +widget_function_yscrollbar = Scrollbar(function_string_frame) +widget_function_text = Text(function_string_frame, bg='white', bd=5, width=cad.editor_width, height=12, yscrollcommand=widget_function_yscrollbar.set, state=DISABLED) +widget_function_text.grid(row=2,column=1) +widget_function_yscrollbar.grid(row=2,column=2,sticky=N+S) +widget_function_yscrollbar.config(command=widget_function_text.yview) +function_string_frame.pack() + # + # CAM file + # +cam_file_frame = Frame(output_frame) +widget_cam_menu_button = Menubutton(cam_file_frame,text="output format", relief=RAISED) +widget_cam_menu_button.pack(side='left') +widget_cam_menu = Menu(widget_cam_menu_button) +widget_cam_menu.add_command(label='.epi (Epilog)',command=select_epi) +widget_cam_menu.add_command(label='.camm (CAMM)',command=select_camm) +widget_cam_menu.add_command(label='.rml (Modela)',command=select_rml) +widget_cam_menu.add_command(label='.sbp (ShopBot)',command=select_sbp) +widget_cam_menu.add_command(label='.gcode (Gcode)',command=select_g) +widget_cam_menu.add_command(label='.ps (Postscript)',command=select_ps) +widget_cam_menu.add_command(label='.ord (OMAX)',command=select_ord) +widget_cam_menu.add_command(label='.oms (Resonetics)',command=select_oms) +widget_cam_menu.add_command(label='.grb (Gerber)',command=select_gerber) +widget_cam_menu.add_command(label='.drl (Excellon)',command=select_excellon) +widget_cam_menu.add_command(label='.stl (STL)',command=select_stl) +widget_cam_menu.add_command(label='.dxf (DXF)',command=select_dxf) +widget_cam_menu.add_command(label='.jpg (JPG)',command=select_jpg) +widget_cam_menu.add_command(label='.png (PNG)',command=select_png) +widget_cam_menu.add_command(label='.ca (CA)',command=select_ca) +widget_cam_menu.add_command(label='.uni (Universal)',command=select_uni) +widget_cam_menu.add_command(label='.epb (Epilog bitmap)',state=DISABLED) +widget_cam_menu_button['menu'] = widget_cam_menu +Label(cam_file_frame, text=" output file: ").pack(side='left') +string_cam_file = StringVar() +widget_cam_file = Entry(cam_file_frame, width=12, bg='white', textvariable=string_cam_file) +widget_cam_file.pack(side='left') +Label(cam_file_frame, text=" ").pack(side='left') +widget_cam_save = Button(cam_file_frame, text="save") +widget_cam_save.bind('',save_cam) +widget_cam_save.pack(side='left') + # + # vectorization + # +cam_vector_frame = Frame(output_frame) +Label(cam_vector_frame, text="maximum vector fit error (lattice units): ").pack(side='left') +string_vector_error = StringVar() +string_vector_error.set('.75') +widget_vector_error = Entry(cam_vector_frame, width=6, bg='white', textvariable=string_vector_error) +widget_vector_error.pack(side='left') + # + # tool + # +cam_dia_frame = Frame(output_frame) +Label(cam_dia_frame, text="tool diameter: ").pack(side='left') +string_tool_dia = StringVar() +string_tool_dia.set('0') +widget_tool_dia = Entry(cam_dia_frame, width=6, bg='white', textvariable=string_tool_dia) +widget_tool_dia.pack(side='left') +Label(cam_dia_frame, text=" tool overlap: ").pack(side='left') +string_tool_overlap = StringVar() +string_tool_overlap.set('0.5') +widget_tool_overlap = Entry(cam_dia_frame, width=6, bg='white', textvariable=string_tool_overlap) +widget_tool_overlap.pack(side='left') + # + # contour + # +cam_contour_frame = Frame(output_frame) +Label(cam_contour_frame, text=" # contours (-1 for max): ").pack(side='left') +string_num_contours = StringVar() +string_num_contours.set('0') +widget_num_contours = Entry(cam_contour_frame, width=6, bg='white', textvariable=string_num_contours) +widget_num_contours.pack(side='left') +Label(cam_contour_frame, text=" ").pack(side='left') +widget_cam_contour = Button(cam_contour_frame, text="contour") +widget_cam_contour.pack(side='left') +widget_cam_contour.bind('',contour) + # + # laser power + # +laser_frame1 = Frame(output_frame) +Label(laser_frame1, text=" power:").pack(side='left') +string_laser_power = StringVar() +Entry(laser_frame1, width=6, bg='white', textvariable=string_laser_power).pack(side='left') +Label(laser_frame1, text=" speed:").pack(side='left') +string_laser_speed = StringVar() +Entry(laser_frame1, width=6, bg='white', textvariable=string_laser_speed).pack(side='left') +Label(laser_frame1, text=" rate: ").pack(side='left') +string_laser_rate = StringVar() +Entry(laser_frame1, width=6, bg='white', textvariable=string_laser_rate).pack(side='left') + # + # power range + # +laser_frame2 = Frame(output_frame) +Label(laser_frame2, text=" min power:").pack(side='left') +string_laser_min_power = StringVar() +Entry(laser_frame2, width=6, bg='white', textvariable=string_laser_min_power).pack(side='left') +Label(laser_frame2, text="% max power:").pack(side='left') +string_laser_max_power = StringVar() +Entry(laser_frame2, width=6, bg='white', textvariable=string_laser_max_power).pack(side='left') +Label(laser_frame2, text="%").pack(side='left') + # + # autofocus + # +laser_frame3 = Frame(output_frame) +integer_laser_autofocus = IntVar() +widget_autofocus = Checkbutton(laser_frame3, text="Auto Focus", variable=integer_laser_autofocus).pack(side='left') + # + # cutting + # +cut_frame = Frame(output_frame) +Label(cut_frame, text="force: ").pack(side='left') +string_cut_force = StringVar() +Entry(cut_frame, width=6, bg='white', textvariable=string_cut_force).pack(side='left') +Label(cut_frame, text=" velocity:").pack(side='left') +string_cut_velocity = StringVar() +Entry(cut_frame, width=6, bg='white', textvariable=string_cut_velocity).pack(side='left') + # + # speed + # +speed_frame = Frame(output_frame) +Label(speed_frame, text="xy speed:").pack(side='left') +string_xy_speed = StringVar() +Entry(speed_frame, width=4, bg='white', textvariable=string_xy_speed).pack(side='left') +Label(speed_frame, text=" z speed:").pack(side='left') +string_z_speed = StringVar() +Entry(speed_frame, width=4, bg='white', textvariable=string_z_speed).pack(side='left') + # + # jog + # +jog_frame = Frame(output_frame) +Label(jog_frame, text="jog xy speed:").pack(side='left') +string_jog_xy_speed = StringVar() +Entry(jog_frame, width=4, bg='white', textvariable=string_jog_xy_speed).pack(side='left') +Label(jog_frame, text=" z speed:").pack(side='left') +string_jog_z_speed = StringVar() +Entry(jog_frame, width=4, bg='white', textvariable=string_jog_z_speed).pack(side='left') +Label(jog_frame, text=" z:").pack(side='left') +string_jog_z = StringVar() +Entry(jog_frame, width=4, bg='white', textvariable=string_jog_z).pack(side='left') + # + # RML move + # +rml_move_frame = Frame(output_frame) +Label(rml_move_frame, text="x: ").pack(side='left') +string_rml_x_move = StringVar() +Entry(rml_move_frame, width=6, bg='white', textvariable=string_rml_x_move).pack(side='left') +Label(rml_move_frame, text=" y: ").pack(side='left') +string_rml_y_move = StringVar() +Entry(rml_move_frame, width=6, bg='white', textvariable=string_rml_y_move).pack(side='left') +Label(rml_move_frame, text=" ").pack(side='left') +widget_rml_move = Button(rml_move_frame, text="move") +widget_rml_move.pack(side='left') +widget_rml_move.bind('',rml_move) + # + # G codes + # +g_frame = Frame(output_frame) +Label(g_frame, text=" feed rate:").pack(side="left") +string_g_feed_rate = StringVar() +Entry(g_frame, width=6, textvariable=string_g_feed_rate).pack(side="left") +Label(g_frame, text=" spindle speed:").pack(side="left") +string_g_spindle_speed = StringVar() +Entry(g_frame, width=6, textvariable=string_g_spindle_speed).pack(side="left") +Label(g_frame, text=" tool:").pack(side="left") +string_g_tool = StringVar() +Entry(g_frame, width=3, textvariable=string_g_tool).pack(side="left") +integer_g_cool = IntVar() +widget_g_cool = Checkbutton(g_frame, text="coolant", variable=integer_g_cool) +widget_g_cool.pack(side="left") + # + # waterjet + # +waterjet_frame = Frame(output_frame) +Label(waterjet_frame,text="lead-in/out: ").pack(side='left') +string_lead_in = StringVar() +widget_lead_in = Entry(waterjet_frame, width=4, bg='white', textvariable=string_lead_in) +widget_lead_in.pack(side='left') +Label(waterjet_frame,text="quality: ").pack(side='left') +string_quality = StringVar() +widget_quality = Entry(waterjet_frame, width=4, bg='white', textvariable=string_quality) +widget_quality.pack(side='left') + # + # excimer + # +excimer_frame = Frame(output_frame) +Label(excimer_frame,text="period (usec): ").pack(side='left') +string_pulse_period = StringVar() +widget_pulse_period = Entry(excimer_frame, width=5, bg='white', textvariable=string_pulse_period) +widget_pulse_period.pack(side='left') +Label(excimer_frame,text="velocity: ").pack(side='left') +string_cut_vel = StringVar() +widget_cut_vel = Entry(excimer_frame, width=4, bg='white', textvariable=string_cut_vel) +widget_cut_vel.pack(side='left') +Label(excimer_frame,text="acceleration: ").pack(side='left') +string_cut_accel = StringVar() +widget_cut_accel = Entry(excimer_frame, width=4, bg='white', textvariable=string_cut_accel) +widget_cut_accel.pack(side='left') + # + # STL + # +STL_frame = Frame(output_frame) +widget_STL_triangulate = Button(STL_frame, text="triangulate") +widget_STL_triangulate.pack(side='left') +widget_STL_triangulate.bind('',triangulate) + # + # Gerber + # +Gerber_frame = Frame(output_frame) +widget_Gerber_convert = Button(Gerber_frame, text="convert") +widget_Gerber_convert.pack(side='left') +widget_Gerber_convert.bind('',flash) + # + # Excellon + # +Excellon_frame = Frame(output_frame) +widget_Excellon_convert = Button(Excellon_frame, text="convert") +widget_Excellon_convert.pack(side='left') +widget_Excellon_convert.bind('',flash) + # + # filling + # +fill_frame = Frame(output_frame) +integer_fill = IntVar() +widget_fill = Checkbutton(fill_frame, text="fill polygons", variable=integer_fill).pack(side='left') + # + # send to + # +send_to_frame = Frame(output_frame) +widget_send_to = Button(send_to_frame, text="send to machine") +widget_send_to.bind('',send_to) +widget_send_to.pack(side='left') +string_send_to_time = StringVar() +string_send_to_time.set("") +Label(send_to_frame,textvariable=string_send_to_time).pack(side='left') + +# +# define .cad template +# +cad_template = """# +# .cad template +# + +# +# define shapes and transformation +# +# circle(x0, y0, r) +# cylinder(x0, y0, z0, z1, r) +# cone(x0, y0, z0, z1, r0) +# sphere(x0, y0, z0, r) +# torus(x0, y0, z0, r0, r1) +# rectangle(x0, x1, y0, y1) +# cube(x0, x1, y0, y1, z0, z1) +# right_triangle(x0, y0, h) +# triangle(x0, y0, x1, y1, x2, y2) (points in clockwise order) +# pyramid(x0, x1, y0, y1, z0, z1) +# function(Z_of_XY) +# functions(upper_Z_of_XY,lower_Z_of_XY) +# add(part1, part2) +# subtract(part1, part2) +# intersect(part1, part2) +# move(part,dx,dy) +# translate(part,dx,dy,dz) +# rotate(part, angle) +# rotate_x(part, angle) +# rotate_y(part, angle) +# rotate_z(part, angle) +# rotate_90(part) +# rotate_180(part) +# rotate_270(part) +# reflect_x(part) +# reflect_y(part) +# reflect_z(part) +# reflect_xy(part) +# reflect_xz(part) +# reflect_yz(part) +# scale_x(part, x0, sx) +# scale_y(part, y0, sy) +# scale_z(part, z0, sz) +# scale_xy(part, x0, y0, sxy) +# scale_xyz(part, x0, y0, z0, sxyz) +# coscale_x_y(part, x0, y0, y1, angle0, angle1, amplitude, offset) +# coscale_x_z(part, x0, z0, z1, angle0, angle1, amplitude, offset) +# coscale_xy_z(part, x0, y0, z0, z1, angle0, angle1, amplitude, offset) +# taper_x_y(part, x0, y0, y1, s0, s1) +# taper_x_z(part, x0, z0, z1, s0, s1) +# taper_xy_z(part, x0, y0, z0, z1, s0, s1) +# shear_x_y(part, y0, y1, dx0, dx1) +# shear_x_z(part, z0, z1, dx0, dx1) +# (more to come) + +def circle(x0, y0, r): + part = "(((X-x0)**2 + (Y-y0)**2) <= r**2)" + part = replace(part,'x0',str(x0)) + part = replace(part,'y0',str(y0)) + part = replace(part,'r',str(r)) + return part + +def cylinder(x0, y0, z0, z1, r): + part = "(((X-x0)**2 + (Y-y0)**2 <= r**2) & (Z >= z0) & (Z <= z1))" + part = replace(part,'x0',str(x0)) + part = replace(part,'y0',str(y0)) + part = replace(part,'z0',str(z0)) + part = replace(part,'z1',str(z1)) + part = replace(part,'r',str(r)) + return part + +def cone(x0, y0, z0, z1, r0): + part = cylinder(x0, y0, z0, z1, r0) + part = taper_xy_z(part, x0, y0, z0, z1, 1.0, 0.0) + return part + +def sphere(x0, y0, z0, r): + part = "(((X-x0)**2 + (Y-y0)**2 + (Z-z0)**2) <= r**2)" + part = replace(part,'x0',str(x0)) + part = replace(part,'y0',str(y0)) + part = replace(part,'z0',str(z0)) + part = replace(part,'r',str(r)) + return part + +def torus(x0, y0, z0, r0, r1): + part = "(((r0 - sqrt((X-x0)**2 + (Y-y0)**2))**2 + (Z-z0)**2) <= r1**2)" + part = replace(part,'x0',str(x0)) + part = replace(part,'y0',str(y0)) + part = replace(part,'z0',str(z0)) + part = replace(part,'r0',str(r0)) + part = replace(part,'r1',str(r1)) + return part + +def rectangle(x0, x1, y0, y1): + part = "((X >= x0) & (X <= x1) & (Y >= y0) & (Y <= y1))" + part = replace(part,'x0',str(x0)) + part = replace(part,'x1',str(x1)) + part = replace(part,'y0',str(y0)) + part = replace(part,'y1',str(y1)) + return part + +def cube(x0, x1, y0, y1, z0, z1): + part = "((X >= x0) & (X <= x1) & (Y >= y0) & (Y <= y1) & (Z >= z0) & (Z <= z1))" + part = replace(part,'x0',str(x0)) + part = replace(part,'x1',str(x1)) + part = replace(part,'y0',str(y0)) + part = replace(part,'y1',str(y1)) + part = replace(part,'z0',str(z0)) + part = replace(part,'z1',str(z1)) + return part + +def right_triangle(x0, y0, h): + part = "((X > x0) & (X < x0 + h - (Y-y0)) & (Y > y0))" + part = replace(part,'x0',str(x0)) + part = replace(part,'y0',str(y0)) + part = replace(part,'h',str(h)) + return part + +def triangle(x0, y0, x1, y1, x2, y2): # points in clockwise order + 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))" + part = replace(part,'x0',str(x0)) + part = replace(part,'y0',str(y0)) + part = replace(part,'x1',str(x1)) + part = replace(part,'y1',str(y1)) + part = replace(part,'x2',str(x2)) + part = replace(part,'y2',str(y2)) + return part + +def pyramid(x0, x1, y0, y1, z0, z1): + part = cube(x0, x1, y0, y1, z0, z1) + part = taper_xy_z(part, (x0+x1)/2., (y0+y1)/2., z0, z1, 1.0, 0.0) + return part + +def function(Z_of_XY): + part = '(Z <= '+Z_of_XY+')' + return part + +def functions(upper_Z_of_XY,lower_Z_of_XY): + part = '(Z <= '+upper_Z_of_XY+') & (Z >= '+lower_Z_of_XY+')' + return part + +def add(part1, part2): + part = "part1 | part2" + part = replace(part,'part1',part1) + part = replace(part,'part2',part2) + return part + +def subtract(part1, part2): + part = "(part1) & ~(part2)" + part = replace(part,'part1',part1) + part = replace(part,'part2',part2) + return part + +def intersect(part1, part2): + part = "(part1) & (part2)" + part = replace(part,'part1',part1) + part = replace(part,'part2',part2) + return part + +def move(part,dx,dy): + part = replace(part,'X','(X-'+str(dx)+')') + part = replace(part,'Y','(Y-'+str(dy)+')') + return part + +def translate(part,dx,dy,dz): + part = replace(part,'X','(X-'+str(dx)+')') + part = replace(part,'Y','(Y-'+str(dy)+')') + part = replace(part,'Z','(Z-'+str(dz)+')') + return part + +def rotate(part, angle): + angle = angle*pi/180 + part = replace(part,'X','(cos(angle)*X+sin(angle)*y)') + part = replace(part,'Y','(-sin(angle)*X+cos(angle)*y)') + part = replace(part,'y','Y') + part = replace(part,'angle',str(angle)) + return part + +def rotate_x(part, angle): + angle = angle*pi/180 + part = replace(part,'Y','(cos(angle)*Y+sin(angle)*z)') + part = replace(part,'Z','(-sin(angle)*Y+cos(angle)*z)') + part = replace(part,'z','Z') + part = replace(part,'angle',str(angle)) + return part + +def rotate_y(part, angle): + angle = angle*pi/180 + part = replace(part,'X','(cos(angle)*X+sin(angle)*z)') + part = replace(part,'Z','(-sin(angle)*X+cos(angle)*z)') + part = replace(part,'z','Z') + part = replace(part,'angle',str(angle)) + return part + +def rotate_z(part, angle): + angle = angle*pi/180 + part = replace(part,'X','(cos(angle)*X+sin(angle)*y)') + part = replace(part,'Y','(-sin(angle)*X+cos(angle)*y)') + part = replace(part,'y','Y') + part = replace(part,'angle',str(angle)) + return part + +def rotate_90(part): + part = reflect_xy(part) + part = reflect_y(part) + return part + +def rotate_180(part): + part = reflect_xy(part) + part = reflect_y(part) + part = reflect_xy(part) + part = reflect_y(part) + return part + +def rotate_270(part): + part = reflect_xy(part) + part = reflect_y(part) + part = reflect_xy(part) + part = reflect_y(part) + part = reflect_xy(part) + part = reflect_y(part) + return part + +def reflect_x(part): + part = replace(part,'X','(-X)') + return part + +def reflect_y(part): + part = replace(part,'Y','(-Y)') + return part + +def reflect_z(part): + part = replace(part,'Z','(-Z)') + return part + +def reflect_xy(part): + part = replace(part,'X','temp') + part = replace(part,'Y','X') + part = replace(part,'temp','Y') + return part + +def reflect_xz(part): + part = replace(part,'X','temp') + part = replace(part,'Z','X') + part = replace(part,'temp','Z') + return part + +def reflect_yz(part): + part = replace(part,'Y','temp') + part = replace(part,'Z','Y') + part = replace(part,'temp','Z') + return part + +def scale_x(part, x0, sx): + part = replace(part,'X','(x0 + (X-x0)/sx)') + part = replace(part,'x0',str(x0)) + part = replace(part,'sx',str(sx)) + return part + +def scale_y(part, y0, sy): + part = replace(part,'Y','(y0 + (Y-y0)/sy)') + part = replace(part,'y0',str(y0)) + part = replace(part,'sy',str(sy)) + return part + +def scale_z(part, z0, sz): + part = replace(part,'Z','(z0 + (Z-z0)/sz)') + part = replace(part,'z0',str(z0)) + part = replace(part,'sz',str(sz)) + return part + +def scale_xy(part, x0, y0, sxy): + part = replace(part,'X','(x0 + (X-x0)/sxy)') + part = replace(part,'Y','(y0 + (Y-y0)/sxy)') + part = replace(part,'x0',str(x0)) + part = replace(part,'y0',str(y0)) + part = replace(part,'sxy',str(sxy)) + return part + +def scale_xyz(part, x0, y0, z0, sxyz): + part = replace(part,'X','(x0 + (X-x0)/sxyz)') + part = replace(part,'Y','(y0 + (Y-y0)/sxyz)') + part = replace(part,'Z','(z0 + (Z-z0)/sxyz)') + part = replace(part,'x0',str(x0)) + part = replace(part,'y0',str(y0)) + part = replace(part,'z0',str(z0)) + part = replace(part,'sxyz',str(sxyz)) + return part + +def coscale_x_y(part, x0, y0, y1, angle0, angle1, amplitude, offset): + phase0 = pi*angle0/180. + phase1 = pi*angle1/180. + part = replace(part,'X','(x0 + (X-x0)/(offset + amplitude*cos(phase0 + (phase1-phase0)*(Y-y0)/(y1-y0))))') + part = replace(part,'x0',str(x0)) + part = replace(part,'y0',str(y0)) + part = replace(part,'y1',str(y1)) + part = replace(part,'phase0',str(phase0)) + part = replace(part,'phase1',str(phase1)) + part = replace(part,'amplitude',str(amplitude)) + part = replace(part,'offset',str(offset)) + return part + +def coscale_x_z(part, x0, z0, z1, angle0, angle1, amplitude, offset): + phase0 = pi*angle0/180. + phase1 = pi*angle1/180. + part = replace(part,'X','(x0 + (X-x0)/(offset + amplitude*cos(phase0 + (phase1-phase0)*(Z-z0)/(z1-z0))))') + part = replace(part,'x0',str(x0)) + part = replace(part,'z0',str(z0)) + part = replace(part,'z1',str(z1)) + part = replace(part,'phase0',str(phase0)) + part = replace(part,'phase1',str(phase1)) + part = replace(part,'amplitude',str(amplitude)) + part = replace(part,'offset',str(offset)) + return part + +def coscale_xy_z(part, x0, y0, z0, z1, angle0, angle1, amplitude, offset): + phase0 = pi*angle0/180. + phase1 = pi*angle1/180. + part = replace(part,'X','(x0 + (X-x0)/(offset + amplitude*cos(phase0 + (phase1-phase0)*(Z-z0)/(z1-z0))))') + part = replace(part,'Y','(y0 + (Y-y0)/(offset + amplitude*cos(phase0 + (phase1-phase0)*(Z-z0)/(z1-z0))))') + part = replace(part,'x0',str(x0)) + part = replace(part,'y0',str(y0)) + part = replace(part,'z0',str(z0)) + part = replace(part,'z1',str(z1)) + part = replace(part,'phase0',str(phase0)) + part = replace(part,'phase1',str(phase1)) + part = replace(part,'amplitude',str(amplitude)) + part = replace(part,'offset',str(offset)) + return part + +def taper_x_y(part, x0, y0, y1, s0, s1): + part = replace(part,'X','(x0 + (X-x0)*(y1-y0)/(s1*(Y-y0) + s0*(y1-Y)))') + part = replace(part,'x0',str(x0)) + part = replace(part,'y0',str(y0)) + part = replace(part,'y1',str(y1)) + part = replace(part,'s0',str(s0)) + part = replace(part,'s1',str(s1)) + return part + +def taper_x_z(part, x0, z0, z1, s0, s1): + part = replace(part,'X','(x0 + (X-x0)*(z1-z0)/(s1*(Z-z0) + s0*(z1-Z)))') + part = replace(part,'x0',str(x0)) + part = replace(part,'z0',str(z0)) + part = replace(part,'z1',str(z1)) + part = replace(part,'s0',str(s0)) + part = replace(part,'s1',str(s1)) + return part + +def taper_xy_z(part, x0, y0, z0, z1, s0, s1): + part = replace(part,'X','(x0 + (X-x0)*(z1-z0)/(s1*(Z-z0) + s0*(z1-Z)))') + part = replace(part,'Y','(y0 + (Y-y0)*(z1-z0)/(s1*(Z-z0) + s0*(z1-Z)))') + part = replace(part,'x0',str(x0)) + part = replace(part,'y0',str(y0)) + part = replace(part,'z0',str(z0)) + part = replace(part,'z1',str(z1)) + part = replace(part,'s0',str(s0)) + part = replace(part,'s1',str(s1)) + return part + +def shear_x_y(part, y0, y1, dx0, dx1): + part = replace(part,'X','(X - dx0 - (dx1-dx0)*(Y-y0)/(y1-y0))') + part = replace(part,'y0',str(y0)) + part = replace(part,'y1',str(y1)) + part = replace(part,'dx0',str(dx0)) + part = replace(part,'dx1',str(dx1)) + return part + +def shear_x_z(part, z0, z1, dx0, dx1): + part = replace(part,'X','(X - dx0 - (dx1-dx0)*(Z-z0)/(z1-z0))') + part = replace(part,'z0',str(z0)) + part = replace(part,'z1',str(z1)) + part = replace(part,'dx0',str(dx0)) + part = replace(part,'dx1',str(dx1)) + return part + +def coshear_x_z(part, z0, z1, angle0, angle1, amplitude, offset): + phase0 = pi*angle0/180. + phase1 = pi*angle1/180. + part = replace(part,'X','(X - offset - amplitude*cos(phase0 + (phase1-phase0)*(Z-z0)/(z1-z0)))') + part = replace(part,'z0',str(z0)) + part = replace(part,'z1',str(z1)) + part = replace(part,'phase0',str(phase0)) + part = replace(part,'phase1',str(phase1)) + part = replace(part,'amplitude',str(amplitude)) + part = replace(part,'offset',str(offset)) + return part + +# +# define part +# + +d = .5 +teapot = cylinder(0,0,-d,d,d) +teapot = coscale_xy_z(teapot,0,0,-d,d,-90,90,.5,.75) + +handle = torus(0,0,0,3.5*d/5.,d/10.) +handle = reflect_xz(handle) +handle = reflect_xy(handle) +handle = scale_x(handle,0,.75) +handle = scale_y(handle,0,3) +handle = translate(handle,-6*d/5.,0,0) +teapot = add(teapot,handle) + +spout = torus(2.1*d,-.2*d,0,1.1*d,.2*d) +spout = reflect_yz(spout) +spout = intersect(spout,cube(-3*d,1.8*d,-3*d,3*d,0,3*d)) +teapot = add(teapot,spout) + +interior = cylinder(0,0,.1-d,.1+d,d-.1) +interior = coscale_xy_z(interior,0,0,-d,d,-90,90,.5,.75) +teapot = subtract(teapot,interior) + +spout_interior = torus(2.1*d,-.2*d,0,1.1*d,.15*d) +spout_interior = reflect_yz(spout_interior) +spout_interior = intersect(spout_interior,cube(-3*d,1.8*d,-3*d,3*d,0,3*d)) +teapot = subtract(teapot,spout_interior) + +part = teapot + +part = subtract(part,cube(0,3*d,-3*d,0,-3*d,3*d)) + +# +# define limits and parameters +# + +width = 2.5 +x0 = 0 +y0 = 0 +z0 = 0 +cad.xmin = x0-width/2. # min x to render +cad.xmax = x0+width/2. # max x to render +cad.ymin = y0-width/2. # min y to render +cad.ymax = y0+width/2. # max y to render +#cad.zmin = z0-width/4. # min z to render +#cad.zmax = z0+width/4. # max x to render +cad.zmin = z0-width/4. # min z to render +cad.zmax = z0+width/4. # max x to render +cad.rx = 30 # x view rotation (degrees) +cad.rz = 20 # z view rotation (degrees) +dpi = 100 # rendering resolution +cad.nx = int(dpi*(cad.xmax-cad.xmin)) # x points to render +cad.ny = int(dpi*(cad.ymax-cad.ymin)) # y points to render +cad.nz = int(dpi*(cad.zmax-cad.zmin)) # z points to render +cad.inches_per_unit = 1.0 # use inch units + +# +# assign part to cad.function +# + +cad.function = part + +""" + +# +# check config file for window parameters +# + +cad_path = os.path.dirname(sys.argv[0]) +if (sys.argv[0] == "cad.py"): + cfg_path = "cad.cfg" +else: + cfg_path = os.path.dirname(sys.argv[0])+"/cad.cfg" +try: + config_file = open(cfg_path, 'r') + string_msg.set("found "+cfg_path) + while 1: + line = config_file.readline() + if (find(line,"window size:") == 0): + string_window_size.set(int(line[12:])) + elif (find(line,"editor width:") == 0): + string_editor_width.set(int(line[13:])) + elif (find(line,"editor height:") == 0): + string_editor_height.set(int(line[14:])) + elif (line == ""): + break + config_file.close() + resize_editor(0) +except: + string_msg.set(cfg_path+" not found") + +# +# read input file if on command line, otherwise use template +# + +if len(sys.argv) == 2: + filename = sys.argv[1] + string_input_file.set(filename) + if (find(filename,'.cad') != -1): + cad_load(0) + elif ((find(filename,'.jpg') != -1) | (find(filename,'.JPG') != -1) | + (find(filename,'.png') != -1) | (find(filename,'.PNG') != -1) | + (find(filename,'.gif') != -1) | (find(filename,'.GIF') != -1)): + widget_cad_text.delete("1.0",END) + image_load(0) + else: + string_msg.set("unsupported input file format") + root.update() +else: + widget_cad_text.insert("1.0",cad_template) + +# +# start GUI +# + +root.mainloop() diff -r 000000000000 -r ee535cb8fb1a stuff/(Cad.py) Plotting with solenoid or Laser.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/stuff/(Cad.py) Plotting with solenoid or Laser.py Sat Nov 07 13:30:15 2015 +0100 @@ -0,0 +1,3848 @@ +#!/usr/bin/env python +# +# cad.py +# +# Neil Gershenfeld +# +# (c) Massachusetts Institute of Technology 2007 +# Permission granted for experimental and personal use; +# license for commercial sale available from MIT. +# +#Altered by Capo to output gcode with the '.gcode' extension as opposed to '.g' +#and to work with a solenoid/Laser cutter. +#For more information see http://capolight.wordpress.com/2012/04/29/converting_images_to_gcode/printers +DATE = "29/04/2012" + +from numpy import * +import scipy.signal.signaltools +from string import * +from Tkinter import * +from tkFileDialog import * +import Image, ImageTk, ImageDraw, ImageFont, ImageOps +import os, struct +#import time + +class point: + # + # an xyz point + # + def __init__(self,x,y,z=0): + self.x = x + self.y = y + self.z = z + +class cad_variables: + # + # cad variables + # + def __init__(self): + self.xmin = 0 # minimum x value to render + self.xmax = 0 # maximum x value to render + self.ymin = 0 # minimum y value to render + self.ymax = 0 # maximum y value to render + self.zmin = 0 # minimum z value to render + self.zmax = 0 # maximum z value to render + self.zlist = [] # z values to render + self.nx = 0 # number of x points to render + self.ny = 0 # number of y points to render + self.nz = 1 # number of z points to render + self.rz = 0 # perspective view z rotation (degrees) + self.rx = 0 # perspective view x rotation (degrees) + self.units = 'in' # file units + self.function = '0' # cad function + self.toolpaths = [] # toolpaths + self.x = [] # x triangulation + self.y = [] # y triangulation + self.z = [] # z triangulation + self.labels = [] # display labels + self.image_r = array(0) # red array + self.image_g = array(0) # green array + self.image_b = array(0) # blue array + self.image_min = 0 # image min value + self.image_max = 0 # image max value + self.stop = 0 # stop rendering + self.nplot = 200 # plot window size + self.inches_per_unit = 1 # file units + self.views = 'xyzr' + self.cam = '' # CAM export type + self.editor_width = 30 # editor width + self.editor_height = 10 # editor height + def view(self,arg): + global canvas_xy,canvas_yz,canvas_xz,canvas_xyz + if (arg == 'xy'): + view_frame2.grid_forget() + view_frame3.grid_forget() + canvas_xy.grid_forget() + self.views = 'xy' + self.nplot = 2*int(string_window_size.get()) # plot window size + canvas_xy = Canvas(view_frame2, width=self.nplot, height=self.nplot) + imxy = Image.new("RGBX",(self.nplot,self.nplot),'black') + image_xy = ImageTk.PhotoImage(imxy) + canvas_xy.create_image(self.nplot/2,self.nplot/2,image=image_xy) + canvas_xy.bind('',msg_xy) + canvas_xy.grid(row=0,column=0) + view_frame2.grid(row=2,column=0) + elif (arg == 'xyzr'): + view_frame2.grid_forget() + view_frame3.grid_forget() + canvas_xy.grid_forget() + canvas_yz.grid_forget() + canvas_xz.grid_forget() + canvas_xyz.grid_forget() + self.views = 'xyzr' + self.nplot = int(string_window_size.get()) # plot window size + canvas_xy = Canvas(view_frame3, width=self.nplot, height=self.nplot) + canvas_yz = Canvas(view_frame3, width=self.nplot, height=self.nplot) + canvas_xz = Canvas(view_frame3, width=self.nplot, height=self.nplot) + canvas_xyz = Canvas(view_frame3, width=self.nplot, height=cad.nplot) + imxy = Image.new("RGBX",(self.nplot,self.nplot),'black') + image_xy = ImageTk.PhotoImage(imxy) + canvas_xy.create_image(self.nplot/2,self.nplot/2,image=image_xy) + canvas_xy.bind('',msg_xy) + canvas_xy.grid(row=0,column=0) + imyz = Image.new("RGBX",(self.nplot,self.nplot),'black') + image_yz = ImageTk.PhotoImage(imyz) + canvas_yz.create_image(self.nplot/2,self.nplot/2,image=image_yz) + canvas_yz.bind('',msg_yz) + canvas_yz.grid(row=0,column=1) + imxz = Image.new("RGBX",(self.nplot,self.nplot),'black') + image_xz = ImageTk.PhotoImage(imxz) + canvas_xz.create_image(self.nplot/2,self.nplot/2,image=image_xz) + canvas_xz.bind('',msg_xz) + canvas_xz.grid(row=1,column=0) + imxyz = Image.new("RGBX",(self.nplot,self.nplot),'black') + image_xyz = ImageTk.PhotoImage(imxyz) + canvas_xyz.create_image(self.nplot/2,self.nplot/2,image=image_xyz) + canvas_xyz.bind('',msg_nomsg) + canvas_xyz.grid(row=1,column=1) + view_frame3.grid(row=2,column=0) + else: + print "view not supported" + def nxplot(self): + xwidth = self.xmax - self.xmin + ywidth = self.ymax - self.ymin + zwidth = self.zmax - self.zmin + if ((xwidth >= ywidth) & (xwidth >= zwidth)): + n = int(self.nplot*xwidth/float(xwidth)) + elif ((ywidth >= xwidth) & (ywidth >= zwidth)): + n = int(self.nplot*xwidth/float(ywidth)) + else: + n = int(self.nplot*xwidth/float(zwidth)) + return n + def nyplot(self): + xwidth = self.xmax - self.xmin + ywidth = self.ymax - self.ymin + zwidth = self.zmax - self.zmin + if ((xwidth >= ywidth) & (xwidth >= zwidth)): + n = int(self.nplot*ywidth/float(xwidth)) + elif ((ywidth >= xwidth) & (ywidth >= zwidth)): + n = int(self.nplot*ywidth/float(ywidth)) + else: + n = int(self.nplot*ywidth/float(zwidth)) + return n + def nzplot(self): + xwidth = self.xmax - self.xmin + ywidth = self.ymax - self.ymin + zwidth = self.zmax - self.zmin + if ((xwidth >= ywidth) & (xwidth >= zwidth)): + n = int(self.nplot*zwidth/float(xwidth)) + elif ((ywidth >= xwidth) & (ywidth >= zwidth)): + n = int(self.nplot*zwidth/float(ywidth)) + else: + n = int(self.nplot*zwidth/float(zwidth)) + return n + +cad = cad_variables() + +class cad_text: + def __init__(self,x,y,z=0,text='',size=10,color='#ff0000',anchor=CENTER): + self.x = x + self.y = y + self.z = z + self.text = text + self.size = size + self.color = color + self.anchor = anchor + +class im_class: + # + # for PIL images + # + def __init__(self): + self.xy = 0 + self.xz = 0 + self.yz = 0 + self.xyz = 0 + self.intensity_xy = 0 + self.intensity_xz = 0 + self.intensity_yz = 0 + self.intensity_xyz = 0 + +im = im_class() + +class images_class: + # + # for PhotoImages + # + def __init__(self): + self.xy = 0 + self.xz = 0 + self.yz = 0 + self.xyz = 0 + +images = images_class() + +class CA_states: + # + # CA state definition class + # + def __init__(self): + self.empty = 0 + self.interior = 1 + self.edge = (1 << 1) # 2 + self.north = (1 << 2) # 4 + self.west = (2 << 2) # 8 + self.east = (3 << 2) # 12 + self.south = (4 << 2) # 16 + self.stop = (5 << 2) # 20 + self.corner = (6 << 2) # 24 + +class rule_table: + # + # CA rule table class + # + # 0 = empty + # 1 = interior + # 2 = edge + # edge+direction = start + # + def __init__(self): + self.table = zeros(2**(9*2),uint32) + self.s = CA_states() + # + # 1 0: + # + # 011 + # 111 + # 111 + self.add_rule(0,1,1,1,1,1,1,1,1,self.s.north) + # 101 + # 111 + # 111 + self.add_rule(1,0,1,1,1,1,1,1,1,self.s.east) + # + # 2 0's: + # + # 001 + # 111 + # 111 + self.add_rule(0,0,1,1,1,1,1,1,1,self.s.east) + # 100 + # 111 + # 111 + self.add_rule(1,0,0,1,1,1,1,1,1,self.s.east) + # 010 + # 111 + # 111 + self.add_rule(0,1,0,1,1,1,1,1,1,self.s.east) + # 011 + # 110 + # 111 + self.add_rule(0,1,1,1,1,0,1,1,1,self.s.south) + # 110 + # 011 + # 111 + self.add_rule(1,1,0,0,1,1,1,1,1,self.s.east) + # 101 + # 011 + # 111 + self.add_rule(1,0,1,0,1,1,1,1,1,self.s.east) + # 101 + # 110 + # 111 + self.add_rule(1,0,1,1,1,0,1,1,1,self.s.south) + # 011 + # 111 + # 110 + self.add_rule(0,1,1,1,1,1,1,1,0,self.s.corner) + # 011 + # 111 + # 101 + self.add_rule(0,1,1,1,1,1,1,0,1,self.s.north) + # 110 + # 111 + # 101 + self.add_rule(1,1,0,1,1,1,1,0,1,self.s.west) + # 101 + # 111 + # 110 + self.add_rule(1,0,1,1,1,1,1,1,0,self.s.south) + # 101 + # 111 + # 011 + self.add_rule(1,0,1,1,1,1,0,1,1,self.s.east) + # + # 3 0's: + # + # 001 + # 011 + # 111 + self.add_rule(0,0,1,0,1,1,1,1,1,self.s.east) + # 010 + # 011 + # 111 + self.add_rule(0,1,0,0,1,1,1,1,1,self.s.east) + # 010 + # 110 + # 111 + self.add_rule(0,1,0,1,1,0,1,1,1,self.s.south) + # 010 + # 111 + # 011 + self.add_rule(0,1,0,1,1,1,0,1,1,self.s.east) + # 010 + # 111 + # 110 + self.add_rule(0,1,0,1,1,1,1,1,0,self.s.south) + # 110 + # 011 + # 011 + self.add_rule(1,1,0,0,1,1,0,1,1,self.s.east) + # 011 + # 110 + # 110 + self.add_rule(0,1,1,1,1,0,1,1,0,self.s.south) + # 101 + # 011 + # 011 + self.add_rule(1,0,1,0,1,1,0,1,1,self.s.east) + # 101 + # 110 + # 110 + self.add_rule(1,0,1,1,1,0,1,1,0,self.s.south) + # 011 + # 011 + # 011 + self.add_rule(0,1,1,0,1,1,0,1,1,self.s.north) + # + # 4 0's: + # + # 001 + # 011 + # 011 + self.add_rule(0,0,1,0,1,1,0,1,1,self.s.east) + # 100 + # 110 + # 110 + self.add_rule(1,0,0,1,1,0,1,1,0,self.s.south) + # 010 + # 011 + # 011 + self.add_rule(0,1,0,0,1,1,0,1,1,self.s.east) + # 010 + # 110 + # 110 + self.add_rule(0,1,0,1,1,0,1,1,0,self.s.south) + # 001 + # 110 + # 110 + self.add_rule(0,0,1,1,1,0,1,1,0,self.s.south) + # 100 + # 011 + # 011 + self.add_rule(1,0,0,0,1,1,0,1,1,self.s.east) + # + # 5 0's: + # + # 000 + # 011 + # 011 + self.add_rule(0,0,0,0,1,1,0,1,1,self.s.east) + # + # edge states + # + # 200 + # 211 + # 211 + self.add_rule(2,0,0,2,1,1,2,1,1,self.s.east+self.s.edge) + # 201 + # 211 + # 211 + self.add_rule(2,0,1,2,1,1,2,1,1,self.s.east+self.s.edge) + # 210 + # 211 + # 211 + self.add_rule(2,1,0,2,1,1,2,1,1,self.s.east+self.s.edge) + # 002 + # 112 + # 112 + self.add_rule(0,0,2,1,1,2,1,1,2,self.s.stop) + # 102 + # 112 + # 112 + self.add_rule(1,0,2,1,1,2,1,1,2,self.s.stop) + # 002 + # 112 + # 102 + self.add_rule(0,0,2,1,1,2,1,0,2,self.s.stop) + # 012 + # 112 + # 112 + self.add_rule(0,1,2,1,1,2,1,1,2,self.s.stop) + # 012 + # 112 + # 102 + self.add_rule(0,1,2,1,1,2,1,0,2,self.s.stop) + + def add_rule(self,nw,nn,ne,ww,cc,ee,sw,ss,se,rule): + # + # add a CA rule, with rotations + # + s = CA_states() + # + # add the rule + # + state = \ + (nw << 0) + (nn << 2) + (ne << 4) + \ + (ww << 6) + (cc << 8) + (ee << 10) + \ + (sw << 12) + (ss << 14) + (se << 16) + self.table[state] = rule + # + # rotate 90 degrees + # + state = \ + (sw << 0) + (ww << 2) + (nw << 4) + \ + (ss << 6) + (cc << 8) + (nn << 10) + \ + (se << 12) + (ee << 14) + (ne << 16) + if (rule == s.east): + self.table[state] = s.south + elif (rule == s.south): + self.table[state] = s.west + elif (rule == s.west): + self.table[state] = s.north + elif (rule == s.north): + self.table[state] = s.east + elif (rule == (s.east+s.edge)): + self.table[state] = s.south+s.edge + elif (rule == (s.south+s.edge)): + self.table[state] = s.west+s.edge + elif (rule == (s.west+s.edge)): + self.table[state] = s.north+s.edge + elif (rule == (s.north+s.edge)): + self.table[state] = s.east+s.edge + elif (rule == s.corner): + self.table[state] = s.corner + elif (rule == s.stop): + self.table[state] = s.stop + # + # rotate 180 degrees + # + state = \ + (se << 0) + (ss << 2) + (sw << 4) + \ + (ee << 6) + (cc << 8) + (ww << 10) + \ + (ne << 12) + (nn << 14) + (nw << 16) + if (rule == s.east): + self.table[state] = s.west + elif (rule == s.south): + self.table[state] = s.north + elif (rule == s.west): + self.table[state] = s.east + elif (rule == s.north): + self.table[state] = s.south + elif (rule == (s.east+s.edge)): + self.table[state] = s.west+s.edge + elif (rule == (s.south+s.edge)): + self.table[state] = s.north+s.edge + elif (rule == (s.west+s.edge)): + self.table[state] = s.east+s.edge + elif (rule == (s.north+s.edge)): + self.table[state] = s.south+s.edge + elif (rule == s.corner): + self.table[state] = s.corner + elif (rule == s.stop): + self.table[state] = s.stop + # + # rotate 270 degrees + # + state = \ + (ne << 0) + (ee << 2) + (se << 4) + \ + (nn << 6) + (cc << 8) + (ss << 10) + \ + (nw << 12) + (ww << 14) + (sw << 16) + if (rule == s.east): + self.table[state] = s.north + elif (rule == s.south): + self.table[state] = s.east + elif (rule == s.west): + self.table[state] = s.south + elif (rule == s.north): + self.table[state] = s.west + elif (rule == (s.east+s.edge)): + self.table[state] = s.north+s.edge + elif (rule == (s.south+s.edge)): + self.table[state] = s.east+s.edge + elif (rule == (s.west+s.edge)): + self.table[state] = s.south+s.edge + elif (rule == (s.north+s.edge)): + self.table[state] = s.west+s.edge + elif (rule == s.corner): + self.table[state] = s.corner + elif (rule == s.stop): + self.table[state] = s.stop + +def evaluate_state(arr): + # + # assemble the state bit strings + # + (ny, nx) = shape(arr) + s = CA_states() + nn = concatenate(([s.edge+zeros(nx,uint32)],arr[:(ny-1)])) + ss = concatenate((arr[1:],[s.edge+zeros(nx,uint32)])) + ww = concatenate((reshape(s.edge+zeros(ny,uint32),(ny,1)),arr[:,:(nx-1)]),1) + ee = concatenate((arr[:,1:],reshape(s.edge+zeros(ny,uint32),(ny,1))),1) + cc = arr + nw = concatenate(([s.edge+zeros(nx,uint32)],ww[:(ny-1)])) + ne = concatenate(([s.edge+zeros(nx,uint32)],ee[:(ny-1)])) + sw = concatenate((ww[1:],[s.edge+zeros(nx,uint32)])) + se = concatenate((ee[1:],[s.edge+zeros(nx,uint32)])) + state = (nw << 0) + (nn << 2) + (ne << 4) + \ + (ww << 6) + (cc << 8) + (ee << 10) + \ + (sw << 12) + (ss << 14) + (se << 16) + return state + +def vectorize_toolpaths(arr): + # + # convert lattice toolpath directions to vectors + # + s = CA_states() + toolpaths = [] + max_dist = float(string_vector_error.get()) + start_sites = (arr == (s.north+s.edge)) | (arr == (s.south+s.edge)) | \ + (arr == (s.east+s.edge)) | (arr == (s.west+s.edge)) + num_start_sites = sum(sum(1.0*start_sites)) + path_sites = (arr == s.north) | (arr == s.south) | (arr == s.east) | \ + (arr == s.west) + num_path_sites = sum(sum(1.0*path_sites)) + remaining_sites = num_start_sites + num_path_sites + while (remaining_sites != 0): + #print remaining_sites + if (num_start_sites > 0): + # + # begin segment on a start state + # + if (argmax(start_sites[0,:],axis=0) != 0): + x = argmax(start_sites[0,:],axis=0) + y = 0 + elif (argmax(start_sites[:,0],axis=0) != 0): + x = 0 + y = argmax(start_sites[:,0],axis=0) + elif (argmax(start_sites[-1,:],axis=0) != 0): + x = argmax(start_sites[-1,:],axis=0) + y = cad.ny-1 + elif (argmax(start_sites[:,-1],axis=0) != 0): + x = cad.nx-1 + y = argmax(start_sites[:,-1],axis=0) + else: + print "error: internal start" + sys.exit() + #print "start from ",x,y + else: + # + # no start states; begin segment on upper-left boundary point + # + maxcols = argmax(path_sites,axis=1) + y = argmax(argmax(path_sites,axis=1)) + x = maxcols[y] + arr[y][x] += s.edge + #print "segment from ",x,y + segment = [point(x,y)] + vector = [point(x,y)] + while 1: + # + # follow path + # + y = vector[-1].y + x = vector[-1].x + state = arr[y][x] + # + # if start state, set stop + # + if (state == (s.north + s.edge)): + state = s.north + arr[y][x] = s.stop + elif (state == (s.south + s.edge)): + state = s.south + arr[y][x] = s.stop + elif (state == (s.east + s.edge)): + state = s.east + arr[y][x] = s.stop + elif (state == (s.west + s.edge)): + state = s.west + arr[y][x] = s.stop + #print "x,y,state,arr: ",x,y,state,arr[y][x] + # + # move if a valid direction + # + if (state == s.north): + direction = "north" + #print "north" + ynew = y - 1 + xnew = x + elif (state == s.south): + direction = "south" + #print "south" + ynew = y + 1 + xnew = x + elif (state == s.east): + direction = "east" + #print "east" + ynew = y + xnew = x + 1 + elif (state == s.west): + direction = "west" + #print "west" + ynew = y + xnew = x - 1 + elif (state == s.corner): + #print "corner" + if (direction == "east"): + #print "south" + xnew = x + ynew = y + 1 + elif (direction == "west"): + #print "north" + xnew = x + ynew = y - 1 + elif (direction == "north"): + #print "east" + ynew = y + xnew = x + 1 + elif (direction == "south"): + #print "west" + ynew = y + xnew = x - 1 + else: + # + # not a valid direction, terminate segment on previous point + # + print "unexpected path termination at",x,y + #sys.exit() + segment.append(point(x,y)) + toolpaths.append(segment) + arr[y][x] = s.interior + break + #print "xnew,ynew,snew",xnew,ynew,arr[ynew][xnew] + # + # check if stop reached + # + if (arr[ynew][xnew] == s.stop): + #print "stop at ",xnew,ynew + segment.append(point(xnew,ynew)) + toolpaths.extend([segment]) + if (state != s.corner): + arr[y][x] = s.interior + arr[ynew][xnew] = s.interior + break + # + # find max transverse distance from vector to new point + # + dmax = 0 + dx = xnew - vector[0].x + dy = ynew - vector[0].y + norm = sqrt(dx**2 + dy**2) + nx = dy / norm + ny = -dx / norm + for i in range(len(vector)): + dx = vector[i].x - vector[0].x + dy = vector[i].y - vector[0].y + d = abs(nx*dx + ny*dy) + if (d > dmax): + dmax = d + # + # start new vector if transverse distance > max_dist + # + if (dmax >= max_dist): + #print "max at ",x,y + segment.append(point(x,y)) + vector = [point(x,y)] + # + # otherwise add point to vector + # + else: + #print "add ",xnew,ynew + vector.append(point(xnew,ynew)) + if ((arr[y][x] != s.corner) & (arr[y][x] != s.stop)): + arr[y][x] = s.interior + start_sites = (arr == (s.north+s.edge)) | (arr == (s.south+s.edge)) | \ + (arr == (s.east+s.edge)) | (arr == (s.west+s.edge)) + num_start_sites = sum(sum(1.0*start_sites)) + path_sites = (arr == s.north) | (arr == s.south) | (arr == s.east) | \ + (arr == s.west) + num_path_sites = sum(sum(1.0*path_sites)) + remaining_sites = num_start_sites + num_path_sites + # + # reverse segment order, to start from inside to out + # + newpaths = [] + for segment in range(len(toolpaths)): + newpaths.append(toolpaths[-1-segment]) + root.update() + return newpaths + +def evaluate(): + # + # evaluate .cad program/image + # + if (len(widget_cad_text.get("1.0",END)) > 1): + # + # .cad + # + cad.zlist = [] + cad_text_string = widget_cad_text.get("1.0",END) + exec cad_text_string in globals() + widget_function_text.config(state=NORMAL) + widget_function_text.delete("1.0",END) + widget_function_text.insert("1.0",cad.function) + widget_function_text.config(state=DISABLED) + if (cad.image_r.size > 1): + # + # image + # + cad.xmin = float(string_image_xmin.get()) + xwidth = float(string_image_xwidth.get()) + cad.xmax = cad.xmin + xwidth + cad.ymin = float(string_image_ymin.get()) + yheight = float(string_image_yheight.get()) + cad.ymax = cad.ymin + yheight + cad.image_min = float(string_image_min.get()) + cad.image_max = float(string_image_max.get()) + cad.zmin = float(string_image_zmin.get()) + cad.zmax = float(string_image_zmax.get()) + cad.nz = int(string_image_nz.get()) + cad.inches_per_unit = float(string_image_units.get()) + +def render(view='xyzr'): + render_stop_flag = 0 + cad.stop = 0 + # + # if .cad doesn't call render, delete windows and add stop button + # + if (find(widget_cad_text.get("1.0",END),"render(") == -1): + string_msg.set("render ...") + widget_stop.pack() + delete_windows() + # + # initialize variables + # + cad.toolpaths = [] + rx = pi*cad.rx/180. + rz = pi*cad.rz/180. + r = rule_table() + s = CA_states() + # + # evaluate coordinate arrays + # + Xarray = outer(ones((cad.ny,1)),cad.xmin+(cad.xmax-cad.xmin)*arange(cad.nx)/(cad.nx-1.0)) + Yarray = outer(cad.ymin+(cad.ymax-cad.ymin)*arange(cad.ny-1,-1,-1)/(cad.ny-1.0),ones((1,cad.nx))) + if (cad.zlist == []): + if ((cad.nz == 1) & (cad.image_r.size != 1)): + cad.zlist = [cad.zmax] + cad.view('xy') + elif (cad.nz == 1): + cad.zlist = [cad.zmin] + cad.view('xy') + else: + cad.zlist = cad.zmin + (cad.zmax-cad.zmin)*arange(cad.nz)/(cad.nz-1.0) + cad.view('xyzr') + else: + cad.nz = len(cad.zlist) + cad.zmin = cad.zlist[0] + cad.zmax = cad.zlist[-1] + # + # draw orthogonal views + # + X = Xarray + Y = Yarray + accum_r = zeros((cad.ny,cad.nx),uint32) + accum_g = zeros((cad.ny,cad.nx),uint32) + accum_b = zeros((cad.ny,cad.nx),uint32) + im.intensity_yz = zeros((cad.ny,cad.nz),uint32) + im.intensity_xz = zeros((cad.nz,cad.nx),uint32) + im.intensity_xyz = zeros((cad.nz,cad.nx),uint32) + for layer in range(cad.nz): + # + # check render stop button + # + if (cad.stop == 1): + break + # + # xy view + # + Z = cad.zlist[layer] + string_msg.set("render z = %.3f"%Z) + # root.update() + if (cad.image_r.size == 1): + # + # .cad + # + array_r = eval(cad.function) + array_g = array_r + array_b = array_r + if ((cad.zmax == cad.zmin) | (cad.nz == 1)): + zi = array([255],uint32) + else: + zi = array([55.0 + 200.0*layer/(cad.nz-1.0)],uint32) + accum_r = where(((zi*array_r) > accum_r),(zi*array_r),accum_r) + accum_g = where(((zi*array_g) > accum_g),(zi*array_g),accum_g) + accum_b = where(((zi*array_b) > accum_b),(zi*array_b),accum_b) + im.intensity_xy = (1 << 16)*accum_b + (1 << 8)*accum_g + (1 << 0)*accum_r + else: + # + # bitmap + # + array_r = (cad.image_r[0,] >= (cad.image_min + (cad.image_max-cad.image_min)*(Z-cad.zmin)/float(cad.zmax-cad.zmin))) + array_g = (cad.image_g[0,] >= (cad.image_min + (cad.image_max-cad.image_min)*(Z-cad.zmin)/float(cad.zmax-cad.zmin))) + array_b = (cad.image_b[0,] >= (cad.image_min + (cad.image_max-cad.image_min)*(Z-cad.zmin)/float(cad.zmax-cad.zmin))) + image_z = int(cad.image_min + (cad.image_max-cad.image_min)*(Z-cad.zmin)/float(cad.zmax-cad.zmin)) + intensity_r = where((cad.image_r[0,] <= image_z),cad.image_r[0,],image_z) + intensity_g = where((cad.image_g[0,] <= image_z),cad.image_g[0,],image_z) + intensity_b = where((cad.image_b[0,] <= image_z),cad.image_b[0,],image_z) + im.intensity_xy = (1 << 16)*intensity_b + (1 << 8)*intensity_g + (1 << 0)*intensity_r + im.xy = Image.fromarray(im.intensity_xy,mode="RGBX") + im.xy_draw = ImageDraw.Draw(im.xy) + im.xy = im.xy.resize((cad.nxplot(),cad.nyplot())) + images.xy = ImageTk.PhotoImage(im.xy) + canvas_xy.create_image(cad.nplot/2,cad.nplot/2,image=images.xy) + # root.update() + # + # find toolpaths if needed + # + ncontours = int(string_num_contours.get()) + if (ncontours == -1): + ncontours = 2**20 # a big number + cad.toolpaths.append([]) + """ + if (ncontours != 0): + # + # grassfire convolve (to come) + # + interior = (array_r | array_g | array_b) + print shape(X[interior]) + conv_array = interior + """ + for contour in range(ncontours): + # + # check render stop button + # + if (cad.stop == 1): + break + # + # convolve tool for contour + # + string_msg.set(" convolve tool ... ") + # + # FFT convolve + # + # root.update() + tool_rad = float(string_tool_dia.get())/2.0 + tool_dia = float(string_tool_dia.get()) + tool_overlap = float(string_tool_overlap.get()) + kernel_rad = tool_rad + contour*tool_overlap*tool_dia + ikernel_rad = 1 + int(cad.nx*kernel_rad/(cad.xmax-cad.xmin)) + if (ikernel_rad > (((cad.nx/2),(cad.ny/2))[(cad.ny/2) > (cad.nx/2)])): + break + kx = 1+outer(ones((2*ikernel_rad,1)),arange(2*ikernel_rad)) + ky = 1+outer(arange(2*ikernel_rad),ones((1,2*ikernel_rad))) + k = (((kx-ikernel_rad)**2 + (ky-ikernel_rad)**2) < ikernel_rad**2).astype('uint32') + interior = (array_r == s.interior).astype('uint32') + #tstart = time.time() + conv = scipy.signal.signaltools.fftconvolve(interior,k,mode='same') + conv = where(conv > 0.01,s.interior,0) + conv_array = conv + (conv != s.interior)*array_r + #tend = time.time() + #print 'convolve:',tend-tstart + # + # use CA rule table to find edge directions + # + string_msg.set(" follow edges ... ") + # root.update() + state = evaluate_state(conv_array) + toolpath = r.table[state] + tool_array = toolpath + (toolpath == s.empty)*conv_array + tool_intensity = \ + ((0 << 16) + (0 << 8) + (0 << 0))*(tool_array == s.empty).astype('uint32') +\ + ((255 << 16) + (255 << 8) + (255 << 0))*(tool_array == s.interior).astype('uint32') +\ + (( 0 << 16) + ( 0 << 8) + (255 << 0))*(tool_array == s.north).astype('uint32') +\ + (( 0 << 16) + (255 << 8) + ( 0 << 0))*(tool_array == s.south).astype('uint32') +\ + ((255 << 16) + ( 0 << 8) + ( 0 << 0))*(tool_array == s.east).astype('uint32') +\ + (( 0 << 16) + (255 << 8) + (255 << 0))*(tool_array == s.west ).astype('uint32') +\ + ((128 << 16) + ( 0 << 8) + (128 << 0))*(tool_array == s.stop).astype('uint32') + + # + # show CA + # + """ + im.xy = Image.fromarray(tool_intensity,mode="RGBX") + im.xy = im.xy.resize((cad.nplot,cad.nplot)) + images.xy = ImageTk.PhotoImage(im.xy) + canvas_xy.create_image(cad.nplot/2,cad.nplot/2,image=images.xy) + """ + # + # vectorize contour + # + #tstart = time.time() + string_msg.set(" vectorize ... ") + # root.update() + new_paths = vectorize_toolpaths(tool_array) + if (len(new_paths) == 0): + break + cad.toolpaths[layer].extend(new_paths) + #tend = time.time() + #print 'vector:',tend-tstart + # + # draw toolpath + # + im.xy_draw = ImageDraw.Draw(im.xy) + for segment in range(len(cad.toolpaths[layer])): + x = cad.nxplot()*(cad.toolpaths[layer][segment][0].x+0.5)/float(cad.nx) + y = cad.nyplot()*(cad.toolpaths[layer][segment][0].y+0.5)/float(cad.ny) + for vertex in range(1,len(cad.toolpaths[layer][segment])): + xnew = cad.nxplot()*(cad.toolpaths[layer][segment][vertex].x+0.5)/float(cad.nx) + ynew = cad.nyplot()*(cad.toolpaths[layer][segment][vertex].y+0.5)/float(cad.ny) + im.xy_draw.line([x,y,xnew,ynew],fill="#ffa0a0",width=1) + x = xnew + y = ynew + # + # show xy toolpath view + # + images.xy = ImageTk.PhotoImage(im.xy) + canvas_xy.create_image(cad.nplot/2,cad.nplot/2,image=images.xy) + # + # add send_to button + # + string_send_to_time.set("") + send_to_frame.pack() + # root.update() + # + # draw labels + # + for label in range(len(cad.labels)): + x = cad.nplot/2. + cad.nxplot()*(cad.labels[label].x-(cad.xmax+cad.xmin)/2.0)/(cad.xmax-cad.xmin) + y = cad.nplot/2. - cad.nyplot()*(cad.labels[label].y-(cad.ymax+cad.ymin)/2.0)/(cad.ymax-cad.ymin) + string = cad.labels[label].text + size = cad.labels[label].size + color = cad.labels[label].color + anch = cad.labels[label].anchor + canvas_xy.create_text(x,y,text=string,font=('arial',size,'bold'),fill=color,anchor=anch,justify=CENTER) + # + # draw origin + # + x0 = cad.nplot/2. + cad.nxplot()*(0-(cad.xmax+cad.xmin)/2.)/(cad.xmax-cad.xmin) + y0 = cad.nplot/2. - cad.nyplot()*(0-(cad.ymax+cad.ymin)/2.)/(cad.ymax-cad.ymin) + dxy = .025*cad.nplot + canvas_xy.create_line([x0-dxy,y0,x0+dxy,y0],fill="green") + canvas_xy.create_line([x0,y0-dxy,x0,y0+dxy],fill="green") + # + # yz view + # + if (cad.views == 'xyzr'): + accum_yz_r = zeros(cad.ny,uint32) + accum_yz_g = zeros(cad.ny,uint32) + accum_yz_b = zeros(cad.ny,uint32) + for vertex in range(cad.nx): + xi = array([55.0 + 200.0*vertex/(cad.nx-1.0)],uint32) + slice_r = array_r[:,vertex] + slice_g = array_g[:,vertex] + slice_b = array_b[:,vertex] + accum_yz_r = where(((xi*slice_r) >= accum_yz_r),(xi*slice_r),accum_yz_r) + accum_yz_g = where(((xi*slice_g) >= accum_yz_g),(xi*slice_g),accum_yz_g) + accum_yz_b = where(((xi*slice_b) >= accum_yz_b),(xi*slice_b),accum_yz_b) + im.intensity_yz[:,layer] = (1 << 16)*accum_yz_b + (1 << 8)*accum_yz_g + (1 << 0)*accum_yz_r + im.yz = Image.fromarray(im.intensity_yz,mode="RGBX") + im.yz = im.yz.transpose(Image.FLIP_LEFT_RIGHT) + im.yz = im.yz.resize((cad.nzplot(),cad.nyplot())) + images.yz = ImageTk.PhotoImage(im.yz) + canvas_yz.create_image(cad.nplot/2,cad.nplot/2,image=images.yz) + # + # draw origin + # + z0 = cad.nplot/2. - cad.nzplot()*(0-(cad.zmax+cad.zmin)/2.)/(cad.zmax-cad.zmin) + y0 = cad.nplot/2. - cad.nyplot()*(0-(cad.ymax+cad.ymin)/2.)/(cad.ymax-cad.ymin) + canvas_yz.create_line([z0-dxy,y0,z0+dxy,y0],fill="green") + canvas_yz.create_line([z0,y0-dxy,z0,y0+dxy],fill="green") + # + # xz view + # + if (cad.views == 'xyzr'): + accum_xz_r = zeros(cad.nx,uint32) + accum_xz_g = zeros(cad.nx,uint32) + accum_xz_b = zeros(cad.nx,uint32) + for vertex in range(cad.ny): + yi = array([55.0+200.0*vertex/(cad.ny-1.0)],uint32) + slice_r = array_r[vertex,:] + slice_g = array_g[vertex,:] + slice_b = array_b[vertex,:] + accum_xz_r = where(((yi*slice_r) >= accum_xz_r),(yi*slice_r),accum_xz_r) + accum_xz_g = where(((yi*slice_g) >= accum_xz_g),(yi*slice_g),accum_xz_g) + accum_xz_b = where(((yi*slice_b) >= accum_xz_b),(yi*slice_b),accum_xz_b) + im.intensity_xz[(cad.nz-1-layer),:] = (1 << 16)*accum_xz_b + (1 << 8)*accum_xz_g + (1 << 0)*accum_xz_r + im.xz = Image.fromarray(im.intensity_xz,mode="RGBX") + im.xz = im.xz.resize((cad.nxplot(),cad.nzplot())) + images.xz = ImageTk.PhotoImage(im.xz) + canvas_xz.create_image(cad.nplot/2,cad.nplot/2,image=images.xz) + # + # draw origin + # + x0 = cad.nplot/2. + cad.nxplot()*(0-(cad.xmax+cad.xmin)/2.)/(cad.xmax-cad.xmin) + z0 = cad.nplot/2. - cad.nzplot()*(0-(cad.zmax+cad.zmin)/2.)/(cad.zmax-cad.zmin) + canvas_xz.create_line([x0-dxy,z0,x0+dxy,z0],fill="green") + canvas_xz.create_line([x0,z0-dxy,x0,z0+dxy],fill="green") + # + # draw it + # + root.update() + # + # rotated view + # + if ((cad.views == 'xyzr') & (cad.image_r.size == 1)): + accum = zeros((cad.ny,cad.nx),uint32) + for z in cad.zlist: + # + # check render stop button + # + if (cad.stop == 1): + break + string_msg.set("render z = %.3f"%z) + dY = cos(rx)*(Yarray-(cad.ymax+cad.ymin)/2.0) - sin(rx)*(z-(cad.zmax+cad.zmin)/2.0) + 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) + X = (cad.xmax+cad.xmin)/2.0 + cos(rz)*(Xarray-(cad.xmax+cad.xmin)/2.0) - sin(rz)*dY + Y = (cad.ymax+cad.ymin)/2.0 + sin(rz)*(Xarray-(cad.xmax+cad.xmin)/2.0) + cos(rz)*dY + arr = eval(cad.function) + if (cad.zmax == cad.zmin): + zi = array([255],uint32) + else: + zi = array([55.0 + 200.0*(z-cad.zmin)/(cad.zmax-cad.zmin)],uint32) + accum = where(((zi*arr) > accum),(zi*arr),accum) + im.intensity_xyz = ((1 << 16) + (1 << 8) + (1 << 0)) * accum + im.xyz = Image.fromarray(im.intensity_xyz,mode="RGBX") + im.xyz = im.xyz.resize((cad.nxplot(),cad.nyplot())) + images.xyz = ImageTk.PhotoImage(im.xyz) + canvas_xyz.create_image(cad.nplot/2,cad.nplot/2,image=images.xyz) + root.update() + # + # return + # + cad.zwrite = cad.zlist + cad.zlist = [] + widget_stop.pack_forget() + string_msg.set("done") + root.update() + return + +def draw_toolpath(): + im.xy = Image.new("RGBX",(cad.nxplot(),cad.nyplot()),'white') + im.xy_draw = ImageDraw.Draw(im.xy) + for layer in range(len(cad.toolpaths)): + for segment in range(len(cad.toolpaths[layer])): + x = cad.nxplot()*(cad.toolpaths[layer][segment][0].x+0.5)/float(cad.nx) + y = cad.nyplot()*(cad.toolpaths[layer][segment][0].y+0.5)/float(cad.ny) + for vertex in range(1,len(cad.toolpaths[layer][segment])): + xnew = cad.nxplot()*(cad.toolpaths[layer][segment][vertex].x+0.5)/float(cad.nx) + ynew = cad.nyplot()*(cad.toolpaths[layer][segment][vertex].y+0.5)/float(cad.ny) + im.xy_draw.line([x,y,xnew,ynew],fill="black") + x = xnew + y = ynew + images.xy = ImageTk.PhotoImage(im.xy) + canvas_xy.create_image(cad.nplot/2,cad.nplot/2,image=images.xy) + +def delete_windows(): + im.xy = Image.new("RGBX",(cad.nplot,cad.nplot),'black') + images.xy = ImageTk.PhotoImage(im.xy) + canvas_xy.create_image(cad.nplot/2,cad.nplot/2,image=images.xy) + im.yz = Image.new("RGBX",(cad.nplot,cad.nplot),'black') + images.yz = ImageTk.PhotoImage(im.yz) + canvas_yz.create_image(cad.nplot/2,cad.nplot/2,image=images.yz) + im.xz = Image.new("RGBX",(cad.nplot,cad.nplot),'black') + images.xz = ImageTk.PhotoImage(im.xz) + canvas_xz.create_image(cad.nplot/2,cad.nplot/2,image=images.xz) + im.xyz = Image.new("RGBX",(cad.nplot,cad.nplot),'black') + images.xyz = ImageTk.PhotoImage(im.xyz) + canvas_xyz.create_image(cad.nplot/2,cad.nplot/2,image=images.xyz) + root.update() + +def select_cad(): + image_x_frame.pack_forget() + image_y_frame.pack_forget() + image_z_frame.pack_forget() + image_intensity_frame.pack_forget() + image_units_frame.pack_forget() + image_invert_frame.pack_forget() + cad_input_frame.pack_forget() + widget_cad_text.delete("1.0",END) + widget_cad_text.insert("1.0",cad_template) + editor_frame.pack() + cad.image = array(0) + cad_input_frame.pack() + cad.toolpaths = [] + string_num_contours.set('0') + widget_cad_save.pack(side='left') + delete_windows() + +def select_image(): + editor_frame.pack_forget() + cad_input_frame.pack_forget() + image_x_frame.pack() + image_y_frame.pack() + image_z_frame.pack() + image_intensity_frame.pack() + image_units_frame.pack() + image_invert_frame.pack() + cad_input_frame.pack() + cad.toolpaths = [] + string_num_contours.set('0') + widget_cad_save.pack_forget() + delete_windows() + +def input_open(): + filename = askopenfilename() + string_input_file.set(filename) + if (find(filename,'.cad') != -1): + cad_load(0) + elif ((find(filename,'.jpg') != -1) | (find(filename,'.JPG') != -1) | + (find(filename,'.png') != -1) | (find(filename,'.PNG') != -1) | + (find(filename,'.gif') != -1) | (find(filename,'.GIF') != -1)): + widget_cad_text.delete("1.0",END) + image_load(0) + else: + string_msg.set("unsupported input file format") + root.update() + +def cad_load(event): + global cad + cad = cad_variables() + cam_pack_forget() + select_cad() + input_file_name = string_input_file.get() + input_file = open(input_file_name,'rb') + cad_text_string = input_file.read() + widget_cad_text.delete("1.0",END) + widget_cad_text.insert("1.0",cad_text_string) + input_file.close() + cad.toolpaths = [] + cad.image = array(0) + cad.nz = 1 + string_num_contours.set('0') + evaluate() + if (find(widget_cad_text.get("1.0",END),"render(") == -1): + render() + +def image_load(event): + global cad + cad = cad_variables() + cam_pack_forget() + select_image() + function_string_frame.pack_forget() + input_file_name = string_input_file.get() + input_file = open(input_file_name,'rb') + input_file.close() + cad.toolpaths = [] + string_num_contours.set('0') + image = Image.open(input_file_name) + num_layers = 1 + while 1: # check number of layers + try: + image.seek(image.tell()+1) + num_layers += 1 + except: + break + image = Image.open(input_file_name) + if image.mode != "RGBX": + image = image.convert("RGBX") + (cad.nx,cad.ny) = image.size + info = image.info + if ('dpi' in info): + (xdpi,ydpi) = info['dpi'] + else: + xdpi = cad.nx + ydpi = xdpi + string_image_nx.set(" nx = "+str(cad.nx)) + string_image_ny.set(" ny = "+str(cad.ny)) + cad.nz = 1 + string_image_nz.set(str(cad.nz)) + cad.xmin = 0 + string_image_xmin.set('0') + cad.xmax = cad.nx/float(xdpi) + string_image_xwidth.set(str(cad.xmax-cad.xmin)) + cad.ymin = 0 + string_image_ymin.set('0') + cad.ymax = cad.ny/float(ydpi) + string_image_yheight.set(str(cad.ymax-cad.ymin)) + cad.zmin = -.005 + string_image_zmin.set('-0.05') + cad.zmax = 0.05 + string_image_zmax.set('0.05') + cad.inches_per_unit = 1.0 + string_image_units.set('25.4') + data = zeros((num_layers,cad.nx*cad.ny,3),uint32) + data[0,] = array(image.convert("RGB").getdata(),uint32) + for layer in range(1,num_layers): + image.seek(image.tell()+1) + data[layer,] = array(image.convert("RGB").getdata(),uint32) + cad.image_r = array(data[:,:,0],uint32) + cad.image_r = cad.image_r.reshape((num_layers,cad.ny,cad.nx)) + cad.image_g = array(data[:,:,1],uint32) + cad.image_g = cad.image_g.reshape((num_layers,cad.ny,cad.nx)) + cad.image_b = array(data[:,:,2],uint32) + cad.image_b = cad.image_b.reshape((num_layers,cad.ny,cad.nx)) + cad.image_min = 1 + string_image_min.set(str(cad.image_min)) + cad.image_max = 255 + string_image_max.set(str(cad.image_max)) + evaluate() + render() + +def invert_image(event): + cad.image_r = 255 - cad.image_r + cad.image_g = 255 - cad.image_g + cad.image_b = 255 - cad.image_b + evaluate() + render() + +def cad_save(event): + input_file_name = string_input_file.get() + input_file = open(input_file_name,'wb') + cad_text_string = widget_cad_text.get("1.0",END) + input_file.write(cad_text_string) + input_file.close() + string_msg.set(input_file_name+" saved") + root.update() + +def render_button(event): + cam_pack_forget() + cad.cam = '' + if (cad.image_r.size == 1): + function_string_frame.pack() + cad.toolpaths = [] + string_num_contours.set('0') + evaluate() + if (find(widget_cad_text.get("1.0",END),"render(") == -1): + render() + +def render_stop(event): + cad.stop = 1 + widget_stop.pack_forget() + +def cam(event): + function_string_frame.pack_forget() + cam_file_frame.pack() + string_num_contours.set('1') + root.update() + +def contour(event): + evaluate() + if (find(widget_cad_text.get("1.0",END),"render(") == -1): + render() + +def triangulate(event): + # + # triangulate for STL + # + # evaluate .cad + # + evaluate() + # + # initialize variables + # + render_stop_flag = 0 + cad.stop = 0 + widget_stop.pack() + delete_windows() + cad.toolpaths = [] + cad.zwrite = [] + cad.x = zeros(0) + cad.y = zeros(0) + cad.z = zeros(0) + ixlr = array([]) + iylrs = array([]) + iylre = array([]) + izlr = array([]) + ixfbs = array([]) + ixfbe = array([]) + iyfb = array([]) + izfb = array([]) + ixtbs = array([]) + ixtbe = array([]) + iytb = array([]) + iztb = array([]) + # + # evaluate coordinate arrays + # + (IY,IX) = indices((cad.ny,cad.nx)) + IY = IY[::-1,:] + X = cad.xmin+(cad.xmax-cad.xmin)*IX/(cad.nx-1.0) + Y = cad.ymin+(cad.ymax-cad.ymin)*IY/(cad.ny-1.0) + cad.zwrite = cad.zmin + (cad.zmax-cad.zmin)*arange(cad.nz)/(cad.nz-1.0) + # + # set up drawing images + # + im.xy = Image.new("RGBX",(cad.nxplot(),cad.nyplot()),'white') + im.xy_draw = ImageDraw.Draw(im.xy) + im.xz = Image.new("RGBX",(cad.nxplot(),cad.nzplot()),'white') + im.xz_draw = ImageDraw.Draw(im.xz) + im.yz = Image.new("RGBX",(cad.nzplot(),cad.nyplot()),'white') + im.yz_draw = ImageDraw.Draw(im.yz) + # + # loop over layers + # + Z = cad.zwrite[0] + array0 = eval(cad.function) + Z = cad.zwrite[1] + array1 = eval(cad.function) + for layer in range(2,len(cad.zwrite)): + # + # check render stop button + # + if (cad.stop == 1): + break + # + # evaluate new layer + # + Z = cad.zwrite[layer] + string_msg.set("triangulate z = %.3f"%Z) + root.update() + array2 = eval(cad.function) + # + # find left faces and merge y + # + elements = hstack((reshape((array1[:,0] == True),(cad.ny,1)),((array1[:,1:] == True) & (array1[:,:-1] == False)))) + starts = vstack((((elements[:-1,:] == True) & (elements[1:,:] == False)),reshape((elements[-1,:] == True),(1,cad.nx)))) + ends = vstack((reshape((elements[0,:] == True),(1,cad.nx)),((elements[1:,:] == True) & (elements[:-1,:] == False)))) + IY_t = transpose(IY) # for starts and ends to be read in same row + IX_t = transpose(IX) + starts_t = transpose(starts) + ends_t = transpose(ends) + ixlr = append(ixlr,IX_t[starts_t]) + iylrs = append(iylrs,IY_t[starts_t]) + iylre = append(iylre,1+IY_t[ends_t]) + izlr = append(izlr,(layer-1)*ones(len(IX_t[starts_t]))) + # + # find right faces and merge y + # + elements = hstack((((array1[:,1:] == False) & (array1[:,:-1] == True)),reshape((array1[:,1] == True),(cad.ny,1)))) + starts = vstack((((elements[:-1,:] == True) & (elements[1:,:] == False)),reshape((elements[-1,:] == True),(1,cad.nx)))) + ends = vstack((reshape((elements[0,:] == True),(1,cad.nx)),((elements[1:,:] == True) & (elements[:-1,:] == False)))) + IY_t = transpose(IY) # for starts and ends to be read in same row + IX_t = transpose(IX) + starts_t = transpose(starts) + ends_t = transpose(ends) + ixlr = append(ixlr,1+IX_t[starts_t]) + iylre = append(iylre,IY_t[starts_t]) + iylrs = append(iylrs,1+IY_t[ends_t]) + izlr = append(izlr,(layer-1)*ones(len(IX_t[starts_t]))) + # + # find front faces and merge x + # + elements = vstack((((array1[:-1,:] == True) & (array1[1:,:] == False)),reshape((array1[0,:] == True),(1,cad.nx)))) + starts = hstack((reshape((elements[:,0] == True),(cad.ny,1)),((elements[:,1:] == True) & (elements[:,:-1] == False)))) + ends = hstack((((elements[:,:-1] == True) & (elements[:,1:] == False)),reshape((elements[:,-1] == True),(cad.ny,1)))) + ixfbs = append(ixfbs,IX[starts]) + ixfbe = append(ixfbe,1+IX[ends]) + iyfb = append(iyfb,IY[starts]) + izfb = append(izfb,(layer-1)*ones(len(IX[starts]))) + # + # find back faces and merge x + # + elements = vstack((reshape((array1[-1,:] == True),(1,cad.nx)),((array1[1:,:] == True) & (array1[:-1,:] == False)))) + starts = hstack((reshape((elements[:,0] == True),(cad.ny,1)),((elements[:,1:] == True) & (elements[:,:-1] == False)))) + ends = hstack((((elements[:,:-1] == True) & (elements[:,1:] == False)),reshape((elements[:,-1] == True),(cad.ny,1)))) + ixfbe = append(ixfbe,IX[starts]) + ixfbs = append(ixfbs,1+IX[ends]) + iyfb = append(iyfb,1+IY[starts]) + izfb = append(izfb,(layer-1)*ones(len(IX[starts]))) + # + # find top faces and merge x + # + elements = ((array2 == False) & (array1 == True)) + starts = hstack((reshape((elements[:,0] == True),(cad.ny,1)),((elements[:,1:] == True) & (elements[:,:-1] == False)))) + ends = hstack((((elements[:,:-1] == True) & (elements[:,1:] == False)),reshape((elements[:,-1] == True),(cad.ny,1)))) + ixtbs = append(ixtbs,IX[starts]) + ixtbe = append(ixtbe,1+IX[ends]) + iytb = append(iytb,IY[starts]) + iztb = append(iztb,layer*ones(len(IX[starts]))) + # + # find bottom faces and merge x + # + elements = ((array0 == False) & (array1 == True)) + starts = hstack((reshape((elements[:,0] == True),(cad.ny,1)),((elements[:,1:] == True) & (elements[:,:-1] == False)))) + ends = hstack((((elements[:,:-1] == True) & (elements[:,1:] == False)),reshape((elements[:,-1] == True),(cad.ny,1)))) + ixtbe = append(ixtbe,IX[starts]) + ixtbs = append(ixtbs,1+IX[ends]) + iytb = append(iytb,IY[starts]) + iztb = append(iztb,(layer-1)*ones(len(IX[starts]))) + # + # push array stack + # + array0 = array1 + array1 = array2 + # + # z merge front/back faces + # + index = lexsort(keys=(izfb,ixfbe,ixfbs,iyfb)) + merge = (iyfb[index[1:]] == iyfb[index[:-1]]) & \ + (ixfbe[index[1:]] == ixfbe[index[:-1]]) & \ + (ixfbs[index[1:]] == ixfbs[index[:-1]]) & \ + ((izfb[index[1:]] - izfb[index[:-1]]) == 1) + merge = append(False,merge).astype(bool_) + starts = ((merge[1:] == True) & (merge[:-1] == False)) + starts = append(starts,False).astype(bool_) + ends = ((merge[1:] == False) & (merge[:-1] == True)) + if (merge[-1] == True): + ends = append(ends,True) + else: + ends = append(ends,False) + ends = ends.astype(bool_) + xs = ixfbs[index][starts | ~merge] + xe = ixfbe[index][starts | ~merge] + y = iyfb[index][starts | ~merge] + zs = izfb[index][starts | ~merge] + ze = izfb[index][ends | ~(merge | starts)]+1 + cad.x = ravel(transpose(vstack((xs,xe,xs,xs,xe,xe)))) + cad.y = ravel(transpose(vstack((y,y,y,y,y,y)))) + cad.z = ravel(transpose(vstack((zs,ze,ze,zs,zs,ze)))) + # + # z merge left/right faces + # + index = lexsort(keys=(izlr,iylre,iylrs,ixlr)) + merge = (ixlr[index[1:]] == ixlr[index[:-1]]) & \ + (iylre[index[1:]] == iylre[index[:-1]]) & \ + (iylrs[index[1:]] == iylrs[index[:-1]]) & \ + ((izlr[index[1:]] - izlr[index[:-1]]) == 1) + merge = append(False,merge).astype(bool_) + starts = ((merge[1:] == True) & (merge[:-1] == False)) + starts = append(starts,False).astype(bool_) + ends = ((merge[1:] == False) & (merge[:-1] == True)) + if (merge[-1] == True): + ends = append(ends,True) + else: + ends = append(ends,False) + ends = ends.astype(bool_) + x = ixlr[index][starts | ~merge] + ys = iylrs[index][starts | ~merge] + ye = iylre[index][starts | ~merge] + zs = izlr[index][starts | ~merge] + ze = izlr[index][ends | ~(merge | starts)]+1 + cad.x = append(cad.x,ravel(transpose(vstack((x,x,x,x,x,x))))) + cad.y = append(cad.y,ravel(transpose(vstack((ys,ye,ys,ys,ye,ye))))) + cad.z = append(cad.z,ravel(transpose(vstack((zs,ze,ze,zs,zs,ze))))) + # + # y merge top/bottom faces + # + index = lexsort(keys=(iytb,ixtbe,ixtbs,iztb)) + merge = (iztb[index[1:]] == iztb[index[:-1]]) & \ + (ixtbe[index[1:]] == ixtbe[index[:-1]]) & \ + (ixtbs[index[1:]] == ixtbs[index[:-1]]) & \ + ((iytb[index[1:]] - iytb[index[:-1]]) == 1) + merge = append(False,merge).astype(bool_) + starts = ((merge[1:] == True) & (merge[:-1] == False)) + starts = append(starts,False).astype(bool_) + ends = ((merge[1:] == False) & (merge[:-1] == True)) + if (merge[-1] == True): + ends = append(ends,True) + else: + ends = append(ends,False) + ends = ends.astype(bool_) + xs = ixtbs[index][starts | ~merge] + xe = ixtbe[index][starts | ~merge] + ys = iytb[index][starts | ~merge] + ye = iytb[index][ends | ~(merge | starts)]+1 + z = iztb[index][starts | ~merge] + cad.x = append(cad.x,ravel(transpose(vstack((xs,xe,xs,xs,xe,xe))))) + cad.y = append(cad.y,ravel(transpose(vstack((ys,ye,ye,ys,ys,ye))))) + cad.z = append(cad.z,ravel(transpose(vstack((z,z,z,z,z,z))))) + # + # draw triangulation + # + widget_stop.pack_forget() + string_msg.set("draw ...") + root.update() + N = len(cad.x) + for i in range(0,N,3): + string_msg.set("draw triangle %d/%d"%(i/3,N/3)) + root.update() + x0 = cad.nxplot()*(cad.x[i]+0.5)/float(cad.nx) + y0 = cad.nyplot()*(cad.ny-cad.y[i]+0.5)/float(cad.ny) + z0 = cad.nzplot()*(cad.nz-cad.z[i]+0.5)/float(cad.nz) + x1 = cad.nxplot()*(cad.x[i+1]+0.5)/float(cad.nx) + y1 = cad.nyplot()*(cad.ny-cad.y[i+1]+0.5)/float(cad.ny) + z1 = cad.nzplot()*(cad.nz-cad.z[i+1]+0.5)/float(cad.nz) + x2 = cad.nxplot()*(cad.x[i+2]+0.5)/float(cad.nx) + y2 = cad.nyplot()*(cad.ny-cad.y[i+2]+0.5)/float(cad.ny) + z2 = cad.nzplot()*(cad.nz-cad.z[i+2]+0.5)/float(cad.nz) + im.xy_draw.line([x0,y0,x1,y1,x2,y2,x0,y0],fill="black") + im.xz_draw.line([x0,z0,x1,z1,x2,z2,x0,z0],fill="black") + im.yz_draw.line([z0,y0,z1,y1,z2,y2,z0,y0],fill="black") + images.xy = ImageTk.PhotoImage(im.xy) + images.xz = ImageTk.PhotoImage(im.xz) + images.yz = ImageTk.PhotoImage(im.yz) + canvas_xy.create_image(cad.nplot/2,cad.nplot/2,image=images.xy) + canvas_xz.create_image(cad.nplot/2,cad.nplot/2,image=images.xz) + canvas_yz.create_image(cad.nplot/2,cad.nplot/2,image=images.yz) + im.xyz = Image.new("RGBX",(cad.nplot,cad.nplot),'white') + images.xyz = ImageTk.PhotoImage(im.xyz) + canvas_xyz.create_image(cad.nplot/2,cad.nplot/2,image=images.xyz) + string_msg.set("done") + root.update() + +def flash(event): + # + # convert to Gerber flashes + # + # evaluate .cad + # + evaluate() + # + # initialize variables + # + render_stop_flag = 0 + cad.stop = 0 + widget_stop.pack() + delete_windows() + cad.toolpaths = [] + cad.zwrite = [] + cad.x = zeros(0) + cad.y = zeros(0) + cad.z = zeros(0) + ixs = array([]) + ixe = array([]) + iy = array([]) + iz = array([]) + # + # evaluate coordinate arrays + # + (IY,IX) = indices((cad.ny,cad.nx)) + IY = IY[::-1,:] + IZ = arange(cad.nz) + X = cad.xmin+(cad.xmax-cad.xmin)*IX/(cad.nx-1.0) + Y = cad.ymin+(cad.ymax-cad.ymin)*IY/(cad.ny-1.0) + if (cad.zwrite == []): + if (cad.nz > 1): + cad.zwrite = cad.zmin + (cad.zmax-cad.zmin)*arange(cad.nz)/(cad.nz-1.0) + else: + cad.zwrite = [cad.zmin] + # + # set up drawing image + # + im.xy = Image.new("RGBX",(cad.nxplot(),cad.nyplot()),'white') + im.xy_draw = ImageDraw.Draw(im.xy) + # + # loop over layers + # + for layer in range(len(cad.zwrite)): + # + # check render stop button + # + if (cad.stop == 1): + break + # + # evaluate layer + # + Z = cad.zwrite[layer] + string_msg.set("convert z = %.3f"%Z) + root.update() + elements = eval(cad.function) + # + # merge x + # + starts = hstack((reshape((elements[:,0] == TRUE),(cad.ny,1)),((elements[:,1:] == TRUE) & (elements[:,:-1] == FALSE)))) + ends = hstack((((elements[:,:-1] == TRUE) & (elements[:,1:] == FALSE)),reshape((elements[:,-1] == TRUE),(cad.ny,1)))) + ixs = append(ixs,IX[starts]) + ixe = append(ixe,1+IX[ends]) + iy = append(iy,IY[starts]) + iz = append(iz,IZ[layer-1]*ones(len(IX[starts]))) + # + # merge y + # + index = lexsort(keys=(iy,ixe,ixs,iz)) + merge = (iz[index[1:]] == iz[index[:-1]]) & \ + (ixe[index[1:]] == ixe[index[:-1]]) & \ + (ixs[index[1:]] == ixs[index[:-1]]) & \ + ((iy[index[1:]] - iy[index[:-1]]) == 1) + merge = append(FALSE,merge).astype(bool_) + starts = ((merge[1:] == TRUE) & (merge[:-1] == FALSE)) + starts = append(starts,FALSE).astype(bool_) + ends = ((merge[1:] == FALSE) & (merge[:-1] == TRUE)) + if (merge[-1] == TRUE): + ends = append(ends,TRUE) + else: + ends = append(ends,FALSE) + ends = ends.astype(bool_) + xs = ixs[index][starts | ~merge] + xe = ixe[index][starts | ~merge] + ys = iy[index][starts | ~merge] + ye = iy[index][ends | ~(merge | starts)]+1 + cad.x = ravel(transpose(vstack((xs,xe)))) + cad.y = ravel(transpose(vstack((ys,ye)))) + # + # draw flashes + # + widget_stop.pack_forget() + cad.view('xy') + string_msg.set("draw ...") + root.update() + N = len(cad.x) + for i in range(0,N,2): + string_msg.set("draw flash %d/%d"%(i/4,N/4)) + root.update() + x0 = cad.nxplot()*(cad.x[i]+0.5)/float(cad.nx) + y0 = cad.nyplot()*(cad.ny-cad.y[i]+0.5)/float(cad.ny) + x1 = cad.nxplot()*(cad.x[i]+0.5)/float(cad.nx) + y1 = cad.nyplot()*(cad.ny-cad.y[i+1]+0.5)/float(cad.ny) + x2 = cad.nxplot()*(cad.x[i+1]+0.5)/float(cad.nx) + y2 = cad.nyplot()*(cad.ny-cad.y[i+1]+0.5)/float(cad.ny) + x3 = cad.nxplot()*(cad.x[i+1]+0.5)/float(cad.nx) + y3 = cad.nyplot()*(cad.ny-cad.y[i]+0.5)/float(cad.ny) + im.xy_draw.line([x0,y0,x1,y1,x2,y2,x3,y3,x0,y0],fill="black") + images.xy = ImageTk.PhotoImage(im.xy) + canvas_xy.create_image(cad.nplot/2,cad.nplot/2,image=images.xy) + string_msg.set("done") + root.update() + +def select_epi(): + input_file_name = string_input_file.get() + string_cam_file.set(input_file_name[0:-4]+'.epi') + cad.cam = 'epi' + cam_pack_forget() + cam_file_frame.pack() + cam_vector_frame.pack() + cam_dia_frame.pack() + cam_contour_frame.pack() + laser_frame1.pack() + if ((cad.nz > 1) | (cad.image_r.size > 1)): + laser_frame2.pack() + laser_frame3.pack() + string_laser_rate.set("2500") + string_laser_power.set("90") + string_laser_speed.set("50") + string_laser_min_power.set("10") + string_laser_max_power.set("100") + string_tool_dia.set("0.01") + root.update() + +def select_camm(): + input_file_name = string_input_file.get() + string_cam_file.set(input_file_name[0:-4]+'.camm') + cad.cam = 'camm' + cam_pack_forget() + cam_file_frame.pack() + cam_vector_frame.pack() + cam_dia_frame.pack() + cam_contour_frame.pack() + cut_frame.pack() + string_cut_force.set("45") + string_cut_velocity.set("2") + string_tool_dia.set("0.01") + root.update() + +def select_ps(): + input_file_name = string_input_file.get() + string_cam_file.set(input_file_name[0:-4]+'.ps') + cad.cam = 'ps' + cam_pack_forget() + cam_file_frame.pack() + cam_vector_frame.pack() + cam_dia_frame.pack() + cam_contour_frame.pack() + fill_frame.pack() + string_tool_dia.set("0.0") + root.update() + +def select_ord(): + input_file_name = string_input_file.get() + string_cam_file.set(input_file_name[0:-4]+'.ord') + cad.cam = 'ord' + cam_pack_forget() + cam_file_frame.pack() + cam_vector_frame.pack() + cam_dia_frame.pack() + cam_contour_frame.pack() + string_tool_dia.set("0.01") + waterjet_frame.pack() + string_lead_in.set("0.05") + string_quality.set("-3") + root.update() + +def select_g(): + input_file_name = string_input_file.get() + string_cam_file.set(input_file_name[0:-4]+'.gcode') + cad.cam = 'g' + cam_pack_forget() + cam_file_frame.pack() + cam_vector_frame.pack() + string_tool_dia.set("0.03") + cam_dia_frame.pack() + cam_contour_frame.pack() + string_g_feed_rate.set("20") + string_g_spindle_speed.set("5000") + string_g_tool.set("1") + integer_g_cool.set("0") + g_frame.pack() + root.update() + +def select_rml(): + input_file_name = string_input_file.get() + string_cam_file.set(input_file_name[0:-4]+'.rml') + cad.cam = 'rml' + cam_pack_forget() + cam_file_frame.pack() + cam_vector_frame.pack() + cam_dia_frame.pack() + cam_contour_frame.pack() + speed_frame.pack() + rml_move_frame.pack() + string_tool_dia.set("0.0156") + string_xy_speed.set("4") + string_z_speed.set("4") + string_rml_x_move.set("1") + string_rml_y_move.set("1") + root.update() + +def select_sbp(): + input_file_name = string_input_file.get() + string_cam_file.set(input_file_name[0:-4]+'.sbp') + cad.cam = 'sbp' + cam_pack_forget() + cam_file_frame.pack() + cam_vector_frame.pack() + cam_dia_frame.pack() + cam_contour_frame.pack() + jog_frame.pack() + speed_frame.pack() + string_tool_dia.set("0.125") + string_xy_speed.set("1.1") + string_z_speed.set("1.1") + string_jog_xy_speed.set("7") + string_jog_z_speed.set("7") + string_jog_z.set(".25") + root.update() + +def select_oms(): + input_file_name = string_input_file.get() + string_cam_file.set(input_file_name[0:-4]+'.oms') + cad.cam = 'oms' + cam_pack_forget() + cam_file_frame.pack() + cam_vector_frame.pack() + cam_dia_frame.pack() + cam_contour_frame.pack() + excimer_frame.pack() + string_pulse_period.set("10000") + string_tool_dia.set("0.001") + string_cut_vel.set("0.1") + string_cut_accel.set("5.0") + root.update() + +def select_dxf(): + input_file_name = string_input_file.get() + string_cam_file.set(input_file_name[0:-4]+'.dxf') + cad.cam = 'dxf' + cam_pack_forget() + cam_file_frame.pack() + cam_vector_frame.pack() + cam_dia_frame.pack() + cam_contour_frame.pack() + string_tool_dia.set("0.0") + root.update() + +def select_uni(): + input_file_name = string_input_file.get() + string_cam_file.set(input_file_name[0:-4]+'.uni') + cad.cam = 'uni' + cam_pack_forget() + cam_file_frame.pack() + cam_vector_frame.pack() + cam_dia_frame.pack() + cam_contour_frame.pack() + laser_frame1.pack() + if ((cad.nz > 1) | (cad.image_r.size > 1)): + laser_frame2.pack() + string_laser_rate.set("500") + string_laser_power.set("60") + string_laser_speed.set("15") + string_tool_dia.set("0.01") + string_laser_min_power.set("10") + string_laser_max_power.set("100") + string_vector_error.set('1.1') + root.update() + +def select_jpg(): + input_file_name = string_input_file.get() + string_cam_file.set(input_file_name[0:-4]+'.jpg') + cad.cam = 'jpg' + cam_pack_forget() + cam_file_frame.pack() + root.update() + +def select_png(): + input_file_name = string_input_file.get() + string_cam_file.set(input_file_name[0:-4]+'.png') + cad.cam = 'png' + cam_pack_forget() + cam_file_frame.pack() + root.update() + +def select_stl(): + input_file_name = string_input_file.get() + string_cam_file.set(input_file_name[0:-4]+'.stl') + cad.cam = 'stl' + cam_pack_forget() + cam_file_frame.pack() + STL_frame.pack() + root.update() + +def select_gerber(): + input_file_name = string_input_file.get() + string_cam_file.set(input_file_name[0:-4]+'.grb') + cad.cam = 'grb' + cam_pack_forget() + cam_file_frame.pack() + Gerber_frame.pack() + root.update() + +def select_excellon(): + input_file_name = string_input_file.get() + string_cam_file.set(input_file_name[0:-4]+'.drl') + cad.cam = 'drl' + cam_pack_forget() + cam_file_frame.pack() + Excellon_frame.pack() + root.update() + +def select_ca(): + input_file_name = string_input_file.get() + string_cam_file.set(input_file_name[0:-4]+'.ca') + cad.cam = 'ca' + cam_pack_forget() + cam_file_frame.pack() + root.update() + +def cam_pack_forget(): + cam_file_frame.pack_forget() + cam_vector_frame.pack_forget() + cam_dia_frame.pack_forget() + cam_contour_frame.pack_forget() + laser_frame1.pack_forget() + laser_frame2.pack_forget() + laser_frame3.pack_forget() + cut_frame.pack_forget() + speed_frame.pack_forget() + jog_frame.pack_forget() + rml_move_frame.pack_forget() + waterjet_frame.pack_forget() + excimer_frame.pack_forget() + STL_frame.pack_forget() + Gerber_frame.pack_forget() + Excellon_frame.pack_forget() + fill_frame.pack_forget() + g_frame.pack_forget() + send_to_frame.pack_forget() + +def save_cam(event): + # + # write toolpath + # + if (cad.cam == "epi"): + write_epi() + elif (cad.cam == "camm"): + write_camm() + elif (cad.cam == "ps"): + write_ps() + elif (cad.cam == "ord"): + write_ord() + elif (cad.cam == "g"): + write_G() + elif (cad.cam == "rml"): + write_rml() + elif (cad.cam == "sbp"): + write_sbp() + elif (cad.cam == "oms"): + write_oms() + elif (cad.cam == "dxf"): + write_dxf() + elif (cad.cam == "uni"): + write_uni() + elif (cad.cam == "jpg"): + write_jpg() + elif (cad.cam == "png"): + write_png() + elif (cad.cam == "stl"): + write_stl() + elif (cad.cam == "grb"): + write_gerber() + elif (cad.cam == "drl"): + write_excellon() + elif (cad.cam == "ca"): + write_ca() + else: + string_msg.set("unsupported output file format") + root.update() + +def write_epi(): + # + # Epilog lasercutter output + # todo: try 1200 DPI + # + units = 600*cad.inches_per_unit + filename = string_cam_file.get() + file = open(filename, 'wb') + if (integer_laser_autofocus.get() == 0): + # + # init with autofocus off + # + 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()+";") + else: + # + # init with autofocus on + # + 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()+";") + power = float(string_laser_power.get()) + min_power = float(string_laser_min_power.get()) + max_power = float(string_laser_max_power.get()) + for layer in range(len(cad.toolpaths)): + if ((len(cad.zwrite) > 1) & (len(cad.toolpaths[layer]) > 0)): + fraction = (cad.zwrite[layer]-cad.zwrite[0])/(cad.zwrite[-1]-cad.zwrite[0]) + layer_power = min_power + fraction*(max_power-min_power) + file.write("YP%f;"%layer_power) + for segment in range(len(cad.toolpaths[layer])): + x = int(units*(cad.xmin + (cad.xmax-cad.xmin)*(cad.toolpaths[layer][segment][0].x+0.5)/float(cad.nx))) + y = int(units*(-cad.ymin - ((cad.ymax-cad.ymin)*((cad.ny-cad.toolpaths[layer][segment][0].y)+0.5)/float(cad.ny)))) + file.write("PU"+str(x)+","+str(y)+";") + for vertex in range(1,len(cad.toolpaths[layer][segment])): + x = int(units*(cad.xmin + (cad.xmax-cad.xmin)*(cad.toolpaths[layer][segment][vertex].x+0.5)/float(cad.nx))) + y = int(units*(-cad.ymin - ((cad.ymax-cad.ymin)*((cad.ny-cad.toolpaths[layer][segment][vertex].y)+0.5)/float(cad.ny)))) + file.write("PD"+str(x)+","+str(y)+";") + file.write("%0B%1BPUE%-12345X@PJL EOJ \r\n") + file.close() + draw_toolpath() + string_msg.set("wrote %s"%filename) + root.update() + +def write_camm(): + filename = string_cam_file.get() + file = open(filename, 'wb') + units = 1016*cad.inches_per_unit + file.write("PA;PA;!ST1;!FS"+string_cut_force.get()+";VS"+string_cut_velocity.get()+";") + for layer in range(len(cad.toolpaths)): + for segment in range(len(cad.toolpaths[layer])): + x = int(units*(cad.xmin + (cad.xmax-cad.xmin)*(cad.toolpaths[layer][segment][0].x+0.5)/float(cad.nx))) + y = int(units*(cad.ymin + (cad.ymax-cad.ymin)*((cad.ny-cad.toolpaths[layer][segment][0].y)+0.5)/float(cad.ny))) + file.write("PU"+str(x)+","+str(y)+";") + for vertex in range(1,len(cad.toolpaths[layer][segment])): + x = int(units*(cad.xmin + (cad.xmax-cad.xmin)*(cad.toolpaths[layer][segment][vertex].x+0.5)/float(cad.nx))) + y = int(units*(cad.ymin + (cad.ymax-cad.ymin)*((cad.ny-cad.toolpaths[layer][segment][vertex].y)+0.5)/float(cad.ny))) + file.write("PD"+str(x)+","+str(y)+";") + file.write("PU0,0;") + file.close() + draw_toolpath() + string_msg.set("wrote %s"%filename) + root.update() + +def write_ps(): + # + # Postscript output + # + units = cad.inches_per_unit + filename = string_cam_file.get() + file = open(filename, 'wb') + file.write("%! cad.py output\n") + file.write("%%%%BoundingBox: 0 0 %.3f %.3f\n"% + (72.0*(cad.xmax-cad.xmin),72.0*(cad.ymax-cad.ymin))) + file.write("/m {moveto} def\n") + file.write("/l {lineto} def\n") + file.write("72 72 scale\n") + file.write(".005 setlinewidth\n") + file.write("%f %f translate\n"%(0.5,0.5)) + for layer in range(len(cad.toolpaths)): + for segment in range(len(cad.toolpaths[layer])): + x = units*(cad.xmin + (cad.xmax-cad.xmin)*(cad.toolpaths[layer][segment][0].x+0.5)/float(cad.nx)) + y = units*(cad.ymin + (cad.ymax-cad.ymin)*((cad.ny-cad.toolpaths[layer][segment][0].y)+0.5)/float(cad.ny)) + file.write("%f %f m\n"%(x,y)) + for vertex in range(1,len(cad.toolpaths[layer][segment])): + x = units*(cad.xmin + (cad.xmax-cad.xmin)*(cad.toolpaths[layer][segment][vertex].x+0.5)/float(cad.nx)) + y = units*(cad.ymin + (cad.ymax-cad.ymin)*((cad.ny-cad.toolpaths[layer][segment][vertex].y)+0.5)/float(cad.ny)) + file.write("%f %f l\n"%(x,y)) + if (integer_fill.get() == 0): + file.write("stroke\n") + else: + file.write("fill\n") + file.write("showpage\n") + file.close() + draw_toolpath() + string_msg.set("wrote %s"%filename) + root.update() + +def write_ord(): + # + # OMAX waterjet output + # + units = cad.inches_per_unit + lead_in = float(string_lead_in.get()) + quality = int(string_quality.get()) + filename = string_cam_file.get() + file = open(filename, 'wb') + xlead = [] + ylead = [] + for layer in range(len(cad.toolpaths)): + for segment in range(len(cad.toolpaths[layer])): + # + # calculate and write lead-in + # + x0 = units*(cad.xmin + (cad.xmax-cad.xmin)*(cad.toolpaths[layer][segment][0].x+0.5)/float(cad.nx)) + y0 = units*(cad.ymin + (cad.ymax-cad.ymin)*((cad.ny-cad.toolpaths[layer][segment][0].y)+0.5)/float(cad.ny)) + x1 = units*(cad.xmin + (cad.xmax-cad.xmin)*(cad.toolpaths[layer][segment][1].x+0.5)/float(cad.nx)) + y1 = units*(cad.ymin + (cad.ymax-cad.ymin)*((cad.ny-cad.toolpaths[layer][segment][1].y)+0.5)/float(cad.ny)) + dx = x1 - x0 + dy = y1 - y0 + norm_x = -dy + norm_y = dx + norm = sqrt(norm_x**2 + norm_y**2) + norm_x = norm_x/norm + norm_y = norm_y/norm + xlead.append(x0 + norm_x*lead_in) + ylead.append(y0 + norm_y*lead_in) + file.write("%f, %f, 0, %d\n"%(xlead[segment],ylead[segment],quality)) + # + # loop over segment + # + for vertex in range(len(cad.toolpaths[layer][segment])): + x = units*(cad.xmin + (cad.xmax-cad.xmin)*(cad.toolpaths[layer][segment][vertex].x+0.5)/float(cad.nx)) + y = units*(cad.ymin + (cad.ymax-cad.ymin)*((cad.ny-cad.toolpaths[layer][segment][vertex].y)+0.5)/float(cad.ny)) + file.write("%f, %f, 0, %d\n"%(x,y,quality)) + # + # write lead-out + # + file.write("%f, %f, 0, 0\n"%(x0,y0)) + file.write("%f, %f, 0, 0\n"%(xlead[segment],ylead[segment])) + file.close() + # + # draw toolpath with lead-in/out + # + im.xy = Image.new("RGBX",(cad.nxplot(),cad.nyplot()),'white') + im.xy_draw = ImageDraw.Draw(im.xy) + for layer in range(len(cad.toolpaths)): + for segment in range(len(cad.toolpaths[layer])): + x = cad.nxplot()*(cad.toolpaths[layer][segment][0].x+0.5)/float(cad.nx) + y = cad.nyplot()*(cad.toolpaths[layer][segment][0].y+0.5)/float(cad.ny) + xl = cad.nxplot()*(xlead[segment]-cad.xmin)/(cad.xmax-cad.xmin) + yl = cad.nyplot()-cad.nyplot()*(ylead[segment]-cad.ymin)/(cad.ymax-cad.ymin) + im.xy_draw.line([xl,yl,x,y],fill="black") + for vertex in range(1,len(cad.toolpaths[layer][segment])): + xnew = cad.nxplot()*(cad.toolpaths[layer][segment][vertex].x+0.5)/float(cad.nx) + ynew = cad.nyplot()*(cad.toolpaths[layer][segment][vertex].y+0.5)/float(cad.ny) + im.xy_draw.line([x,y,xnew,ynew],fill="black") + x = xnew + y = ynew + images.xy = ImageTk.PhotoImage(im.xy) + canvas_xy.create_image(cad.nplot/2,cad.nplot/2,image=images.xy) + string_msg.set("wrote %s"%filename) + root.update() + +def distance(x1, y1, x2, y2): + return sqrt((x1-x2)**2+(y1-y2)**2) + +def write_G(): + # + # G code output + # + units = cad.inches_per_unit + zup = units*cad.zmax + feed_rate = float(string_g_feed_rate.get()) + spindle_speed = float(string_g_spindle_speed.get()) + coolant = integer_g_cool.get() + tool = int(string_g_tool.get()) + if (cad.nz == 1): + cad.zwrite = [cad.zmin] + filename = string_cam_file.get() + file = open(filename, 'wb') + file.write("""(---------------------------------------------------------------) +(---------------------------------------------------------------) +(Start of sheet header) +G21 (metric) +G92 X0 Y0 Z0 (zero all axes) +(End of sheet header)\n""") + dxy = 0 + dz = 0 + xold = 0 + yold = 0 + for layer in range(len(cad.zwrite)-1,-1,-1): + zdown = units*cad.zwrite[layer] + # + # follow toolpaths CCW, for CW tool motion + # + unsorted_segments = cad.toolpaths[layer] + sorted_segments = [] + if len(unsorted_segments) > 0: + sorted_segments.append(unsorted_segments.pop(0)) #starts with the first path in the list + else: + print "empty path --- strange" + + while len(unsorted_segments) > 0: + #find closest start to the the last sorted segment start + min_dist = 99999 + min_dist_index = None + for i in range(len(unsorted_segments)): + dist = distance(sorted_segments[-1][0].x, sorted_segments[-1][0].y, + unsorted_segments[i][0].x, unsorted_segments[i][0].y) + if dist < min_dist: + min_dist = dist + min_dist_index = i + + #print "min_dist: %d index: %d" % (min_dist, min_dist_index) + sorted_segments.append(unsorted_segments.pop(min_dist_index)) + + for segment in range(len(sorted_segments)): + + x = units*(cad.xmin + (cad.xmax-cad.xmin)*(sorted_segments[segment][0].x+0.5)/float(cad.nx)) + y = units*(cad.ymin + (cad.ymax-cad.ymin)*((cad.ny-sorted_segments[segment][0].y)+0.5)/float(cad.ny)) + file.write("M106 S255 (Pen Up)\n") + file.write("G4 P120\n") + file.write("G1 X%0.4f "%x+"Y%0.4f "%y+" F2000.00\n") # rapid motion + file.write("M107 (Pen Down)\n") # linear motion + file.write("G4 P120\n") + dxy += sqrt((xold-x)**2+(yold-y)**2) + xold = x + yold = y + dz += zup-zdown + for vertex in range(1,len(sorted_segments[segment])): + x = units*(cad.xmin + (cad.xmax-cad.xmin)*(sorted_segments[segment][vertex].x+0.5)/float(cad.nx)) + y = units*(cad.ymin + (cad.ymax-cad.ymin)*((cad.ny-sorted_segments[segment][vertex].y)+0.5)/float(cad.ny)) + file.write("G1 X%0.4f "%x+"Y%0.4f"%y+" F2000.00\n") + dxy += sqrt((xold-x)**2+(yold-y)**2) + xold = x + yold = y + file.write("""(Start of sheet footer.) +M106 (Pen Up) +G4 P120 (wait 120ms) +G0 X0 Y0 Z15 F3500.00 (go to position for retrieving platform -- increase Z to Z25 or similar if you have trouble avoiding tool) +G4 P300 (wait 300ms) +G0 Z0 F3500.00 (return to start position of current sheet) + +G4 P300 (wait 300ms) +M18 (disengage drives) +(End of sheet footer) + +M01 (Printing on the next sheet?) +(yes, if dropping the default .1 mm to next sheet; no, if you will print again on same sheet) +G0 Z-0.10 F3500.00 (drop 0.1mm to next sheet) +M107 (Pen Down so as not to overheat solenoid) + +(Paste in further sheets below) +(---------------------------------------------------------------) +(---------------------------------------------------------------) +""") + file.close() + print "Path length: %f" % dxy + time = (dxy/feed_rate + dz/feed_rate) + string_send_to_time.set(" estimated time: %.1f minutes"%time) + draw_toolpath() + string_msg.set("wrote %s"%filename) + root.update() + +def write_rml(): + # + # Roland Modela output + # + units = 1016*cad.inches_per_unit # 40/mm + filename = string_cam_file.get() + file = open(filename, 'wb') + file.write("PA;PA;VS"+string_xy_speed.get()+";!VZ"+string_z_speed.get()+";!MC1;") + zup = cad.zmax + izup = int(units*zup) + if (cad.nz == 1): + cad.zwrite = [cad.zmin] + xy_speed = float(string_xy_speed.get()) # mm/s + z_speed = float(string_z_speed.get()) # mm/s + dxy = 0 + dz = 0 + xold = 0 + yold = 0 + for layer in range(len(cad.zwrite)-1,-1,-1): + zdown = cad.zwrite[layer] + izdown = int(units*zdown) + file.write("!PZ"+str(izdown)+","+str(izup)+";") + # + # follow toolpaths CCW, for CW tool motion + # + for segment in range(len(cad.toolpaths[layer])): + x = int(units*(cad.xmin + (cad.xmax-cad.xmin)*(cad.toolpaths[layer][segment][0].x+0.5)/float(cad.nx))) + y = int(units*(cad.ymin + (cad.ymax-cad.ymin)*((cad.ny-cad.toolpaths[layer][segment][0].y)+0.5)/float(cad.ny))) + file.write("PU"+str(x)+","+str(y)+";") + dxy += sqrt((xold-x)**2+(yold-y)**2) + xold = x + yold = y + dz += izup-izdown + for vertex in range(1,len(cad.toolpaths[layer][segment])): + x = int(units*(cad.xmin + (cad.xmax-cad.xmin)*(cad.toolpaths[layer][segment][vertex].x+0.5)/float(cad.nx))) + y = int(units*(cad.ymin + (cad.ymax-cad.ymin)*((cad.ny-cad.toolpaths[layer][segment][vertex].y)+0.5)/float(cad.ny))) + file.write("PD"+str(x)+","+str(y)+";") + dxy += sqrt((xold-x)**2+(yold-y)**2) + xold = x + yold = y + file.write("PU"+str(x)+","+str(y)+";!MC0;") + # + # file padding hack for end-of-file buffering problems + # + for i in range(1000): + file.write("!MC0;") + file.close() + time = ((dxy/40.0)/xy_speed + (dz/40.0)/z_speed)/60.0 + string_send_to_time.set(" estimated time: %.1f minutes"%time) + draw_toolpath() + string_msg.set("wrote %s"%filename) + root.update() + +def rml_move(event): + # + # move Roland Modela + # + units = 1016*cad.inches_per_unit # 40/mm + x = float(string_rml_x_move.get()) + y = float(string_rml_y_move.get()) + ix = int(units*x) + iy = int(units*y) + filename = "move.rml" + file = open(filename, 'wb') + file.write("PA;PA;!PZ0,400;VS10;!VZ10;!MC0;PU%d,%d;!MC0;"%(ix,iy)) + file.close() + send_to_file("move.rml") + os.remove("move.rml") + +def write_sbp(): + # + # ShopBot output + # + units = cad.inches_per_unit + filename = string_cam_file.get() + file = open(filename, 'wb') + file.write("SA\r\n") # set to absolute distances + file.write("SO,1,1\r\n") # set output number 1 to on + file.write("pause 2\r\n") # let spindle come up to speed + xy_speed = units*float(string_xy_speed.get()) + z_speed = units*float(string_z_speed.get()) + file.write("MS %f,%f\r\n"%(xy_speed,z_speed)) # set xy,z speed + jog_xy_speed = units*float(string_jog_xy_speed.get()) + jog_z_speed = units*float(string_jog_z_speed.get()) + file.write("JS %f,%f\r\n"%(jog_xy_speed,jog_z_speed)) # set jog xy,z speed + zup = units*float(string_jog_z.get()) + dxy = 0 + dz = 0 + xold = 0 + yold = 0 + for layer in range(len(cad.zwrite)-1,-1,-1): + zdown = cad.zwrite[layer] + # + # follow toolpaths CCW, for CW tool motion + # + for segment in range(len(cad.toolpaths[layer])): + x = units*(cad.xmin + (cad.xmax-cad.xmin)*(cad.toolpaths[layer][segment][0].x+0.5)/float(cad.nx)) + y = units*(cad.ymin + (cad.ymax-cad.ymin)*((cad.ny-cad.toolpaths[layer][segment][0].y)+0.5)/float(cad.ny)) + file.write("JZ %f\r\n"%zup) + file.write("J2 %f,%f\r\n"%(x,y)) + file.write("MZ %f\r\n"%zdown) + dxy += sqrt((xold-x)**2+(yold-y)**2) + xold = x + yold = y + dz += zup-zdown + for vertex in range(1,len(cad.toolpaths[layer][segment])): + x = units*(cad.xmin + (cad.xmax-cad.xmin)*(cad.toolpaths[layer][segment][vertex].x+0.5)/float(cad.nx)) + y = units*(cad.ymin + (cad.ymax-cad.ymin)*((cad.ny-cad.toolpaths[layer][segment][vertex].y)+0.5)/float(cad.ny)) + file.write("M2 %f,%f\r\n"%(x,y)) + dxy += sqrt((xold-x)**2+(yold-y)**2) + xold = x + yold = y + file.write("JZ %f\r\n"%zup) + file.close() + time = (dxy/xy_speed + dz/z_speed)/60.0 + string_send_to_time.set(" estimated time: %.1f minutes"%time) + draw_toolpath() + string_msg.set("wrote %s"%filename) + root.update() + +def write_oms(): + # + # Resonetics excimer micromachining center output + # + units = 25.4*cad.inches_per_unit + pulseperiod = float(string_pulse_period.get()) + cutvel = float(string_cut_vel.get()) + cutaccel = float(string_cut_accel.get()) + slewvel = 1 + slewaccel = 5 + settle = 100 + filename = string_cam_file.get() + file = open(filename, 'wb') + file.write("AA LP0,0,0,0,0\n") # set origin + file.write("PP%d\n"%pulseperiod) # set pulse period + for layer in range(len(cad.toolpaths)): + for segment in range(len(cad.toolpaths[layer])): + x = units*(cad.xmin + (cad.xmax-cad.xmin)*(cad.toolpaths[layer][segment][0].x+0.5)/float(cad.nx)) + y = units*(cad.ymin + (cad.ymax-cad.ymin)*((cad.ny-cad.toolpaths[layer][segment][0].y)+0.5)/float(cad.ny)) + file.write("VL%.1f,%.1f\n"%(slewvel,slewvel)) + file.write("AC%.1f,%.1f\n"%(slewaccel,slewaccel)) + file.write("MA%f,%f\n"%(x,y)) + file.write("VL%.1f,%.1f\n"%(cutvel,cutvel)) + file.write("AC%.1f,%.1f\n"%(cutaccel,cutaccel)) + file.write("WT%d\n"%settle) # wait to settle + for vertex in range(1,len(cad.toolpaths[layer][segment])): + x = units*(cad.xmin + (cad.xmax-cad.xmin)*(cad.toolpaths[layer][segment][vertex].x+0.5)/float(cad.nx)) + y = units*(cad.ymin + (cad.ymax-cad.ymin)*((cad.ny-cad.toolpaths[layer][segment][vertex].y)+0.5)/float(cad.ny)) + file.write("CutAbs %f,%f\n"%(x,y)) + file.write("END\n") + file.close() + draw_toolpath() + string_msg.set("wrote %s"%filename) + root.update() + +def write_dxf(): + # + # DXF output + # + units = cad.inches_per_unit + filename = string_cam_file.get() + file = open(filename, 'wb') + file.write("999\nDXF written by cad.py\n") + file.write("0\nSECTION\n") + file.write("2\nHEADER\n") + file.write("9\n$EXTMIN\n") + file.write("10\n%f\n"%cad.xmin) + file.write("20\n%f\n"%cad.ymin) + file.write("9\n$EXTMAX\n") + file.write("10\n%f\n"%cad.xmax) + file.write("20\n%f\n"%cad.ymax) + file.write("0\nENDSEC\n") + file.write("0\nSECTION\n") + file.write("2\nTABLES\n") + file.write("0\nTABLE\n") + file.write("2\nLTYPE\n70\n1\n") + file.write("0\nLTYPE\n") + file.write("2\nCONTINUOUS\n") + file.write("70\n64\n3\n") + file.write("Solid line\n") + file.write("72\n65\n73\n0\n40\n0.000000\n") + file.write("0\nENDTAB\n") + file.write("0\nTABLE\n2\nLAYER\n70\n1\n") + file.write("0\nLAYER\n2\ndefault\n70\n64\n62\n7\n6\n") + file.write("CONTINUOUS\n0\nENDTAB\n") + file.write("0\nENDSEC\n") + file.write("0\nSECTION\n") + file.write("2\nBLOCKS\n") + file.write("0\nENDSEC\n") + file.write("0\nSECTION\n") + file.write("2\nENTITIES\n") + for layer in range(len(cad.toolpaths)): + for segment in range(len(cad.toolpaths[layer])): + for vertex in range(1,len(cad.toolpaths[layer][segment])): + x0 = units*(cad.xmin + (cad.xmax-cad.xmin)*(cad.toolpaths[layer][segment][vertex-1].x+0.5)/float(cad.nx)) + y0 = units*(cad.ymin + (cad.ymax-cad.ymin)*((cad.ny-cad.toolpaths[layer][segment][vertex-1].y)+0.5)/float(cad.ny)) + x1 = units*(cad.xmin + (cad.xmax-cad.xmin)*(cad.toolpaths[layer][segment][vertex].x+0.5)/float(cad.nx)) + y1 = units*(cad.ymin + (cad.ymax-cad.ymin)*((cad.ny-cad.toolpaths[layer][segment][vertex].y)+0.5)/float(cad.ny)) + file.write("0\nLINE\n") + file.write("10\n%f\n"%x0) + file.write("20\n%f\n"%y0) + file.write("11\n%f\n"%x1) + file.write("21\n%f\n"%y1) + file.write("0\nENDSEC\n") + file.write("0\nEOF\n") + file.close() + draw_toolpath() + string_msg.set("wrote %s"%filename) + root.update() + +def write_uni(): + # + # Universal lasercutter output + # + units = 1000*cad.inches_per_unit + filename = string_cam_file.get() + file = open(filename, 'wb') + file.write("Z") # initialize + file.write("t%s~;"%filename) # title + file.write("IN;DF;PS0;DT~") # initialize + ppibyte = int(float(string_laser_rate.get())/10) + file.write("s%c"%ppibyte) # PPI + speed_hibyte = int(648*float(string_laser_speed.get()))/256 + speed_lobyte = int(648*float(string_laser_speed.get()))%256 + file.write("v%c%c"%(speed_hibyte,speed_lobyte)) # speed + power = float(string_laser_power.get()) + min_power = float(string_laser_min_power.get()) + max_power = float(string_laser_max_power.get()) + power_hibyte = (320*int(power))/256 + power_lobyte = (320*int(power))%256 + file.write("p%c%c"%(power_hibyte,power_lobyte)) # power + file.write("a%c"%2) # air assist on high + for layer in range(len(cad.toolpaths)): + if ((len(cad.zwrite) > 1) & (len(cad.toolpaths[layer]) > 0)): + fraction = (cad.zwrite[layer]-cad.zwrite[0])/(cad.zwrite[-1]-cad.zwrite[0]) + layer_power = min_power + fraction*(max_power-min_power) + power_hibyte = (320*int(layer_power))/256 + power_lobyte = (320*int(layer_power))%256 + file.write("p%c%c"%(power_hibyte,power_lobyte)) # power + for segment in range(len(cad.toolpaths[layer])): + x = int(units*(cad.xmin + (cad.xmax-cad.xmin)*(cad.toolpaths[layer][segment][0].x+0.5)/float(cad.nx))) + y = int(units*(cad.ymin + ((cad.ymax-cad.ymin)*((cad.ny-cad.toolpaths[layer][segment][0].y)+0.5)/float(cad.ny)))) + file.write("PU;PA"+str(x)+","+str(y)+";PD;") + for vertex in range(1,len(cad.toolpaths[layer][segment])): + x = int(units*(cad.xmin + (cad.xmax-cad.xmin)*(cad.toolpaths[layer][segment][vertex].x+0.5)/float(cad.nx))) + y = int(units*(cad.ymin + ((cad.ymax-cad.ymin)*((cad.ny-cad.toolpaths[layer][segment][vertex].y)+0.5)/float(cad.ny)))) + file.write("PA"+str(x)+","+str(y)+";") + file.write("e") # end of file + file.close() + draw_toolpath() + string_msg.set("wrote %s"%filename) + root.update() + +def write_jpg(): + # + # JPG image output + # + if (cad.views == "xy"): + filename = string_cam_file.get() + im.xy = Image.fromarray(im.intensity_xy,mode="RGBX") + im_rgb_xy = im.xy.convert("RGB") + dpi = int(cad.nx/float(cad.xmax-cad.xmin)) + im_rgb_xy.save(filename,dpi=(dpi,dpi)) + string_msg.set("wrote %s"%filename) + elif (cad.views == "xyzr"): + border = 5 + filename = string_cam_file.get() + im.xy = Image.fromarray(im.intensity_xy,mode="RGBX") + im.xz = Image.fromarray(im.intensity_xz,mode="RGBX") + im.yz = Image.fromarray(im.intensity_yz,mode="RGBX") + im.yz = im.yz.transpose(Image.FLIP_LEFT_RIGHT) + im.xyz = Image.fromarray(im.intensity_xyz,mode="RGBX") + (nx,ny) = im.xy.size + ny = (nx*cad.nyplot())/cad.nxplot() + nz = (nx*cad.nzplot())/cad.nxplot() + im.xy = im.xy.resize((nx,ny)) + im.yz = im.yz.resize((nz,ny)) + im.xz = im.xz.resize((nx,nz)) + im.xyz = im.xyz.resize((nx,ny)) + im_rgb_xy = im.xy.convert("RGB") + im_rgb_xz = im.xz.convert("RGB") + im_rgb_yz = im.yz.convert("RGB") + im_rgb_xyz = im.xyz.convert("RGB") + img = Image.new("RGB",(nx+border+nx,ny+border+ny),"white") + img.paste(im_rgb_xy,(0,0)) + img.paste(im_rgb_xz,(0,border+ny)) + img.paste(im_rgb_yz,(border+nx,0)) + img.paste(im_rgb_xyz,(border+nx,border+ny)) + img.save(filename) + string_msg.set("wrote %s"%filename) + else: + string_msg.set("unknown view") + +def write_png(): + # + # PNG image output + # + if (cad.views == "xy"): + filename = string_cam_file.get() + im.xy = Image.fromarray(im.intensity_xy,mode="RGBX") + im_rgb_xy = im.xy.convert("RGB") + dpi = int(cad.nx/float(cad.xmax-cad.xmin)) + im_rgb_xy.save(filename,dpi=(dpi,dpi)) + string_msg.set("wrote %s"%filename) + elif (cad.views == "xyzr"): + border = 5 + filename = string_cam_file.get() + im.xy = Image.fromarray(im.intensity_xy,mode="RGBX") + im.xz = Image.fromarray(im.intensity_xz,mode="RGBX") + im.yz = Image.fromarray(im.intensity_yz,mode="RGBX") + im.yz = im.yz.transpose(Image.FLIP_LEFT_RIGHT) + im.xyz = Image.fromarray(im.intensity_xyz,mode="RGBX") + (nx,ny) = im.xy.size + ny = (nx*cad.nyplot())/cad.nxplot() + nz = (nx*cad.nzplot())/cad.nxplot() + im.xy = im.xy.resize((nx,ny)) + im.yz = im.yz.resize((nz,ny)) + im.xz = im.xz.resize((nx,nz)) + im.xyz = im.xyz.resize((nx,ny)) + im_rgb_xy = im.xy.convert("RGB") + im_rgb_xz = im.xz.convert("RGB") + im_rgb_yz = im.yz.convert("RGB") + im_rgb_xyz = im.xyz.convert("RGB") + img = Image.new("RGB",(nx+border+nx,ny+border+ny),"white") + img.paste(im_rgb_xy,(0,0)) + img.paste(im_rgb_xz,(0,border+ny)) + img.paste(im_rgb_yz,(border+nx,0)) + img.paste(im_rgb_xyz,(border+nx,border+ny)) + img.save(filename) + string_msg.set("wrote %s"%filename) + else: + string_msg.set("unknown view") + +def write_stl(): + # + # STL output + # + filename = string_cam_file.get() + file = open(filename, 'wb') + units = cad.inches_per_unit + x = cad.xmin+(cad.xmax-cad.xmin)*(cad.x+0.5)/float(cad.nx) + y = cad.ymin+(cad.ymax-cad.ymin)*(cad.y+0.5)/float(cad.ny) + z = cad.zmin+(cad.zmax-cad.zmin)*(cad.z+0.5)/float(cad.nz) + # + # header + # + file.write('cad.py') + file.write('a'*74) + # + # length + # + N = len(cad.x) + file.write(struct.pack('L',N/3)) + # + # triangles + # + for i in range(0,N,3): + string_msg.set("write triangle %d/%d"%(i/3,N/3)) + root.update() + # + # normals + # + file.write(struct.pack('f',0)) + file.write(struct.pack('f',0)) + file.write(struct.pack('f',0)) + # + # vertices + # + file.write(struct.pack('f',x[i]*units)) + file.write(struct.pack('f',y[i]*units)) + file.write(struct.pack('f',z[i]*units)) + file.write(struct.pack('f',x[i+1]*units)) + file.write(struct.pack('f',y[i+1]*units)) + file.write(struct.pack('f',z[i+1]*units)) + file.write(struct.pack('f',x[i+2]*units)) + file.write(struct.pack('f',y[i+2]*units)) + file.write(struct.pack('f',z[i+2]*units)) + # + # padding + # + file.write(struct.pack('xx')) + file.close() + string_msg.set("wrote %s"%filename) + root.update() + +def write_gerber(): + # + # Gerber (RS-274X) output + # + filename = string_cam_file.get() + file = open(filename, 'wb') + units = cad.inches_per_unit + # + # write parameters + # + file.write("%FSLAX24Y24*%\n") # leading zeros omitted, absolute coordinates, 2.4 + file.write("%MOIN*%\n") # inches units + file.write("%OFA0B0*%\n") # no offset + # + # find and write apertures + # + ixs = cad.x[::2] + xs = cad.xmin+(cad.xmax-cad.xmin)*(ixs+0.5)/float(cad.nx) + ixe = cad.x[1::2] + xe = cad.xmin+(cad.xmax-cad.xmin)*(ixe+0.5)/float(cad.nx) + idx = ixe - ixs + dx = xe - xs + iys = cad.y[::2] + ys = cad.ymin+(cad.ymax-cad.ymin)*(iys+0.5)/float(cad.ny) + iye = cad.y[1::2] + ye = cad.ymin+(cad.ymax-cad.ymin)*(iye+0.5)/float(cad.ny) + idy = iye - iys + dy = ye - ys + mins = where((idx < idy),idx,idy) + uniques = unique(mins) + apertures = (cad.xmax-cad.xmin)*uniques/float(cad.nx) + index = searchsorted(uniques,mins) + for i in range(len(uniques)): + file.write("%%ADD%dR,%.4fX%.4f*%%\n"%(i+10,apertures[i],apertures[i])) + # + # write flashes + # + coords = arange(len(mins)) + for i in range(len(uniques)): + file.write("D%d*\n"%(i+10)) + coord = coords[index == i] + delta = apertures[i]/2. + ixs = (10000*(xs+delta)).astype(int32) + ixe = (10000*(xe-delta)).astype(int32) + iys = (10000*(ys+delta)).astype(int32) + iye = (10000*(ye-delta)).astype(int32) + for j in range(len(coord)): + n = coord[j] + if (idx[n] == idy[n]): + # + # flash + # + file.write('X%dY%dD03*\n'%(ixs[n],iys[n])) + elif (idx[n] > idy[n]): + # + # stroke horizontal + # + file.write('X%dY%dD02*\n'%(ixs[n],iys[n])) + file.write('X%dY%dD01*\n'%(ixe[n],iys[n])) + else: + # + # stroke vertical + # + file.write('X%dY%dD02*\n'%(ixs[n],iys[n])) + file.write('X%dY%dD01*\n'%(ixs[n],iye[n])) + file.write("M02*\n") # end of file + file.close() + string_msg.set("wrote %s (RS-274X)"%filename) + root.update() + +def write_excellon(): + # + # Excellon (RS-) output + # + """ +% Rewind and Stop +X#Y# Move and Drill +T# Tool Selection +M30 End of Program +M00 End of Program +R#X#Y# Repeat Hole +G05, G81 Select Drill Mode +G90 Absolute Mode +G91 Incremental Mode +G92 X#Y# Set Zero +G93 X#Y# Set Zero +M48 Program Header to first "%" +M72 English-Imperial Mode + + """ + filename = string_cam_file.get() + file = open(filename, 'wb') + units = cad.inches_per_unit + # + # write parameters + # + file.write("%FSLAX24Y24*%\n") # leading zeros omitted, absolute coordinates, 2.4 + file.write("%MOIN*%\n") # inches units + file.write("%OFA0B0*%\n") # no offset + # + # find and write apertures + # + ixs = cad.x[::2] + xs = cad.xmin+(cad.xmax-cad.xmin)*(ixs+0.5)/float(cad.nx) + ixe = cad.x[1::2] + xe = cad.xmin+(cad.xmax-cad.xmin)*(ixe+0.5)/float(cad.nx) + idx = ixe - ixs + dx = xe - xs + iys = cad.y[::2] + ys = cad.ymin+(cad.ymax-cad.ymin)*(iys+0.5)/float(cad.ny) + iye = cad.y[1::2] + ye = cad.ymin+(cad.ymax-cad.ymin)*(iye+0.5)/float(cad.ny) + idy = iye - iys + dy = ye - ys + mins = where((idx < idy),idx,idy) + uniques = unique(mins) + apertures = (cad.xmax-cad.xmin)*uniques/float(cad.nx) + index = searchsorted(uniques,mins) + for i in range(len(uniques)): + file.write("%%ADD%dR,%.4fX%.4f*%%\n"%(i+10,apertures[i],apertures[i])) + # + # write flashes + # + coords = arange(len(mins)) + for i in range(len(uniques)): + file.write("D%d*\n"%(i+10)) + coord = coords[index == i] + delta = apertures[i]/2. + ixs = (10000*(xs+delta)).astype(int32) + ixe = (10000*(xe-delta)).astype(int32) + iys = (10000*(ys+delta)).astype(int32) + iye = (10000*(ye-delta)).astype(int32) + for j in range(len(coord)): + n = coord[j] + if (idx[n] == idy[n]): + # + # flash + # + file.write('X%dY%dD03*\n'%(ixs[n],iys[n])) + elif (idx[n] > idy[n]): + # + # stroke horizontal + # + file.write('X%dY%dD02*\n'%(ixs[n],iys[n])) + file.write('X%dY%dD01*\n'%(ixe[n],iys[n])) + else: + # + # stroke vertical + # + file.write('X%dY%dD02*\n'%(ixs[n],iys[n])) + file.write('X%dY%dD01*\n'%(ixs[n],iye[n])) + file.write("M02*\n") # end of file + file.close() + string_msg.set("wrote %s (RS-274X)"%filename) + root.update() + +def write_ca(): + # + # CA output + # + filename = string_cam_file.get() + file = open(filename, 'wb') + file.write(chr(0xB9)) # magic number 0xB9 + file.write(chr(ca.nx/256)) # x size + file.write(chr(ca.nx%256)) # + file.write(chr(ca.ny/256)) # y size + file.write(chr(ca.ny%256)) # + file.write(chr(4)) # LED sub-array x + file.write(chr(2)) # LED sub-array y + for y in range(ca.nx): + for x in range(ca.nx): + if (ca.in1[y,x] == ca.E): + config = 0 + elif (ca.in1[y,x] == ca.NE): + config = 1 + elif (ca.in1[y,x] == ca.N): + config = 2 + elif (ca.in1[y,x] == ca.NW): + config = 3 + elif (ca.in1[y,x] == ca.W): + config = 4 + elif (ca.in1[y,x] == ca.SW): + config = 5 + elif (ca.in1[y,x] == ca.S): + config = 6 + elif (ca.in1[y,x] == ca.SE): + config = 7 + elif (ca.in1[y,x] == ca.empty): # XOR W W for empty + config = 4 + if (ca.in2[y,x] == ca.E): + config += 0 + elif (ca.in2[y,x] == ca.NE): + config += (1 << 3) + elif (ca.in2[y,x] == ca.N): + config += (2 << 3) + elif (ca.in2[y,x] == ca.NW): + config += (3 << 3) + elif (ca.in2[y,x] == ca.W): + config += (4 << 3) + elif (ca.in2[y,x] == ca.SW): + config += (5 << 3) + elif (ca.in2[y,x] == ca.S): + config += (6 << 3) + elif (ca.in2[y,x] == ca.SE): + config += (7 << 3) + elif (ca.in2[y,x] == ca.empty): # XOR W W for empty + config += (4 << 3) + if (ca.gates[y,x] == ca.AND): + config += 0 + elif (ca.gates[y,x] == ca.OR): + config += (1 << 6) + elif (ca.gates[y,x] == ca.XOR): + config += (2 << 6) + elif (ca.gates[y,x] == ca.NAND): + config += (3 << 6) + elif (ca.gates[y,x] == ca.empty): # XOR W W for empty + config += (2 << 6) + file.write(chr(config)) + for y in range(ca.ny): + for x in range((ca.nx/8)): + state = \ + (ca.states[y,8*x+0] << 7) \ + + (ca.states[y,8*x+1] << 6) \ + + (ca.states[y,8*x+2] << 5) \ + + (ca.states[y,8*x+3] << 4) \ + + (ca.states[y,8*x+4] << 3) \ + + (ca.states[y,8*x+5] << 2) \ + + (ca.states[y,8*x+6] << 1) \ + + (ca.states[y,8*x+7] << 0) + file.write(chr(state)) + if ((ca.nx%8) != 0): + x = cad.nx/8 + state = 0 + for i in range((ca.nx%8)): + state += (ca.states[y,8*x+i] << (7-i)) + file.write(chr(state)) + file.close() + string_msg.set("wrote %s"%filename) + root.update() + +def msg_xy(event): + x = (cad.xmin+cad.xmax)/2. + (cad.xmax-cad.xmin)*(1+event.x-cad.nplot/2.)/float(cad.nxplot()) + y = (cad.ymin+cad.ymax)/2. + (cad.ymin-cad.ymax)*(1+event.y-cad.nplot/2.)/float(cad.nyplot()) + string_msg.set("x = %.2f y = %.2f"%(x,y)) + +def msg_yz(event): + if (cad.nz > 1): + y = (cad.ymin+cad.ymax)/2. + (cad.ymin-cad.ymax)*(1+event.y-cad.nplot/2.)/float(cad.nyplot()) + z = (cad.zmin+cad.zmax)/2. + (cad.zmin-cad.zmax)*(1+event.x-cad.nplot/2.)/float(cad.nzplot()) + string_msg.set("y = %.2f z = %.2f"%(y,z)) + else: + string_msg.set("") + +def msg_xz(event): + if (cad.nz > 1): + x = (cad.xmin+cad.xmax)/2. + (cad.xmax-cad.xmin)*(1+event.x-cad.nplot/2.)/float(cad.nxplot()) + z = (cad.zmin+cad.zmax)/2. + (cad.zmin-cad.zmax)*(1+event.y-cad.nplot/2.)/float(cad.nzplot()) + string_msg.set("x = %.2f z = %.2f"%(x,z)) + else: + string_msg.set("") + +def msg_nomsg(event): + string_msg.set("") + +def image_min_x(event): + cad.xmin = float(string_image_xmin.get()) + xwidth = float(string_image_xwidth.get()) + cad.xmax = cad.xmin + xwidth + root.update() + +def image_min_y(event): + cad.ymin = float(string_image_ymin.get()) + yheight = float(string_image_yheight.get()) + cad.ymax = cad.ymin + yheight + root.update() + +def image_scale_x(event): + yheight = float(string_image_yheight.get()) + xwidth = yheight*cad.nx/float(cad.ny) + cad.xmax = cad.xmin + xwidth + string_image_xwidth.set(str(xwidth)) + root.update() + +def image_scale_y(event): + xwidth = float(string_image_xwidth.get()) + yheight = xwidth*cad.ny/float(cad.nx) + cad.ymax = cad.ymin + yheight + string_image_yheight.set(str(yheight)) + root.update() + +def send_to(event): + save_cam(0) + cam_file_name = string_cam_file.get() + send_to_file(cam_file_name) + +def send_to_file(cam_file_name): + cad_path = os.path.dirname(sys.argv[0]) + if (sys.argv[0] == "cad.py"): + cfg_path = "cad.cfg" + else: + cfg_path = os.path.dirname(sys.argv[0])+"/cad.cfg" + try: + config_file = open(cfg_path, 'r') + except: + string_msg.set(cfg_path+" not found") + root.update() + return() + dot = find(cam_file_name,".") + while 1: + new_dot = find(cam_file_name,".",dot+1) + if (new_dot == -1): + break + else: + dot = new_dot + suffix = cam_file_name[dot+1:] + while 1: + line = config_file.readline() + if (find(line,suffix) == 0): + string_msg.set("sending "+cam_file_name+" ...") + root.update() + quote1 = find(line,"'") + quote2 = find(line,"'",quote1+1) + cmd = line[(quote1+1):quote2] + if (os.name == 'nt'): + cam_file_name = replace(cam_file_name,'/','\\') + cmd = replace(cmd,'file','"'+cam_file_name+'"') + os.system(cmd) + string_msg.set(cam_file_name+" sent") + root.update() + config_file.close() + root.update() + return() + elif (line == ""): + string_msg.set(suffix+" driver not defined in "+cfg_path) + config_file.close() + root.update() + return() + +def resize_window(event): + # + # resize drawing windows + # + cad.nplot = int(string_window_size.get()) + cad.view(cad.views) + render() + +def resize_editor(event): + # + # resize editing windows + # + cad.editor_height = int(string_editor_height.get()) + widget_cad_text.config(height=cad.editor_height) + cad.editor_width = int(string_editor_width.get()) + widget_cad_text.config(width=cad.editor_width) + widget_function_text.config(width=cad.editor_width) + root.update() + +def reload(): + # + # reload input file + # + filename = string_input_file.get() + if (find(filename,'.cad') != -1): + cad_load(0) + elif ((find(filename,'.jpg') != -1) | (find(filename,'.JPG') != -1) | + (find(filename,'.png') != -1) | (find(filename,'.PNG') != -1) | + (find(filename,'.gif') != -1) | (find(filename,'.GIF') != -1)): + widget_cad_text.delete("1.0",END) + image_load(0) + else: + string_msg.set("unsupported input file format") + root.update() + +# +# set up GUI +# +root = Tk() +root.title('cad.py') +# +# message frame +# +msg_frame = Frame(root) +string_msg = StringVar() +widget_msg = Label(msg_frame, textvariable = string_msg) +widget_msg.pack(side='right') +Label(msg_frame, text=" ").pack(side='right') +widget_stop = Button(msg_frame, text='stop', borderwidth=2) +widget_stop.bind('',render_stop) +msg_frame.grid(row=0,column=0) +# +# size frame +# +size_frame = Frame(root) +Label(size_frame, text="window size: ").pack(side='left') +string_window_size = StringVar() +string_window_size.set(str(cad.nplot)) +widget_window_size = Entry(size_frame, width=4, bg='white', textvariable=string_window_size) +widget_window_size.bind('',resize_window) +widget_window_size.pack(side='left') +Label(size_frame, text=" editor width: ").pack(side='left') +string_editor_width = StringVar() +string_editor_width.set(str(cad.editor_width)) +widget_editor_width = Entry(size_frame, width=3, bg='white', textvariable=string_editor_width) +widget_editor_width.bind('',resize_editor) +widget_editor_width.pack(side='left') +Label(size_frame, text=" height: ").pack(side='left') +string_editor_height = StringVar() +string_editor_height.set(str(cad.editor_height)) +widget_editor_height = Entry(size_frame, width=3, bg='white', textvariable=string_editor_height) +widget_editor_height.bind('',resize_editor) +widget_editor_height.pack(side='left') +size_frame.grid(row=0,column=1) +# +# view frame +# +view_frame2 = Frame(root) +view_frame3 = Frame(root) +canvas_xy = Canvas(view_frame3) +canvas_xz = Canvas(view_frame3) +canvas_yz = Canvas(view_frame3) +canvas_xyz = Canvas(view_frame3) +cad.view('xyzr') +# +# I/O frame +# +io_frame = Frame(root) +io_frame.grid(row=2,column=1,sticky=N) +#cad_frame.bind('',msg_nomsg) + # + # input frame + # +input_frame = Frame(io_frame) +input_frame.pack() + # + # .cad editor + # +editor_frame = Frame(input_frame) +widget_text_yscrollbar = Scrollbar(editor_frame) +widget_cad_text = Text(editor_frame, bg='white', bd=5, width=cad.editor_width, height=cad.editor_height, yscrollcommand=widget_text_yscrollbar.set) +widget_cad_text.grid(row=1,column=1) +widget_text_yscrollbar.grid(row=1,column=2,sticky=N+S) +widget_text_yscrollbar.config(command=widget_cad_text.yview) +widget_cad_text.bind('',msg_nomsg) +editor_frame.pack() + # + # input file + # +cad_input_frame = Frame(input_frame) +widget_input_file = Button(cad_input_frame, text="input:",command=input_open) +widget_input_file.pack(side='left') +string_input_file = StringVar() +string_input_file.set('out.cad') +widget_cad = Entry(cad_input_frame, width=17, bg='white', textvariable=string_input_file) +widget_cad.pack(side='left') +Label(cad_input_frame, text=" ").pack(side='left') +widget_cad_save = Button(cad_input_frame, text="save") +widget_cad_save.bind('',cad_save) +widget_cad_save.pack(side='left') +Label(cad_input_frame, text=" ").pack(side='left') +widget_reload = Button(cad_input_frame, text="reload",command=reload) +widget_reload.pack(side='left') +cad_input_frame.pack() + # + # image x + # +image_x_frame = Frame(input_frame) +Label(image_x_frame, text="x min: ").pack(side='left') +string_image_xmin = StringVar() +widget_image_xmin = Entry(image_x_frame, width=6, bg='white', textvariable=string_image_xmin) +widget_image_xmin.bind('',image_min_x) +widget_image_xmin.pack(side='left') +Label(image_x_frame, text=" x width: ").pack(side='left') +string_image_xwidth = StringVar() +widget_image_xwidth = Entry(image_x_frame, width=6, bg='white', textvariable=string_image_xwidth) +widget_image_xwidth.bind('',image_scale_y) +widget_image_xwidth.pack(side='left') +string_image_nx = StringVar() +Label(image_x_frame, textvariable = string_image_nx).pack(side='left') + # + # image y + # +image_y_frame = Frame(input_frame) +Label(image_y_frame, text="y min: ").pack(side='left') +string_image_ymin = StringVar() +widget_image_ymin = Entry(image_y_frame, width=6, bg='white', textvariable=string_image_ymin) +widget_image_ymin.bind('',image_min_y) +widget_image_ymin.pack(side='left') +Label(image_y_frame, text=" y height: ").pack(side='left') +string_image_yheight = StringVar() +widget_image_yheight = Entry(image_y_frame, width=6, bg='white', textvariable=string_image_yheight) +widget_image_yheight.bind('',image_scale_x) +widget_image_yheight.pack(side='left') +string_image_ny = StringVar() +Label(image_y_frame, textvariable = string_image_ny).pack(side='left') + # + # image z + # +image_z_frame = Frame(input_frame) +Label(image_z_frame, text="z min: ").pack(side='left') +string_image_zmin = StringVar() +widget_image_zmin = Entry(image_z_frame, width=6, bg='white', textvariable=string_image_zmin) +widget_image_zmin.pack(side='left') +Label(image_z_frame, text=" z max: ").pack(side='left') +string_image_zmax = StringVar() +widget_image_zmax = Entry(image_z_frame, width=6, bg='white', textvariable=string_image_zmax) +widget_image_zmax.pack(side='left') +Label(image_z_frame, text=" nz: ").pack(side='left') +string_image_nz = StringVar() +widget_image_nz = Entry(image_z_frame, width=6, bg='white', textvariable=string_image_nz) +widget_image_nz.pack(side='left') + # + # image intensity + # +image_intensity_frame = Frame(input_frame) +Label(image_intensity_frame, text="intensity min: ").pack(side='left') +string_image_min = StringVar() +widget_image_min = Entry(image_intensity_frame, width=6, bg='white', textvariable=string_image_min) +widget_image_min.pack(side='left') +Label(image_intensity_frame, text=" intensity max: ").pack(side='left') +string_image_max = StringVar() +widget_image_max = Entry(image_intensity_frame, width=6, bg='white', textvariable=string_image_max) +widget_image_max.pack(side='left') + # + # image units + # +image_units_frame = Frame(input_frame) +Label(image_units_frame, text="inches per unit: ").pack(side='left') +string_image_units = StringVar() +widget_image_units = Entry(image_units_frame, width=6, bg='white', textvariable=string_image_units) +widget_image_units.pack(side='left') + # + # image invert + # +image_invert_frame = Frame(input_frame) +Label(image_invert_frame, text=" ").pack(side='left') +widget_image_invert = Button(image_invert_frame, text="invert image") +widget_image_invert.pack(side='left') +widget_image_invert.bind('',invert_image) + # + # output frame + # +output_frame = Frame(io_frame) +output_frame.pack() + # + # controls + # +control_frame = Frame(output_frame) +widget_render = Button(control_frame, text="render") +widget_render.bind('',render_button) +widget_render.pack(side='left') +Label(control_frame, text=" ").pack(side='left') +canvas_logo = Canvas(control_frame, width=26, height=26, background="white") +canvas_logo.create_oval(2,2,8,8,fill="red",outline="") +canvas_logo.create_rectangle(11,2,17,8,fill="blue",outline="") +canvas_logo.create_rectangle(20,2,26,8,fill="blue",outline="") +canvas_logo.create_rectangle(2,11,8,17,fill="blue",outline="") +canvas_logo.create_oval(10,10,16,16,fill="red",outline="") +canvas_logo.create_rectangle(20,11,26,17,fill="blue",outline="") +canvas_logo.create_rectangle(2,20,8,26,fill="blue",outline="") +canvas_logo.create_rectangle(11,20,17,26,fill="blue",outline="") +canvas_logo.create_rectangle(20,20,26,26,fill="blue",outline="") +canvas_logo.pack(side='left') +control_text = " cad.py (%s) "%DATE +Label(control_frame, text=control_text).pack(side='left') +widget_cam = Button(control_frame, text="cam") +widget_cam.bind('',cam) +widget_cam.pack(side='left') +Label(control_frame, text=" ").pack(side='left') +widget_quit = Button(control_frame, text="quit", command='exit') +widget_quit.pack(side='left') +control_frame.pack() + # + # function string + # +function_string_frame = Frame(output_frame) +Label(function_string_frame, text="function:").grid(row=1,column=1) +widget_function_yscrollbar = Scrollbar(function_string_frame) +widget_function_text = Text(function_string_frame, bg='white', bd=5, width=cad.editor_width, height=12, yscrollcommand=widget_function_yscrollbar.set, state=DISABLED) +widget_function_text.grid(row=2,column=1) +widget_function_yscrollbar.grid(row=2,column=2,sticky=N+S) +widget_function_yscrollbar.config(command=widget_function_text.yview) +function_string_frame.pack() + # + # CAM file + # +cam_file_frame = Frame(output_frame) +widget_cam_menu_button = Menubutton(cam_file_frame,text="output format", relief=RAISED) +widget_cam_menu_button.pack(side='left') +widget_cam_menu = Menu(widget_cam_menu_button) +widget_cam_menu.add_command(label='.epi (Epilog)',command=select_epi) +widget_cam_menu.add_command(label='.camm (CAMM)',command=select_camm) +widget_cam_menu.add_command(label='.rml (Modela)',command=select_rml) +widget_cam_menu.add_command(label='.sbp (ShopBot)',command=select_sbp) +widget_cam_menu.add_command(label='.gcode (Gcode)',command=select_g) +widget_cam_menu.add_command(label='.ps (Postscript)',command=select_ps) +widget_cam_menu.add_command(label='.ord (OMAX)',command=select_ord) +widget_cam_menu.add_command(label='.oms (Resonetics)',command=select_oms) +widget_cam_menu.add_command(label='.grb (Gerber)',command=select_gerber) +widget_cam_menu.add_command(label='.drl (Excellon)',command=select_excellon) +widget_cam_menu.add_command(label='.stl (STL)',command=select_stl) +widget_cam_menu.add_command(label='.dxf (DXF)',command=select_dxf) +widget_cam_menu.add_command(label='.jpg (JPG)',command=select_jpg) +widget_cam_menu.add_command(label='.png (PNG)',command=select_png) +widget_cam_menu.add_command(label='.ca (CA)',command=select_ca) +widget_cam_menu.add_command(label='.uni (Universal)',command=select_uni) +widget_cam_menu.add_command(label='.epb (Epilog bitmap)',state=DISABLED) +widget_cam_menu_button['menu'] = widget_cam_menu +Label(cam_file_frame, text=" output file: ").pack(side='left') +string_cam_file = StringVar() +widget_cam_file = Entry(cam_file_frame, width=12, bg='white', textvariable=string_cam_file) +widget_cam_file.pack(side='left') +Label(cam_file_frame, text=" ").pack(side='left') +widget_cam_save = Button(cam_file_frame, text="save") +widget_cam_save.bind('',save_cam) +widget_cam_save.pack(side='left') + # + # vectorization + # +cam_vector_frame = Frame(output_frame) +Label(cam_vector_frame, text="maximum vector fit error (lattice units): ").pack(side='left') +string_vector_error = StringVar() +string_vector_error.set('.75') +widget_vector_error = Entry(cam_vector_frame, width=6, bg='white', textvariable=string_vector_error) +widget_vector_error.pack(side='left') + # + # tool + # +cam_dia_frame = Frame(output_frame) +Label(cam_dia_frame, text="tool diameter: ").pack(side='left') +string_tool_dia = StringVar() +string_tool_dia.set('0') +widget_tool_dia = Entry(cam_dia_frame, width=6, bg='white', textvariable=string_tool_dia) +widget_tool_dia.pack(side='left') +Label(cam_dia_frame, text=" tool overlap: ").pack(side='left') +string_tool_overlap = StringVar() +string_tool_overlap.set('0.5') +widget_tool_overlap = Entry(cam_dia_frame, width=6, bg='white', textvariable=string_tool_overlap) +widget_tool_overlap.pack(side='left') + # + # contour + # +cam_contour_frame = Frame(output_frame) +Label(cam_contour_frame, text=" # contours (-1 for max): ").pack(side='left') +string_num_contours = StringVar() +string_num_contours.set('0') +widget_num_contours = Entry(cam_contour_frame, width=6, bg='white', textvariable=string_num_contours) +widget_num_contours.pack(side='left') +Label(cam_contour_frame, text=" ").pack(side='left') +widget_cam_contour = Button(cam_contour_frame, text="contour") +widget_cam_contour.pack(side='left') +widget_cam_contour.bind('',contour) + # + # laser power + # +laser_frame1 = Frame(output_frame) +Label(laser_frame1, text=" power:").pack(side='left') +string_laser_power = StringVar() +Entry(laser_frame1, width=6, bg='white', textvariable=string_laser_power).pack(side='left') +Label(laser_frame1, text=" speed:").pack(side='left') +string_laser_speed = StringVar() +Entry(laser_frame1, width=6, bg='white', textvariable=string_laser_speed).pack(side='left') +Label(laser_frame1, text=" rate: ").pack(side='left') +string_laser_rate = StringVar() +Entry(laser_frame1, width=6, bg='white', textvariable=string_laser_rate).pack(side='left') + # + # power range + # +laser_frame2 = Frame(output_frame) +Label(laser_frame2, text=" min power:").pack(side='left') +string_laser_min_power = StringVar() +Entry(laser_frame2, width=6, bg='white', textvariable=string_laser_min_power).pack(side='left') +Label(laser_frame2, text="% max power:").pack(side='left') +string_laser_max_power = StringVar() +Entry(laser_frame2, width=6, bg='white', textvariable=string_laser_max_power).pack(side='left') +Label(laser_frame2, text="%").pack(side='left') + # + # autofocus + # +laser_frame3 = Frame(output_frame) +integer_laser_autofocus = IntVar() +widget_autofocus = Checkbutton(laser_frame3, text="Auto Focus", variable=integer_laser_autofocus).pack(side='left') + # + # cutting + # +cut_frame = Frame(output_frame) +Label(cut_frame, text="force: ").pack(side='left') +string_cut_force = StringVar() +Entry(cut_frame, width=6, bg='white', textvariable=string_cut_force).pack(side='left') +Label(cut_frame, text=" velocity:").pack(side='left') +string_cut_velocity = StringVar() +Entry(cut_frame, width=6, bg='white', textvariable=string_cut_velocity).pack(side='left') + # + # speed + # +speed_frame = Frame(output_frame) +Label(speed_frame, text="xy speed:").pack(side='left') +string_xy_speed = StringVar() +Entry(speed_frame, width=4, bg='white', textvariable=string_xy_speed).pack(side='left') +Label(speed_frame, text=" z speed:").pack(side='left') +string_z_speed = StringVar() +Entry(speed_frame, width=4, bg='white', textvariable=string_z_speed).pack(side='left') + # + # jog + # +jog_frame = Frame(output_frame) +Label(jog_frame, text="jog xy speed:").pack(side='left') +string_jog_xy_speed = StringVar() +Entry(jog_frame, width=4, bg='white', textvariable=string_jog_xy_speed).pack(side='left') +Label(jog_frame, text=" z speed:").pack(side='left') +string_jog_z_speed = StringVar() +Entry(jog_frame, width=4, bg='white', textvariable=string_jog_z_speed).pack(side='left') +Label(jog_frame, text=" z:").pack(side='left') +string_jog_z = StringVar() +Entry(jog_frame, width=4, bg='white', textvariable=string_jog_z).pack(side='left') + # + # RML move + # +rml_move_frame = Frame(output_frame) +Label(rml_move_frame, text="x: ").pack(side='left') +string_rml_x_move = StringVar() +Entry(rml_move_frame, width=6, bg='white', textvariable=string_rml_x_move).pack(side='left') +Label(rml_move_frame, text=" y: ").pack(side='left') +string_rml_y_move = StringVar() +Entry(rml_move_frame, width=6, bg='white', textvariable=string_rml_y_move).pack(side='left') +Label(rml_move_frame, text=" ").pack(side='left') +widget_rml_move = Button(rml_move_frame, text="move") +widget_rml_move.pack(side='left') +widget_rml_move.bind('',rml_move) + # + # G codes + # +g_frame = Frame(output_frame) +Label(g_frame, text=" feed rate:").pack(side="left") +string_g_feed_rate = StringVar() +Entry(g_frame, width=6, textvariable=string_g_feed_rate).pack(side="left") +Label(g_frame, text=" spindle speed:").pack(side="left") +string_g_spindle_speed = StringVar() +Entry(g_frame, width=6, textvariable=string_g_spindle_speed).pack(side="left") +Label(g_frame, text=" tool:").pack(side="left") +string_g_tool = StringVar() +Entry(g_frame, width=3, textvariable=string_g_tool).pack(side="left") +integer_g_cool = IntVar() +widget_g_cool = Checkbutton(g_frame, text="coolant", variable=integer_g_cool) +widget_g_cool.pack(side="left") + # + # waterjet + # +waterjet_frame = Frame(output_frame) +Label(waterjet_frame,text="lead-in/out: ").pack(side='left') +string_lead_in = StringVar() +widget_lead_in = Entry(waterjet_frame, width=4, bg='white', textvariable=string_lead_in) +widget_lead_in.pack(side='left') +Label(waterjet_frame,text="quality: ").pack(side='left') +string_quality = StringVar() +widget_quality = Entry(waterjet_frame, width=4, bg='white', textvariable=string_quality) +widget_quality.pack(side='left') + # + # excimer + # +excimer_frame = Frame(output_frame) +Label(excimer_frame,text="period (usec): ").pack(side='left') +string_pulse_period = StringVar() +widget_pulse_period = Entry(excimer_frame, width=5, bg='white', textvariable=string_pulse_period) +widget_pulse_period.pack(side='left') +Label(excimer_frame,text="velocity: ").pack(side='left') +string_cut_vel = StringVar() +widget_cut_vel = Entry(excimer_frame, width=4, bg='white', textvariable=string_cut_vel) +widget_cut_vel.pack(side='left') +Label(excimer_frame,text="acceleration: ").pack(side='left') +string_cut_accel = StringVar() +widget_cut_accel = Entry(excimer_frame, width=4, bg='white', textvariable=string_cut_accel) +widget_cut_accel.pack(side='left') + # + # STL + # +STL_frame = Frame(output_frame) +widget_STL_triangulate = Button(STL_frame, text="triangulate") +widget_STL_triangulate.pack(side='left') +widget_STL_triangulate.bind('',triangulate) + # + # Gerber + # +Gerber_frame = Frame(output_frame) +widget_Gerber_convert = Button(Gerber_frame, text="convert") +widget_Gerber_convert.pack(side='left') +widget_Gerber_convert.bind('',flash) + # + # Excellon + # +Excellon_frame = Frame(output_frame) +widget_Excellon_convert = Button(Excellon_frame, text="convert") +widget_Excellon_convert.pack(side='left') +widget_Excellon_convert.bind('',flash) + # + # filling + # +fill_frame = Frame(output_frame) +integer_fill = IntVar() +widget_fill = Checkbutton(fill_frame, text="fill polygons", variable=integer_fill).pack(side='left') + # + # send to + # +send_to_frame = Frame(output_frame) +widget_send_to = Button(send_to_frame, text="send to machine") +widget_send_to.bind('',send_to) +widget_send_to.pack(side='left') +string_send_to_time = StringVar() +string_send_to_time.set("") +Label(send_to_frame,textvariable=string_send_to_time).pack(side='left') + +# +# define .cad template +# +cad_template = """# +# .cad template +# + +# +# define shapes and transformation +# +# circle(x0, y0, r) +# cylinder(x0, y0, z0, z1, r) +# cone(x0, y0, z0, z1, r0) +# sphere(x0, y0, z0, r) +# torus(x0, y0, z0, r0, r1) +# rectangle(x0, x1, y0, y1) +# cube(x0, x1, y0, y1, z0, z1) +# right_triangle(x0, y0, h) +# triangle(x0, y0, x1, y1, x2, y2) (points in clockwise order) +# pyramid(x0, x1, y0, y1, z0, z1) +# function(Z_of_XY) +# functions(upper_Z_of_XY,lower_Z_of_XY) +# add(part1, part2) +# subtract(part1, part2) +# intersect(part1, part2) +# move(part,dx,dy) +# translate(part,dx,dy,dz) +# rotate(part, angle) +# rotate_x(part, angle) +# rotate_y(part, angle) +# rotate_z(part, angle) +# rotate_90(part) +# rotate_180(part) +# rotate_270(part) +# reflect_x(part) +# reflect_y(part) +# reflect_z(part) +# reflect_xy(part) +# reflect_xz(part) +# reflect_yz(part) +# scale_x(part, x0, sx) +# scale_y(part, y0, sy) +# scale_z(part, z0, sz) +# scale_xy(part, x0, y0, sxy) +# scale_xyz(part, x0, y0, z0, sxyz) +# coscale_x_y(part, x0, y0, y1, angle0, angle1, amplitude, offset) +# coscale_x_z(part, x0, z0, z1, angle0, angle1, amplitude, offset) +# coscale_xy_z(part, x0, y0, z0, z1, angle0, angle1, amplitude, offset) +# taper_x_y(part, x0, y0, y1, s0, s1) +# taper_x_z(part, x0, z0, z1, s0, s1) +# taper_xy_z(part, x0, y0, z0, z1, s0, s1) +# shear_x_y(part, y0, y1, dx0, dx1) +# shear_x_z(part, z0, z1, dx0, dx1) +# (more to come) + +def circle(x0, y0, r): + part = "(((X-x0)**2 + (Y-y0)**2) <= r**2)" + part = replace(part,'x0',str(x0)) + part = replace(part,'y0',str(y0)) + part = replace(part,'r',str(r)) + return part + +def cylinder(x0, y0, z0, z1, r): + part = "(((X-x0)**2 + (Y-y0)**2 <= r**2) & (Z >= z0) & (Z <= z1))" + part = replace(part,'x0',str(x0)) + part = replace(part,'y0',str(y0)) + part = replace(part,'z0',str(z0)) + part = replace(part,'z1',str(z1)) + part = replace(part,'r',str(r)) + return part + +def cone(x0, y0, z0, z1, r0): + part = cylinder(x0, y0, z0, z1, r0) + part = taper_xy_z(part, x0, y0, z0, z1, 1.0, 0.0) + return part + +def sphere(x0, y0, z0, r): + part = "(((X-x0)**2 + (Y-y0)**2 + (Z-z0)**2) <= r**2)" + part = replace(part,'x0',str(x0)) + part = replace(part,'y0',str(y0)) + part = replace(part,'z0',str(z0)) + part = replace(part,'r',str(r)) + return part + +def torus(x0, y0, z0, r0, r1): + part = "(((r0 - sqrt((X-x0)**2 + (Y-y0)**2))**2 + (Z-z0)**2) <= r1**2)" + part = replace(part,'x0',str(x0)) + part = replace(part,'y0',str(y0)) + part = replace(part,'z0',str(z0)) + part = replace(part,'r0',str(r0)) + part = replace(part,'r1',str(r1)) + return part + +def rectangle(x0, x1, y0, y1): + part = "((X >= x0) & (X <= x1) & (Y >= y0) & (Y <= y1))" + part = replace(part,'x0',str(x0)) + part = replace(part,'x1',str(x1)) + part = replace(part,'y0',str(y0)) + part = replace(part,'y1',str(y1)) + return part + +def cube(x0, x1, y0, y1, z0, z1): + part = "((X >= x0) & (X <= x1) & (Y >= y0) & (Y <= y1) & (Z >= z0) & (Z <= z1))" + part = replace(part,'x0',str(x0)) + part = replace(part,'x1',str(x1)) + part = replace(part,'y0',str(y0)) + part = replace(part,'y1',str(y1)) + part = replace(part,'z0',str(z0)) + part = replace(part,'z1',str(z1)) + return part + +def right_triangle(x0, y0, h): + part = "((X > x0) & (X < x0 + h - (Y-y0)) & (Y > y0))" + part = replace(part,'x0',str(x0)) + part = replace(part,'y0',str(y0)) + part = replace(part,'h',str(h)) + return part + +def triangle(x0, y0, x1, y1, x2, y2): # points in clockwise order + 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))" + part = replace(part,'x0',str(x0)) + part = replace(part,'y0',str(y0)) + part = replace(part,'x1',str(x1)) + part = replace(part,'y1',str(y1)) + part = replace(part,'x2',str(x2)) + part = replace(part,'y2',str(y2)) + return part + +def pyramid(x0, x1, y0, y1, z0, z1): + part = cube(x0, x1, y0, y1, z0, z1) + part = taper_xy_z(part, (x0+x1)/2., (y0+y1)/2., z0, z1, 1.0, 0.0) + return part + +def function(Z_of_XY): + part = '(Z <= '+Z_of_XY+')' + return part + +def functions(upper_Z_of_XY,lower_Z_of_XY): + part = '(Z <= '+upper_Z_of_XY+') & (Z >= '+lower_Z_of_XY+')' + return part + +def add(part1, part2): + part = "part1 | part2" + part = replace(part,'part1',part1) + part = replace(part,'part2',part2) + return part + +def subtract(part1, part2): + part = "(part1) & ~(part2)" + part = replace(part,'part1',part1) + part = replace(part,'part2',part2) + return part + +def intersect(part1, part2): + part = "(part1) & (part2)" + part = replace(part,'part1',part1) + part = replace(part,'part2',part2) + return part + +def move(part,dx,dy): + part = replace(part,'X','(X-'+str(dx)+')') + part = replace(part,'Y','(Y-'+str(dy)+')') + return part + +def translate(part,dx,dy,dz): + part = replace(part,'X','(X-'+str(dx)+')') + part = replace(part,'Y','(Y-'+str(dy)+')') + part = replace(part,'Z','(Z-'+str(dz)+')') + return part + +def rotate(part, angle): + angle = angle*pi/180 + part = replace(part,'X','(cos(angle)*X+sin(angle)*y)') + part = replace(part,'Y','(-sin(angle)*X+cos(angle)*y)') + part = replace(part,'y','Y') + part = replace(part,'angle',str(angle)) + return part + +def rotate_x(part, angle): + angle = angle*pi/180 + part = replace(part,'Y','(cos(angle)*Y+sin(angle)*z)') + part = replace(part,'Z','(-sin(angle)*Y+cos(angle)*z)') + part = replace(part,'z','Z') + part = replace(part,'angle',str(angle)) + return part + +def rotate_y(part, angle): + angle = angle*pi/180 + part = replace(part,'X','(cos(angle)*X+sin(angle)*z)') + part = replace(part,'Z','(-sin(angle)*X+cos(angle)*z)') + part = replace(part,'z','Z') + part = replace(part,'angle',str(angle)) + return part + +def rotate_z(part, angle): + angle = angle*pi/180 + part = replace(part,'X','(cos(angle)*X+sin(angle)*y)') + part = replace(part,'Y','(-sin(angle)*X+cos(angle)*y)') + part = replace(part,'y','Y') + part = replace(part,'angle',str(angle)) + return part + +def rotate_90(part): + part = reflect_xy(part) + part = reflect_y(part) + return part + +def rotate_180(part): + part = reflect_xy(part) + part = reflect_y(part) + part = reflect_xy(part) + part = reflect_y(part) + return part + +def rotate_270(part): + part = reflect_xy(part) + part = reflect_y(part) + part = reflect_xy(part) + part = reflect_y(part) + part = reflect_xy(part) + part = reflect_y(part) + return part + +def reflect_x(part): + part = replace(part,'X','(-X)') + return part + +def reflect_y(part): + part = replace(part,'Y','(-Y)') + return part + +def reflect_z(part): + part = replace(part,'Z','(-Z)') + return part + +def reflect_xy(part): + part = replace(part,'X','temp') + part = replace(part,'Y','X') + part = replace(part,'temp','Y') + return part + +def reflect_xz(part): + part = replace(part,'X','temp') + part = replace(part,'Z','X') + part = replace(part,'temp','Z') + return part + +def reflect_yz(part): + part = replace(part,'Y','temp') + part = replace(part,'Z','Y') + part = replace(part,'temp','Z') + return part + +def scale_x(part, x0, sx): + part = replace(part,'X','(x0 + (X-x0)/sx)') + part = replace(part,'x0',str(x0)) + part = replace(part,'sx',str(sx)) + return part + +def scale_y(part, y0, sy): + part = replace(part,'Y','(y0 + (Y-y0)/sy)') + part = replace(part,'y0',str(y0)) + part = replace(part,'sy',str(sy)) + return part + +def scale_z(part, z0, sz): + part = replace(part,'Z','(z0 + (Z-z0)/sz)') + part = replace(part,'z0',str(z0)) + part = replace(part,'sz',str(sz)) + return part + +def scale_xy(part, x0, y0, sxy): + part = replace(part,'X','(x0 + (X-x0)/sxy)') + part = replace(part,'Y','(y0 + (Y-y0)/sxy)') + part = replace(part,'x0',str(x0)) + part = replace(part,'y0',str(y0)) + part = replace(part,'sxy',str(sxy)) + return part + +def scale_xyz(part, x0, y0, z0, sxyz): + part = replace(part,'X','(x0 + (X-x0)/sxyz)') + part = replace(part,'Y','(y0 + (Y-y0)/sxyz)') + part = replace(part,'Z','(z0 + (Z-z0)/sxyz)') + part = replace(part,'x0',str(x0)) + part = replace(part,'y0',str(y0)) + part = replace(part,'z0',str(z0)) + part = replace(part,'sxyz',str(sxyz)) + return part + +def coscale_x_y(part, x0, y0, y1, angle0, angle1, amplitude, offset): + phase0 = pi*angle0/180. + phase1 = pi*angle1/180. + part = replace(part,'X','(x0 + (X-x0)/(offset + amplitude*cos(phase0 + (phase1-phase0)*(Y-y0)/(y1-y0))))') + part = replace(part,'x0',str(x0)) + part = replace(part,'y0',str(y0)) + part = replace(part,'y1',str(y1)) + part = replace(part,'phase0',str(phase0)) + part = replace(part,'phase1',str(phase1)) + part = replace(part,'amplitude',str(amplitude)) + part = replace(part,'offset',str(offset)) + return part + +def coscale_x_z(part, x0, z0, z1, angle0, angle1, amplitude, offset): + phase0 = pi*angle0/180. + phase1 = pi*angle1/180. + part = replace(part,'X','(x0 + (X-x0)/(offset + amplitude*cos(phase0 + (phase1-phase0)*(Z-z0)/(z1-z0))))') + part = replace(part,'x0',str(x0)) + part = replace(part,'z0',str(z0)) + part = replace(part,'z1',str(z1)) + part = replace(part,'phase0',str(phase0)) + part = replace(part,'phase1',str(phase1)) + part = replace(part,'amplitude',str(amplitude)) + part = replace(part,'offset',str(offset)) + return part + +def coscale_xy_z(part, x0, y0, z0, z1, angle0, angle1, amplitude, offset): + phase0 = pi*angle0/180. + phase1 = pi*angle1/180. + part = replace(part,'X','(x0 + (X-x0)/(offset + amplitude*cos(phase0 + (phase1-phase0)*(Z-z0)/(z1-z0))))') + part = replace(part,'Y','(y0 + (Y-y0)/(offset + amplitude*cos(phase0 + (phase1-phase0)*(Z-z0)/(z1-z0))))') + part = replace(part,'x0',str(x0)) + part = replace(part,'y0',str(y0)) + part = replace(part,'z0',str(z0)) + part = replace(part,'z1',str(z1)) + part = replace(part,'phase0',str(phase0)) + part = replace(part,'phase1',str(phase1)) + part = replace(part,'amplitude',str(amplitude)) + part = replace(part,'offset',str(offset)) + return part + +def taper_x_y(part, x0, y0, y1, s0, s1): + part = replace(part,'X','(x0 + (X-x0)*(y1-y0)/(s1*(Y-y0) + s0*(y1-Y)))') + part = replace(part,'x0',str(x0)) + part = replace(part,'y0',str(y0)) + part = replace(part,'y1',str(y1)) + part = replace(part,'s0',str(s0)) + part = replace(part,'s1',str(s1)) + return part + +def taper_x_z(part, x0, z0, z1, s0, s1): + part = replace(part,'X','(x0 + (X-x0)*(z1-z0)/(s1*(Z-z0) + s0*(z1-Z)))') + part = replace(part,'x0',str(x0)) + part = replace(part,'z0',str(z0)) + part = replace(part,'z1',str(z1)) + part = replace(part,'s0',str(s0)) + part = replace(part,'s1',str(s1)) + return part + +def taper_xy_z(part, x0, y0, z0, z1, s0, s1): + part = replace(part,'X','(x0 + (X-x0)*(z1-z0)/(s1*(Z-z0) + s0*(z1-Z)))') + part = replace(part,'Y','(y0 + (Y-y0)*(z1-z0)/(s1*(Z-z0) + s0*(z1-Z)))') + part = replace(part,'x0',str(x0)) + part = replace(part,'y0',str(y0)) + part = replace(part,'z0',str(z0)) + part = replace(part,'z1',str(z1)) + part = replace(part,'s0',str(s0)) + part = replace(part,'s1',str(s1)) + return part + +def shear_x_y(part, y0, y1, dx0, dx1): + part = replace(part,'X','(X - dx0 - (dx1-dx0)*(Y-y0)/(y1-y0))') + part = replace(part,'y0',str(y0)) + part = replace(part,'y1',str(y1)) + part = replace(part,'dx0',str(dx0)) + part = replace(part,'dx1',str(dx1)) + return part + +def shear_x_z(part, z0, z1, dx0, dx1): + part = replace(part,'X','(X - dx0 - (dx1-dx0)*(Z-z0)/(z1-z0))') + part = replace(part,'z0',str(z0)) + part = replace(part,'z1',str(z1)) + part = replace(part,'dx0',str(dx0)) + part = replace(part,'dx1',str(dx1)) + return part + +def coshear_x_z(part, z0, z1, angle0, angle1, amplitude, offset): + phase0 = pi*angle0/180. + phase1 = pi*angle1/180. + part = replace(part,'X','(X - offset - amplitude*cos(phase0 + (phase1-phase0)*(Z-z0)/(z1-z0)))') + part = replace(part,'z0',str(z0)) + part = replace(part,'z1',str(z1)) + part = replace(part,'phase0',str(phase0)) + part = replace(part,'phase1',str(phase1)) + part = replace(part,'amplitude',str(amplitude)) + part = replace(part,'offset',str(offset)) + return part + +# +# define part +# + +d = .5 +teapot = cylinder(0,0,-d,d,d) +teapot = coscale_xy_z(teapot,0,0,-d,d,-90,90,.5,.75) + +handle = torus(0,0,0,3.5*d/5.,d/10.) +handle = reflect_xz(handle) +handle = reflect_xy(handle) +handle = scale_x(handle,0,.75) +handle = scale_y(handle,0,3) +handle = translate(handle,-6*d/5.,0,0) +teapot = add(teapot,handle) + +spout = torus(2.1*d,-.2*d,0,1.1*d,.2*d) +spout = reflect_yz(spout) +spout = intersect(spout,cube(-3*d,1.8*d,-3*d,3*d,0,3*d)) +teapot = add(teapot,spout) + +interior = cylinder(0,0,.1-d,.1+d,d-.1) +interior = coscale_xy_z(interior,0,0,-d,d,-90,90,.5,.75) +teapot = subtract(teapot,interior) + +spout_interior = torus(2.1*d,-.2*d,0,1.1*d,.15*d) +spout_interior = reflect_yz(spout_interior) +spout_interior = intersect(spout_interior,cube(-3*d,1.8*d,-3*d,3*d,0,3*d)) +teapot = subtract(teapot,spout_interior) + +part = teapot + +part = subtract(part,cube(0,3*d,-3*d,0,-3*d,3*d)) + +# +# define limits and parameters +# + +width = 2.5 +x0 = 0 +y0 = 0 +z0 = 0 +cad.xmin = x0-width/2. # min x to render +cad.xmax = x0+width/2. # max x to render +cad.ymin = y0-width/2. # min y to render +cad.ymax = y0+width/2. # max y to render +#cad.zmin = z0-width/4. # min z to render +#cad.zmax = z0+width/4. # max x to render +cad.zmin = z0-width/4. # min z to render +cad.zmax = z0+width/4. # max x to render +cad.rx = 30 # x view rotation (degrees) +cad.rz = 20 # z view rotation (degrees) +dpi = 100 # rendering resolution +cad.nx = int(dpi*(cad.xmax-cad.xmin)) # x points to render +cad.ny = int(dpi*(cad.ymax-cad.ymin)) # y points to render +cad.nz = int(dpi*(cad.zmax-cad.zmin)) # z points to render +cad.inches_per_unit = 1.0 # use inch units + +# +# assign part to cad.function +# + +cad.function = part + +""" + +# +# check config file for window parameters +# + +cad_path = os.path.dirname(sys.argv[0]) +if (sys.argv[0] == "cad.py"): + cfg_path = "cad.cfg" +else: + cfg_path = os.path.dirname(sys.argv[0])+"/cad.cfg" +try: + config_file = open(cfg_path, 'r') + string_msg.set("found "+cfg_path) + while 1: + line = config_file.readline() + if (find(line,"window size:") == 0): + string_window_size.set(int(line[12:])) + elif (find(line,"editor width:") == 0): + string_editor_width.set(int(line[13:])) + elif (find(line,"editor height:") == 0): + string_editor_height.set(int(line[14:])) + elif (line == ""): + break + config_file.close() + resize_editor(0) +except: + string_msg.set(cfg_path+" not found") + +# +# read input file if on command line, otherwise use template +# + +if len(sys.argv) == 2: + filename = sys.argv[1] + string_input_file.set(filename) + if (find(filename,'.cad') != -1): + cad_load(0) + elif ((find(filename,'.jpg') != -1) | (find(filename,'.JPG') != -1) | + (find(filename,'.png') != -1) | (find(filename,'.PNG') != -1) | + (find(filename,'.gif') != -1) | (find(filename,'.GIF') != -1)): + widget_cad_text.delete("1.0",END) + image_load(0) + else: + string_msg.set("unsupported input file format") + root.update() +else: + widget_cad_text.insert("1.0",cad_template) + +# +# start GUI +# + +root.mainloop() diff -r 000000000000 -r ee535cb8fb1a stuff/HPGL_PREPROCESSOR --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/stuff/HPGL_PREPROCESSOR Sat Nov 07 13:30:15 2015 +0100 @@ -0,0 +1,1 @@ +hp2xx --mode nc Laser_Bestueckung.hpgl \ No newline at end of file