Template:Team:Valencia Biocampus/Templates/js/simuelegans1.js
From 2013.igem.org
Raphael.fn.arrow = function(x1, y1, x2, y2, size) { var angle = Raphael.angle(x1, y1, x2, y2); var a45 = Raphael.rad(angle-45); var a45m = Raphael.rad(angle+45); var a135 = Raphael.rad(angle-135); var a135m = Raphael.rad(angle+135); var x1a = x1 + Math.cos(a135) * size; var y1a = y1 + Math.sin(a135) * size; var x1b = x1 + Math.cos(a135m) * size; var y1b = y1 + Math.sin(a135m) * size; var x2a = x2 + Math.cos(a45) * size; var y2a = y2 + Math.sin(a45) * size; var x2b = x2 + Math.cos(a45m) * size; var y2b = y2 + Math.sin(a45m) * size; return this.path( "M"+x1+" "+y1+"L"+x1a+" "+y1a+ "M"+x1+" "+y1+"L"+x1b+" "+y1b+ "M"+x1+" "+y1+"L"+x2+" "+y2+ "M"+x2+" "+y2+"L"+x2a+" "+y2a+ "M"+x2+" "+y2+"L"+x2b+" "+y2b ); };
simuelegans = function() {};
var initialx = -1; var initialy = -1;
var initialr; var initiala;
var canvas = Raphael("raphael", 500, 500); // Back canvas (contains the drawing)
var path_in_coords = new Array();
function xytopath(x, y){
var guide_path, path, full_path;
if(initialx==-1 && initialy==-1){ initialx = 0; initialy = 0; }
var path2return = new Array(x.length);
var tmpx, tmpy;
tmpx = (x[0] * plate.attrs.r / simulator.plate_radius + plate.attrs.cx); tmpy = (y[0] * plate.attrs.r / simulator.plate_radius + plate.attrs.cy);
path2return[-1] = "[\"M"+tmpx+","+tmpy+"\"";
for(var i =1; i<x.length ; i++){
tmpx = (x[i-1] * plate.attrs.r / simulator.plate_radius + plate.attrs.cx); tmpy = (y[i-1] * plate.attrs.r / simulator.plate_radius + plate.attrs.cy);
path2return[i-1] = "[\"M"+tmpx+","+tmpy+"\", ";
tmpx = (x[i] * plate.attrs.r / simulator.plate_radius + plate.attrs.cx); tmpy = (y[i] * plate.attrs.r / simulator.plate_radius + plate.attrs.cy);
path2return[i-1] += "\"L"+tmpx+","+tmpy+"\" ]";
path_in_coords.push({x: tmpx, y: tmpy});
}
return path2return;
}
function Attractant(x, y){ this.x = x; this.y = y; }
simuelegans.RandNorm = function(m, s){
this.mean = m; this.stdDev = s; this.isSpareReady = false; this.spare = 0; this.valuern = 0; }
simuelegans.RandNorm.prototype.getRandNorm = function() { if (this.isSpareReady) { this.isSpareReady = false; this.valuern = this.spare * this.stdDev + this.mean; } else { var u, v, s; do { u = Math.random() * 2 - 1; v = Math.random() * 2 - 1; s = u * u + v * v; } while (s >= 1 || s == 0); var mul = Math.sqrt(-2.0 * Math.log(s) / s); this.spare = v * mul; this.isSpareReady = true; this.valuern = this.mean + this.stdDev * u * mul; } return this.valuern; }; simuelegans.RandNorm = function(m, s){
this.mean = m; this.stdDev = s; this.isSpareReady = false; this.spare = 0; this.valuern = 0; }
simuelegans.RandNorm.prototype.getRandNorm = function() { if (this.isSpareReady) { this.isSpareReady = false; this.valuern = this.spare * this.stdDev + this.mean; } else { var u, v, s; do { u = Math.random() * 2 - 1; v = Math.random() * 2 - 1; s = u * u + v * v; } while (s >= 1 || s == 0); var mul = Math.sqrt(-2.0 * Math.log(s) / s); this.spare = v * mul; this.isSpareReady = true; this.valuern = this.mean + this.stdDev * u * mul; } return this.valuern; };
simuelegans.RandWalk = function(h, t, r0, a0){
this.tmax = t; this.h = h; a0 *= Math.PI / 180.0; this.x0 = r0 * Math.cos(a0); this.y0 = r0 * Math.sin(a0); this.tsize = this.tmax / h; this.x = new Array(this.tsize); this.y = new Array(this.tsize); this.v = new Array(this.tsize); this.g = new Array(this.tsize); this.dg = new Array(this.tsize); this.d = new Array(this.tsize); this.temp = new Array(this.tsize);
}
simuelegans.RandWalk.prototype.simulate = function(r0, a0) {
//a0 *= Math.PI / 180.0;
this.x0 = r0 * Math.cos(a0);
this.y0 = r0 * Math.sin(a0);
this.x[0] = this.x0;
this.y[0] = this.y0;
this.temp[0] = 0;
this.v[0] = 0;
this.g[0] = 2 * Math.PI * Math.random();
this.dg[0] = 0;
var rnd1 = new simuelegans.RandNorm(0.0152, 0.00702);
var rnd2 = new simuelegans.RandNorm(0.861 * Math.PI / 180, 38.9 * Math.PI / 180);
var rnd3 = new simuelegans.RandNorm(0.441 * Math.PI / 180, 2.12 * Math.PI / 180);
this.d[0] = rnd3.getRandNorm();
for (var i = 0; i < this.tsize - 1; i++) { this.temp[i + 1] = this.h * i; this.x[i + 1] = this.x[0] - 0.01; this.y[i + 1] = this.y[0] - 0.01; this.v[i + 1] = 0.01;
do { this.v[i + 1] = rnd1.getRandNorm();
this.dg[i + 1] = rnd2.getRandNorm();
this.d[i + 1] = rnd3.getRandNorm();
var l = this.h * this.v[i + 1];
this.g[i + 1] = this.h * (this.dg[i + 1] + this.d[i + 1]) + this.g[i]; this.x[i + 1] = l * Math.cos(this.g[i + 1]) + this.x[i]; this.y[i + 1] = l * Math.sin(this.g[i + 1]) + this.y[i]; } while ((Math.sqrt(this.x[i + 1] * this.x[i + 1] + this.y[i + 1] * this.y[i + 1]) > simulator.plate_radius)); } }
var strpath; var path1; var pathcolor = {stroke : "#5a7881"};
var plate;
var circle; var arrow_radius; var arrow_title;
var c_elegans;
var gui = new dat.GUI({ autoPlace: false });
var customContainer = document.getElementById('simuelegans_gui');
customContainer.appendChild(gui.domElement);
function simulator(){ this.plate_radius = 1; this.steps = 2000; this.duration = 50; }
var simulator = new simulator();
gui.add(simulator, 'plate_radius', 0.8, 4.5).name("Plate radius (cm)"); gui.add(simulator, 'steps', 200, 4000).name("Duration ");
function initPlate(){ plate = canvas.circle(250, 250, 230); plate.attr("stroke", "#cac0b0"); plate.attr("fill", "#cac0b0"); plate.attr("fill-opacity", "0"); plate.attr("cursor", "crosshair"); plate.click(onclickplate); arrow_radius = canvas.arrow(250, 493, 470, 493, 10); arrow_title = canvas.text(360, 487, "Radius: "+simulator.plate_radius.toFixed(1)+"cm").attr({fill: '#000'}) }
function initCircle(x, y){ circle = canvas.circle(x, y, 3); circle.attr("stroke-width", 1); circle.attr("stroke", "#f00"); circle.attr("fill", "#f00");
//c_elegans = canvas.image("", x - 120/7/2, y - 120/7/2, 120/7, 74/7); c_elegans = canvas.circle(x, y, 3); c_elegans.attr("stroke-width", 1); c_elegans.attr("stroke", "#5a7881"); }
function animateCircle(step, strpath){
if(step <= strpath.length){
path1 = canvas.path(strpath[step]).attr( { stroke: "#5a7881", fill: "none" });
//c_elegans.attr({guide : path1, along : 1}).animate({along : 0}, 50, "linear"); //c_elegans.attr({along: 0});
//c_elegans.rotate(Math.atan2(c_elegans.attrs.y, c_elegans.attrs.x))
c_elegans.animate({ cx: path_in_coords[step+1].x, cy: path_in_coords[step+1].y}, 50);
path1.animate({path: strpath[step+1]}, 50, function(){
animateCircle(step+1, strpath);
})
}
}
function simndraw(x, y){
initialx = x ; initialy = y;
initialr = (Math.sqrt( (initialx - plate.attrs.cx )*(initialx - plate.attrs.cx ) + (initialy - plate.attrs.cy)*(initialy - plate.attrs.cy ) ) / plate.attrs.r) * simulator.plate_radius;
initiala = Math.atan2(initialy - plate.attrs.cy, initialx - plate.attrs.cx)
rw = new simuelegans.RandWalk(1.0, simulator.steps.toFixed(), initialr, initiala);
rw.simulate(initialr, initiala);
strpath = xytopath(rw.x, rw.y);
animateCircle(-1, strpath);
}
var x0, y0;
initPlate();
initCircle(plate.attrs.cx, plate.attrs.cy);
simndraw(plate.attrs.cx, plate.attrs.cy);
var rw;
function onclickplate(e) {
circle.remove();
path1.remove();
path_in_coords.length = 0;
canvas.clear();
initPlate();
x0 = e.clientX - $("#raphael").offset().left; y0 = e.clientY - $("#raphael").offset().top;
simndraw(x0, y0); initCircle(x0, y0);
circle.toFront(); plate.toFront();
};