#Code to turn a 3d function in R into a stl file for molding and casting something BIG #Laura Perovich Nov 2012 #Same stl building block functions as other weeks #Load package misc3d that includes surfaceTriangles function library(misc3d) library(plotrix) #Define character constants used in the stl files tristart1<-"facet normal 0 0 0" tristart2<-" outer loop" triend1<-" endloop" triend2<-"endfacet" startline1<-"+" startline2<-" solid LAURA" endline<-" endsolid LAURA" #Make a function that will make each facet from data returned from surfaceTriangles applied to a function #(probably a more elegant way to do this?) makefacet<-function(data){ facetvector<-c() for (i in 1:nrow(data[[1]])){ v1<-paste(" vertex", as.character(data[[1]][i, 1]), as.character(data[[1]][i, 2]), as.character(data[[1]][i, 3]), sep=" ") v2<-paste(" vertex", as.character(data[[2]][i, 1]), as.character(data[[2]][i, 2]), as.character(data[[2]][i, 3]), sep=" ") v3<-paste(" vertex", as.character(data[[3]][i, 1]), as.character(data[[3]][i, 2]), as.character(data[[3]][i, 3]), sep=" ") facetvector<-c(facetvector, tristart1, tristart2, v1, v2, v3, triend1, triend2) } return(facetvector) } #Make a function that puts the facets together with the file headers and writes it out makestl<-function(location, facetvector){ fileConn<-file(location) writeLines(c(startline1, startline2, facetvector, endline), fileConn) close(fileConn) } ########################################################################## ######################## TABLE SURFACE ################################### ########################################################################## #square edge; four legs on outside corners, each on a local maxima #Bottom of the table is a curve, top of the table is mostly flat with contour plot etched in. #Define some constants to use in the function aa<-2 kk<-3 bb<-function(x) (cos(x)/kk) cc<-function(y) (cos(y)/kk) #Add ledges and edges for molding and casting #define edge amounts ee<-.3 dd<-.7 #Dimensions: #I want the top of the table to be roughly two feet square #It need to be less that this because the width of the piece is only 2 ft and I need border space #Scale the whole thing to 22", make sure the depth must be less than 4 inches--aim for 3.5. rOverI<-2*(pi+ee+dd)/22 iOverR<-1/rOverI #each inch is 0.3765 R units #each R unit is 2.656 inches #Functions for all the pieces of the mold #Just the function for the contours to etch (internal) mytableInternal<-function(x,y) (ifelse(x-pi &y-pi, -(cc(y)*cos(y*aa)+bb(x)*cos(x*aa)), ifelse(x-pi-dd &y-pi-dd, NA, NA))) #Estimate the max and min of the function to figure out approximate limits for the contours w<-seq(-pi-ee-dd,pi+ee+dd,len=90) q<-seq(-pi-ee-dd,pi+ee+dd,len=90) Tmin<-min(outer(w,q, mytableInternal), na.rm=TRUE) Tmax<-ma(outer(w,q, mytableInternal), na.rm=TRUE) #The bottom surface of the table, plus the edges for molding/casting: mytableSquare<-function(x,y) (ifelse(x-pi &y-pi, -(cc(y)*cos(y*aa)+bb(x)*cos(x*aa)), ifelse(x-pi-dd &y-pi-dd, 1.2*Tmax, 1.35*Tmax))) drawScene(surfaceTriangles(seq(-pi-ee-dd,pi+ee+dd,len=90), seq(-pi-ee-dd,pi+ee+dd,len=90), mytableSquare, color2 = "green")) #The top surface of the table, plus the edges, minus the contours: mytableJustSquare<-function(x,y) (ifelse(x-pi &y-pi, 1.4*Tmax, ifelse(x-pi-dd &y-pi-dd, 1.35*Tmax, 1.2*Tmax))) drawScene(surfaceTriangles(seq(-pi-ee-dd,pi+ee+dd,len=90), seq(-pi-ee-dd,pi+ee+dd,len=90), mytableJustSquare, color2 = "green")) #Check that the depth here is okay. .2*Tmax #Gives 0.133 R units which is 0.35 inches so no problem #The real life size of this piece should be 22" square, check: 2*(pi+ee+dd)/rOverI==22 #Write out the stl files: #NOTE: These planes need to be made into 3D surfaces. Can do this in meshlab--see trials and tribulations and week 4 instructions. triA<-surfaceTriangles(seq(-pi-ee-dd, pi+ee+dd,len=150), seq(-pi-ee-dd, pi+ee+dd,len=150), mytableSquare) fv<-makefacet(triA) makestl("/media/6AD8BBE2D8BBAAA9/Users/perovich/Documents/MIT/HTMAA/week8/squareTable.stl", fv) triA<-surfaceTriangles(seq(-pi-ee-dd, pi+ee+dd,len=150), seq(-pi-ee-dd, pi+ee+dd,len=150), mytableJustSquare) fv<-makefacet(triA) makestl("/media/6AD8BBE2D8BBAAA9/Users/perovich/Documents/MIT/HTMAA/week8/squareTableContour.stl", fv) #Now come up with an image for the contour plot that will be the top of the table: #Just the inside here, not the molding/casting edges--can re-z zero here with the shopbot (?) bmp("/media/6AD8BBE2D8BBAAA9/Users/perovich/Documents/MIT/HTMAA/week8/contourOnly.bmp", width=960, height=960) contour(w, q, outer(w,q, mytableInternal), drawlabels=FALSE, axes=FALSE, asp=1) #Add lines so I know exactly where to crop the image to get my expected dimensions #Should go from -pi to pi abline(h=-pi) abline(h=pi) abline(v=-pi) abline(v=pi) dev.off() #Dimensions this should scale to: 2*pi/rOverI #16.688 inches square #Make a ("22 inch") square file to cut out molds as needed for assembly bmp("/media/6AD8BBE2D8BBAAA9/Users/perovich/Documents/MIT/HTMAA/week8/square.bmp", width=960, height=960) plot(0,0, xlim=c(0, 22), ylim=c(0, 22), type="n", axes=FALSE, asp=1, xlab="", ylab="") polygon(c(0, 22, 22, 0),c(0, 0, 22, 22)) dev.off() #Table legs #Want about 20" of height. Equivalent to ~45 circles per leg. 180 circles total (!!) #There should be enough wood. So assume width of 0.46" #Circle discs will go on a dowel. #Dowel diameter is 7/16th. Make the hole just a smidgen bigger 15/32nd. #Diameters of overall circles from about 2 to 4 inches should give nice range. Make incremental. #Cut on the wood so we have 48" to play with in width, minus some for edge space. Up to 8 ft for y. (96" ->94") #Make sure to space them out some. #All the external circle radiuses Lrad<-seq(2/2, 4/2, .2/2) #Constant internal circle radius Lradint<-(15/32)/2 #Put one circle every 5 inches--should leave enough material space for things to stay in place(?) cstartx<-3 cstarty<-3 cposx<-seq(cstartx, 46-cstartx, 5) cposy<-seq(cstarty, 94-cstarty, 5) #This gives us 9 by 18 or 162 circles. This will have to do (short ~two inches per leg) #Plot away. rcount<-1 bmp("/media/6AD8BBE2D8BBAAA9/Users/perovich/Documents/MIT/HTMAA/week8/circleLegs.bmp", width=960, height=960) plot(0,0, asp=1, xlim=c(0, 94), ylim=c(0, 94), type="n", axes=FALSE, xlab="", ylab="") for (i in 1:length(cposx)){ for (j in 1:length(cposy)){ draw.circle(cposx[i],cposy[j],Lradint,nv=100,border=NULL,col=NA,lty=1,lwd=1) draw.circle(cposx[i],cposy[j],Lrad[rcount %% length(Lrad)+1],nv=100,border=NULL,col=NA,lty=1,lwd=1) #Made sure to mod plus one since we don't have a zero spot in the radius list. rcount<-(rcount+1) } } #Draw lines so I know exactly where to crop the image for scaling purposes. #0 to 96 and 0 to 48 (inches) #Note that things end up a bit off centered since we don't have exactly nice dividing with the circle dimensions. abline(h=0) abline(h=96) abline(v=0) abline(v=48) dev.off()