jsketcher/web/app/3d/main.js
2015-11-25 20:51:33 -08:00

335 lines
9 KiB
JavaScript

TCAD = {};
TCAD.App = function() {
this.id = window.location.hash.substring(1);
if (!this.id) {
this.id = "DEFAULT";
}
this.bus = new TCAD.Bus();
this.viewer = new TCAD.Viewer(this.bus);
this.ui = new TCAD.UI(this);
this.craft = new TCAD.Craft(this);
if (this.id == '$scratch$') {
this.addBox();
} else {
this.load();
}
this._refreshSketches();
this.viewer.render();
var viewer = this.viewer;
var app = this;
function storage_handler(evt) {
// console.log('The modified key was '+evt.key);
// console.log('The original value was '+evt.oldValue);
// console.log('The new value is '+evt.newValue);
// console.log('The URL of the page that made the change was '+evt.url);
// console.log('The window where the change was made was '+evt.source);
var prefix = "TCAD.projects."+app.id+".sketch.";
if (evt.key.indexOf(prefix) < 0) return;
var sketchFaceId = evt.key.substring(prefix.length);
for (var oi = 0; oi < viewer.scene.children.length; ++oi) {
var obj = viewer.scene.children[oi];
if (obj.geometry !== undefined && obj.geometry.polyFaces !== undefined) {
for (var i = 0; i < box.geometry.polyFaces.length; i++) {
var sketchFace = box.geometry.polyFaces[i];
if (sketchFace.id == sketchFaceId) {
var geom = TCAD.workbench.readSketchGeom(JSON.parse(evt.newValue));
sketchFace.syncSketches(geom);
viewer.render();
break;
}
}
}
}
}
this.bus.subscribe("craft", function() {
app._refreshSketches();
});
window.addEventListener('storage', storage_handler, false);
};
TCAD.App.prototype.findAllSolids = function() {
return this.viewer.workGroup.children
.filter(function(obj) {return obj.__tcad_solid !== undefined} )
.map(function(obj) {return obj.__tcad_solid} )
};
TCAD.App.prototype.findFace = function(faceId) {
var solids = this.findAllSolids();
for (var i = 0; i < solids.length; i++) {
var solid = solids[i];
for (var j = 0; j < solid.polyFaces.length; j++) {
var face = solid.polyFaces[j];
if (face.id == faceId) {
return face;
}
}
}
return null;
};
TCAD.App.prototype.findSolid = function(solidId) {
var solids = this.findAllSolids();
for (var i = 0; i < solids.length; i++) {
var solid = solids[i];
if (solid.tCadId == solidId) {
return solid;
}
}
return null;
};
TCAD.App.prototype.indexEntities = function() {
var out = {solids : {}, faces : {}};
var solids = this.findAllSolids();
for (var i = 0; i < solids.length; i++) {
var solid = solids[i];
out.solids[solid.tCadId] = solid;
for (var j = 0; j < solid.polyFaces.length; j++) {
var face = solid.polyFaces[j];
out.faces[face.id] = face;
}
}
return out;
};
TCAD.App.prototype.faceStorageKey = function(polyFaceId) {
return "TCAD.projects."+this.id+".sketch." + polyFaceId;
};
TCAD.App.prototype.projectStorageKey = function(polyFaceId) {
return "TCAD.projects."+this.id;
};
TCAD.App.prototype.sketchFace = function() {
if (this.viewer.selectionMgr.selection.length == 0) {
return;
}
var polyFace = this.viewer.selectionMgr.selection[0];
var faceStorageKey = this.faceStorageKey(polyFace.id);
var savedFace = localStorage.getItem(faceStorageKey);
var data;
if (savedFace == null) {
data = {};
} else {
data = JSON.parse(savedFace);
}
data.boundary = {lines : [], arcs : [], circles : []};
function sameSketchObject(a, b) {
if (a.sketchConnectionObject === undefined || b.sketchConnectionObject === undefined) {
return false;
}
return a.sketchConnectionObject.id === b.sketchConnectionObject.id;
}
var paths = TCAD.craft.reconstructSketchBounds(polyFace.solid.csg, polyFace);
//polyFace.polygon.collectPaths(paths);
var _3dTransformation = new TCAD.Matrix().setBasis(polyFace.basis());
var _2dTr = _3dTransformation.invert();
function addSegment(a, b) {
data.boundary.lines.push({
a : {x : a.x, y: a.y},
b : {x : b.x, y: b.y}
});
}
function addArc(arc) {
if (arc.length < 2) {
return;
}
var a = arc[0], b = arc[arc.length - 1];
if (arc.length == 2) {
addSegment(a, b);
return;
}
var mid = (arc.length / 2) >> 0;
var c = TCAD.math.circleFromPoints(arc[0], arc[mid], arc[arc.length-1]);
if (c == null) {
for (var i = 1; i < arc.length; i++) {
addSegment(arc[i - 1], arc[i]);
}
return;
}
if (!TCAD.geom.isCCW([arc[0], arc[mid], arc[arc.length-1]])) {
var t = a;
a = b;
b = t;
}
data.boundary.arcs.push({
a : {x : a.x, y: a.y},
b : {x : b.x, y: b.y},
c : {x : c.x, y : c.y}
});
}
function addCircle(circle) {
var n = circle.length;
//var c = TCAD.math.circleFromPoints(circle[0], circle[((n / 3) >> 0) % n], circle[((2 * n / 3) >> 0) % n]);
var c = TCAD.math.circleFromPoints(circle[0], circle[1], circle[2]);
if (c === null) return;
var r = TCAD.math.distanceAB(circle[0], c);
data.boundary.circles.push({
c : {x : c.x, y: c.y},
r : r
});
}
function isCircle(path) {
for (var i = 0; i < path.length; i++) {
var p = path[i];
if (p.sketchConnectionObject === undefined
|| p.sketchConnectionObject._class !== 'TCAD.TWO.Circle'
|| p.sketchConnectionObject.id !== path[0].sketchConnectionObject.id) {
return false;
}
}
return true;
}
function trPath (path) {
var out = [];
for (var i = 0; i < path.length; i++) {
out.push(_2dTr.apply(path[i]));
}
return out;
}
for (var i = 0; i < paths.length; i++) {
var path = paths[i].vertices;
if (path.length < 3) continue;
var shift = 0;
if (isCircle(path)) {
addCircle(trPath(path));
continue;
}
TCAD.utils.iteratePath(path, 0, function(a, b, ai, bi) {
shift = bi;
return sameSketchObject(a, b);
});
var currSko = null;
var arc = null;
TCAD.utils.iteratePath(path, shift+1, function(a, b, ai, bi, iterNumber, path) {
var isArc = a.sketchConnectionObject !== undefined &&
(a.sketchConnectionObject._class == 'TCAD.TWO.Arc' || a.sketchConnectionObject._class == 'TCAD.TWO.Circle'); //if circle gets splitted
var a2d = _2dTr.apply(a);
if (isArc) {
if (currSko !== a.sketchConnectionObject.id) {
currSko = a.sketchConnectionObject.id;
if (arc != null) {
arc.push(a2d);
addArc(arc);
}
arc = [];
}
arc.push(a2d);
if (iterNumber === path.length - 1) {
arc.push(_2dTr.apply(b));
addArc(arc);
}
} else {
if (arc != null) {
arc.push(a2d);
addArc(arc);
arc = null;
}
currSko = null;
addSegment(a2d, _2dTr.apply(b));
}
return true;
});
}
localStorage.setItem(faceStorageKey, JSON.stringify(data));
window.open("sketcher.html#" + faceStorageKey.substring(14), "Edit Sketch", "height=900,width=1200");
};
TCAD.App.prototype.extrude = function() {
if (this.viewer.selectionMgr.selection.length == 0) {
return;
}
var polyFace = this.viewer.selectionMgr.selection[0];
var height = prompt("Height", "50");
if (!height) return;
var app = this;
var solids = [polyFace.solid];
this.craft.modify({
type: 'PAD',
solids : solids,
face : polyFace,
height : height
});
};
TCAD.App.prototype.cut = function() {
if (this.viewer.selectionMgr.selection.length == 0) {
return;
}
var polyFace = this.viewer.selectionMgr.selection[0];
var depth = prompt("Depth", "50");
if (!depth) return;
var app = this;
var solids = [polyFace.solid];
this.craft.modify({
type: 'CUT',
solids : solids,
face : polyFace,
depth : depth
});
};
TCAD.App.prototype.addBox = function() {
this.craft.modify({
type: 'BOX',
solids : [],
size : 500
});
};
TCAD.App.prototype.refreshSketches = function() {
this._refreshSketches();
this.viewer.render();
};
TCAD.App.prototype._refreshSketches = function() {
var allSolids = this.findAllSolids();
for (var oi = 0; oi < allSolids.length; ++oi) {
var obj = allSolids[oi];
for (var i = 0; i < obj.polyFaces.length; i++) {
var sketchFace = obj.polyFaces[i];
var faceStorageKey = this.faceStorageKey(sketchFace.id);
var savedFace = localStorage.getItem(faceStorageKey);
if (savedFace != null) {
var geom = TCAD.workbench.readSketchGeom(JSON.parse(savedFace));
sketchFace.syncSketches(geom);
}
}
}
};
TCAD.App.prototype.save = function() {
var data = {};
data.history = this.craft.history;
localStorage.setItem(this.projectStorageKey(), JSON.stringify(data));
};
TCAD.App.prototype.load = function() {
var project = localStorage.getItem(this.projectStorageKey());
if (!!project) {
var data = JSON.parse(project);
if (!!data.history) {
this.craft.loadHistory(data.history);
}
}
};