<!DOCTYPE html>
<html lang="en">
	<head>
		<title>MetaVoxel</title>
		<meta charset="utf-8">
		<meta name="viewport" content="width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0">
		<!-- <link type="text/css" rel="stylesheet" href="main.css"> -->
		<style>
			body {
				background-color: #f0f0f0;
				color: #444;
			}
			a {
				color: #08f;
			}
		</style>
	</head>
	<body>
		<div id="container"></div>
		<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js"></script>

		<script type="text/javascript" src="https://files.mcneel.com/rhino3dm/js/latest/rhino3dm.js"></script>
		
		<script src="https://cdn.jsdelivr.net/npm/@tensorflow/tfjs@1.0.0/dist/tf.min.js"></script>

		<!-- <script src="./lib/require.js"></script> -->

		<script src="../lib/three.min.js"></script>

        <script src="../lib/stats.js"></script>
        <script src="../lib/dat.gui.js"></script>

		<script src="../lib/SVGRenderer.js"></script>
		

        <script src="../lib/DragControls.js"></script>
        <script src="../lib/OrbitControls.js"></script>
		<script src="../lib/TransformControls.js"></script>
		
		<script src="../lib/js-colormaps.js"></script>
		<script src="../lib/LineSegments2.js"></script>
		<script src="../lib/LineSegmentsGeometry.js"></script>
		<script src="../lib/Line2.js"></script>
		<script src="../lib/LineMaterial.js"></script>
		<script src="../lib/LineGeometry.js"></script>
		<script src="../lib/GeometryUtils.js"></script>

		<script src="../visualization/utils.js"></script> 

		<!-- <script src="./beamFea.js"></script> 
		<script src="./geometry.js"></script>  -->
		<script src="../fea/parallelFea.js"></script> 
		<script src="../visualization/main.js"></script> 

		<script>
			$.getJSON("../json/setup1.json", function(json) {
				setup=json.setup;
				console.log(json)

				setup.viz.colorMaps=[YlGnBu,coolwarm, winter ,jet];
				// setup.viz.minStress=10e6;
				// setup.viz.maxStress=-10e6;

				setup.animation.exaggeration=75444;

				// setup.viz.colorMaps=[coolwarm,YlGnBu, winter ,jet];

				three= new threejs(setup,"container","");
			
				three.init();
				// three.drawStructure();
				// three.colorEdges();
				// three.animate();
				function composeMatrix(  quaternion ) {

					var te = [

					1, 0, 0, 0,
					0, 1, 0, 0,
					0, 0, 1, 0,
					0, 0, 0, 1

					];
					var scale=new THREE.Vector3(1,1,1);
					var position=new THREE.Vector3(0,0,0);

					var x = quaternion.x, y = quaternion.y, z = quaternion.z, w = quaternion.w;
					var x2 = x + x,	y2 = y + y, z2 = z + z;
					var xx = x * x2, xy = x * y2, xz = x * z2;
					var yy = y * y2, yz = y * z2, zz = z * z2;
					var wx = w * x2, wy = w * y2, wz = w * z2;

					var sx = scale.x, sy = scale.y, sz = scale.z;

					te[ 0 ] = ( 1 - ( yy + zz ) ) * sx;
					te[ 1 ] = ( xy + wz ) * sx;
					te[ 2 ] = ( xz - wy ) * sx;
					te[ 3 ] = 0;

					te[ 4 ] = ( xy - wz ) * sy;
					te[ 5 ] = ( 1 - ( xx + zz ) ) * sy;
					te[ 6 ] = ( yz + wx ) * sy;
					te[ 7 ] = 0;

					te[ 8 ] = ( xz + wy ) * sz;
					te[ 9 ] = ( yz - wx ) * sz;
					te[ 10 ] = ( 1 - ( xx + yy ) ) * sz;
					te[ 11 ] = 0;

					te[ 12 ] = position.x;
					te[ 13 ] = position.y;
					te[ 14 ] = position.z;
					te[ 15 ] = 1;

					return te;

				}

				function clamp( value, min, max ) {

					return Math.max( min, Math.min( max, value ) );

				}

				function setFromRotationMatrix ( te ) {

					var order='XYZ';
					// assumes the upper 3x3 of m is a pure rotation matrix (i.e, unscaled)

					var m11 = te[ 0 ], m12 = te[ 4 ], m13 = te[ 8 ];
					var m21 = te[ 1 ], m22 = te[ 5 ], m23 = te[ 9 ];
					var m31 = te[ 2 ], m32 = te[ 6 ], m33 = te[ 10 ];

					var eul=new THREE.Vector3(0,0,0);

					if ( order === 'XYZ' ) {

						eul.y = Math.asin( clamp( m13, - 1, 1 ) );

						if ( Math.abs( m13 ) < 0.9999999 ) {
							

							eul.x = Math.atan2( - m23, m33 );
							eul.z = Math.atan2( - m12, m11 );

						} else {

							eul.x = Math.atan2( m32, m22 );
							eul.z = 0;

						}

					} else if ( order === 'YXZ' ) {

						eul.x = Math.asin( - clamp( m23, - 1, 1 ) );

						if ( Math.abs( m23 ) < 0.9999999 ) {

							eul.y = Math.atan2( m13, m33 );
							eul.z = Math.atan2( m21, m22 );

						} else {

							eul.y = Math.atan2( - m31, m11 );
							eul.z = 0;

						}

					} else if ( order === 'ZXY' ) {

						eul.x = Math.asin( clamp( m32, - 1, 1 ) );

						if ( Math.abs( m32 ) < 0.9999999 ) {

							eul.y = Math.atan2( - m31, m33 );
							eul.z = Math.atan2( - m12, m22 );

						} else {

							eul.y = 0;
							eul.z = Math.atan2( m21, m11 );

						}

					} else if ( order === 'ZYX' ) {

						eul.y = Math.asin( - clamp( m31, - 1, 1 ) );

						if ( Math.abs( m31 ) < 0.9999999 ) {

							eul.x = Math.atan2( m32, m33 );
							eul.z = Math.atan2( m21, m11 );

						} else {

							eul.x = 0;
							eul.z = Math.atan2( - m12, m22 );

						}

					} else if ( order === 'YZX' ) {

						eul.z = Math.asin( clamp( m21, - 1, 1 ) );

						if ( Math.abs( m21 ) < 0.9999999 ) {

							eul.x = Math.atan2( - m23, m22 );
							eul.y = Math.atan2( - m31, m11 );

						} else {

							eul.x = 0;
							eul.y = Math.atan2( m13, m33 );

						}

					} else if ( order === 'XZY' ) {

						eul.z = Math.asin( - clamp( m12, - 1, 1 ) );

						if ( Math.abs( m12 ) < 0.9999999 ) {

							eul.x = Math.atan2( m32, m22 );
							eul.y = Math.atan2( m13, m11 );

						} else {

							eul.x = Math.atan2( - m23, m33 );
							eul.y = 0;

						}
					}

					return eul;

				}

				function setFromEuler( euler ) {

			
					var quat=new THREE.Quaternion();
					var x = euler.x, y = euler.y, z = euler.z, order = 'XYZ';

					// http://www.mathworks.com/matlabcentral/fileexchange/
					// 	20696-function-to-convert-between-dcm-euler-angles-quaternions-and-euler-vectors/
					//	content/SpinCalc.m

					var cos = Math.cos;
					var sin = Math.sin;

					var c1 = cos( x / 2 );
					var c2 = cos( y / 2 );
					var c3 = cos( z / 2 );

					var s1 = sin( x / 2 );
					var s2 = sin( y / 2 );
					var s3 = sin( z / 2 );

					if ( order === 'XYZ' ) {

						quat.x = s1 * c2 * c3 + c1 * s2 * s3;
						quat.y = c1 * s2 * c3 - s1 * c2 * s3;
						quat.z = c1 * c2 * s3 + s1 * s2 * c3;
						quat.w = c1 * c2 * c3 - s1 * s2 * s3;

					} else if ( order === 'YXZ' ) {

						quat.x = s1 * c2 * c3 + c1 * s2 * s3;
						quat.y = c1 * s2 * c3 - s1 * c2 * s3;
						quat.z = c1 * c2 * s3 - s1 * s2 * c3;
						quat.w = c1 * c2 * c3 + s1 * s2 * s3;

					} else if ( order === 'ZXY' ) {

						quat.x = s1 * c2 * c3 - c1 * s2 * s3;
						quat.y = c1 * s2 * c3 + s1 * c2 * s3;
						quat.z = c1 * c2 * s3 + s1 * s2 * c3;
						quat.w = c1 * c2 * c3 - s1 * s2 * s3;

					} else if ( order === 'ZYX' ) {

						quat.x = s1 * c2 * c3 - c1 * s2 * s3;
						quat.y = c1 * s2 * c3 + s1 * c2 * s3;
						quat.z = c1 * c2 * s3 - s1 * s2 * c3;
						quat.w = c1 * c2 * c3 + s1 * s2 * s3;

					} else if ( order === 'YZX' ) {

						quat.x = s1 * c2 * c3 + c1 * s2 * s3;
						quat.y = c1 * s2 * c3 + s1 * c2 * s3;
						quat.z = c1 * c2 * s3 - s1 * s2 * c3;
						quat.w = c1 * c2 * c3 - s1 * s2 * s3;

					} else if ( order === 'XZY' ) {

						quat.x = s1 * c2 * c3 - c1 * s2 * s3;
						quat.y = c1 * s2 * c3 - s1 * c2 * s3;
						quat.z = c1 * c2 * s3 + s1 * s2 * c3;
						quat.w = c1 * c2 * c3 + s1 * s2 * s3;

					}

					return quat;

				}

				function applyQuaternion (eul1, q ) {


					var x = eul1.x, y = eul1.y, z = eul1.z;
					var qx = q.x, qy = q.y, qz = q.z, qw = q.w;

					// calculate quat * vector

					var ix = qw * x + qy * z - qz * y;
					var iy = qw * y + qz * x - qx * z;
					var iz = qw * z + qx * y - qy * x;
					var iw = - qx * x - qy * y - qz * z;

					// calculate result * inverse quat

					eul1.x = ix * qw + iw * - qx + iy * - qz - iz * - qy;
					eul1.y = iy * qw + iw * - qy + iz * - qx - ix * - qz;
					eul1.z = iz * qw + iw * - qz + ix * - qy - iy * - qx;

					return eul1;

				}

				
				
				function toAxisXVector31(v,axis){ //TODO CHANGE


					var vector=axis.clone();
					vector.normalize();
					var xaxis=new THREE.Vector3(1,0,0);
					var geometry = new THREE.BoxGeometry( 1, 1, 1 );
					var material = new THREE.MeshBasicMaterial( {color: 0x00ff00} );
					var cube = new THREE.Mesh( geometry, material );
					var quaternion = new THREE.Quaternion(); // create one and reuse it
					quaternion.setFromUnitVectors( vector, xaxis );
					// console.log(quaternion)
					cube.applyQuaternion( quaternion );
					// console.log(cube.matrix.clone())

					// console.log(cube.rotation.clone())
					eul=setFromRotationMatrix ( composeMatrix(  quaternion.clone() ));
					
					// console.log(applyQuaternion(v.clone(), quaternion.clone()));
					// console.log(composeMatrix(  quaternion.clone() ))
					// console.log(eul.clone() )
					// console.log(setFromEuler( eul.clone() ));
					// console.log("");
					// console.log(applyQuaternion(v.clone(), setFromEuler( eul.clone() ) ));
					// console.log(cube.rotation);
					v.applyEuler(cube.rotation);
					// var res=6;
					// v=new THREE.Vector3( parseFloat(v.x.toFixed(res)),parseFloat(v.y.toFixed(res)),parseFloat(v.z.toFixed(res)))



					return v.clone();

				} //transforms a vec3D in the original orientation of the bond to that as if the bond was in +X direction

				function  toAxisXQuat1(q,axis){
					
					var v=new THREE.Vector3(q.x,q.y,q.z);
					var vector=axis.clone();
					vector.normalize();
					var xaxis=new THREE.Vector3(1,0,0);
					var geometry = new THREE.BoxGeometry( 1, 1, 1 );
					var material = new THREE.MeshBasicMaterial( {color: 0x00ff00} );
					var cube = new THREE.Mesh( geometry, material );
					var quaternion = new THREE.Quaternion(); // create one and reuse it
					quaternion.setFromUnitVectors( vector, xaxis );
					cube.applyQuaternion( quaternion );
					v.applyEuler(cube.rotation);

					return new THREE.Quaternion(v.x,v.y,v.z,q.w);

				} //transforms a vec3D in the original orientation of the bond to that as if the bond was in +X direction

				console.log(toAxisXVector31(new THREE.Vector3(-5,0,5),new THREE.Vector3(-0.7071067811865475, 0.0, 0.7071067811865475)))
				console.log(toAxisXVector31(new THREE.Vector3(-5,0,-5),new THREE.Vector3(-0.7071067811865475,0,-0.7071067811865475)))
				console.log(toAxisXVector31(new THREE.Vector3(5,-5,0),new THREE.Vector3(0.7071067811865475,-0.7071067811865475,0)))
				console.log(toAxisXVector31(new THREE.Vector3(-5,5,0),new THREE.Vector3(-0.7071067811865475,0.7071067811865475,0)))
				console.log(toAxisXVector31(new THREE.Vector3(-5,-5,0),new THREE.Vector3(-0.7071067811865475,-0.7071067811865475,0)))
				console.log(toAxisXVector31(new THREE.Vector3(5,0,5),new THREE.Vector3(0.7071067811865475,0,0.7071067811865475)))
				console.log(toAxisXVector31(new THREE.Vector3(0,5,5),new THREE.Vector3(0,0.7071067811865475,0.7071067811865475)))
				console.log("")
				// console.log(toAxisXVector3(new THREE.Vector3(-5,0,5),new THREE.Vector3(-0.7071067811865475, 0.0, 0.7071067811865475)))
				// console.log(toAxisXVector3(new THREE.Vector3(-5,0,-5),new THREE.Vector3(-0.7071067811865475,0,-0.7071067811865475)))
				// console.log(toAxisXVector3(new THREE.Vector3(5,-5,0),new THREE.Vector3(0.7071067811865475,-0.7071067811865475,0)))
				// console.log(toAxisXVector3(new THREE.Vector3(-5,5,0),new THREE.Vector3(-0.7071067811865475,0.7071067811865475,0)))
				// console.log(toAxisXVector3(new THREE.Vector3(-5,-5,0),new THREE.Vector3(-0.7071067811865475,-0.7071067811865475,0)))
				// console.log(toAxisXVector3(new THREE.Vector3(5,0,5),new THREE.Vector3(0.7071067811865475,0,0.7071067811865475)))
				// console.log(toAxisXVector3(new THREE.Vector3(0,5,5),new THREE.Vector3(0,0.7071067811865475,0.7071067811865475)))

				// console.log("");

				// console.log(toAxisOriginalVector3(new THREE.Vector3(1,0,0),new THREE.Vector3(0,0,1)))
				// console.log(toAxisOriginalVector3(new THREE.Vector3(0,1,0),new THREE.Vector3(0,0,1)))
				// console.log(toAxisOriginalVector3(new THREE.Vector3(0,0,1),new THREE.Vector3(0,0,1)))
				// console.log("");

				// console.log(toAxisXVector3(new THREE.Vector3(1,0,0),new THREE.Vector3(0,0,1)))
				// console.log(toAxisXVector3(new THREE.Vector3(0,1,0),new THREE.Vector3(0,0,1)))
				// console.log(toAxisXVector3(new THREE.Vector3(0,0,1),new THREE.Vector3(0,0,1)))

				console.log("");

				var numTimeSteps=10;
				var dt=0.0251646; //?? todo change to recommended step
				// var dt=0.001; //?? todo change to recommended step
				var static=true;
				simulateParallel(setup,numTimeSteps,dt)
				
				// initialize(setup);
				// var tt0 = performance.now();
				// for(var i=0;i<numTimeSteps;i++){
				// 	var t0 = performance.now();
				// 	doTimeStep(setup,dt);
				// 	var t1 = performance.now();
				// 	console.log("doTimeStep "+ i+" took " + (t1 - t0) + " milliseconds.");
				// 	// console.log("")
				// 	// console.log("")
				// }
				// var tt1 = performance.now();
				// console.log("total time: "+ (tt1 - tt0) + " milliseconds.");
				three.colorEdges();
				
				
			});
		</script>

		


    </body>
</html>