Team:Evry/arbor/src/physics/worker.js

From 2012.igem.org

// // worker.js // // wraps physics.js in an onMessage/postMessage protocol that the // Kernel object can deal with // importScripts('atoms.js'); importScripts('barnes-hut.js'); importScripts('physics.js'); // alias over the missing jquery utils so we can run in a worker $ = {

 each:function(obj, callback){
   if ($.isArray(obj)){
     for (var i=0, j=obj.length; i<j; i++) callback(i, obj[i])
   }else{
     for (var k in obj) callback(k, obj[k])
   }
 },
 map:function(arr, fn){
   var out = []
   $.each(arr, function(i, elt){
     var result = fn(elt, i)
     if (result!==undefined) out.push(result)
   })
   return out
 },
 isArray:function(obj){
   return (obj.constructor.toString().indexOf("Array") != -1)
 },
 inArray:function(elt, arr){
   for (var i=0, j=arr.length; i<j; i++) if (arr[i]===elt) return i;
   return -1
 }    

} // endalias var PhysicsWorker = function(){

 var _timeout = 20
 var _physics = null
 var _physicsInterval = null
 var _lastTick = null
 
 var times = []
 var last = new Date().valueOf()
 
 var that = {  
   init:function(param){
     that.timeout(param.timeout)
     _physics = Physics(param.dt, param.stiffness, param.repulsion, param.friction, that.tock)
     return that
   },
   timeout:function(newTimeout){
     if (newTimeout!=_timeout){
       _timeout = newTimeout
       if (_physicsInterval!==null){
         that.stop()
         that.go()
       }
     }
   },
   go:function(){
     if (_physicsInterval!==null) return
     // postMessage('starting')
     _lastTick=null
     _physicsInterval = setInterval(that.tick, _timeout)
   },
   stop:function(){
     if (_physicsInterval===null) return
     clearInterval(_physicsInterval);
     _physicsInterval = null;
     // postMessage('stopping')
   },
   tick:function(){
     // iterate the system
     _physics.tick()    


     // but stop the simulation when energy of the system goes below a threshold
     var sysEnergy = _physics.systemEnergy()
     if ((sysEnergy.mean + sysEnergy.max)/2 < 0.05){
       if (_lastTick===null) _lastTick=new Date().valueOf()
       if (new Date().valueOf()-_lastTick>1000){
         that.stop()
       }else{
         // postMessage('pausing')
       }
     }else{
       _lastTick = null
     }
     
   },
   tock:function(sysData){
     sysData.type = "geometry"
     postMessage(sysData)
   },
   
   modifyNode:function(id, mods){
     _physics.modifyNode(id, mods)  
     that.go()
   },
   modifyPhysics:function(param){
     _physics.modifyPhysics(param)
   },
   
   update:function(changes){
     var epoch = _physics._update(changes)
   }
 }
 
 return that

}


var physics = PhysicsWorker()

onmessage = function(e){

 if (!e.data.type){
   postMessage("¿kérnèl?")
   return
 }
 
 if (e.data.type=='physics'){
   var param = e.data.physics
   physics.init(e.data.physics)
   return
 }
 
 switch(e.data.type){
   case "modify":
     physics.modifyNode(e.data.id, e.data.mods)
     break
   case "changes":
     physics.update(e.data.changes)
     physics.go()
     break
     
   case "start":
     physics.go()
     break
     
   case "stop":
     physics.stop()
     break
     
   case "sys":
     var param = e.data.param || {}
     if (!isNaN(param.timeout)) physics.timeout(param.timeout)
     physics.modifyPhysics(param)
     physics.go()
     break
   }  

}