# # tippy.cad # # tippy-top molding and casting example # # Neil Gershenfeld # CBA MIT 11/2/09 # # (c) Massachusetts Institute of Technology 2009 # Permission granted for experimental and personal use; # license for commercial sale available from MIT. # # # define shapes and transformation # # circle(x0, y0, r) # cylinder(x0, y0, z0, z1, r) # sphere(x0, y0, z0, r) # torus(x0, y0, z0, r0, r1) # rectangle(x0, x1, y0, y1) # cube(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_z_90(part) # rotate_z_180(part) # rotate_z_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) # coshear 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 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 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_z_90(part): part = reflect_xy(part) part = reflect_y(part) return part def rotate_z_180(part): part = reflect_xy(part) part = reflect_y(part) part = reflect_xy(part) part = reflect_y(part) return part def rotate_z_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)/sx)') part = replace(part,'Y','(y0 + (Y-y0)/sy)') 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, sxy): part = replace(part,'X','(x0 + (X-x0)/sx)') part = replace(part,'Y','(y0 + (Y-y0)/sy)') part = replace(part,'Z','(z0 + (Z-z0)/sz)') 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 # # dimensions # button_height = .375 button_radius = .5 inset = 2/16. depth = 2/16. sphere_radius = ((button_radius-inset)**2+depth**2)/(2*depth) wall = 0.2 x0 = 1.0 y0 = 1.0 # # define part # part = "True" part = subtract(part, cylinder(0,0,-button_height-wall,10,button_radius+wall)) part = add(part, cylinder(0,0,-button_height-wall,-wall,button_radius)) part = subtract(part, sphere(0,0,sphere_radius-depth-wall,sphere_radius)) # # cutout to see interior (remove for machining) # #part = subtract(part,cube(0,10,-10,0,-10,10)) # # move to location to machine # part = move(part,x0+button_radius+wall,y0+button_radius+wall) # # rendering settings # cad.xmin = x0-wall cad.xmax = x0+2*button_radius+3*wall cad.ymin = y0-wall cad.ymax = y0+2*button_radius+3*wall cad.zmin = -button_height-2*wall cad.zmax = 0 cad.rx = 20 # x view rotation (degrees) cad.rz = 20 # z view rotation (degrees) dpi = 100 # low resolution for previewing #dpi = 250 # high resolution for machining nxy = int(dpi*(cad.xmax-cad.xmin)) cad.nx = nxy cad.ny = nxy dz = 0.01 # layer thickness cad.nz = 1+int(0.5+(cad.zmax-cad.zmin)/dz) cad.inches_per_unit = 1.0 # use inch units # # machining settings # string_tool_dia.set("0.125") string_xy_speed.set("20") string_z_speed.set("20") string_rml_x_move.set("1") string_rml_y_move.set("1") # # assign part to cad.function # cad.function = part