var calls={ addSupportBox:addSupportBox, addLoadBox:addLoadBox, Export:function() { exportBoundaryConditions(); } } function render() { renderer.render( scene, camera ); } function guiCreate(setup){ var f1 = gui.addFolder('Displacement Animation'); f1.add(setup.animation, 'showDisplacement'); f1.add(setup.animation, 'exaggeration', 0, 1000); f1.add(setup.animation, 'speed', 0, 10); var f2 = gui.addFolder('Stresses Visualization'); f2.add(setup.viz, 'minStress', -1000, 0).listen(); f2.add(setup.viz, 'maxStress', 0, 1000).listen(); f2.add(setup.viz, 'colorMap', {coolwarm:0, YlGnBu:1, winter:2,jet:3}); guiAddSupports(); // gui.add(setup, 'solve'); // for (j in f2.__controllers) f2.__controllers[j].onChange (updateColors.bind(this)); //todo check three // for (j in f1.__controllers) f1.__controllers[j].onChange (renderLast.bind(this)); //todo check three } function guiAddSupports(){ guiSupport = gui.addFolder('Supports'); guiSupport.add(calls, 'addSupportBox'); guiLoad = gui.addFolder('Loads'); guiLoad.add(calls, 'addLoadBox'); gui.add(calls, 'Export'); window.addEventListener( 'keydown', function ( event ) { switch ( event.keyCode ) { // case 81: // Q // control.setSpace( control.space === "local" ? "world" : "local" ); // break; // case 16: // Shift // control.setTranslationSnap( 100 ); // control.setRotationSnap( THREE.MathUtils.degToRad( 15 ) ); // control.setScaleSnap( 0.25 ); // break; case 87: // W for(var i=0;i<supportCount;i++){ supportControls[i].setMode( "translate" ); }; for(var i=0;i<loadCount;i++){ loadControls[i].setMode( "translate" ); }; break; case 69: // E for(var i=0;i<supportCount;i++){ supportControls[i].setMode( "rotate" ); }; for(var i=0;i<loadCount;i++){ loadControls[i].setMode( "rotate" ); }; break; case 82: // R for(var i=0;i<supportCount;i++){ supportControls[i].setMode( "scale" ); }; for(var i=0;i<loadCount;i++){ loadControls[i].setMode( "scale" ); }; break; // case 67: // C // const position = currentCamera.position.clone(); // currentCamera = currentCamera.isPerspectiveCamera ? cameraOrtho : cameraPersp; // currentCamera.position.copy( position ); // orbit.object = currentCamera; // control.camera = currentCamera; // currentCamera.lookAt( orbit.target.x, orbit.target.y, orbit.target.z ); // onWindowResize(); // break; // case 86: // V // const randomFoV = Math.random() + 0.1; // const randomZoom = Math.random() + 0.1; // cameraPersp.fov = randomFoV * 160; // cameraOrtho.bottom = - randomFoV * 500; // cameraOrtho.top = randomFoV * 500; // cameraPersp.zoom = randomZoom * 5; // cameraOrtho.zoom = randomZoom * 5; // onWindowResize(); // break; case 187: case 107: // +, =, num+ for(var i=0;i<supportCount;i++){ supportControls[i].setSize( supportControls[i].size + 0.1 ); }; for(var i=0;i<loadCount;i++){ loadControls[i].setSize( loadControls[i].size + 0.1 ); }; break; case 189: case 109: // -, _, num- for(var i=0;i<supportCount;i++){ supportControls[i].setSize( Math.max( supportControls[i].size - 0.1, 0.1 ) ); }; for(var i=0;i<loadCount;i++){ loadControls[i].setSize( Math.max( loadControls[i].size - 0.1, 0.1 ) ); }; break; // case 88: // X // control.showX = ! control.showX; // break; // case 89: // Y // control.showY = ! control.showY; // break; // case 90: // Z // control.showZ = ! control.showZ; // break; // case 32: // Spacebar // control.enabled = ! control.enabled; // break; } } ); window.addEventListener( 'keyup', function ( event ) { switch ( event.keyCode ) { case 16: // Shift for(var i=0;i<supportCount;i++){ supportControls[i].setTranslationSnap( null ); supportControls[i].setRotationSnap( null ); supportControls[i].setScaleSnap( null ); } for(var i=0;i<loadCount;i++){ loadControls[i].setTranslationSnap( null ); loadControls[i].setRotationSnap( null ); loadControls[i].setScaleSnap( null ); }; break; } } ); } function loadGraph(setup,scale){ setup.viz.colorMaps=[YlGnBu,coolwarm, winter ,jet]; gData = { nodes: setup.nodes.map(node => ({ id: node.id, px:node.position.x*scale, py:node.position.y*scale, pz:node.position.z*scale, dx:node.displacement.x*scale, dy:node.displacement.y*scale, dz:node.displacement.z*scale, restrained1:node.restrained_degrees_of_freedom[0], restrained:node.restrained })), links: setup.edges .filter(edge => edge.id) .map(edge => ({ source: 'n'+edge.source, target: 'n'+edge.target, color:getColor(setup.viz,edge.stress) })) }; // var gData = { // nodes: [], // links:[] // }; Graph = ForceGraph3D({ controlType: 'orbit' }).backgroundColor(color2) (document.getElementById('3d-graph')) .d3Force('center', null) .d3Force('charge', null) .linkWidth(2.0) .linkOpacity(1.0) .enableNodeDrag(false) // .enableNavigationControls(false) // .linkColor(color3) .nodeThreeObject(({ restrained }) => new THREE.Mesh( new THREE.BoxGeometry(scale, scale, scale), new THREE.MeshLambertMaterial({ color: getNodeColor(restrained), transparent: true, opacity: 0.8 }) )) .d3Force('box', () => { gData.nodes.forEach(node => { node.fx=node.px; node.fy=node.py; node.fz=node.pz; }); }) .cooldownTime(Infinity) .graphData(gData); drawGridHelper(scene,scale); // console.log(Graph.controls()); // console.log(Graph.renderer()); return [Graph.scene(),Graph.camera(),Graph.renderer(),Graph.controls()]; } function drawGridHelper(scene,scale){ var helper = new THREE.GridHelper( 100, 100 ); helper.position.y = -5.0*scale; helper.material.opacity = 0.5; helper.material.transparent = true; helper.scale.x=2.0*scale helper.scale.z=2.0*scale scene.add(helper); } function addSupportBox(){ console.log("Added Support!") supports=setup.supports; var support=[ { min:{ x:-scale, y:-scale, z:-scale }, max:{ x:scale, y:scale, z:scale }, id: supportCount, restrained:true }, [true,true,true,true,true,true], ]; supports.push(support); supportBoxes.push(drawBox (support[0].min,support[0].max,color4,scene,scale)); supportControls.push( new THREE.TransformControls( camera, renderer.domElement )); supportControls[supportCount].addEventListener( 'change', render ); supportControls[supportCount].addEventListener( 'dragging-changed', function ( event ) { updateNodeColors(); orbit.enabled = ! event.value; } ); supportControls[supportCount].attach( supportBoxes[supportCount] ); scene.add( supportControls[supportCount] ); guiSupports.push(guiSupport.addFolder('Support'+supportCount)) var val=guiSupports[supportCount].add(setup.supports[supportCount][0], 'restrained'); var minFolder=guiSupports[supportCount].addFolder('min'); minFolder.add(setup.supports[supportCount][0].min,'x',-scale*10,scale*10).listen(); minFolder.add(setup.supports[supportCount][0].min,'y',-scale*10,scale*10).listen(); minFolder.add(setup.supports[supportCount][0].min,'z',-scale*10,scale*10).listen(); var maxFolder=guiSupports[supportCount].addFolder('max'); maxFolder.add(setup.supports[supportCount][0].max,'x',-scale*10,scale*10).listen(); maxFolder.add(setup.supports[supportCount][0].max,'y',-scale*10,scale*10).listen(); maxFolder.add(setup.supports[supportCount][0].max,'z',-scale*10,scale*10).listen(); supportCount++; updateNodeColors(); } function addLoadBox(){ console.log("Added Load!") loads=setup.loads; var load=[ { min:{ x:-scale, y:-scale, z:-scale }, max:{ x:scale, y:scale, z:scale }, id: loadCount, restrained:true }, { x:0, y:-0.1, z:0 }, ]; loads.push(load); loadBoxes.push(drawBox (load[0].min,load[0].max,color7,scene,scale)); loadControls.push( new THREE.TransformControls( camera, renderer.domElement )); loadControls[loadCount].addEventListener( 'change', render ); loadControls[loadCount].addEventListener( 'dragging-changed', function ( event ) { updateNodeColors(); orbit.enabled = ! event.value; } ); loadControls[loadCount].attach( loadBoxes[loadCount] ); scene.add( loadControls[loadCount] ); guiLoads.push(guiLoad.addFolder('Load'+loadCount)) var forceFolder=guiLoads[loadCount].addFolder('force'); forceFolder.add(setup.loads[loadCount][1],'x',-scale*10,scale*10).listen(); forceFolder.add(setup.loads[loadCount][1],'y',-scale*10,scale*10).listen(); forceFolder.add(setup.loads[loadCount][1],'z',-scale*10,scale*10).listen(); var minFolder=guiLoads[loadCount].addFolder('min'); minFolder.add(setup.loads[loadCount][0].min,'x',-scale*10,scale*10).listen(); minFolder.add(setup.loads[loadCount][0].min,'y',-scale*10,scale*10).listen(); minFolder.add(setup.loads[loadCount][0].min,'z',-scale*10,scale*10).listen(); var maxFolder=guiLoads[loadCount].addFolder('max'); maxFolder.add(setup.loads[loadCount][0].max,'x',-scale*10,scale*10).listen(); maxFolder.add(setup.loads[loadCount][0].max,'y',-scale*10,scale*10).listen(); maxFolder.add(setup.loads[loadCount][0].max,'z',-scale*10,scale*10).listen(); loadCount++; updateNodeColors(); } function drawConstraintBoundingBoxes(setup,scene,scale){ //grid helper var helper = new THREE.GridHelper( 100, 100 ); helper.position.y = -5.0*scale; helper.material.opacity = 0.5; helper.material.transparent = true; helper.scale.x=2.0*scale helper.scale.z=2.0*scale scene.add(helper); let supports=setup.supports; let loads=setup.loads; let mat=setup.materials; let disps=setup.fixedDisplacements; if (supports ) { for (var i=0;i< supports.length;i++) { let s=supports[i][0]; drawBox(s.min,s.max,color4,scene,scale); } } if (loads ) { for (var i=0;i< loads.length;i++) { let l=loads[i][0]; drawBox(l.min,l.max,color7,scene,scale); } } if (disps ) { for (var i=0;i< disps.length;i++) { let l=disps[i][0]; drawBox(l.min,l.max,color7,scene,scale); } } if (mat ) { for (var i=0;i< mat.length;i++) { let l=mat[i][0]; // console.log(l) drawBox(l.min,l.max,color5,scene,scale); } } }; function drawBox (min,max,color,scene,scale) { // var box = new THREE.Box3(new THREE.Vector3(min.x*scale,min.y*scale,min.z*scale),new THREE.Vector3(max.x*scale,max.y*scale,max.z*scale)); // var mesh = new THREE.Box3Helper( box, color ); // scene.add( mesh ); var geometry = new THREE.BoxBufferGeometry( max.x*scale-min.x*scale, max.y*scale-min.y*scale, max.z*scale-min.z*scale ); var material = new THREE.MeshLambertMaterial( { wireframe:true, transparent: true,color:color } ); var mesh = new THREE.Mesh( geometry, material ); scene.add( mesh ); return mesh; // todo add name?? };