diff --git a/js/lattice/CompositeEditorLattice.js b/js/lattice/CompositeEditorLattice.js index 7e3eeee05cfaf4eeca77a74d3cec75534dfe98fc..1f7112758c19f76cf112559cdfc512df8ca99b8f 100644 --- a/js/lattice/CompositeEditorLattice.js +++ b/js/lattice/CompositeEditorLattice.js @@ -80,6 +80,7 @@ define(['underscore', 'backbone', 'appState', 'lattice', 'globals', 'plist', 'th self.unset(key, {silent:true}); }); this.compositeCells = null; + this.showCells(); }, }; diff --git a/js/lattice/CubeLattice.js b/js/lattice/CubeLattice.js index 2853e6c4e0f1c89f4fa3561b1451f37690044ba8..492fddc8e02bb17b6363ba5e68b4fdb23e237ed3 100644 --- a/js/lattice/CubeLattice.js +++ b/js/lattice/CubeLattice.js @@ -2,8 +2,8 @@ * Created by aghassaei on 5/26/15. */ -define(['underscore', 'backbone', 'appState', 'lattice', 'globals', 'plist', 'three', 'threeModel'], - function(_, Backbone, appState, lattice, globals, plist, THREE, three){ +define(['underscore', 'backbone', 'appState', 'globals', 'plist', 'three', 'threeModel'], + function(_, Backbone, appState, globals, plist, THREE, three){ var CubeLattice = { diff --git a/js/lattice/GIKLattice.js b/js/lattice/GIKLattice.js index c92f0443f79e214706f015e6e56ac4033d831e7e..25e65679fe5af5c72c1612ccb0a419b3da37acad 100644 --- a/js/lattice/GIKLattice.js +++ b/js/lattice/GIKLattice.js @@ -2,8 +2,8 @@ * Created by aghassaei on 5/26/15. */ -define(['underscore', 'backbone', 'appState', 'lattice', 'globals', 'plist', 'three', 'threeModel'], - function(_, Backbone, appState, lattice, globals, plist, THREE, three){ +define(['underscore', 'backbone', 'appState', 'globals', 'plist', 'three', 'threeModel'], + function(_, Backbone, appState, globals, plist, THREE, three){ var GIKLattice = { diff --git a/js/lattice/KelvinLattice.js b/js/lattice/KelvinLattice.js index f84156ff5fd5dcb6fc1c428ec58f3ee6794412d1..231de87ab506a8eef4d944d930de0a0bbea595e8 100644 --- a/js/lattice/KelvinLattice.js +++ b/js/lattice/KelvinLattice.js @@ -3,8 +3,8 @@ */ -define(['underscore', 'backbone', 'appState', 'lattice', 'globals', 'plist', 'three', 'threeModel'], - function(_, Backbone, appState, lattice, globals, plist, THREE, three){ +define(['underscore', 'backbone', 'appState', 'globals', 'plist', 'three', 'threeModel'], + function(_, Backbone, appState, globals, plist, THREE, three){ var KelvinLattice = { diff --git a/js/lattice/Lattice.js b/js/lattice/Lattice.js index 6db3e6a7e5806f6bc18f0c3c939e48b2c3a3d86c..701b7ceb6491bf02a677de4b38463d4a5f6189a9 100644 --- a/js/lattice/Lattice.js +++ b/js/lattice/Lattice.js @@ -3,161 +3,124 @@ */ -define(['underscore', 'backbone', 'appState', 'globals', 'plist', 'three', 'threeModel'], - function(_, Backbone, appState, globals, plist, THREE, three){ +define(['underscore', 'backbone', 'appState', 'globals', 'plist', 'three', 'threeModel', 'latticeBase'], + function(_, Backbone, appState, globals, plist, THREE, three, LatticeBase){ - var Lattice = Backbone.Model.extend({ + var Lattice = LatticeBase.extend({ - defaults: { + defaults: _.extend(LatticeBase.prototype.defaults, { units: "mm", nodes: [], - cellsMin: null,//min position of cells matrix - cellsMax: null,//max position of cells matrix - numCells: 0, - - //spacing for connectors/joints - cellSeparation: {xy:0, z:0}, - - cellType: "cube", - connectionType: "face", - partType: null, - materialType: null, - materialClass: "mechanical" - }, - initialize: function(){ + cellSeparation: {xy:0, z:0},//spacing for connectors/joints + partType: null + }), + - this.cells = [[[null]]];//3D matrix containing all cells and null, dynamic size - this.sparseCells = [[[null]]];//3D matrix containing highest hierarchical level of cells and null - //bind events + __bindEvents: function(){ + this.listenTo(this, "change:partType", this._updatePartType); this.listenTo(this, "change:cellType change:connectionType", function(){ this._updateLatticeType(false); }); this.listenTo(this, "change:cellSeparation", this._updateCellSeparation); - this.listenTo(appState, "change:cellMode", this._updateForMode); - this.listenTo(appState, "change:cellsVisible", this._setCellVisibility); - this.listenTo(this, "change:materialClass", this._loadMaterialClass); this.listenTo(appState, "change:currentNav", this._navChanged); + }, + __initialize: function(){ this._updateLatticeType(false); - - appState.setLattice(this); }, - //add/remove cells - addCellsInRange: function(range){//add a block of cells (extrude) - this.checkForMatrixExpansion(this.sparseCells, range.max, range.min); - var cellsMin = this.get("cellsMin"); - var relativeMin = (new THREE.Vector3()).subVectors(range.min, cellsMin); - var relativeMax = (new THREE.Vector3()).subVectors(range.max, this.get("cellsMin")); - - for (var x=relativeMin.x;x<=relativeMax.x;x++){ - for (var y=relativeMin.y;y<=relativeMax.y;y++){ - for (var z=relativeMin.z;z<=relativeMax.z;z++){ - if (!this.sparseCells[x][y][z]) { - var self = this; - this.makeCellForLatticeType((new THREE.Vector3(x, y, z)).add(cellsMin), function(cell){ - self.sparseCells[x][y][z] = cell; - self.set("numCells", self.get("numCells")+1); - }); - } else console.warn("already a cell there"); - } - } - } - three.render(); - }, + //lattice type - addCellAtIndex: function(indices, noRender, noCheck){//no render no check from fill + _updateLatticeType: function(loadingFromFile){//do not clear cells if loading from file (cells array contains important metadata) - if (!noCheck || noCheck === undefined) this.checkForMatrixExpansion(this.sparseCells, indices, indices); + this._setToDefaultsSilently(); + this._setDefaultCellMode(); + this._loadMaterialClass(); - var index = (new THREE.Vector3()).subVectors(indices, this.get("cellsMin") || indices); - if (!this.sparseCells[index.x][index.y][index.z]) { - var self = this; - if (!noRender || noRender === undefined) three.setRenderFlag(); - this.makeCellForLatticeType(indices, function(cell){ - self.sparseCells[index.x][index.y][index.z] = cell; - self.set("numCells", self.get("numCells")+1); - }); - } else console.warn("already a cell there"); + if (loadingFromFile === undefined) loadingFromFile = false; + if (loadingFromFile) console.warn('loading from file'); + this.clearCells(); - }, + if (this._undo) this._undo(); + if (globals.basePlane) globals.basePlane.destroy(); + if (globals.highlighter) globals.highlighter.destroy(); - _indexForPosition: function(absPosition){ - return new THREE.Vector3( - Math.round(absPosition.x/this.xScale()), - Math.round(absPosition.y/this.yScale()), - Math.round(absPosition.z/this.zScale())); + this._initLatticeSubclass(); }, - _positionForIndex: function(index){ - var position = index.clone(); - position.x = (position.x)*this.xScale(); - position.y = (position.y)*this.yScale(); - position.z = (position.z)*this.zScale(); - return position; + _setToDefaultsSilently: function(){ + var newCellType = this.get("cellType"); + var newConnectionType = this.get("connectionType"); + if (newConnectionType == this.previous("connectionType")){ + newConnectionType = _.keys(plist["allConnectionTypes"][newCellType])[0]; + this.set("connectionType", newConnectionType, {silent:true}); + } + var partType = _.keys(plist["allPartTypes"][newCellType][newConnectionType])[0]; + this.set("partType", partType, {silent:true}); + this.set("materialClass", plist.allMaterialTypes[newCellType][newConnectionType], {silent:true}); }, - // removeCellAtIndex: function(indices){ - // - // var index = this._subtract(indices, this.get("cellsMin")); - // var cells = this.get("cells"); - // if (index.x<cells.length && index.y<cells[0].length && index.z<cells[0][0].length){ - // this.removeCell(cells[index.x][index.y][index.z]); - // } - // }, - - removeCell: function(cell){ - if (!cell) return; - var index = (new THREE.Vector3()).subVectors(cell.index, this.get("cellsMin")); - cell.destroy(); - this.sparseCells[index.x][index.y][index.z] = null; + _setDefaultCellMode: function(){//if no part associated with this lattice type + if (!plist["allPartTypes"][this.get("cellType")][this.get("connectionType")]){ + appState.set("cellMode", "cell"); + } + }, - //todo shrink cells matrix if needed + _updateCellSeparation: function(){ + var cellSep = this.get("cellSeparation"); + globals.basePlane.updateXYSeparation(cellSep.xy); - this.set("numCells", this.get("numCells")-1); + var cellMode = appState.get("cellMode"); + var partType = this.get("partType"); +// this._iterCells(this.cells, function(cell){ +// if (cell) cell.updateForScale(cellMode, partType); +// }); three.render(); }, - clearCells: function(){ - this._loopCells(this.sparseCells, function(cell){//send destroy to top level - if (cell) cell.destroy(); + + + + + + //events + + _loadMaterialClass: function(){ + var materialClass = this.get("materialClass"); + this.set("materialType", _.keys(plist.allMaterials[materialClass])[0], {silent:true});//set to default silently + if (globals.materials[materialClass]) return;//already loaded + require([materialClass + "Materials"], function(MaterialClass){ + globals.materials[materialClass] = MaterialClass; }); - three.removeAllCells();//todo add flag in cell destroy to avoid redundancy here - this.cells = [[[null]]]; - this.sparseCells = [[[null]]]; - this.set("cellsMax", null); - this.set("cellsMin", null); - this.set("nodes", []); - this.set("numCells", 0); - if (globals.basePlane) globals.basePlane.set("zIndex", 0); - three.render(); }, - calculateBoundingBox: function(){ - var scale = this._allAxesScales(); - var min = _.clone(this.get("cellsMin")); - var max = _.clone(this.get("cellsMax")); - _.each(_.keys(scale), function(key){ - min[key] *= scale[key]; - max[key] *= scale[key]; - }); - return {min:min, max:max}; + showCellAtIndex: function(index){ + var latticeIndex = (new THREE.Vector3()).subVectors(index, this.get("cellsMin"));//index is probably a json object from gcode comment + var cell = this.cells[latticeIndex.x][latticeIndex.y][latticeIndex.z]; + if (cell) cell.show(); + else console.warn("placing a cell that does not exist"); }, + _navChanged: function(){ + var currentNav = appState.get("currentNav"); + if (!this.inCompositeMode() && this._undoCompositeEditor) this._undoCompositeEditor(); + }, + + @@ -216,295 +179,29 @@ define(['underscore', 'backbone', 'appState', 'globals', 'plist', 'three', 'thre - - //cells array - - checkForMatrixExpansion: function(cells, indicesMax, indicesMin){ - - if (!cells) { - console.warn("no cells specified in matrix expansion"); - return; - } - - if (!this.get("cellsMax") || !this.get("cellsMin")){ - this.set("cellsMax", indicesMax); - this.set("cellsMin", indicesMin); - this._expandCellsArray(cells, (new THREE.Vector3()).subVectors(indicesMax, indicesMin), false); - return; - } - - var lastMax = this.get("cellsMax"); - var lastMin = this.get("cellsMin"); - var newMax = this._updateCellsMax(indicesMax, lastMax); - var newMin = this._updateCellsMin(indicesMin, lastMin); - if (newMax) { - this._expandCellsArray(cells, (new THREE.Vector3()).subVectors(newMax, lastMax), false); - this.set("cellsMax", newMax); - } - if (newMin) { - this._expandCellsArray(cells, (new THREE.Vector3()).subVectors(lastMin, newMin), true); - this.set("cellsMin", newMin); - } - }, - - _expandCellsArray: function(cells, expansion, fromFront){ - - _.each(_.keys(expansion), function(key){ - if (expansion[key] == 0) return;//no expansion on this axis - - var cellsX = cells.length; - var cellsY = cells[0].length; - var cellsZ = cells[0][0].length; - - if (key=="x"){ - for (var x=0;x<expansion[key];x++){ - var newLayer = []; - for (var y=0;y<cellsY;y++){ - var newCol = []; - for (var z=0;z<cellsZ;z++){ - newCol.push(null); - } - newLayer.push(newCol); - } - if (fromFront) cells.unshift(newLayer); - else cells.push(newLayer); - } - } else if (key=="y"){ - for (var x=0;x<cellsX;x++){ - for (var y=0;y<expansion[key];y++){ - var newCol = []; - for (var z=0;z<cellsZ;z++){ - newCol.push(null); - } - if (fromFront) cells[x].unshift(newCol); - else cells[x].push(newCol); - } - } - } else if (key=="z"){ - for (var x=0;x<cellsX;x++){ - for (var y=0;y<cellsY;y++){ - for (var z=0;z<expansion[key];z++){ - if (fromFront) cells[x][y].unshift(null); - else cells[x][y].push(null); - } - } - } - } - }); - }, - - _updateCellsMin: function(newPosition, currentMin){ - var newMin = new THREE.Vector3(); - var hasChanged = false; - _.each(_.keys(newPosition), function(key){ - if (newPosition[key]<currentMin[key]){ - hasChanged = true; - newMin[key] = newPosition[key]; - } else { - newMin[key] = currentMin[key]; - } - }); - if (hasChanged) return newMin; - return false; - }, - - _updateCellsMax: function(newPosition, currentMax){ - var newMax = new THREE.Vector3(); - var hasChanged = false; - _.each(_.keys(newPosition), function(key){ - if (newPosition[key]>currentMax[key]){ - hasChanged = true; - newMax[key] = newPosition[key]; - } else { - newMax[key] = currentMax[key]; - } - }); - if (hasChanged) return newMax; - return false; - }, - - - - - //composite Cells setToCompositeMode: function(id, data){ var self = this; require(['compositeEditorLattice'], function(CompositeEditorLattice){ + self.hideCells(); _.extend(self, CompositeEditorLattice); self._initCompositeEditor(id, data); appState.set("currentNav", "navComposite"); }); }, - - - - - //events - - _updatePartType: function(){ - this._iterCells(this.sparseCells, function(cell){ - if (cell) cell.destroyParts(); - }); - this._updateForMode(); - }, - - _updateForMode: function(){ - var cellMode = appState.get("cellMode"); - var numCells = this.get("numCells"); - this._iterCells(this.sparseCells, function(cell){ - if (cell) cell.setMode(cellMode, function(){ - if (--numCells <= 0) three.render(); - }); - }); - }, - - _updateCellSeparation: function(){ - var cellSep = this.get("cellSeparation"); - globals.basePlane.updateXYSeparation(cellSep.xy); - - var cellMode = appState.get("cellMode"); - var partType = this.get("partType"); -// this._iterCells(this.cells, function(cell){ -// if (cell) cell.updateForScale(cellMode, partType); -// }); - three.render(); - }, - - _setCellVisibility: function(){ - if (appState.get("cellsVisible")) this.showCells(); - else this.hideCells(); - }, - - //hide/show cells during stock simulation - hideCells: function(){ - this._iterCells(this.cells, function(cell){ - if (cell) cell.hide(); - }); - three.render(); - }, - - showCells: function(){ - var cellMode = appState.get("cellMode"); - this._iterCells(this.cells, function(cell){ - if (cell) cell.show(cellMode) - }); - three.render(); + inCompositeMode: function(){ + return appState.get("currentNav") == "navComposite"; }, - showCellAtIndex: function(index){ - var latticeIndex = (new THREE.Vector3()).subVectors(index, this.get("cellsMin"));//index is probably a json object from gcode comment - var cell = this.cells[latticeIndex.x][latticeIndex.y][latticeIndex.z]; - if (cell) cell.show(); - else console.warn("placing a cell that does not exist"); - }, + clearCompositeCells: function(){ - _loadMaterialClass: function(){ - var materialClass = this.get("materialClass"); - this.set("materialType", _.keys(plist.allMaterials[materialClass])[0], {silent:true});//set to default silently - if (globals.materials[materialClass]) return;//already loaded - require([materialClass + "Materials"], function(MaterialClass){ - globals.materials[materialClass] = MaterialClass; - }); }, - _navChanged: function(){ - var currentNav = appState.get("currentNav"); - if (currentNav != "navComposite" && this._undoCompositeEditor) this._undoCompositeEditor(); - }, - - - - - - //lattice type - - _updateLatticeType: function(loadingFromFile){//do not clear cells if loading from file (cells array contains important metadata) - - this._setToDefaultsSilently(); - this._setDefaultCellMode(); - this._loadMaterialClass(); - - if (loadingFromFile === undefined) loadingFromFile = false; - if (loadingFromFile) console.warn('loading from file'); - this.clearCells(); - if (this._undo) this._undo(); - if (globals.basePlane) globals.basePlane.destroy(); - if (globals.highlighter) globals.highlighter.destroy(); - var subclass = this._getSubclassForLatticeType(); - var self = this; - require([subclass], function(subclassObject){ - - _.extend(self, subclassObject); - self._initLatticeType(); - - //copy over cells to new lattice type - var cells = self.cells; - self._loopCells(cells, function(cell, x, y, z){ - if (!cell) return; - var index = _.clone(cell.index); - if (cell.destroy) cell.destroy(); - self.makeCellForLatticeType(index, function(newCell){ - cells[x][y][z] = newCell; - }); - }); - three.render(); - }); - }, - _getSubclassForLatticeType: function(){ - var cellType = this.get("cellType"); - var connectionType = this.get("connectionType"); - if (cellType == "octa"){ - if (connectionType == "face"){ - return "octaFaceLattice"; - } else if (connectionType == "edge"){ - return "octaEdgeLattice"; - } else if (connectionType == "edgeRot"){ - return "octaRotEdgeLattice"; - } else if (connectionType == "vertex"){ - return "octaVertexLattice"; - } - } else if (cellType == "tetra"){ - if (connectionType == "stacked") return "tetraStackedLattice"; - else if (connectionType == "vertex") return "tetraVertexLattice"; - } else if (cellType == "cube"){ - if (connectionType == "face"){ - return "cubeLattice"; - } else if (connectionType == "gik"){ - return "gikLattice"; - } - } else if (cellType == "truncatedCube"){ - return "truncatedCubeLattice"; - } else if (cellType == "kelvin"){ - return "kelvinLattice"; - } else { - console.warn("unrecognized cell type " + cellType); - } - return null; - }, - - _setToDefaultsSilently: function(){ - var newCellType = this.get("cellType"); - var newConnectionType = this.get("connectionType"); - if (newConnectionType == this.previous("connectionType")){ - newConnectionType = _.keys(plist["allConnectionTypes"][newCellType])[0]; - this.set("connectionType", newConnectionType, {silent:true}); - } - var partType = _.keys(plist["allPartTypes"][newCellType][newConnectionType])[0]; - this.set("partType", partType, {silent:true}); - this.set("materialClass", plist.allMaterialTypes[newCellType][newConnectionType], {silent:true}); - }, - - _setDefaultCellMode: function(){//if no part associated with this lattice type - if (!plist["allPartTypes"][this.get("cellType")][this.get("connectionType")]){ - appState.set("cellMode", "cell"); - } - }, @@ -512,27 +209,6 @@ define(['underscore', 'backbone', 'appState', 'globals', 'plist', 'three', 'thre //utils - _iterCells: function(cells, callback){ - _.each(cells, function(cellLayer){ - _.each(cellLayer, function(cellColumn){ - _.each(cellColumn, function(cell){ - callback(cell, cellColumn, cellLayer); - }); - }); - - }); - }, - - _loopCells: function(cells, callback){ - for (var x=0;x<cells.length;x++){ - for (var y=0;y<cells[0].length;y++){ - for (var z=0;z<cells[0][0].length;z++){ - callback(cells[x][y][z], x, y, z, this); - } - } - } - }, - rasterCells: function(order, callback, var1, var2, var3, cells){//used for CAM raster x/y/z in any order permutation //order is of form 'XYZ' var firstLetter = order.charAt(0); @@ -600,27 +276,13 @@ define(['underscore', 'backbone', 'appState', 'globals', 'plist', 'three', 'thre _getRasterLoopIterator: function(variable){ if (variable.neg) return -1; return 1; - }, - - _allAxesScales: function(){ - var xScale = this.xScale(); - var yScale = this.yScale(); - var zScale = this.zScale(); - return {x:xScale, y:yScale, z:zScale}; - }, - - - - - - //save/load + } + }); - toJSON: function(){//a minimal toJSON for ui stuff - no need to parse all cells - return _.omit(this.attributes, ["cells", "nodes"]);//omit makes a copy - }//todo something weird here - }); - return new Lattice(); + var lattice = new Lattice(); + appState.setLattice(lattice); + return lattice; }); \ No newline at end of file diff --git a/js/lattice/LatticeBase.js b/js/lattice/LatticeBase.js new file mode 100644 index 0000000000000000000000000000000000000000..5c8d7986b5c16ada1a86e640f6ee9637fe592fac --- /dev/null +++ b/js/lattice/LatticeBase.js @@ -0,0 +1,405 @@ +/** + * Created by aghassaei on 6/11/15. + */ + + +/** + * Created by aghassaei on 1/16/15. + */ + + +define(['underscore', 'backbone', 'appState', 'globals', 'plist', 'three', 'threeModel'], + function(_, Backbone, appState, globals, plist, THREE, three){ + + return Backbone.Model.extend({ + + defaults: { + + cellsMin: null,//min position of cells matrix + cellsMax: null,//max position of cells matrix + numCells: 0, + + cellType: "cube", + connectionType: "face", + materialType: null, + materialClass: "mechanical" + }, + + + initialize: function(){ + + this.cells = [[[null]]];//3D matrix containing all cells and null, dynamic size + this.sparseCells = [[[null]]];//3D matrix containing highest hierarchical level of cells and null + + //bind events + + this.listenTo(appState, "change:cellMode", this._updateForMode); + this.listenTo(appState, "change:cellsVisible", this._setCellVisibility); + + if (this.__bindEvents) this.__bindEvents(); + if (this.__initialize) this.__initialize(); + }, + + + _initLatticeSubclass: function(){ + var subclass = this._getSubclassForLatticeType(); + var self = this; + require([subclass], function(subclassObject){ + + _.extend(self, subclassObject); + self._initLatticeType(); + + //copy over cells to new lattice type + var cells = self.cells; + self._loopCells(cells, function(cell, x, y, z){ + if (!cell) return; + var index = _.clone(cell.index); + if (cell.destroy) cell.destroy(); + self.makeCellForLatticeType(index, function(newCell){ + cells[x][y][z] = newCell; + }); + }); + three.render(); + }); + }, + + _getSubclassForLatticeType: function(){ + var cellType = this.get("cellType"); + var connectionType = this.get("connectionType"); + if (cellType == "octa"){ + if (connectionType == "face"){ + return "octaFaceLattice"; + } else if (connectionType == "edge"){ + return "octaEdgeLattice"; + } else if (connectionType == "edgeRot"){ + return "octaRotEdgeLattice"; + } else if (connectionType == "vertex"){ + return "octaVertexLattice"; + } + } else if (cellType == "tetra"){ + if (connectionType == "stacked") return "tetraStackedLattice"; + else if (connectionType == "vertex") return "tetraVertexLattice"; + } else if (cellType == "cube"){ + if (connectionType == "face"){ + return "cubeLattice"; + } else if (connectionType == "gik"){ + return "gikLattice"; + } + } else if (cellType == "truncatedCube"){ + return "truncatedCubeLattice"; + } else if (cellType == "kelvin"){ + return "kelvinLattice"; + } else { + console.warn("unrecognized cell type " + cellType); + } + return null; + }, + + + + + + //add/remove cells + + addCellsInRange: function(range){//add a block of cells (extrude) + this.checkForMatrixExpansion(this.sparseCells, range.max, range.min); + + var cellsMin = this.get("cellsMin"); + var relativeMin = (new THREE.Vector3()).subVectors(range.min, cellsMin); + var relativeMax = (new THREE.Vector3()).subVectors(range.max, this.get("cellsMin")); + + for (var x=relativeMin.x;x<=relativeMax.x;x++){ + for (var y=relativeMin.y;y<=relativeMax.y;y++){ + for (var z=relativeMin.z;z<=relativeMax.z;z++){ + if (!this.sparseCells[x][y][z]) { + var self = this; + this.makeCellForLatticeType((new THREE.Vector3(x, y, z)).add(cellsMin), function(cell){ + self.sparseCells[x][y][z] = cell; + self.set("numCells", self.get("numCells")+1); + }); + } else console.warn("already a cell there"); + } + } + } + three.render(); + }, + + addCellAtIndex: function(indices, noRender, noCheck){//no render no check from fill + + if (!noCheck || noCheck === undefined) this.checkForMatrixExpansion(this.sparseCells, indices, indices); + + var index = (new THREE.Vector3()).subVectors(indices, this.get("cellsMin") || indices); + if (!this.sparseCells[index.x][index.y][index.z]) { + var self = this; + if (!noRender || noRender === undefined) three.setRenderFlag(); + this.makeCellForLatticeType(indices, function(cell){ + self.sparseCells[index.x][index.y][index.z] = cell; + self.set("numCells", self.get("numCells")+1); + }); + } else console.warn("already a cell there"); + + }, + + _indexForPosition: function(absPosition){ + return new THREE.Vector3( + Math.round(absPosition.x/this.xScale()), + Math.round(absPosition.y/this.yScale()), + Math.round(absPosition.z/this.zScale())); + }, + + _positionForIndex: function(index){ + var position = index.clone(); + position.x = (position.x)*this.xScale(); + position.y = (position.y)*this.yScale(); + position.z = (position.z)*this.zScale(); + return position; + }, + + // removeCellAtIndex: function(indices){ + // + // var index = this._subtract(indices, this.get("cellsMin")); + // var cells = this.get("cells"); + // if (index.x<cells.length && index.y<cells[0].length && index.z<cells[0][0].length){ + // this.removeCell(cells[index.x][index.y][index.z]); + // } + // }, + + removeCell: function(cell){ + if (!cell) return; + var index = (new THREE.Vector3()).subVectors(cell.index, this.get("cellsMin")); + cell.destroy(); + this.sparseCells[index.x][index.y][index.z] = null; + + //todo shrink cells matrix if needed + + this.set("numCells", this.get("numCells")-1); + three.render(); + }, + + clearCells: function(){ + this._loopCells(this.sparseCells, function(cell){//send destroy to top level + if (cell) cell.destroy(); + }); + three.removeAllCells();//todo add flag in cell destroy to avoid redundancy here + this.cells = [[[null]]]; + this.sparseCells = [[[null]]]; + this.set("cellsMax", null); + this.set("cellsMin", null); + this.set("nodes", []); + this.set("numCells", 0); + if (globals.basePlane) globals.basePlane.set("zIndex", 0); + three.render(); + }, + + calculateBoundingBox: function(){ + var scale = this._allAxesScales(); + var min = _.clone(this.get("cellsMin")); + var max = _.clone(this.get("cellsMax")); + _.each(_.keys(scale), function(key){ + min[key] *= scale[key]; + max[key] *= scale[key]; + }); + return {min:min, max:max}; + }, + + + + + + + + + //cells array + + checkForMatrixExpansion: function(cells, indicesMax, indicesMin){ + + if (!cells) { + console.warn("no cells specified in matrix expansion"); + return; + } + + if (!this.get("cellsMax") || !this.get("cellsMin")){ + this.set("cellsMax", indicesMax); + this.set("cellsMin", indicesMin); + this._expandCellsArray(cells, (new THREE.Vector3()).subVectors(indicesMax, indicesMin), false); + return; + } + + var lastMax = this.get("cellsMax"); + var lastMin = this.get("cellsMin"); + var newMax = this._updateCellsMax(indicesMax, lastMax); + var newMin = this._updateCellsMin(indicesMin, lastMin); + if (newMax) { + this._expandCellsArray(cells, (new THREE.Vector3()).subVectors(newMax, lastMax), false); + this.set("cellsMax", newMax); + } + if (newMin) { + this._expandCellsArray(cells, (new THREE.Vector3()).subVectors(lastMin, newMin), true); + this.set("cellsMin", newMin); + } + }, + + _expandCellsArray: function(cells, expansion, fromFront){ + + _.each(_.keys(expansion), function(key){ + if (expansion[key] == 0) return;//no expansion on this axis + + var cellsX = cells.length; + var cellsY = cells[0].length; + var cellsZ = cells[0][0].length; + + if (key=="x"){ + for (var x=0;x<expansion[key];x++){ + var newLayer = []; + for (var y=0;y<cellsY;y++){ + var newCol = []; + for (var z=0;z<cellsZ;z++){ + newCol.push(null); + } + newLayer.push(newCol); + } + if (fromFront) cells.unshift(newLayer); + else cells.push(newLayer); + } + } else if (key=="y"){ + for (var x=0;x<cellsX;x++){ + for (var y=0;y<expansion[key];y++){ + var newCol = []; + for (var z=0;z<cellsZ;z++){ + newCol.push(null); + } + if (fromFront) cells[x].unshift(newCol); + else cells[x].push(newCol); + } + } + } else if (key=="z"){ + for (var x=0;x<cellsX;x++){ + for (var y=0;y<cellsY;y++){ + for (var z=0;z<expansion[key];z++){ + if (fromFront) cells[x][y].unshift(null); + else cells[x][y].push(null); + } + } + } + } + }); + }, + + _updateCellsMin: function(newPosition, currentMin){ + var newMin = new THREE.Vector3(); + var hasChanged = false; + _.each(_.keys(newPosition), function(key){ + if (newPosition[key]<currentMin[key]){ + hasChanged = true; + newMin[key] = newPosition[key]; + } else { + newMin[key] = currentMin[key]; + } + }); + if (hasChanged) return newMin; + return false; + }, + + _updateCellsMax: function(newPosition, currentMax){ + var newMax = new THREE.Vector3(); + var hasChanged = false; + _.each(_.keys(newPosition), function(key){ + if (newPosition[key]>currentMax[key]){ + hasChanged = true; + newMax[key] = newPosition[key]; + } else { + newMax[key] = currentMax[key]; + } + }); + if (hasChanged) return newMax; + return false; + }, + + + + //events + + _updatePartType: function(){ + this._iterCells(this.sparseCells, function(cell){ + if (cell) cell.destroyParts(); + }); + this._updateForMode(); + }, + + _updateForMode: function(){ + var cellMode = appState.get("cellMode"); + var numCells = this.get("numCells"); + this._iterCells(this.sparseCells, function(cell){ + if (cell) cell.setMode(cellMode, function(){ + if (--numCells <= 0) three.render(); + }); + }); + }, + + _setCellVisibility: function(){ + if (appState.get("cellsVisible")) this.showCells(); + else this.hideCells(); + }, + + hideCells: function(){ + this._iterCells(this.sparseCells, function(cell){ + if (cell) cell.hide(); + }); + three.render(); + }, + + showCells: function(){ + var cellMode = appState.get("cellMode"); + this._iterCells(this.sparseCells, function(cell){ + if (cell) cell.show(cellMode) + }); + three.render(); + }, + + + + + + + //utils + + _iterCells: function(cells, callback){ + _.each(cells, function(cellLayer){ + _.each(cellLayer, function(cellColumn){ + _.each(cellColumn, function(cell){ + callback(cell, cellColumn, cellLayer); + }); + }); + + }); + }, + + _loopCells: function(cells, callback){ + for (var x=0;x<cells.length;x++){ + for (var y=0;y<cells[0].length;y++){ + for (var z=0;z<cells[0][0].length;z++){ + callback(cells[x][y][z], x, y, z, this); + } + } + } + }, + + _allAxesScales: function(){ + var xScale = this.xScale(); + var yScale = this.yScale(); + var zScale = this.zScale(); + return {x:xScale, y:yScale, z:zScale}; + }, + + + + + + //save/load + + toJSON: function(){//a minimal toJSON for ui stuff - no need to parse all cells + return _.omit(this.attributes, ["cells", "nodes"]);//omit makes a copy + }//todo something weird here + + }); +}); \ No newline at end of file diff --git a/js/lattice/OctaEdgeLattice.js b/js/lattice/OctaEdgeLattice.js index 1c80e60e33a7d5feffe507b0545ccff636afee19..6d95089e8caf3cd98d817828a743d0e19fcad53f 100644 --- a/js/lattice/OctaEdgeLattice.js +++ b/js/lattice/OctaEdgeLattice.js @@ -2,8 +2,8 @@ * Created by aghassaei on 5/26/15. */ -define(['underscore', 'backbone', 'appState', 'lattice', 'globals', 'plist', 'three', 'threeModel'], - function(_, Backbone, appState, lattice, globals, plist, THREE, three){ +define(['underscore', 'backbone', 'appState', 'globals', 'plist', 'three', 'threeModel'], + function(_, Backbone, appState, globals, plist, THREE, three){ var OctaEdgeLattice = { diff --git a/js/lattice/OctaFaceLattice.js b/js/lattice/OctaFaceLattice.js index 5cc6b5d56ff2ea1d5784fc9b06c9a48546a01e8d..e4b4250fb270fd63adfa1c2df481b98cf9e05d82 100644 --- a/js/lattice/OctaFaceLattice.js +++ b/js/lattice/OctaFaceLattice.js @@ -2,8 +2,8 @@ * Created by aghassaei on 5/26/15. */ -define(['underscore', 'backbone', 'appState', 'lattice', 'globals', 'plist', 'three', 'threeModel'], - function(_, Backbone, appState, lattice, globals, plist, THREE, three){ +define(['underscore', 'backbone', 'appState', 'globals', 'plist', 'three', 'threeModel'], + function(_, Backbone, appState, globals, plist, THREE, three){ var OctaFaceLattice = { diff --git a/js/lattice/OctaRotEdgeLattice.js b/js/lattice/OctaRotEdgeLattice.js index 6f94d781b265f973a105942270ade7c5069735c2..b189274e507f876606459e497b3b1e1d15920e9c 100644 --- a/js/lattice/OctaRotEdgeLattice.js +++ b/js/lattice/OctaRotEdgeLattice.js @@ -2,8 +2,8 @@ * Created by aghassaei on 5/26/15. */ -define(['underscore', 'backbone', 'appState', 'lattice', 'globals', 'plist', 'three', 'threeModel'], - function(_, Backbone, appState, lattice, globals, plist, THREE, three){ +define(['underscore', 'backbone', 'appState', 'globals', 'plist', 'three', 'threeModel'], + function(_, Backbone, appState, globals, plist, THREE, three){ var OctaRotEdgeLattice = { diff --git a/js/lattice/OctaVertexLattice.js b/js/lattice/OctaVertexLattice.js index 7173dece647f911852b0e121d11bf85457db1c50..0e2af7538c08fc9c404da51c47c8a7db0fb902a4 100644 --- a/js/lattice/OctaVertexLattice.js +++ b/js/lattice/OctaVertexLattice.js @@ -2,8 +2,8 @@ * Created by aghassaei on 5/26/15. */ -define(['underscore', 'backbone', 'appState', 'lattice', 'globals', 'plist', 'three', 'threeModel'], - function(_, Backbone, appState, lattice, globals, plist, THREE, three){ +define(['underscore', 'backbone', 'appState', 'globals', 'plist', 'three', 'threeModel'], + function(_, Backbone, appState, globals, plist, THREE, three){ var OctaVertexLattice = { diff --git a/js/lattice/TetraStackedLattice.js b/js/lattice/TetraStackedLattice.js index 9cdbc6d00dd408f2106ecc9582884ffdd82d5041..5be5601b4b2d3f0fe624dd971a356174e2c6c194 100644 --- a/js/lattice/TetraStackedLattice.js +++ b/js/lattice/TetraStackedLattice.js @@ -2,8 +2,8 @@ * Created by aghassaei on 6/4/15. */ -define(['underscore', 'backbone', 'appState', 'lattice', 'globals', 'plist', 'three', 'threeModel'], - function(_, Backbone, appState, lattice, globals, plist, THREE, three){ +define(['underscore', 'backbone', 'appState', 'globals', 'plist', 'three', 'threeModel'], + function(_, Backbone, appState, globals, plist, THREE, three){ var TetraStackedLattice = { diff --git a/js/lattice/TetraVertexLattice.js b/js/lattice/TetraVertexLattice.js index 09537f95e54fb6db43871e22b8d08a22230ab95c..47dd4fd0374bed389dc5c61710bc95364d766ead 100644 --- a/js/lattice/TetraVertexLattice.js +++ b/js/lattice/TetraVertexLattice.js @@ -2,8 +2,8 @@ * Created by aghassaei on 6/4/15. */ -define(['underscore', 'backbone', 'appState', 'lattice', 'globals', 'plist', 'three', 'threeModel'], - function(_, Backbone, appState, lattice, globals, plist, THREE, three){ +define(['underscore', 'backbone', 'appState', 'globals', 'plist', 'three', 'threeModel'], + function(_, Backbone, appState, globals, plist, THREE, three){ var TetraVertexLattice = { diff --git a/js/lattice/TruncatedCubeLattice.js b/js/lattice/TruncatedCubeLattice.js index 2c8eaf4dae8867dd06774ea1071e39f8496d62eb..8df8ebabf1a91a03dd8981676d5bce35bff18aa5 100644 --- a/js/lattice/TruncatedCubeLattice.js +++ b/js/lattice/TruncatedCubeLattice.js @@ -3,8 +3,8 @@ */ -define(['underscore', 'backbone', 'appState', 'lattice', 'globals', 'plist', 'three', 'threeModel'], - function(_, Backbone, appState, lattice, globals, plist, THREE, three){ +define(['underscore', 'backbone', 'appState', 'globals', 'plist', 'three', 'threeModel'], + function(_, Backbone, appState, globals, plist, THREE, three){ var TruncatedCubeLattice = { diff --git a/js/main.js b/js/main.js index d930f73df6405fd0d92be6df438a90e51164592c..f26f8c4b0bb3adc275d41327a6e95368d22fc2cd 100644 --- a/js/main.js +++ b/js/main.js @@ -27,6 +27,7 @@ require.config({ fileSaver: 'models/FileSaver', //lattice + latticeBase: 'lattice/LatticeBase', lattice: 'lattice/Lattice', cubeLattice: 'lattice/CubeLattice', gikLattice: 'lattice/GIKLattice',