diff --git a/js/cam/Assembler.js b/js/cam/Assembler.js
index c5b31d3801ab2eed81d74a232a528cbe42369772..6c2bbfd061d51639a243a0e97a6c2997d8027f4a 100644
--- a/js/cam/Assembler.js
+++ b/js/cam/Assembler.js
@@ -10,7 +10,10 @@ Assembler = Backbone.Model.extend({
         exporter: null,
         dataOut: "",
         needsPostProcessing: true,
-        editsMadeToProgram: false//warn the user that they will override changes
+        editsMadeToProgram: false,//warn the user that they will override changes
+
+        rapidHeight: 12,
+        stockHeight: 3,
     },
 
     initialize: function(){
@@ -58,8 +61,26 @@ Assembler = Backbone.Model.extend({
         data += "\n\n";
         data += exporter.addComment("begin program");
         data += "\n";
-        data += exporter.moveZ(3);
-        data += exporter.move3(1, 4, 5);
+
+        var rapidHeight = this.get("rapidHeight");
+        var stockHeight = this.get("stockHeight");
+        data += exporter.moveZ(rapidHeight);
+        dmaGlobals.lattice.rasterCells("XYZ", function(cell, x, y, z){
+            if (!cell) return;
+
+            data += exporter.rapidXY(0, 0);
+            data += exporter.moveZ(stockHeight);
+            data += exporter.moveZ(rapidHeight);
+
+            var cellPosition = cell.getPosition();
+            data += exporter.rapidXY(cellPosition.x, cellPosition.y);
+            data += exporter.moveZ(stockHeight);
+            data += exporter.moveZ(rapidHeight);
+
+            data += "\n";
+        });
+        data += exporter.rapidXY(0, 0);
+
         data += "\n\n";
         data += exporter.addComment("end program");
         data += "\n";
diff --git a/js/cam/GCodeExporter.js b/js/cam/GCodeExporter.js
index d2ef3bd2b6362b70e72bee5cd0ec2227e0c999d9..3ad33a5baf5fdce6ecfbdb8603ef07c5461a6e6a 100644
--- a/js/cam/GCodeExporter.js
+++ b/js/cam/GCodeExporter.js
@@ -38,25 +38,34 @@ GCodeExporter.prototype.addComment = function(comment){
     return "(" + comment + ")" + "\n";
 };
 
-GCodeExporter.prototype.rapid3 = function(x, y, z){
-    return this.move3(x,y,z);
+GCodeExporter.prototype.rapidXYZ = function(x, y, z){
+    return this.moveXYZ(x,y,z);
 };
 
-GCodeExporter.prototype.move3 = function(x, y, z){
+GCodeExporter.prototype.rapidXY = function(x, y){
+    return this.rapidXYZ(x, y, null);
+};
+
+GCodeExporter.prototype.moveXYZ = function(x, y, z){
     if (x !== null) x = "X"+x;
     if (y !== null) y = "Y"+y;
     if (z !== null) z = "Z"+z;
     return this.addLine("G01", [x,y,z]);
 };
 
-GCodeExporter.prototype.goHome = function(){
-    return this.move3(0,0,0);
+GCodeExporter.prototype.moveXY = function(x, y){
+    return this.moveXYZ(x, y, null);
 };
 
 GCodeExporter.prototype.moveZ = function(z){
-    return this.move3(null, null, z);
+    return this.moveXYZ(null, null, z);
 };
 
+GCodeExporter.prototype.goHome = function(){
+    return this.moveXYZ(0,0,dmaGlobals.assembler.get("rapidHeight"));
+};
+
+
 GCodeExporter.prototype.makeFooter = function(){
     var data = "";
     data += this.goHome();
diff --git a/js/cam/ShopbotExporter.js b/js/cam/ShopbotExporter.js
index 9845103a8e12783400735ce453366bfa6333226f..60652cd788d813ee0dbdc5a8d24c28c4eb893b97 100644
--- a/js/cam/ShopbotExporter.js
+++ b/js/cam/ShopbotExporter.js
@@ -31,20 +31,30 @@ ShopbotExporter.prototype.addComment = function(comment){
     return "'" + comment + "\n";
 };
 
-ShopbotExporter.prototype.rapid3 = function(x, y, z){
+ShopbotExporter.prototype.rapidXYZ = function(x, y, z){
     return this.addLine("J3", [x,y,z]);
 };
 
-ShopbotExporter.prototype.move3 = function(x, y, z){
+ShopbotExporter.prototype.rapidXY = function(x, y){
+    return this.addLine("J2", [x,y]);
+};
+
+ShopbotExporter.prototype.moveXYZ = function(x, y, z){
     return this.addLine("M3", [x,y,z]);
 };
 
-ShopbotExporter.prototype.goHome = function(){
-    return this.addLine("JH", [], "go home");
+ShopbotExporter.prototype.moveXY = function(x, y){
+    return this.addLine("M2", [x,y]);
 };
 
 ShopbotExporter.prototype.moveZ = function(z){
-    return this.move3("", "", z);
+    return this.moveXYZ("", "", z);
+};
+
+ShopbotExporter.prototype.goHome = function(){
+    var data = this.moveZ(dmaGlobals.assembler.get("rapidHeight"));
+    data += this.moveXY(0,0);
+    return data;
 };
 
 ShopbotExporter.prototype.makeFooter = function(){
diff --git a/js/models/AppState.js b/js/models/AppState.js
index 846148a84bbbd9e2f5acc631db29a0ab655433b9..182a88882a6046b2b82fd566954109d47b3f0962 100644
--- a/js/models/AppState.js
+++ b/js/models/AppState.js
@@ -94,6 +94,39 @@ AppState = Backbone.Model.extend({
             }
         },
 
+        allMachineTypes:{
+            shopbot: "Shopbot"
+        },
+//        allAssemblyStrategies:{
+//            octa:{
+//                face: {},
+//                freeformFace: {},
+//                edge: {},
+//                edgeRot: {
+//                    xRaster: "X Raster",
+//                    yRaster: "Y Raster"
+//                },
+//                vertex: {
+//                    xRaster: "X Raster",
+//                    yRaster: "Y Raster"
+//                }
+//            },
+//            tetra: {
+//                vertex: {}
+//            },
+//            cube:{
+//                face: {
+//                    xRaster: "X Raster",
+//                    yRaster: "Y Raster"
+//                }
+//            },
+//            truncatedCube:{
+//                face: {}
+//            },
+//            kelvin:{
+//                face: {}
+//            }
+//        },
         allAssemblyStrategies: {
             xRaster: "X Raster",
             yRaster: "Y Raster"
diff --git a/js/models/Lattice.js b/js/models/Lattice.js
index 1cd038171fe499488aaa13a298dc8a072837c9c4..27234a502594d1cf81a27261ca32ece27a80bc13 100644
--- a/js/models/Lattice.js
+++ b/js/models/Lattice.js
@@ -423,6 +423,70 @@ Lattice = Backbone.Model.extend({
         }
     },
 
+    rasterCells: function(order, callback, var1Order, var1Dim, var2Order, var2Dim, var3Order, var3Dim){//used for CAM raster x/y/z in any order permutation
+        //order is of form 'XYZ'
+        var firstLetter = order.charAt(0);
+        var cells = this.get("cells");
+        var newVarOrder;
+        var newVarDim;
+        if (firstLetter == 'X'){
+            newVarOrder = 0;
+            newVarDim = cells.length;
+        } else if (firstLetter == 'Y'){
+            newVarOrder = 1;
+            newVarDim = cells[0].length;
+        } else if (firstLetter == 'Z'){
+            newVarOrder = 2;
+            newVarDim = cells[0][0].length;
+        } else if (firstLetter == ""){
+//            console.log(var1Dim);
+//            console.log(var2Dim);
+//            console.log(var3Dim);
+//            console.log(var1Order);
+//            console.log(var2Order);
+//            console.log(var3Order);
+            for (var i=0;i<var1Dim;i++){
+                for (var j=0;j<var2Dim;j++){
+                    for (var k=0;k<var3Dim;k++){
+                        if (var1Order == 0){
+                            if (var2Order == 1){
+                                callback(cells[i][j][k], i, j, k);
+                            } else if (var2Order == 2){
+                                callback(cells[i][k][j], i, k, j);
+                            }
+                        } else if (var1Order == 1){
+                            if (var2Order == 0){
+                                callback(cells[j][i][k], j, i, k);
+                            } else if (var2Order == 2){
+                                callback(cells[k][i][j], k, i, j);
+                            }
+                        } else {
+                            if (var2Order == 0){
+                                callback(cells[j][k][i], j, k, i);
+                            } else if (var2Order == 1){
+                                callback(cells[k][j][i], k, j, i);
+                            }
+                        }
+
+                    }
+                }
+            }
+            return;
+        }
+        if (var3Order == null) {
+            var3Order = newVarOrder;
+            var3Dim = newVarDim;
+        } else if (var2Order  == null) {
+            var2Order = newVarOrder;
+            var2Dim = newVarDim;
+        } else {
+            var1Order = newVarOrder;
+            var1Dim = newVarDim;
+        }
+        order = order.substr(1);
+        this.rasterCells(order, callback, var1Order, var1Dim, var2Order, var2Dim, var3Order, var3Dim);
+    },
+
     ////////////////////////////////////////////////////////////////////////////////////
     ////////////////////////////////////SAVE////////////////////////////////////////////
     ////////////////////////////////////////////////////////////////////////////////////