-
Amanda Ghassaei authoredAmanda Ghassaei authored
Cam.js 13.85 KiB
/**
* Created by aghassaei on 3/10/15.
*/
define(['underscore', 'three', 'backbone', 'appState', 'latticeCAM', 'threeModel', 'camPlist', 'materials'],
function(_, THREE, Backbone, appState, lattice, three, camPlist, materials){
var Cam = Backbone.Model.extend({
defaults: {
camStrategy: "raster",
placementOrder: "XYZ",//used for raster strategy entry
camProcess: "gcode",
machineName: "stapler",
assembler: null,
exporter: null,
editingComponent: null,
dataOut: "",
needsPostProcessing: true,
editsMadeToProgram: false,//warn the user that they will override changes
rapidHeight: 6,//always store relative to origin
rapidHeightRelative: true,
safeHeight: 0.5,//inches above stock or assembly, when feed rate should slow
origin: null,
originPosition: new THREE.Vector3(20,0,0),//in abs coordinates
stock: null,
stockPosition: new THREE.Vector3(20,0,0),//in abs coordinates
stockPositionRelative: true,
stockFixed: false,//stock is fixed position from origin
multipleStockPositions: false,
stockArraySize: {x:4, y:4},
stockSeparation: 2.78388,
rapidSpeeds:{xy: 3, z: 2},//rapids at clearance height
feedRate:{xy: 0.1, z: 0.1},//speed when heading towards assembly
simLineNumber: 0,//used for stock simulation, reading through gcode
simSpeed: 16,//#X times real speed
allCAMMaterialTypes: []//all types of stock needed
},
initialize: function(){
_.bindAll(this, "postProcess", "_stockSimulation");
//bind events
this.listenTo(appState, "change:currentTab", this._tabChanged);
this.listenTo(appState, "change:currentNav", this._navChanged);
this.listenTo(this, "change:originPosition", this._moveOrigin);
// this.listenTo(this, "change:stockPosition", this._moveStock);
this.listenTo(this,
"change:originPosition " +
"change:stockPosition " +
"change:feedRate " +
"change:rapidSpeeds " +
"change:camProcess " +
"change:camStrategy " +
"change:placementOrder " +
"change:safeHeight " +
"change:stockArraySize " +
"change:stockSeparation " +
"change:multipleStockPositions " +
"change:rapidHeight " +
"change:machineName",
this._setNeedsPostProcessing);
this.listenTo(lattice,//todo this isn't working
"change:scale" +
"change:units" +
"change:numCells " +
"change:cellType " +
"change:connectionType",
this._setNeedsPostProcessing);
this.listenTo(appState, "change:stockSimulationPlaying", this._stockSimulation);
this.listenTo(lattice, "change:partType", this._updatePartType);
this.listenTo(appState, "change:cellMode", this._updateCellMode);
this.listenTo(this, "change:machineName", this.selectMachine);
this.listenTo(this, "change:editingComponent", this._editComponent);
this._navChanged();
// this._initOriginAndStock();
this.selectMachine();
},
_calculateNumMaterials: function(){//todo calc length of gik cells as separate material types
this.set("allCAMMaterialTypes", materials.getChildCellTypes(lattice.sparseCells, true) || []);
},
selectMachine: function(json){
var machineJSON = json;
if (machineJSON === undefined){
var machineName = this.get("machineName");
if (this.get("assembler")){
if (this.get("assembler").getID() == machineName) return;
else {
this.get("assembler").destroy();
this.set("assembler", null);
}
}
machineJSON = camPlist.allMachines[machineName];
} else {
machineName = "customMachine";
this.set("machineName", machineName, {silent:true});
}
if (machineJSON.defaults) this._setMachineDefaults(machineJSON.defaults);
if (machineJSON.lattice) this._setLatticeDefaults(machineJSON.lattice)
var self = this;
require(['assembler'], function(Assembler){
self.set('assembler', new Assembler(machineName, machineJSON));
});
},
_setLatticeDefaults: function(defaults){
_.each(defaults, function(value, key){
lattice.set(key, value);
});
},
_setMachineDefaults: function(defaults){
var self = this;
_.each(defaults, function(value, key){
if (value.x !== undefined && value.x !== null) self.set(key, new THREE.Vector3(value.x, value.y, value.z), {silent:true});
else self.set(key, value, {silent:true});
});
},
makeProgramEdits: function(data){
this.set("dataOut", data, {silent:true});
this.set("editsMadeToProgram", true, {silent: true});
},
//events
_navChanged: function(){
if (appState.get("currentNav") == "navAssemble") {
this._setDefaultMachineForLatticeType();
this._calculateNumMaterials();
}
},
_setDefaultMachineForLatticeType: function(){
//call this each time we switch to assemble tab
var availableMachines = camPlist.machineTypesForLattice[lattice.get("cellType")][lattice.get("connectionType")];
if (availableMachines.indexOf(this.get("machineName")) < 0){
this.set("machineName", availableMachines[0], {silent:true});
}
},
_tabChanged: function(){
this._setCAMVisibility();
var currentTab = appState.get("currentTab");
if (currentTab == "assemblerSetup") this.get("assembler").buildComponentTree();
if (currentTab != "animate") this.resetSimulation();
else this.postProcess();//if (this.get("needsPostProcessing"))
},
_setCAMVisibility: function(){
var visible = this.isVisible();
// this.get("origin").visible = visible;
// this.get("stock").visible = visible;
if (visible && !this.get("assembler")) this.selectMachine();
if (this.get("assembler")) this.get("assembler").setVisibility(visible);
if (appState.get("currentNav") == "navAssemble") {
appState.set("basePlaneIsVisible", !visible);
}
three.render();
},
_updatePartType: function(){
if (this.get("assembler")) this.get("assembler").updatePartType();
},
_updateCellMode: function(){
if (this.get("assembler")) this.get("assembler").updateCellMode();
three.render();
},
_editComponent: function(){
var componentId = this.get("editingComponent");
if (componentId) this.get("assembler").highlight(componentId);
},
//visualization
isVisible: function(){
var currentTab = appState.get("currentTab");
var currentNav = appState.get("currentNav");
return (currentTab == "assemblerSetup" || currentTab == "cam" || currentTab == "animate" || currentNav == "navComm"
|| currentTab == "editComponent");
},
_initOriginAndStock: function(){//todo this is ugly
var origin = new THREE.Mesh(new THREE.SphereGeometry(1),
new THREE.MeshBasicMaterial({color:0xff0000}));
three.sceneAdd(origin);
this.set("origin", origin);
this._moveOrigin();
//init stock mesh
var stock = new THREE.Mesh(new THREE.SphereGeometry(1),
new THREE.MeshBasicMaterial({color:0xff00ff}));
three.sceneAdd(stock);
this.set("stock", stock);
this._moveStock();
this._setCAMVisibility();
},
_moveOrigin: function(){
var position = this.get("originPosition");
// this.get("origin").position.set(position.x, position.y, position.z);
if (this.get("stockFixed")) this._updateStockPosToOrigin(position, this.previous("originPosition"));
three.render();
if (this.get("assembler")) this.get("assembler").moveMachine(position);
},
_updateStockPosToOrigin: function(newOrigin, lastOrigin){
var newStockPosition = _.clone(this.get("stockPosition"));
_.each(_.keys(newStockPosition), function(key){
newStockPosition[key] += newOrigin[key] - lastOrigin[key];
newStockPosition[key] = parseFloat(newStockPosition[key].toFixed(4));
});
this.set("stockPosition", newStockPosition);
},
_moveStock: function(){
var position = this.get("stockPosition");
this.get("stock").position.set(position.x, position.y, position.z);
three.render();
},
//simulation
resetSimulation: function(){
this.set("simLineNumber", 0, {silent:true});
appState.set("stockSimulationPlaying", false);
//todo isStreaming = false;
three.stopAnimationLoop();
lattice.showCells("cells");
},
_stockSimulation: function(){
if (appState.get("stockSimulationPlaying")){
var currentLineNum = this.get("simLineNumber");
var self = this;
this.simulateCurrentLine(function(){
currentLineNum++;
self.set("simLineNumber", currentLineNum);
self._stockSimulation();
});
} else {
three.stopAnimationLoop();
this.get("assembler").pause();
}
},
simulateCurrentLine: function(callback){
var lineNum = this.get("simLineNumber");
three.startAnimationLoop();
if (lineNum == 0) lattice.hideCells("cells");
var allLines = this.get("dataOut").split("\n");
if(lineNum < allLines.length){
var scale = lattice.get("scale");
var scaledSettings = {
scale: scale,
originPosition: this.get("originPosition").clone().divideScalar(scale),
stockPosition: this.get("stockPosition").clone().divideScalar(scale)
};
this.get("exporter").simulate(allLines[lineNum], this.get("assembler"),
scaledSettings, callback);
} else {
//finished simulation
this.resetSimulation();
}
},
setPosition: function(position){
var scale = lattice.get("scale");
var originOffset = this.get("originPosition");
_.each(position, function(val, key){
if (key == "x") position[key] -= originOffset.x;
if (key == "y") position[key] -= originOffset.y;
if (key == "z") position[key] -= originOffset.z;
position[key] = val/scale;
});
this.get("assembler").immediatelyMoveTo(position);
three.render();
},
//post processing
_setNeedsPostProcessing: function(){
this.set("needsPostProcessing", true);
},
postProcess: function(callback){
console.log("process");
this.set("needsPostProcessing", false);
var scale = lattice.get("scale");
var scaledSettings = {
scale: scale,
rapidHeight: this.get("rapidHeight"),
safeHeight: this.get("safeHeight"),
originPosition: this.get("originPosition").clone().multiplyScalar(scale),
stockPosition: this.get("stockPosition").clone().multiplyScalar(scale),
rapidSpeeds: new THREE.Vector3(this.get("rapidSpeeds").xy, this.get("rapidSpeeds").xy, this.get("rapidSpeeds").z),
feedRate: new THREE.Vector3(this.get("feedRate").xy, this.get("feedRate").xy, this.get("feedRate").z),
units: lattice.get("units")
};
var self = this;
this._getExporter(function(exporter){
self.set("dataOut", self.get("assembler").postProcess(scaledSettings, exporter));
self.set("editsMadeToProgram", false);
self.set("exporter", exporter);
if (!appState.get("stockSimulationPlaying")) self.resetSimulation();
if (callback) callback(exporter, self.get("dataOut"));
});
},
_getExporter: function(callback){
// var currentExporter = this.get("exporter");
var camProcess = this.get("camProcess");
require([camProcess], function(ProcessClass){
if (callback) callback(new ProcessClass());
});
},
_getOrder: function(strategy){
if (strategy == "raster") return this.get("placementOrder");
console.warn("strategy not recognized");
return "";
},
save: function(){
// if (this.get("needsPostProcessing")){
this.postProcess(function(exporter, data){
exporter.save(data);
});
// }
}
});
return new Cam();
});