mramine364

force directed layout

Jul 10th, 2016
119
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1.  
  2. function Node(id, ix, iy){
  3.     return {
  4.         node: document.getElementById(id),
  5.         getX:function () {
  6.             return parseInt(this.node.getAttribute('cx'));
  7.         },
  8.         getY:function () {
  9.             return parseInt(this.node.getAttribute('cy'));
  10.         },
  11.         setX:function (x) {
  12.             this.node.setAttribute('cx',x);
  13.         },
  14.         setY:function (y) {
  15.             this.node.setAttribute('cy',y);
  16.         },
  17.         ix: ix, iy: iy,
  18.         setI:function () {
  19.             this.setY(this.iy);
  20.             this.setX(this.ix);
  21.         },
  22.         net_force:{x:0,y:0},
  23.         velocity:{x:0,y:0},
  24.     };
  25. }
  26.  
  27. // <circle cx="114" cy="93" r="17" fill="rgba(0, 0, 0, 1)" class="circle" id="c5">
  28. //              </circle>
  29. //              <circle cx="299" cy="108" r="17" fill="rgba(0, 0, 0, 1)" class="circle" id="c6">
  30. //              </circle>
  31.  
  32. let nodes=[
  33.     Node('c1',190,49),
  34.     Node('c2',329,204),
  35.     Node('c3',118,194),
  36.     Node('c4',214,223),
  37.     Node('c5',114,93),
  38.     Node('c6',299,108)
  39. ];
  40.  
  41.  
  42. // <line x1="114" y1="93" x2="329" y2="204" style="stroke:rgb(255,0,0);stroke-width:2" id="l25"/>
  43. // <line x1="114" y1="93" x2="118" y2="194" style="stroke:rgb(255,0,0);stroke-width:2" id="l35"/>
  44. // <line x1="299" y1="108" x2="329" y2="204" style="stroke:rgb(255,0,0);stroke-width:2" id="l26"/>
  45. // <line x1="299" y1="108" x2="214" y2="223" style="stroke:rgb(255,0,0);stroke-width:2" id="l46"/>
  46.  
  47. let lines=[
  48.     {line:document.getElementById('l12'),a:0,b:1},
  49.     {line:document.getElementById('l13'),a:0,b:2},
  50.     {line:document.getElementById('l14'),a:0,b:3},
  51.     {line:document.getElementById('l24'),a:1,b:3},
  52.     {line:document.getElementById('l25'),a:1,b:4},
  53.     {line:document.getElementById('l35'),a:2,b:4}, 
  54.     {line:document.getElementById('l26'),a:1,b:5},
  55.     {line:document.getElementById('l46'),a:3,b:5}
  56. ];
  57.  
  58. let ctxHeight=400, ctxWidth=500, circleRadius=25;
  59. let R=100,A=0.02, damping=0.7;
  60.  
  61. function fdl_barycentric_method(){
  62.    
  63.     // calculate repulsive forces
  64.     for(let i=0;i<nodes.length;i++){
  65.         let v=nodes[i];
  66.         let u;
  67.         v.net_force.x=v.net_force.y=0;
  68.         for(let j=0;j<nodes.length;j++){
  69.             if(i==j)
  70.                 continue;
  71.             u=nodes[j];
  72.             let rsq=(v.getX()-u.getX())*(v.getX()-u.getX())+(v.getY()-u.getY())*(v.getY()-u.getY());
  73.             // repulsion
  74.             v.net_force.x += R * (v.getX()-u.getX()) /rsq;
  75.             v.net_force.y += R * (v.getY()-u.getY()) /rsq;
  76.         }
  77.         for(let j=0;j<lines.length;j++){
  78.             let l=lines[j];
  79.             if(l.a!=i && l.b!=i)
  80.                 continue;
  81.             if(l.a==i)
  82.                 u=nodes[l.b];
  83.             else
  84.                 u=nodes[l.a];
  85.             // countin the attraction
  86.             v.net_force.x+=A*(u.getX() - v.getX());
  87.             v.net_force.y+=A*(u.getY() - v.getY());
  88.         }
  89.         // counting the velocity (with damping 0.85)
  90.         v.velocity.x = (v.velocity.x + v.net_force.x)*damping;
  91.         v.velocity.y = (v.velocity.y + v.net_force.y)*damping;
  92.  
  93.     }
  94.     // draw egdes or lines
  95.     for(let i=0;i<lines.length;i++){
  96.         let l =lines[i];
  97.         l.line.setAttribute('x1',nodes[l.a].getX())
  98.         l.line.setAttribute('y1',nodes[l.a].getY())
  99.         l.line.setAttribute('x2',nodes[l.b].getX())
  100.         l.line.setAttribute('y2',nodes[l.b].getY())
  101.     }
  102.  
  103.     let vsum=0;
  104.     // set new positions
  105.     for(let i=0;i<nodes.length;i++){
  106.         let v = nodes[i];
  107.         // v.x += v.velocity.x;
  108.         // v.y += v.velocity.y;
  109.         v.setX(v.getX()+v.velocity.x);
  110.         v.setY(v.getY()+v.velocity.y);
  111.         vsum+=Math.abs(v.velocity.x)+Math.abs(v.velocity.y);
  112.         console.log("velocity: ("+v.velocity.x+", "+v.velocity.y+")")
  113.     }
  114.    
  115.     // draw txts
  116.     for(let i=0;i<nodes.length;i++){
  117.         let t =document.getElementById('t'+(i+1));
  118.         t.setAttribute('x',nodes[i].getX())
  119.         t.setAttribute('y',nodes[i].getY())
  120.     }
  121.  
  122.     console.log("vsum: "+vsum)
  123.     if( vsum<1 ) // equilibrium
  124.         clearInterval(si);
  125. }
  126.  
  127. let si;
  128.  
  129. document.getElementById('draw_btn').addEventListener('click', function(e){
  130.     console.log('Draw')
  131.     let k=0, tr, ta;
  132.     R = isNaN(tr=document.getElementById('rval').value)?R:parseFloat(tr);
  133.     A = isNaN(ta=document.getElementById('aval').value)?R:parseFloat(ta);
  134.     console.log(`R: ${R}, A: ${A}`)
  135.     si = setInterval(
  136.         function(){
  137.             fdl_barycentric_method();
  138.             k++;
  139.             console.log("k: "+k)
  140.         }
  141.     , 100);
  142.  
  143.     // fdl();
  144. });
  145.  
  146. document.getElementById('stop_btn').addEventListener('click', function(e){
  147.     console.log('Stop')
  148.     clearInterval(si);
  149.     // fdl();
  150. });
  151.  
  152. document.getElementById('refresh_btn').addEventListener('click', function(e){
  153.     console.log('Refresh')
  154.     // nodes
  155.     for(let i=0;i<nodes.length;i++){
  156.         let v = nodes[i];
  157.         v.setI();
  158.     }
  159.     // texts
  160.     for(let i=0;i<nodes.length;i++){
  161.         let t =document.getElementById('t'+(i+1));
  162.         t.setAttribute('x',nodes[i].ix)
  163.         t.setAttribute('y',nodes[i].iy)
  164.     }
  165.  
  166.     // lines
  167.     for(let i=0;i<lines.length;i++){
  168.         let l =lines[i];
  169.         l.line.setAttribute('x1',nodes[l.a].ix)
  170.         l.line.setAttribute('y1',nodes[l.a].iy)
  171.         l.line.setAttribute('x2',nodes[l.b].ix)
  172.         l.line.setAttribute('y2',nodes[l.b].iy)
  173.     }
  174. });
Advertisement
Add Comment
Please, Sign In to add comment