3856 lines
134 KiB
Python
3856 lines
134 KiB
Python
#!/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('<Motion>',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('<Motion>',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('<Motion>',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('<Motion>',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('<Motion>',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('<Button-1>',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('<Return>',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('<Return>',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('<Return>',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('<Motion>',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('<Motion>',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('<Button-1>',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('<Return>',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('<Return>',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('<Return>',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('<Return>',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('<Button-1>',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('<Button-1>',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('<Button-1>',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('<Button-1>',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('<Button-1>',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('<Button-1>',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('<Button-1>',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('<Button-1>',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('<Button-1>',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('<Button-1>',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()
|