// Amira Abdel-Rahman // (c) Massachusetts Institute of Technology 2019 ////////////utils///////////////////// function map (value, x1, y1, x2, y2) { return (value - x1) * (y2 - x2) / (y1 - x1) + x2; } function enforceBounds(x) { if (x < 0) { return 0; } else if (x > 1){ return 1; } else { return x; } } function interpolateLinearly(x, values) { // Split values into four lists var x_values = []; var r_values = []; var g_values = []; var b_values = []; for (i in values) { x_values.push(values[i][0]); r_values.push(values[i][1][0]); g_values.push(values[i][1][1]); b_values.push(values[i][1][2]); } var i = 1; while (x_values[i] < x) { i = i+1; } i = i-1; var width = Math.abs(x_values[i] - x_values[i+1]); var scaling_factor = (x - x_values[i]) / width; // Get the new color values though interpolation var r = r_values[i] + scaling_factor * (r_values[i+1] - r_values[i]) var g = g_values[i] + scaling_factor * (g_values[i+1] - g_values[i]) var b = b_values[i] + scaling_factor * (b_values[i+1] - b_values[i]) return [enforceBounds(r), enforceBounds(g), enforceBounds(b)]; } function getColor(viz,stress){ var val=map(stress,viz.minStress,viz.maxStress,1.0,0.0); color=interpolateLinearly(val, viz.colorMaps[viz.colorMap]); return new THREE.Color(color[0],color[1],color[2]).getHex(); } function getColorRGB(viz,stress){ var val=map(stress,viz.minStress,viz.maxStress,1.0,0.0); color=interpolateLinearly(val, viz.colorMaps[viz.colorMap]); return new THREE.Color(color[0],color[1],color[2]); } function toThreeVec(point){ return new THREE.Vector3(point.x,point.y,point.z); } function toPosition(array){ return { x:array[0] ,y:array[1],z:array[2]}; } function toTf3D(point){ return tf.tensor([point.x,point.y,point.z]); } function toPos(point){ return { x:point.x ,y:point.y,z:point.z}; } function tf_delete(tensor,remove_indices,axis){ var unstacked=tf.unstack(tensor,axis); var newTensor=[]; for(var i=0;i<unstacked.length;i++){ if(!remove_indices.includes(i)){ newTensor.push(unstacked[i]); } } return tf.stack(newTensor,axis); } function add(p1,p2){ return {x:p1.x+p2.x,y:p1.y+p2.y,z:p1.z+p2.z}; } //////////nodes/////////////// function nodeAt(setup,pos){ var tolerance=1e-6; return setup.nodes.find(node => (node.position.x>pos.x-tolerance && node.position.x<pos.x+tolerance) && (node.position.y>pos.y-tolerance && node.position.y<pos.y+tolerance) && (node.position.z>pos.z-tolerance && node.position.z<pos.z+tolerance) ); return setup.nodes.find(node => (node.position.x==pos.x) && (node.position.y== pos.y) && (node.position.z== pos.z) ); return setup.nodes.filter(node => node.position.x==pos.x && node.position.y== pos.y && node.position.z== pos.z); } function getNodebyName(setup,name){ return setup.nodes.find(node => node.name===name); } function edgeNeeded(setup,source,target){ var e=setup.edges.find(edge => (edge.source===source && edge.target===target) || (edge.source===target && edge.target===source)); var b=(typeof e === 'undefined'); return b; } ////////////// function updateDisplacement(X){ var count=0; for(var i=0;i<setup.nodes.length;i++){ if(!setup.nodes[i].restrained_degrees_of_freedom[0]){ setup.nodes[i].displacement.x =X[count++]; } if(!setup.nodes[i].restrained_degrees_of_freedom[1]){ setup.nodes[i].displacement.y =X[count++]; } if(!setup.nodes[i].restrained_degrees_of_freedom[2]){ setup.nodes[i].displacement.z =X[count++]; } if(!setup.bar){ if(!setup.nodes[i].restrained_degrees_of_freedom[3]){ setup.nodes[i].angle.x =X[count++]; } if(!setup.nodes[i].restrained_degrees_of_freedom[4]){ setup.nodes[i].angle.y =X[count++]; } if(!setup.nodes[i].restrained_degrees_of_freedom[5]){ setup.nodes[i].angle.z =X[count++]; } } } } function updateStresses(S){ setup.viz.minStress=Math.min(...S)*1.1; setup.viz.maxStress=Math.max(...S)*1.1; var count=0; for(var ii=0;ii<setup.edges.length;ii++){ var element=setup.edges[ii]; element.stress=S[ii]; } if(!node){ three.colorEdges(); //todo check!! } } //////////inverse/////////////// // Lower Upper Solver function lusolve(A, b, update) { var lu = ludcmp(A, update) if (lu === undefined){ console.log("Singular Matrix!") return // Singular Matrix! } return lubksb(lu, b, update) } // Lower Upper Decomposition function ludcmp(A, update) { // A is a matrix that we want to decompose into Lower and Upper matrices. var d = true; var n = A.length; // var n= A.shape[0]; var idx = new Array(n) // Output vector with row permutations from partial pivoting var vv = new Array(n) // Scaling information for (var i=0; i<n; i++) { var max = 0 for (var j=0; j<n; j++) { var temp = Math.abs(A[i][j]) if (temp > max) max = temp } if (max == 0) return // Singular Matrix! vv[i] = 1 / max // Scaling } if (!update) { // make a copy of A var Acpy = new Array(n) for (var i=0; i<n; i++) { var Ai = A[i] Acpyi = new Array(Ai.length) for (j=0; j<Ai.length; j+=1) Acpyi[j] = Ai[j] Acpy[i] = Acpyi } A = Acpy } var tiny = 1e-20 // in case pivot element is zero for (var i=0; ; i++) { for (var j=0; j<i; j++) { var sum = A[j][i] for (var k=0; k<j; k++) sum -= A[j][k] * A[k][i]; A[j][i] = sum } var jmax = 0 var max = 0; for (var j=i; j<n; j++) { var sum = A[j][i] for (var k=0; k<i; k++) sum -= A[j][k] * A[k][i]; A[j][i] = sum var temp = vv[j] * Math.abs(sum) if (temp >= max) { max = temp jmax = j } } if (i <= jmax) { for (var j=0; j<n; j++) { var temp = A[jmax][j] A[jmax][j] = A[i][j] A[i][j] = temp } d = !d; vv[jmax] = vv[i] } idx[i] = jmax; if (i == n-1) break; var temp = A[i][i] if (temp == 0) A[i][i] = temp = tiny temp = 1 / temp for (var j=i+1; j<n; j++) A[j][i] *= temp } return {A:A, idx:idx, d:d} } // Lower Upper Back Substitution function lubksb(lu, b, update) { // solves the set of n linear equations A*x = b. // lu is the object containing A, idx and d as determined by the routine ludcmp. var A = lu.A var idx = lu.idx var n = idx.length if (!update) { // make a copy of b var bcpy = new Array(n) for (var i=0; i<b.length; i+=1) bcpy[i] = b[i] b = bcpy } for (var ii=-1, i=0; i<n; i++) { var ix = idx[i] var sum = b[ix] b[ix] = b[i] if (ii > -1) for (var j=ii; j<i; j++) sum -= A[i][j] * b[j] else if (sum) ii = i b[i] = sum } for (var i=n-1; i>=0; i--) { var sum = b[i] for (var j=i+1; j<n; j++) sum -= A[i][j] * b[j] b[i] = sum / A[i][i] } return b // solution vector x } ///save json function saveJSON(data, filename){ if(!data) { console.error('No data') return; } if(!filename) filename = 'console.json' if(typeof data === "object"){ data = JSON.stringify(data, undefined, 4) } var blob = new Blob([data], {type: 'text/json'}), e = document.createEvent('MouseEvents'), a = document.createElement('a') a.download = filename a.href = window.URL.createObjectURL(blob) a.dataset.downloadurl = ['text/json', a.download, a.href].join(':') e.initMouseEvent('click', true, false, window, 0, 0, 0, 0, 0, false, false, false, false, 0, null) a.dispatchEvent(e) }