anetmodel.cc
上传用户:rrhhcc
上传日期:2015-12-11
资源大小:54129k
文件大小:21k
源码类别:

通讯编程

开发平台:

Visual C++

  1. /*
  2.  * Network model with automatic layout
  3.  *
  4.  * Layout code from nem by Elan Amir
  5.  *
  6.  * $Header: /cvsroot/nsnam/nam-1/anetmodel.cc,v 1.25 2000/11/12 23:19:39 mehringe Exp $
  7.  */
  8. #include <stdlib.h>
  9. #include <math.h>
  10. #include <float.h>
  11. #include "random.h"
  12. #include "view.h"
  13. #include "netview.h"
  14. #include "animation.h"
  15. #include "queue.h"
  16. #include "edge.h"
  17. #include "node.h"
  18. #include "agent.h"
  19. #include "sincos.h"
  20. #include "state.h"
  21. #include "packet.h"
  22. #include "anetmodel.h"
  23. class AutoNetworkModelClass : public TclClass {
  24. public:
  25. AutoNetworkModelClass() : TclClass("NetworkModel/Auto") {}
  26. TclObject* create(int argc, const char*const* argv) {
  27. if (argc < 5) 
  28. return 0;
  29. return (new AutoNetModel(argv[4]));
  30. }
  31. } autonetworkmodel_class;
  32. int AutoNetModel::AUTO_ITERATIONS_ = 1;
  33. int AutoNetModel::INCR_ITERATIONS_ = 200;
  34. int AutoNetModel::RANDOM_SEED_ = 1;
  35. int AutoNetModel::recalc_ = 1;
  36. double AutoNetModel::INIT_TEMP_ = 0.30; // follow Elan's 
  37. double AutoNetModel::MINX_ = 0.0; 
  38. double AutoNetModel::MAXX_ = 1.0;
  39. double AutoNetModel::MINY_ = 0.0;
  40. double AutoNetModel::MAXY_ = 1.0;
  41. AutoNetModel::AutoNetModel(const char *animator) : NetModel(animator)
  42. {
  43. iterations_ = AUTO_ITERATIONS_;
  44. bind("KCa_", &kca_);
  45. bind("KCr_", &kcr_);
  46. bind("Recalc_", &recalc_);
  47. bind("INCR_ITERATIONS_", &INCR_ITERATIONS_);
  48. bind("AUTO_ITERATIONS_", &AUTO_ITERATIONS_);
  49. bind("RANDOM_SEED_", &RANDOM_SEED_);
  50. }
  51. AutoNetModel::~AutoNetModel()
  52. {
  53. }
  54. int AutoNetModel::command(int argc, const char *const *argv)
  55. {
  56. if (argc == 2) {
  57. if (strcmp(argv[1], "layout") == 0) {
  58. /*
  59.  * <net> layout
  60.  * compute layout using Elan's nem
  61.  */
  62. layout();
  63. return (TCL_OK);
  64. }
  65. if (strcmp(argv[1], "relayout") == 0) {
  66. relayout();
  67. return (TCL_OK);
  68. }
  69. if (strcmp(argv[1], "reset") == 0) {
  70. reset_layout();
  71. return (TCL_OK);
  72. }
  73. return (NetModel::command(argc, argv));
  74. }
  75. void AutoNetModel::reset_layout() 
  76. {
  77. Node *n;
  78. Edge *e;
  79. initEmbedding();
  80. for (n = nodes_; n != 0; n = n->next_)
  81. for (e = n->links(); e != 0; e = e->next_)
  82. e->unmark();
  83. scale_estimate();
  84. placeEverything();
  85. for (View *p = views_; p != 0; p = p->next_)
  86. if ((p->width() > 0) && (p->height() > 0)) {
  87. p->redrawModel();
  88. p->draw();
  89. }
  90. }
  91. void AutoNetModel::initEmbedding() 
  92. {
  93. Node *n;
  94. double maxx, maxy;
  95. Random::seed_heuristically();
  96. maxx = MINX_ + (MAXX_-MINX_) * 0.4;
  97. maxy = MINY_ + (MAXY_-MINY_) * 0.4;
  98. // randomize nodes' position within square [(0,0), (1,1)]
  99. for (nNodes_ = 0, n = nodes_; n != 0; n = n->next_, nNodes_++) {
  100. n->place(Random::uniform(MINX_, maxx),
  101.  Random::uniform(MINY_, maxy));
  102. }
  103. //optk_ = kc_ * sqrt((MAXX_-MINX_)*(MAXY_-MINY_) / (double)nNodes);
  104. optka_ = kca_ * sqrt((MAXX_-MINX_)*(MAXY_-MINY_) / (double)nNodes_);
  105. optkr_ = kcr_ * sqrt((MAXX_-MINX_)*(MAXY_-MINY_) / (double)nNodes_);
  106. temp_ = INIT_TEMP_;
  107. }
  108. void AutoNetModel::placeEverything()
  109. {
  110. Node *n; 
  111. // Should re-initialize nymin_ and nymax_
  112. nymin_ = FLT_MAX;
  113. nymax_ = -FLT_MAX;
  114. for (n = nodes_; n != 0; n = n->next_) {
  115. for (Edge *e = n->links(); e != 0; e = e->next_)
  116. placeEdge(e, n);
  117. placeAllAgents(n);
  118. if (nymin_ > n->y())
  119. nymin_ = n->y();
  120. if (nymax_ < n->y())
  121. nymax_ = n->y();
  122. }
  123. // Place all routes
  124. for (n = nodes_; n != 0; n = n->next_) {
  125. n->clear_routes();
  126. n->place_all_routes();
  127. }
  128. }
  129. // do more passes
  130. void AutoNetModel::relayout()
  131. {
  132. Node *n;
  133. Edge *e;
  134. temp_ = INIT_TEMP_;
  135. for (n = nodes_; n != 0; n = n->next_)
  136. for (e = n->links(); e != 0; e = e->next_)
  137. e->unmark();
  138. //weigh_subtrees();
  139. //bifucate_graph();
  140. // in case that the two constants changed
  141. optka_ = kca_ * sqrt((MAXX_-MINX_)*(MAXY_-MINY_) / (double)nNodes_);
  142. optkr_ = kcr_ * sqrt((MAXX_-MINX_)*(MAXY_-MINY_) / (double)nNodes_);
  143. for (int i = 0; i < 100; i++) {
  144.   //alternate doses of vigorous shaking and letting it settle a little
  145.           //seem to work best.
  146.         if ((i==0)||(i==60)) temp_ = INIT_TEMP_;
  147.         if ((i==50)||(i==70)) temp_ = INIT_TEMP_/4.0;
  148.         if ((i<50)||((i>=60)&&(i<70)))
  149. {
  150.   embed_phase1();
  151. }
  152. else
  153. {
  154.   embed_phase2();
  155. }
  156. for (n = nodes_; n != 0; n = n->next_)
  157. for (e = n->links(); e != 0; e = e->next_)
  158. e->unmark();
  159. scale_estimate();
  160. placeEverything();
  161. for (View *p = views_; p != 0; p = p->next_)
  162. if ((p->width() > 0) && (p->height() > 0)) {
  163. // XXX assume this means tk has been 
  164. // initialized
  165. p->redrawModel();
  166. p->draw();
  167. }
  168. }
  169. }
  170. // do several passes of embedding
  171. void AutoNetModel::layout()
  172. {
  173. initEmbedding();
  174. for (int i = 0; i < iterations_; i++) {
  175. embed_phase2();
  176. }
  177. scale_estimate(); // find node size after layout
  178. placeEverything();
  179. }
  180. void AutoNetModel::cool()
  181. {
  182. if (temp_ > 0.001)
  183. temp_ *= 0.95;
  184. else 
  185. temp_ = 0.001;
  186. }
  187. void AutoNetModel::placeAllAgents(Node *src) const
  188. {
  189. // clear all marks and clear all angles
  190. for (Agent *a = src->agents(); a != NULL; a = a->next()) {
  191. a->mark(0), a->angle(NO_ANGLE);
  192. placeAgent(a, src);
  193. }
  194. }
  195. // we need to use edge length, instead of delay, to estimate scale
  196. void AutoNetModel::scale_estimate()
  197. {
  198. /* Determine the maximum link delay. */
  199. double emax = 0., emean = 0., dist;
  200. Node *n;
  201. int edges=0;
  202. for (n = nodes_; n != 0; n = n->next_) {
  203. for (Edge* e = n->links(); e != 0; e = e->next_) {
  204.         edges++;
  205. dist = n->distance(*(e->neighbor()));
  206. emean+=dist;
  207. if (dist > emax)
  208. emax = dist;
  209. }
  210. }
  211. emean/=edges;
  212. /*store this because we need it for monitors*/
  213. node_size_ = node_sizefac_ * emean;
  214. /*
  215.  * Check for missing node or edge sizes. If any are found,
  216.  * compute a reasonable default based on the maximum edge
  217.  * dimension.
  218.  */
  219. for (n = nodes_; n != 0; n = n->next_) {
  220. n->size(node_size_);
  221. for (Edge* e = n->links(); e != 0; e = e->next_)
  222. e->size(.03 * emean);
  223. }
  224. }
  225. // Fruchterman, T.M.J and Reingold, E.M.,
  226. // Graph Drawing by Force-directed Placement,
  227. // Software-Practice and Experience, vol. 21(11), 1129-1164 (Nov. 91)
  228. //
  229. // Do one pass of embedding
  230. void AutoNetModel::embed_phase1()
  231. {
  232. Node *v, *u;
  233. Edge* e;
  234. double dx, dy, mag, f, minn, rx, ry;
  235. /*
  236.  * Randomly jitter everything to try and break out of local minima
  237.          */
  238. for (v = nodes_; v != 0; v = v->next_) {
  239.   v->displace(0., 0.);
  240.   rx=0.1*(MAXX_-MINX_)*
  241.     ((INIT_TEMP_-temp_)/INIT_TEMP_)*
  242.     ((Random::random()&0xffff)/32768.0 - 1.0);
  243.   ry=0.1*(MAXX_-MINX_)*
  244.     ((INIT_TEMP_-temp_)/INIT_TEMP_)*
  245.     ((Random::random()&0xffff)/32768.0 - 1.0);
  246.   v->displace(rx,ry);
  247. }
  248. /*
  249.  * Calculate repulsive forces between all vertices.
  250.  */
  251. for (v = nodes_; v != 0; v = v->next_) {
  252. for (u = nodes_; u != 0; u = u->next_) {
  253. if (u == v) 
  254. continue;
  255. dx = v->x() - u->x();
  256. dy = v->y() - u->y();
  257. if (dx == 0 && dy == 0)
  258. dx = dy = 0.001;
  259. mag = sqrt(dx * dx + dy * dy);
  260. f = REP(mag, optkr_);
  261. v->displace(v->dx() + ((dx / mag) * f),
  262.     v->dy() + ((dy / mag) * f));
  263. }
  264. }
  265. /* 
  266.  * Limit the maximum displacement to the temperature temp;
  267.  * and then prevent from being displaced outside frame.
  268.  */
  269. if (recalc_==1) {
  270.   for (v = nodes_; v != 0; v = v->next_) {
  271.     mag = sqrt(v->dx()*v->dx() + v->dy() * v->dy());
  272.     double posx = v->x(), posy = v->y();
  273.     if (mag != 0) {
  274.       minn = min(mag, temp_);
  275.       posx += v->dx() / mag * minn;
  276.       posy += v->dy() / mag * minn;
  277.     }
  278.     
  279.     v->place(posx, posy);
  280.     v->displace(0.,0.);
  281.   }
  282. }
  283. /*
  284.  * Calculate attractive forces between neighbors.
  285.  */
  286. for (v = nodes_; v != 0; v = v->next_) {
  287. for (e = v->links(); e != 0; e = e->next_) {
  288. u = e->neighbor();
  289. dx = v->x() - u->x();
  290. dy = v->y() - u->y();
  291. mag = sqrt(dx * dx + dy * dy);
  292. // XXX we consider single direction edge as 
  293. // of single direction attraction. So we only
  294. // attract one node toward the other. If later 
  295. // we have the other edge, the other node will be 
  296. // attracted too.
  297. if (mag >= 0) {
  298. f = ATT(mag, optka_);
  299. v->displace(v->dx() - dx / mag * f,
  300.     v->dy() - dy / mag * f);
  301. }
  302. }
  303. }
  304. /* 
  305.  * Limit the maximum displacement to the temperature temp;
  306.  * and then prevent from being displaced outside frame.
  307.  */
  308. for (v = nodes_; v != 0; v = v->next_) {
  309. mag = sqrt(v->dx()*v->dx() + v->dy() * v->dy());
  310. double posx = v->x(), posy = v->y();
  311. if (mag != 0) {
  312. minn = min(mag, temp_);
  313. posx += v->dx() / mag * minn;
  314. posy += v->dy() / mag * minn;
  315. }
  316. #if 0
  317. posx = min(MAXX_, max(MINX_, posx));
  318. posy = min(MAXY_, max(MINY_, posy));
  319. #endif
  320. v->place(posx, posy);
  321. #if 0
  322. printf("Position of node %s: (%f, %f)n", 
  323.        v->name(), posx, posy);
  324. #endif
  325. }
  326. /* Cool the temperature */
  327. if (temp_ > 0.001)
  328. temp_ *= 0.95;
  329. else 
  330. temp_ = 0.001;
  331. #if 0
  332. printf("------------------------------n");
  333. #endif
  334. }
  335. void AutoNetModel::embed_phase2()
  336. {
  337. Node *v, *u;
  338. Edge* e;
  339. double dx, dy, mag, f, minn;
  340. /*
  341.  * Calculate repulsive forces between all vertices.
  342.  */
  343. for (v = nodes_; v != 0; v = v->next_) {
  344. //XXX why not 0. as in paper?
  345.         v->displace(0.,0.);
  346. for (u = nodes_; u != 0; u = u->next_) {
  347. if (u == v) 
  348. continue;
  349. dx = v->x() - u->x();
  350. dy = v->y() - u->y();
  351. if (dx == 0 && dy == 0)
  352. dx = dy = 0.001;
  353. mag = sqrt(dx * dx + dy * dy);
  354. f = REP(mag, optkr_);
  355. if (f < 2*u->size()) {
  356.   if (f<temp_)
  357.   {
  358.     f=2*u->size()/(mag/* *temp_*/);
  359.   }
  360.   else 
  361.     f=2*u->size()/mag;
  362. }
  363. v->displace(v->dx() + ((dx / mag) * f),
  364.     v->dy() + ((dy / mag) * f));
  365. }
  366. }
  367. /* 
  368.  * Limit the maximum displacement to the temperature temp;
  369.  * and then prevent from being displaced outside frame.
  370.  */
  371. if (recalc_==1) {
  372.   for (v = nodes_; v != 0; v = v->next_) {
  373.     mag = sqrt(v->dx()*v->dx() + v->dy() * v->dy());
  374.     double posx = v->x(), posy = v->y();
  375.     if (mag != 0) {
  376.       minn = min(mag, temp_);
  377.       posx += v->dx() / mag * minn;
  378.       posy += v->dy() / mag * minn;
  379.     }
  380.     
  381.     v->place(posx, posy);
  382.     v->displace(0.,0.);
  383.   }
  384. }
  385. /*
  386.  * Calculate attractive forces between neighbors.
  387.  */
  388. for (v = nodes_; v != 0; v = v->next_) {
  389.   //if(v->mass()<=0) continue;
  390. for (e = v->links(); e != 0; e = e->next_) {
  391. u = e->neighbor();
  392. //if(u->mass()<=0) continue;
  393. dx = v->x() - u->x();
  394. dy = v->y() - u->y();
  395. mag = sqrt(dx * dx + dy * dy);
  396. // XXX we consider single direction edge as 
  397. // of single direction attraction. So we only
  398. // attract one node toward the other. If later 
  399. // we have the other edge, the other node will be 
  400. // attracted too.
  401. if (mag >= ((INIT_TEMP_-temp_)/INIT_TEMP_)*(e->length()+(v->size()+u->size())*0.75)) {
  402. f = ATT2(mag, optka_);
  403. v->displace(v->dx() - dx / mag * f,
  404.     v->dy() - dy / mag * f);
  405. }
  406. }
  407. }
  408. /* 
  409.  * Limit the maximum displacement to the temperature temp;
  410.  * and then prevent from being displaced outside frame.
  411.  */
  412. for (v = nodes_; v != 0; v = v->next_) {
  413.   //if(v->mass()<=0) continue;
  414. mag = sqrt(v->dx()*v->dx() + v->dy() * v->dy());
  415. double posx = v->x(), posy = v->y();
  416. if (mag != 0) {
  417. minn = min(mag, temp_);
  418. posx += v->dx() * minn / mag;
  419. posy += v->dy() * minn / mag;
  420. }
  421. #if 0
  422. posx = min(MAXX_, max(MINX_, posx));
  423. posy = min(MAXY_, max(MINY_, posy));
  424. #endif
  425. v->place(posx, posy);
  426. #if 0
  427. printf("Position of node %s: (%f, %f)n", 
  428.        v->name(), posx, posy);
  429. #endif
  430. }
  431. /* Cool the temperature */
  432.         if (temp_ > 0.001)
  433.                 temp_ *= 0.95;
  434.         else
  435.                 temp_ = 0.001;
  436. #if 0
  437. printf("------------------------------n");
  438. #endif
  439. }
  440. // packet handling stuff. use new packet
  441. void AutoNetModel::handle(const TraceEvent& e, double now, int direction)
  442. {
  443. switch (e.tt) {
  444. case 'a':
  445. {
  446. NetModel::handle(e, now, direction);
  447. // recalculate bounding box so that all agents will be within
  448. // view
  449. for (View *v = views_; v != 0; v = v->next_)
  450. v->redrawModel();
  451. break;
  452. }
  453. default:
  454. NetModel::handle(e, now, direction);
  455. break;
  456. }
  457. }
  458. void AutoNetModel::bifucate_graph()
  459. {
  460.     Node *n, *m;
  461.     for (n = nodes_; n != 0; n = n->next_) {
  462.       if (n->mass()<=0) continue;
  463.       int remaining=0;
  464.       for (m = nodes_; m != 0; m = m->next_) {
  465. if (m->mass()>0) remaining++;
  466. m->mark(0);
  467.       }
  468.       int depth=0;
  469.       int result=2;
  470.       while((result!=0)&&(result!=1))
  471.       {
  472. depth++;
  473. for (m = nodes_; m != 0; m = m->next_) {
  474.   if (m->mass()>0) {
  475.     m->mark(0);
  476.     m->color("black");
  477.   }
  478. }
  479. result=mark_to_depth(n, depth);
  480. printf("depth: %d result: %dn", depth, result);
  481.       }
  482.       if (result==1) {
  483. int ctr=0;
  484. for (m = nodes_; m != 0; m = m->next_) {
  485.   if (m->marked()==1) ctr++;
  486. }
  487. printf("remaining: %d ctr: %dn", remaining, ctr);
  488. if ((remaining-ctr>1)&&(ctr>1)&&(ctr<remaining/2))
  489. {
  490.   printf("success!n");
  491.   for (m = nodes_; m != 0; m = m->next_) {
  492.     if (m->marked()==1)
  493.     {
  494.       m->mass(-1);
  495.       m->color("blue");
  496.     }
  497.   }
  498. }
  499.       } else {
  500. printf("failed at depth %d!n", depth);
  501.       }
  502.     }
  503. }
  504. int AutoNetModel::mark_to_depth(Node *n, int depth)
  505. {
  506.   int sum=0;
  507.   if (depth==0) {
  508.     n->mark(2);
  509.     return 1;
  510.   }
  511.   if (n->marked()==2) sum--;
  512.   n->mark(1);
  513.   for(Edge *e = n->links(); e != 0; e = e->next_)
  514.   {
  515.     Node *dst=e->neighbor();
  516.     if ((dst->mass()>0)&&(dst->marked()==0))
  517.       sum+=mark_to_depth(dst, depth-1);
  518.   }
  519.   return sum;
  520. }
  521. void AutoNetModel::weigh_subtrees()
  522. {
  523.   Node *n, *dst, *newdst;
  524.   Edge* e;
  525.   int nodes=0;
  526.   for (n = nodes_; n != 0; n = n->next_) {
  527.     n->mass(1);
  528.   }
  529.   for (n = nodes_; n != 0; n = n->next_) {
  530.     int ctr=0;
  531.     for (e = n->links(); e != 0; e = e->next_)
  532.       ctr++;
  533.     if (ctr==1)
  534.     {
  535.       dst=n->links()->neighbor();
  536.       dst->mass(2);
  537.       n->mass(0);
  538.       n->color("green");
  539.       nodes++;
  540.     }
  541.     while(ctr==1) {
  542.       ctr=0;
  543.       for (e = dst->links(); e != 0; e = e->next_)
  544. if (e->neighbor()->mass()==1) ctr++;
  545.       if (ctr==1)
  546.       {
  547. for (e = dst->links(); e != 0; e = e->next_)
  548.   if (e->neighbor()->mass()==1) {
  549.     newdst=e->neighbor();
  550.     newdst->mass(1+dst->mass());
  551.     dst->mass(0);
  552.     dst->color("red");
  553.     nodes++;
  554.     dst=newdst;
  555.     break;
  556.   }
  557.       }
  558.     }
  559.   }
  560.   printf("massless nodes: %dn", nodes);
  561.   nodes=0;
  562.   for (n = nodes_; n != 0; n = n->next_) {
  563.     if (n->mass()==0) {
  564.       nodes++;
  565.       n->color("grey");
  566.     }
  567.   }
  568.   printf("massless nodes: %dn", nodes);
  569. }
  570.     
  571. void AutoNetModel::place_subtrees()
  572. {
  573.   Node *n, *dst;
  574.   Edge* e;
  575.   double angle;
  576.   int nodes=0, did_something=1;
  577.   double comx=0.0, comy=0.0, x, y;
  578.   for (n = nodes_; n != 0; n = n->next_) {
  579.     if (n->mass()!=0)
  580.     {
  581.       comx+=n->x();
  582.       comy+=n->y();
  583.       nodes++;
  584.     }
  585.   }
  586.   comx/=nodes;
  587.   comy/=nodes;
  588.   printf("com at %.2f,%.2fn", comx, comy);
  589.   while (did_something) {
  590.     did_something=0;
  591.     for (n = nodes_; n != 0; n = n->next_) {
  592.       if (n->mass()==0)
  593.       {
  594. for (e = n->links(); e != 0; e = e->next_)
  595.   if (e->neighbor()->mass()>0)
  596.   {
  597.     dst=e->neighbor();
  598.     n->mass(1);
  599.     n->color("green");
  600.     x=dst->x();
  601.     y=dst->y();
  602.     if (y-comy!=0)
  603.       angle=atan((x-comx)/(y-comy));
  604.     else
  605.       angle=0;
  606.     if (y-comy>0)
  607.       angle+=M_PI;
  608.     n->place(x-2*n->size()*sin(angle), 
  609.      y-2*n->size()*cos(angle));
  610.     did_something=1;
  611.     break;
  612.   }
  613.       }
  614.     }
  615.   }
  616. }
  617. //------------------------------------------------------------------
  618. //  The following is a big hack and I hope it works
  619. //
  620. //  - It is being done to speed up the layout of realtime dynamic nodes
  621. //    by only laying out that node and not the others
  622. //  - These procedures should be integrated into the main relayout 
  623. //    procedure when time permits 
  624. //------------------------------------------------------------------
  625. //------------------------------------------------------------------
  626. //
  627. //------------------------------------------------------------------
  628. void AutoNetModel::relayoutNode(Node *v) {
  629.   Node *n;
  630.   Edge *e;
  631.   temp_ = INIT_TEMP_;
  632.   for (n = nodes_; n != 0; n = n->next_)
  633.     for (e = n->links(); e != 0; e = e->next_)
  634.       e->unmark();
  635. // in case that the two constants changed
  636. optka_ = kca_ * sqrt((MAXX_-MINX_)*(MAXY_-MINY_) / (double)nNodes_);
  637. optkr_ = kcr_ * sqrt((MAXX_-MINX_)*(MAXY_-MINY_) / (double)nNodes_);
  638.   for (int i = 0; i < 100; i++) {
  639.     // alternate doses of vigorous shaking and letting it settle a little
  640.     // seem to work best.
  641.     if ((i==0)||(i==60))
  642.        temp_ = INIT_TEMP_;
  643.     if ((i==50)||(i==70))
  644.        temp_ = INIT_TEMP_/4.0;
  645.     if ((i < 50) || ((i >= 60) && (i < 70))) {
  646.       embed_phase1(v);
  647.     } else {
  648.   embed_phase2(v);
  649. }
  650. for (n = nodes_; n != 0; n = n->next_)
  651. for (e = n->links(); e != 0; e = e->next_)
  652. e->unmark();
  653. scale_estimate();
  654. placeEverything();
  655. }
  656. }
  657. //------------------------------------------------------------------
  658. //
  659. //------------------------------------------------------------------
  660. void AutoNetModel::embed_phase1(Node *v) {
  661. Node *u;
  662. Edge* e;
  663. double dx, dy, mag, f, minn, rx, ry;
  664. /*
  665.  * Randomly jitter everything to try and break out of local minima
  666.    */
  667. v->displace(0., 0.);
  668. rx = 0.1 * (MAXX_-MINX_) *
  669.       ((INIT_TEMP_-temp_)/INIT_TEMP_) *
  670.       ((Random::random()&0xffff)/32768.0 - 1.0);
  671.   ry = 0.1 * (MAXX_-MINX_) *
  672.        ((INIT_TEMP_-temp_)/INIT_TEMP_) *
  673.        ((Random::random()&0xffff)/32768.0 - 1.0);
  674.   v->displace(rx,ry);
  675. /*
  676.  * Calculate repulsive forces between all vertices.
  677.  */
  678. for (u = nodes_; u != 0; u = u->next_) {
  679.    if (u == v) 
  680.       continue;
  681.    dx = v->x() - u->x();
  682.    dy = v->y() - u->y();
  683.    if (dx == 0 && dy == 0)
  684.      dx = dy = 0.001;
  685.    mag = sqrt(dx * dx + dy * dy);
  686.    f = REP(mag, optkr_);
  687.      v->displace(v->dx() + ((dx / mag) * f),
  688.                  v->dy() + ((dy / mag) * f));
  689. }
  690. /* 
  691.  * Limit the maximum displacement to the temperature temp;
  692.  * and then prevent from being displaced outside frame.
  693.  */
  694. if (recalc_ == 1) {
  695.    mag = sqrt(v->dx()*v->dx() + v->dy() * v->dy());
  696.    double posx = v->x(), posy = v->y();
  697.    if (mag != 0) {
  698.       minn = min(mag, temp_);
  699.       posx += v->dx() / mag * minn;
  700.       posy += v->dy() / mag * minn;
  701.    }
  702.     
  703.    v->place(posx, posy);
  704.    v->displace(0.,0.);
  705. }
  706. /*
  707.  * Calculate attractive forces between neighbors.
  708.  */
  709. for (e = v->links(); e != 0; e = e->next_) {
  710.    u = e->neighbor();
  711.    dx = v->x() - u->x();
  712.    dy = v->y() - u->y();
  713.    mag = sqrt(dx * dx + dy * dy);
  714.    // XXX we consider single direction edge as 
  715.    // of single direction attraction. So we only
  716.    // attract one node toward the other. If later 
  717.    // we have the other edge, the other node will be 
  718.    // attracted too.
  719.    if (mag >= 0) {
  720.       f = ATT(mag, optka_);
  721.       v->displace(v->dx() - dx / mag * f,
  722.   v->dy() - dy / mag * f);
  723.    }
  724. }
  725. /* 
  726.  * Limit the maximum displacement to the temperature temp;
  727.  * and then prevent from being displaced outside frame.
  728.  */
  729. mag = sqrt(v->dx()*v->dx() + v->dy() * v->dy());
  730. double posx = v->x(), posy = v->y();
  731. if (mag != 0) {
  732.    minn = min(mag, temp_);
  733.    posx += v->dx() / mag * minn;
  734.    posy += v->dy() / mag * minn;
  735. }
  736. v->place(posx, posy);
  737. /* Cool the temperature */
  738. if (temp_ > 0.001)
  739. temp_ *= 0.95;
  740. else 
  741. temp_ = 0.001;
  742. }
  743. //------------------------------------------------------------------
  744. //
  745. //------------------------------------------------------------------
  746. void AutoNetModel::embed_phase2(Node *v) {
  747. Node *u;
  748. Edge* e;
  749. double dx, dy, mag, f, minn;
  750. /*
  751.  * Calculate repulsive forces between all vertices.
  752.  */
  753. //XXX why not 0. as in paper?
  754. v->displace(0.,0.);
  755. for (u = nodes_; u != 0; u = u->next_) {
  756.    if (u == v) 
  757.       continue;
  758.    dx = v->x() - u->x();
  759.    dy = v->y() - u->y();
  760.    if (dx == 0 && dy == 0)
  761.       dx = dy = 0.001;
  762.    mag = sqrt(dx * dx + dy * dy);
  763.    f = REP(mag, optkr_);
  764.    if (f < 2*u->size()) {
  765.       if (f<temp_) {
  766.       f=2*u->size()/(mag/* *temp_*/);
  767.     } else { 
  768.       f=2*u->size()/mag;
  769.         }
  770.    }
  771.    v->displace(v->dx() + ((dx / mag) * f),
  772.        v->dy() + ((dy / mag) * f));
  773. }
  774. /* 
  775.  * Limit the maximum displacement to the temperature temp;
  776.  * and then prevent from being displaced outside frame.
  777.  */
  778. if (recalc_==1) {
  779.    mag = sqrt(v->dx()*v->dx() + v->dy() * v->dy());
  780.    double posx = v->x(), posy = v->y();
  781.    if (mag != 0) {
  782.       minn = min(mag, temp_);
  783.       posx += v->dx() / mag * minn;
  784.       posy += v->dy() / mag * minn;
  785.    }
  786.    
  787.    v->place(posx, posy);
  788.    v->displace(0.,0.);
  789. }
  790. /*
  791.  * Calculate attractive forces between neighbors.
  792.  */
  793. for (e = v->links(); e != 0; e = e->next_) {
  794.    u = e->neighbor();
  795.    //if(u->mass()<=0) continue;
  796.    dx = v->x() - u->x();
  797.    dy = v->y() - u->y();
  798.    mag = sqrt(dx * dx + dy * dy);
  799.    // XXX we consider single direction edge as 
  800.    // of single direction attraction. So we only
  801.    // attract one node toward the other. If later 
  802.    // we have the other edge, the other node will be 
  803.    // attracted too.
  804.    if (mag >= ((INIT_TEMP_-temp_)/INIT_TEMP_) * 
  805.                  (e->length()+(v->size()+u->size()) *
  806.                  0.75)) {
  807.       f = ATT2(mag, optka_);
  808.       v->displace(v->dx() - dx / mag * f,
  809.   v->dy() - dy / mag * f);
  810.    }
  811. }
  812. /* 
  813.  * Limit the maximum displacement to the temperature temp;
  814.  * and then prevent from being displaced outside frame.
  815.  */
  816. mag = sqrt(v->dx()*v->dx() + v->dy() * v->dy());
  817. double posx = v->x(), posy = v->y();
  818. if (mag != 0) {
  819.    minn = min(mag, temp_);
  820.    posx += v->dx() * minn / mag;
  821.    posy += v->dy() * minn / mag;
  822. }
  823. v->place(posx, posy);
  824. /* Cool the temperature */
  825.         if (temp_ > 0.001)
  826.                 temp_ *= 0.95;
  827.         else
  828.                 temp_ = 0.001;
  829. }