|
|
Line 246: |
Line 246: |
| | | |
| //cool_color_ramp = [[0,0,0], [0,0,1], [1,1,1]]; | | //cool_color_ramp = [[0,0,0], [0,0,1], [1,1,1]]; |
- | function plot_3d(){
| |
- | data_3d = [];
| |
- | errorbars_3d = [];
| |
- | particles = [];
| |
- | meshchildren = [];
| |
- | //Parse datas!
| |
- | $('.zdata_3d').each(
| |
- | function(index)
| |
- | {
| |
- | particles.push(new THREE.Geometry());
| |
- | thisdataz = $(this).text().split(',');
| |
- | thisdatax = $('.xdata_3d').eq(index).text().split(',');
| |
- | thisdatay = $('.ydata_3d').eq(index).text().split(',');
| |
- | thisdataerr = $('.stdevs_3d').eq(index).text().split(',');
| |
- |
| |
- |
| |
- | //numxpoints = thisdatax.length;
| |
- | //numypoints = thisdatay.length;
| |
- | meshchildren.push(new THREE.Object3D());
| |
- | errorbars_3d.push(new THREE.Object3D());
| |
- | data_3d.push(new THREE.PlaneGeometry(100,100,numxpoints-1, numypoints-1));
| |
- | var i;
| |
- | for(i=0; i < thisdatax.length; ++i)
| |
- | {
| |
- | thisdatax[i] = parseFloat(thisdatax[i]);
| |
- | }
| |
- | for(i=0; i < thisdatay.length; ++i)
| |
- | {
| |
- | thisdatay[i] = parseFloat(thisdatay[i]);
| |
- | }
| |
- | for(i=0; i < thisdataz.length; ++i)
| |
- | {
| |
- | thisdataz[i] = parseFloat(thisdataz[i]);
| |
- |
| |
- | /*
| |
- | particle = new THREE.Vertex(
| |
- | new THREE.Vector3(thisdatax[i%thisdatax.length]/axisdimensions[1]*100,
| |
- | thisdatay[Math.floor(i/thisdatax.length)]/axisdimensions[3]*100,
| |
- | thisdataz[i]/axisdimensions[5]*100)
| |
- | );
| |
- | particles[index].vertices.push(particle);
| |
- | newparticle = new THREE.Particle(pointMaterial)
| |
- | newparticle.position.x = particle.position.x;
| |
- | newparticle.position.y = particle.position.y;
| |
- | newparticle.position.z = particle.position.z;
| |
- | meshchildren[index].addChild(newparticle);
| |
- | */
| |
- |
| |
- |
| |
- | }
| |
- | lineMat = new THREE.LineBasicMaterial(
| |
- | {
| |
- | color:mutantcolors_hex[index],
| |
- | opacity:1,
| |
- | linewidth:2
| |
- | }
| |
- | );
| |
- | for(i=0; i < thisdataerr.length; i++)
| |
- | {
| |
- | thisdataerr[i] = parseFloat(thisdataerr[i]);
| |
- | errbargeom = new THREE.Geometry();
| |
- | errbargeom.vertices.push(new THREE.Vertex(new THREE.Vector3(
| |
- | thisdatax[i%thisdatax.length]/axisdimensions[1]*100,
| |
- | thisdatay[Math.floor(i/thisdatax.length)]/axisdimensions[3]*100,
| |
- | thisdataz[i]/axisdimensions[5]*100-thisdataerr[i]/axisdimensions[5]*100
| |
- | )));
| |
- | errbargeom.vertices.push(new THREE.Vertex(new THREE.Vector3(
| |
- | thisdatax[i%thisdatax.length]/axisdimensions[1]*100,
| |
- | thisdatay[Math.floor(i/thisdatax.length)]/axisdimensions[3]*100,
| |
- | thisdataz[i]/axisdimensions[5]*100+thisdataerr[i]/axisdimensions[5]*100
| |
- | )));
| |
- | errbar = new THREE.Line(errbargeom, lineMat);
| |
- | errorbars_3d[index].addChild(errbar);
| |
- | }
| |
- | //Particles look like ass.
| |
- | //Use lines instead.
| |
- |
| |
- | for(i=0; i < thisdatax.length*(thisdatay.length-1); i++)
| |
- | {
| |
- |
| |
- | linegeom = new THREE.Geometry();
| |
- | linegeom.vertices.push(new THREE.Vertex(new THREE.Vector3(
| |
- | thisdatax[i%thisdatax.length]/axisdimensions[1]*100,
| |
- | thisdatay[Math.floor(i/thisdatax.length)]/axisdimensions[3]*100,
| |
- | thisdataz[i]/axisdimensions[5]*100
| |
- | )));
| |
- | linegeom.vertices.push(new THREE.Vertex(new THREE.Vector3(
| |
- | thisdatax[(i+thisdatax.length)%thisdatax.length]/axisdimensions[1]*100,
| |
- | thisdatay[Math.floor((i+thisdatax.length)/thisdatax.length)]/axisdimensions[3]*100,
| |
- | thisdataz[i+thisdatax.length]/axisdimensions[5]*100
| |
- | )));
| |
- | meshchildren[index].addChild(new THREE.Line(linegeom, lineMat));
| |
- | }
| |
- | for(i=0; i < (thisdatax.length-1)*(thisdatay.length); i++)
| |
- | {
| |
- | //Particles look like ass.
| |
- | //Use lines instead.
| |
- | linegeom = new THREE.Geometry();
| |
- | linegeom.vertices.push(new THREE.Vertex(new THREE.Vector3(
| |
- | thisdatax[i%(thisdatax.length-1)]/axisdimensions[1]*100,
| |
- | thisdatay[Math.floor(i/(thisdatax.length-1))]/axisdimensions[3]*100,
| |
- | thisdataz[Math.floor(i/(thisdatax.length-1))+i]/axisdimensions[5]*100
| |
- | )));
| |
- | linegeom.vertices.push(new THREE.Vertex(new THREE.Vector3(
| |
- | thisdatax[i%(thisdatax.length-1)+1]/axisdimensions[1]*100,
| |
- | thisdatay[Math.floor(i/(thisdatax.length-1))]/axisdimensions[3]*100,
| |
- | thisdataz[Math.floor(i/(thisdatax.length-1))+i+1]/axisdimensions[5]*100
| |
- | )));
| |
- | meshchildren[index].addChild(new THREE.Line(linegeom, lineMat));
| |
- | }
| |
- |
| |
- | for(i=0; i < numxpoints; ++i)
| |
- | {
| |
- | for(var j=0; j < numypoints; ++j)
| |
- | {
| |
- | var thisx = thisdatax[thisdatax.length-1]*i/(numxpoints-1);
| |
- | var thisy = thisdatay[thisdatay.length-1]*j/(numypoints-1);
| |
- | data_3d[index].vertices[j*numxpoints+i].position.x = thisx/axisdimensions[1]*100;
| |
- | data_3d[index].vertices[j*numxpoints+i].position.y = thisy/axisdimensions[3]*100;
| |
- | //Find flanking x,y values
| |
- | var kx = ky = 0;
| |
- | while(thisx >= thisdatax[kx]) {
| |
- | kx=kx+1;
| |
- | }
| |
- | while(thisy >= thisdatay[ky]) {
| |
- | ky=ky+1;
| |
- | }
| |
- | if(kx > thisdatax.length-1)
| |
- | {
| |
- | kx = thisdatax.length-1;
| |
- | }
| |
- | if(ky > thisdatay.length-1)
| |
- | {
| |
- | ky = thisdatay.length-1;
| |
- | }
| |
- | kx--;
| |
- | ky--;
| |
- |
| |
- | kx = parseInt(kx);
| |
- | ky = parseInt(ky);
| |
- | var tli = kx+ky*thisdatax.length;
| |
- | var tri = kx+ky*thisdatax.length+1;
| |
- | var bli = kx+(ky+1)*thisdatax.length;
| |
- | var bri = kx+1+(ky+1)*thisdatax.length;
| |
- | if(!thisdataz[bli] || !thisdataz[tli] || !thisdataz[tri] || !thisdataz[bri])
| |
- | {
| |
- | alert("Porblem!\nkx:" + kx + "\nky:" + ky + "\nkx is a "+typeof(kx) + "\nky is a" +typeof(ky) + "\nset:" + index);
| |
- | }
| |
- | thisz = interp2(thisdatax[kx],
| |
- | thisdatay[ky],
| |
- | thisdatax[kx+1],
| |
- | thisdatay[ky+1],
| |
- | thisdataz[tli],
| |
- | thisdataz[tri],
| |
- | thisdataz[bli],
| |
- | thisdataz[bri], thisx, thisy)
| |
- | data_3d[index].vertices[j*numxpoints+i].position.z = thisz/axisdimensions[5]*100;
| |
- | }
| |
- | }
| |
- | data_3d[index].computeCentroids();
| |
- | //vertex colors
| |
- | /*
| |
- | var colors = [];
| |
- | for(i=0; i < thisdataz.length; ++i)
| |
- | {
| |
- | var color = new THREE.Color(0x550000);
| |
- | // color.setHSV(.125, 1, 0);
| |
- | colors.push(color);
| |
- | }
| |
- | */
| |
- | materials = [];
| |
- | for(i=0; i < data_3d[index].faces.length; ++i)
| |
- | {
| |
- | thisfacecolor = (
| |
- | data_3d[index].vertices[data_3d[index].faces[i].a].position.z+
| |
- | data_3d[index].vertices[data_3d[index].faces[i].b].position.z+
| |
- | data_3d[index].vertices[data_3d[index].faces[i].c].position.z+
| |
- | data_3d[index].vertices[data_3d[index].faces[i].d].position.z)/4/100;
| |
- | materials.push([new THREE.MeshBasicMaterial(
| |
- | {
| |
- | color:thisfacecolor*0xffffff,
| |
- | opacity:.6
| |
- | }
| |
- | )]);
| |
- | if(!thisfacecolor)
| |
- | {
| |
- | alert("Something is terribly wrong!\na ("+data_3d[index].faces[i].a+"):"+data_3d[index].vertices[data_3d[index].faces[i].a].position.z+"\nb("+data_3d[index].faces[i].b+"):"+data_3d[index].vertices[data_3d[index].faces[i].b].position.z+"\nc("+data_3d[index].faces[i].c+"):"+data_3d[index].vertices[data_3d[index].faces[i].c].position.z+"\nd("+data_3d[index].faces[i].d+"):"+data_3d[index].vertices[data_3d[index].faces[i].a].position.z);
| |
- | }
| |
- | var newcolor = colorRamp(thisfacecolor, cool_color_ramp);
| |
- | materials[i][0].color.setRGB(newcolor[0], newcolor[1], newcolor[2]);
| |
- | data_3d[index].faces[i].materials = materials[i];
| |
- | }
| |
- |
| |
- | }
| |
- | );
| |
- |
| |
- | var origin = new THREE.Vertex(new THREE.Vector3(0,0,0));
| |
- |
| |
- | theta = -Math.PI/4;
| |
- | phi = Math.PI/8;
| |
- |
| |
- | //Axis labels
| |
- | var x = document.createElement("canvas");
| |
- | var xc = x.getContext("2d");
| |
- | x.width = 400;
| |
- | x.height = 40;
| |
- | xc.fillStyle = "#ffffff";
| |
- | xc.font = "20pt arial";
| |
- | xc.textBaseline = "top";
| |
- | xc.fillText("Arabinose (% w/v)", 10, 0);
| |
- |
| |
- | var xm = new THREE.MeshBasicMaterial({
| |
- | map: new THREE.Texture(x)
| |
- | });
| |
- | xm.map.needsUpdate = true;
| |
- |
| |
- | xaxislabel = new THREE.Mesh(new THREE.PlaneGeometry(400, 40, 2, 2), xm);
| |
- | xaxislabel.position.x = -50;
| |
- | xaxislabel.position.y = 0;
| |
- | xaxislabel.position.z = -48;
| |
- | xaxislabel.scale.x = 0.2;
| |
- | xaxislabel.scale.y = -0.2;
| |
- | xaxislabel.rotation.x = -Math.PI/2;
| |
- | xaxislabel.rotation.y = -Math.PI/2;
| |
- | xaxislabel.doubleSided = true;
| |
- |
| |
- | var x = document.createElement("canvas");
| |
- | var xc = x.getContext("2d");
| |
- | x.width = 400;
| |
- | x.height = 40;
| |
- | xc.fillStyle = "#ffffff";
| |
- | xc.font = "20pt arial";
| |
- | xc.textBaseline = "top";
| |
- | xc.fillText("Theophylline (mM)", 10, 0);
| |
- |
| |
- | var xm = new THREE.MeshBasicMaterial({
| |
- | map: new THREE.Texture(x)
| |
- | });
| |
- | xm.map.needsUpdate = true;
| |
- |
| |
- | yaxislabel = new THREE.Mesh(new THREE.PlaneGeometry(400, 40, 2, 2), xm);
| |
- | yaxislabel.position.x = 0;
| |
- | yaxislabel.position.y = -50;
| |
- | yaxislabel.position.z = -48;
| |
- | yaxislabel.scale.x = 0.2;
| |
- | yaxislabel.scale.y = -0.2;
| |
- | yaxislabel.rotation.x = -Math.PI/2;
| |
- | yaxislabel.doubleSided = true;
| |
- |
| |
- | var x = document.createElement("canvas");
| |
- | var xc = x.getContext("2d");
| |
- | x.width = 400;
| |
- | x.height = 40;
| |
- | xc.fillStyle = "#ffffff";
| |
- | xc.font = "20pt arial";
| |
- | xc.textBaseline = "top";
| |
- | xc.fillText("Fluorescence/OD", 10, 0);
| |
- |
| |
- | var xm = new THREE.MeshBasicMaterial({
| |
- | map: new THREE.Texture(x)
| |
- | });
| |
- | xm.map.needsUpdate = true;
| |
- |
| |
- | zaxislabel = new THREE.Mesh(new THREE.PlaneGeometry(400, 40, 2, 2), xm);
| |
- | zaxislabel.position.x = -50;
| |
- | zaxislabel.position.y = -52;
| |
- | zaxislabel.position.z = 0;
| |
- | zaxislabel.rotation.x = -Math.PI/2;
| |
- | zaxislabel.rotation.y = -Math.PI/2;
| |
- | zaxislabel.rotation.z = -Math.PI/2;
| |
- | zaxislabel.scale.x = 0.2;
| |
- | zaxislabel.scale.y = -0.2;
| |
- |
| |
- | zaxislabel.doubleSided = true;
| |
- | zaxislabel.updateMatrix();
| |
- |
| |
- |
| |
- | var $container = $('#mw_3dplot');
| |
- | $('body').mouseup(function(){
| |
- | isdragging = false;
| |
- | $container.unbind('mousemove');
| |
- | });
| |
- | $container.mousedown(function(event){
| |
- | isdragging = true;
| |
- | lastMouseX = event.pageX;
| |
- | lastMouseY = event.pageY;
| |
- | $container.mousemove(function(event)
| |
- | {
| |
- | theta += (lastMouseX - event.pageX)/70
| |
- | phi -= (lastMouseY - event.pageY)/70;
| |
- | lastMouseX = event.pageX;
| |
- | lastMouseY = event.pageY;
| |
- | rerender();
| |
- | });
| |
- | });
| |
- | renderer = new THREE.CanvasRenderer();
| |
- | //renderer.autoClear = false;
| |
- | camera = new THREE.OrthoCamera( -75, 75, 75, -75, - 2000, 1000 );
| |
- |
| |
- | scene = new THREE.Scene();
| |
- | camera.position.x = 250;
| |
- | camera.position.y = -150;
| |
- | camera.position.z = 75;
| |
- | camera.up.y = 0;
| |
- | camera.up.z = 1;
| |
- | // camera.rotation.y = -Math.PI/6;
| |
- | camera.position.x = 250*Math.cos(theta);
| |
- | camera.position.y = 250*Math.sin(theta);
| |
- | renderer.setSize(WIDTH, HEIGHT);
| |
- | $container.append(renderer.domElement);
| |
- | var radius = 50, segments = 16, rings = 16;
| |
- |
| |
- | sphere = new THREE.Mesh(
| |
- | new THREE.SphereGeometry(radius,
| |
- | segments,
| |
- | rings),
| |
- | sphereMaterial
| |
- | );
| |
- | sphere.position.x = 50;
| |
- | sphere.position.y = 50;
| |
- | sphere.position.z = 50;
| |
- |
| |
- | // add it to the scene
| |
- | plot_mesh = [];
| |
- | plot_points = [];
| |
- | for(var i = 0; i < data_3d.length; ++i)
| |
- | {
| |
- | plot_mesh.push(new THREE.Mesh(data_3d[i], plotMaterial));
| |
- | plot_mesh[i].doubleSided = true;
| |
- |
| |
- | plot_points.push(new THREE.ParticleSystem(
| |
- | particles[i],
| |
- | pointMaterial));
| |
- | }
| |
- |
| |
- | plot_obj = new THREE.Object3D();
| |
- | plot_obj.rotation.z = -Math.PI/2;
| |
- | plot_obj.scale.x = -1;
| |
- | //plot_mesh.addChild(sphere);
| |
- |
| |
- |
| |
- | axisgeom = new THREE.Geometry();
| |
- | axisgeom.vertices.push(origin);
| |
- | axisgeom.vertices.push(new THREE.Vertex(new THREE.Vector3(100,0,0)));
| |
- | axisgeom.vertices.push(new THREE.Vertex(new THREE.Vector3(98, 1, 0)));
| |
- | axisgeom.vertices.push(new THREE.Vertex(new THREE.Vector3(98, -1, 0)));
| |
- | axisgeom.vertices.push(new THREE.Vertex(new THREE.Vector3(100, 0, 0)));
| |
- |
| |
- | xaxis = new THREE.Line(
| |
- | axisgeom,
| |
- | axisMat
| |
- | );
| |
- |
| |
- | yaxis = new THREE.Line(
| |
- | axisgeom,
| |
- | axisMat
| |
- | );
| |
- | yaxis.rotation.z = 90*Math.PI/180;
| |
- |
| |
- | zaxis = new THREE.Line(
| |
- | axisgeom,
| |
- | axisMat
| |
- | );
| |
- | scene.addChild(xaxislabel);
| |
- | scene.addChild(yaxislabel);
| |
- | scene.addChild(zaxislabel);
| |
- |
| |
- | zaxis.rotation.y = -90*Math.PI/180;
| |
- |
| |
- | plot_obj.position.x = -50;
| |
- | plot_obj.position.z = -50;
| |
- | plot_obj.position.y = -50;
| |
- |
| |
- | zaxis.position.x = -50;
| |
- | zaxis.position.z = -50;
| |
- | zaxis.position.y = -50;
| |
- |
| |
- | xaxis.position.x = -50;
| |
- | xaxis.position.z = -50;
| |
- | xaxis.position.y = -50;
| |
- |
| |
- | yaxis.position.x = -50;
| |
- | yaxis.position.z = -50;
| |
- | yaxis.position.y = -50;
| |
- |
| |
- | //plot_obj.addChild(particleSystem);
| |
- |
| |
- |
| |
- | scene.addChild(xaxis);
| |
- | scene.addChild(yaxis);
| |
- | scene.addChild(zaxis);
| |
- | scene.addChild(plot_obj);
| |
- | // origin_object.addChild(sphere);
| |
- |
| |
- |
| |
- | //Grid
| |
- | var gridlinegeom = new THREE.Geometry();
| |
- | gridlinegeom.vertices.push(new THREE.Vertex(new THREE.Vector3(0,0,0)));
| |
- | gridlinegeom.vertices.push(new THREE.Vertex(new THREE.Vector3(100,0,0)));
| |
- |
| |
- | for(var i=1; i <= 5; i++)
| |
- | {
| |
- | var gridline = new THREE.Line(gridlinegeom, axisMat);
| |
- | gridline.position.y = i/5*100-50;
| |
- | gridline.position.x = -50;
| |
- | gridline.position.z = -50;
| |
- | scene.addChild(gridline);
| |
- |
| |
- |
| |
- |
| |
- | var gridline = new THREE.Line(gridlinegeom, axisMat);
| |
- | gridline.position.x = i/5*100-50;
| |
- | gridline.position.y = -50;
| |
- | gridline.position.z = -50;
| |
- | gridline.rotation.z = Math.PI/2;
| |
- | scene.addChild(gridline);
| |
- | }
| |
- | yticklabels = [];
| |
- | xticklabels = [];
| |
- | for(var i=1; i <= 5; i++)
| |
- | {
| |
- | var x = document.createElement("canvas");
| |
- | var xc = x.getContext("2d");
| |
- | x.width = 40;
| |
- | x.height = 40;
| |
- | xc.fillStyle = "#ffffff";
| |
- | xc.font = "12pt arial";
| |
- | xc.textBaseline = "top";
| |
- | xc.fillText(i/5*axisdimensions[1], 10, 0);
| |
- |
| |
- | var xm = new THREE.MeshBasicMaterial({
| |
- | map: new THREE.Texture(x)
| |
- | });
| |
- | xm.map.needsUpdate = true;
| |
- | var xtick = new THREE.Mesh(new THREE.PlaneGeometry(13/ASPECT, 13, 2, 2), xm);
| |
- | xtick.position.y = i/5*100-50;
| |
- | xtick.position.x = -50;
| |
- | xtick.position.z = -58;
| |
- | xtick.rotation.x = Math.PI/2;
| |
- | xtick.doubleSided = true;
| |
- | xtick.updateMatrix();
| |
- | scene.addChild(xtick);
| |
- |
| |
- | var x = document.createElement("canvas");
| |
- | var xc = x.getContext("2d");
| |
- | x.width = 80;
| |
- | x.height = 40;
| |
- | xc.fillStyle = "#ffffff";
| |
- | xc.font = "12pt arial";
| |
- | xc.textBaseline = "top";
| |
- | xc.fillText((i/5*axisdimensions[3]).toFixed(4), 10, 0);
| |
- |
| |
- | var xm = new THREE.MeshBasicMaterial({
| |
- | map: new THREE.Texture(x)
| |
- | });
| |
- | xm.map.needsUpdate = true;
| |
- | var ytick = new THREE.Mesh(new THREE.PlaneGeometry(26/ASPECT, 13, 2, 2), xm);
| |
- | ytick.position.x = i/5*100-50;
| |
- | ytick.position.y = -50;
| |
- | ytick.position.z = -58;
| |
- | ytick.rotation.x = Math.PI/2;
| |
- | ytick.doubleSided = true;
| |
- | ytick.updateMatrix();
| |
- | scene.addChild(ytick);
| |
- |
| |
- | xticklabels.push(xtick);
| |
- | yticklabels.push(ytick);
| |
- | }
| |
- |
| |
- | var particle = new THREE.Particle(pointMaterial);
| |
- |
| |
- | renderer.clear();
| |
- | renderer.render(scene, camera);
| |
- | $('#mw_grapharea').append('<div id="mw_3dplot"/>');
| |
- | update3DPlotMeshes();
| |
- | }
| |
| | | |
| var WIDTH = 650; | | var WIDTH = 650; |
Line 835: |
Line 359: |
| {$('#mw_optionsmenu td').eq(0).mouseover().click();} | | {$('#mw_optionsmenu td').eq(0).mouseover().click();} |
| else | | else |
- | {axisdimensions = [0, 1, 0, 10, 0, dataMax]; | + | {} |
- | delete $('#mw_3dplot');
| + | |
- | plot_3d()}
| + | |
| }); | | }); |
| | | |