topfisheyeview.c 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481
  1. /*************************************************************************
  2. * Copyright (c) 2011 AT&T Intellectual Property
  3. * All rights reserved. This program and the accompanying materials
  4. * are made available under the terms of the Eclipse Public License v1.0
  5. * which accompanies this distribution, and is available at
  6. * https://www.eclipse.org/legal/epl-v10.html
  7. *
  8. * Contributors: Details at https://graphviz.org
  9. *************************************************************************/
  10. #include "topfisheyeview.h"
  11. #include <math.h>
  12. #include "viewport.h"
  13. #include "viewportcamera.h"
  14. #include "draw.h"
  15. #include "smyrna_utils.h"
  16. #include <assert.h>
  17. #include "hier.h"
  18. #include "topfisheyeview.h"
  19. #include <string.h>
  20. #include <common/color.h>
  21. #include <common/colorprocs.h>
  22. #include <util/alloc.h>
  23. static int get_temp_coords(topview * t, int level, int v, double *coord_x,
  24. double *coord_y);
  25. static void color_interpolation(glCompColor srcColor, glCompColor tarColor,
  26. glCompColor * color, int levelcount,
  27. int level)
  28. {
  29. if (levelcount <= 0)
  30. return;
  31. color->R =
  32. ((float) level * tarColor.R - (float) level * srcColor.R +
  33. (float) levelcount * srcColor.R) / (float) levelcount;
  34. color->G =
  35. ((float) level * tarColor.G - (float) level * srcColor.G +
  36. (float) levelcount * srcColor.G) / (float) levelcount;
  37. color->B =
  38. ((float) level * tarColor.B - (float) level * srcColor.B +
  39. (float) levelcount * srcColor.B) / (float) levelcount;
  40. }
  41. static v_data *makeGraph(Agraph_t* gg, int *nedges)
  42. {
  43. int i;
  44. int ne = agnedges(gg);
  45. int nv = agnnodes(gg);
  46. v_data *graph = gv_calloc(nv, sizeof(v_data));
  47. int *edges = gv_calloc(2 * ne + nv, sizeof(int)); /* reserve space for self loops */
  48. float *ewgts = gv_calloc(2 * ne + nv, sizeof(float));
  49. Agnode_t *np;
  50. Agedge_t *ep;
  51. Agraph_t *g = NULL;
  52. int i_nedges;
  53. ne = 0;
  54. i=0;
  55. for (np = agfstnode(gg); np; np = agnxtnode(gg, np))
  56. {
  57. graph[i].edges = edges++; /* reserve space for the self loop */
  58. graph[i].ewgts = ewgts++;
  59. #ifdef STYLES
  60. graph[i].styles = NULL;
  61. #endif
  62. i_nedges = 1; /* one for the self */
  63. if (!g)
  64. g = agraphof(np);
  65. for (ep = agfstedge(g, np); ep; ep = agnxtedge(g, ep, np))
  66. {
  67. Agnode_t *vp;
  68. Agnode_t *tp = agtail(ep);
  69. Agnode_t *hp = aghead(ep);
  70. assert(hp != tp);
  71. /* FIX: handle multiedges */
  72. vp = (tp == np ? hp : tp);
  73. ne++;
  74. i_nedges++;
  75. *edges++ = ND_TVref(vp);
  76. *ewgts++ = 1;
  77. }
  78. graph[i].nedges = i_nedges;
  79. graph[i].edges[0] = i;
  80. graph[i].ewgts[0] = 1 - i_nedges;
  81. i++;
  82. }
  83. ne /= 2; /* each edge counted twice */
  84. *nedges = ne;
  85. return graph;
  86. }
  87. static void refresh_old_values(topview * t)
  88. {
  89. int level, v;
  90. Hierarchy *hp = t->fisheyeParams.h;
  91. for (level = 0; level < hp->nlevels; level++) {
  92. for (v = 0; v < hp->nvtxs[level]; v++) {
  93. ex_vtx_data *gg = hp->geom_graphs[level];
  94. gg[v].old_physical_x_coord = gg[v].physical_x_coord;
  95. gg[v].old_physical_y_coord = gg[v].physical_y_coord;
  96. gg[v].old_active_level = gg[v].active_level;
  97. }
  98. }
  99. }
  100. /* To use:
  101. * double* x_coords; // initial x coordinates
  102. * double* y_coords; // initial y coordinates
  103. * focus_t* fs;
  104. * int ne;
  105. * v_data* graph = makeGraph (topview*, &ne);
  106. * hierarchy = makeHier(topview->NodeCount, ne, graph, x_coords, y_coords);
  107. * freeGraph (graph);
  108. * fs = initFocus (topview->Nodecount); // create focus set
  109. */
  110. void prepare_topological_fisheye(Agraph_t* g,topview * t)
  111. {
  112. double *x_coords = gv_calloc(t->Nodecount, sizeof(double)); // initial x coordinates
  113. double *y_coords = gv_calloc(t->Nodecount, sizeof(double)); // initial y coordinates
  114. focus_t *fs;
  115. int ne;
  116. int i;
  117. int closest_fine_node;
  118. int cur_level = 0;
  119. Hierarchy *hp;
  120. gvcolor_t cl;
  121. Agnode_t *np;
  122. v_data *graph = makeGraph(g, &ne);
  123. i=0;
  124. for (np = agfstnode(g); np; np = agnxtnode(g, np))
  125. {
  126. x_coords[i]=ND_A(np).x;
  127. y_coords[i]=ND_A(np).y;
  128. i++;
  129. }
  130. hp = t->fisheyeParams.h =
  131. makeHier(agnnodes(g), ne, graph, x_coords, y_coords,
  132. &(t->fisheyeParams.hier));
  133. freeGraph(graph);
  134. free(x_coords);
  135. free(y_coords);
  136. fs = t->fisheyeParams.fs = initFocus(agnnodes(g)); // create focus set
  137. closest_fine_node = 0; /* first node */
  138. fs->num_foci = 1;
  139. fs->foci_nodes[0] = closest_fine_node;
  140. fs->x_foci[0] = hp->geom_graphs[cur_level][closest_fine_node].x_coord;
  141. fs->y_foci[0] = hp->geom_graphs[cur_level][closest_fine_node].y_coord;
  142. view->Topview->fisheyeParams.repos.width =
  143. (int) (view->bdxRight - view->bdxLeft);
  144. view->Topview->fisheyeParams.repos.height =
  145. (int) (view->bdyTop - view->bdyBottom);
  146. //topological fisheye
  147. colorxlate(get_attribute_value
  148. ("topologicalfisheyefinestcolor", view,
  149. view->g[view->activeGraph]), &cl, RGBA_DOUBLE);
  150. view->Topview->fisheyeParams.srcColor.R = (float) cl.u.RGBA[0];
  151. view->Topview->fisheyeParams.srcColor.G = (float) cl.u.RGBA[1];
  152. view->Topview->fisheyeParams.srcColor.B = (float) cl.u.RGBA[2];
  153. colorxlate(get_attribute_value
  154. ("topologicalfisheyecoarsestcolor", view,
  155. view->g[view->activeGraph]), &cl, RGBA_DOUBLE);
  156. view->Topview->fisheyeParams.tarColor.R = (float) cl.u.RGBA[0];
  157. view->Topview->fisheyeParams.tarColor.G = (float) cl.u.RGBA[1];
  158. view->Topview->fisheyeParams.tarColor.B = (float) cl.u.RGBA[2];
  159. sscanf(agget
  160. (view->g[view->activeGraph],
  161. "topologicalfisheyedistortionfactor"), "%lf",
  162. &view->Topview->fisheyeParams.repos.distortion);
  163. sscanf(agget
  164. (view->g[view->activeGraph], "topologicalfisheyefinenodes"),
  165. "%d", &view->Topview->fisheyeParams.level.num_fine_nodes);
  166. sscanf(agget
  167. (view->g[view->activeGraph],
  168. "topologicalfisheyecoarseningfactor"), "%lf",
  169. &view->Topview->fisheyeParams.level.coarsening_rate);
  170. sscanf(agget
  171. (view->g[view->activeGraph], "topologicalfisheyedist2limit"),
  172. "%d", &view->Topview->fisheyeParams.hier.dist2_limit);
  173. sscanf(agget(view->g[view->activeGraph], "topologicalfisheyeanimate"),
  174. "%d", &view->Topview->fisheyeParams.animate);
  175. set_active_levels(hp, fs->foci_nodes, fs->num_foci, &(t->fisheyeParams.level));
  176. positionAllItems(hp, fs, &(t->fisheyeParams.repos));
  177. refresh_old_values(t);
  178. }
  179. static void drawtopfishnodes(topview * t)
  180. {
  181. glCompColor srcColor;
  182. glCompColor tarColor;
  183. glCompColor color;
  184. int level, v;
  185. Hierarchy *hp = t->fisheyeParams.h;
  186. static int max_visible_level = 0;
  187. srcColor.R = view->Topview->fisheyeParams.srcColor.R;
  188. srcColor.G = view->Topview->fisheyeParams.srcColor.G;
  189. srcColor.B = view->Topview->fisheyeParams.srcColor.B;
  190. tarColor.R = view->Topview->fisheyeParams.tarColor.R;
  191. tarColor.G = view->Topview->fisheyeParams.tarColor.G;
  192. tarColor.B = view->Topview->fisheyeParams.tarColor.B;
  193. //drawing nodes
  194. glPointSize(7);
  195. level = 0;
  196. glBegin(GL_POINTS);
  197. for (level = 0; level < hp->nlevels; level++) {
  198. for (v = 0; v < hp->nvtxs[level]; v++) {
  199. double x0, y0;
  200. if (get_temp_coords(t, level, v, &x0, &y0)) {
  201. if (!(((-x0 / view->zoom > view->clipX1)
  202. && (-x0 / view->zoom < view->clipX2)
  203. && (-y0 / view->zoom > view->clipY1)
  204. && (-y0 / view->zoom < view->clipY2))))
  205. continue;
  206. if (max_visible_level < level)
  207. max_visible_level = level;
  208. color_interpolation(srcColor, tarColor, &color,
  209. max_visible_level, level);
  210. glColor4f(color.R, color.G, color.B, view->defaultnodealpha);
  211. glVertex3f((float)x0, (float)y0, 0.0f);
  212. }
  213. }
  214. }
  215. glEnd();
  216. }
  217. static void drawtopfishedges(topview * t)
  218. {
  219. glCompColor srcColor;
  220. glCompColor tarColor;
  221. glCompColor color;
  222. int level, v, i, n;
  223. Hierarchy *hp = t->fisheyeParams.h;
  224. static int max_visible_level = 0;
  225. srcColor.R = view->Topview->fisheyeParams.srcColor.R;
  226. srcColor.G = view->Topview->fisheyeParams.srcColor.G;
  227. srcColor.B = view->Topview->fisheyeParams.srcColor.B;
  228. tarColor.R = view->Topview->fisheyeParams.tarColor.R;
  229. tarColor.G = view->Topview->fisheyeParams.tarColor.G;
  230. tarColor.B = view->Topview->fisheyeParams.tarColor.B;
  231. //and edges
  232. glBegin(GL_LINES);
  233. for (level = 0; level < hp->nlevels; level++) {
  234. for (v = 0; v < hp->nvtxs[level]; v++) {
  235. v_data *g = hp->graphs[level];
  236. double x0, y0;
  237. if (get_temp_coords(t, level, v, &x0, &y0)) {
  238. for (i = 1; i < g[v].nedges; i++) {
  239. double x, y;
  240. n = g[v].edges[i];
  241. if (max_visible_level < level)
  242. max_visible_level = level;
  243. color_interpolation(srcColor, tarColor, &color,
  244. max_visible_level, level);
  245. glColor4f(color.R, color.G, color.B, view->defaultnodealpha);
  246. if (get_temp_coords(t, level, n, &x, &y)) {
  247. glVertex3f((float)x0, (float)y0, 0.0f);
  248. glVertex3f((float)x, (float)y, 0.0f);
  249. } else
  250. {
  251. int levell, nodee;
  252. find_active_ancestor_info(hp, level, n, &levell,
  253. &nodee);
  254. if (get_temp_coords(t, levell, nodee, &x, &y)) {
  255. if (!(-x0 / view->zoom > view->clipX1
  256. && -x0 / view->zoom < view->clipX2
  257. && -y0 / view->zoom > view->clipY1
  258. && -y0 / view->zoom < view->clipY2)
  259. && !(-x / view->zoom > view->clipX1
  260. && -x / view->zoom < view->clipX2
  261. && -y / view->zoom > view->clipY1
  262. && -y / view->zoom < view->clipY2))
  263. continue;
  264. glVertex3f((float)x0, (float)y0, 0.0f);
  265. glVertex3f((float)x, (float)y, 0.0f);
  266. }
  267. }
  268. }
  269. }
  270. }
  271. }
  272. glEnd();
  273. }
  274. static int get_active_frame(void)
  275. {
  276. int fr;
  277. gdouble seconds = g_timer_elapsed(view->timer, NULL);
  278. fr = (int)(seconds * 1000.0);
  279. if (fr < view->total_frames) {
  280. if (fr == view->active_frame)
  281. return 0;
  282. else {
  283. view->active_frame = fr;
  284. return 1;
  285. }
  286. } else {
  287. g_timer_stop(view->timer);
  288. view->Topview->fisheyeParams.animate = 0;
  289. return 0;
  290. }
  291. }
  292. void drawtopologicalfisheye(topview * t)
  293. {
  294. get_active_frame();
  295. drawtopfishnodes(t);
  296. drawtopfishedges(t);
  297. }
  298. static void get_interpolated_coords(double x0, double y0, double x1, double y1,
  299. int fr, int total_fr, double *x, double *y)
  300. {
  301. *x = x0 + (x1 - x0) / (double) total_fr *(double) (fr + 1);
  302. *y = y0 + (y1 - y0) / (double) total_fr *(double) (fr + 1);
  303. }
  304. static int get_temp_coords(topview * t, int level, int v, double *coord_x,
  305. double *coord_y)
  306. {
  307. Hierarchy *hp = t->fisheyeParams.h;
  308. ex_vtx_data *gg = hp->geom_graphs[level];
  309. if (!t->fisheyeParams.animate) {
  310. if (gg[v].active_level != level)
  311. return 0;
  312. *coord_x = (double) gg[v].physical_x_coord;
  313. *coord_y = (double) gg[v].physical_y_coord;
  314. } else {
  315. double x0, y0, x1, y1;
  316. int OAL, AL;
  317. x0 = 0;
  318. y0 = 0;
  319. x1 = 0;
  320. y1 = 0;
  321. AL = gg[v].active_level;
  322. OAL = gg[v].old_active_level;
  323. if ((OAL < level) || (AL < level)) //no draw
  324. return 0;
  325. if ((OAL >= level) || (AL >= level)) //draw the node
  326. {
  327. if ((OAL == level) && (AL == level)) //draw as is from old coords to new)
  328. {
  329. x0 = (double) gg[v].old_physical_x_coord;
  330. y0 = (double) gg[v].old_physical_y_coord;
  331. x1 = (double) gg[v].physical_x_coord;
  332. y1 = (double) gg[v].physical_y_coord;
  333. }
  334. if ((OAL > level) && (AL == level)) //draw as from ancs to new)
  335. {
  336. find_old_physical_coords(t->fisheyeParams.h, level, v, &x0, &y0);
  337. x1 = (double) gg[v].physical_x_coord;
  338. y1 = (double) gg[v].physical_y_coord;
  339. }
  340. if ((OAL == level) && (AL > level)) //draw as from ancs to new)
  341. {
  342. find_physical_coords(t->fisheyeParams.h, level, v, &x1, &y1);
  343. x0 = (double) gg[v].old_physical_x_coord;
  344. y0 = (double) gg[v].old_physical_y_coord;
  345. }
  346. get_interpolated_coords(x0, y0, x1, y1, view->active_frame,
  347. view->total_frames, coord_x, coord_y);
  348. if ((x0 == 0) || (x1 == 0))
  349. return 0;
  350. }
  351. }
  352. return 1;
  353. }
  354. void changetopfishfocus(topview * t, float *x, float *y, int num_foci)
  355. {
  356. gvcolor_t cl;
  357. focus_t *fs = t->fisheyeParams.fs;
  358. int i;
  359. int closest_fine_node;
  360. int cur_level = 0;
  361. Hierarchy *hp = t->fisheyeParams.h;
  362. refresh_old_values(t);
  363. fs->num_foci = num_foci;
  364. for (i = 0; i < num_foci; i++) {
  365. find_closest_active_node(hp, x[i], y[i], &closest_fine_node);
  366. fs->foci_nodes[i] = closest_fine_node;
  367. fs->x_foci[i] =
  368. hp->geom_graphs[cur_level][closest_fine_node].x_coord;
  369. fs->y_foci[i] =
  370. hp->geom_graphs[cur_level][closest_fine_node].y_coord;
  371. }
  372. view->Topview->fisheyeParams.repos.width =
  373. (int) (view->bdxRight - view->bdxLeft);
  374. view->Topview->fisheyeParams.repos.height =
  375. (int) (view->bdyTop - view->bdyBottom);
  376. colorxlate(get_attribute_value
  377. ("topologicalfisheyefinestcolor", view,
  378. view->g[view->activeGraph]), &cl, RGBA_DOUBLE);
  379. view->Topview->fisheyeParams.srcColor.R = (float) cl.u.RGBA[0];
  380. view->Topview->fisheyeParams.srcColor.G = (float) cl.u.RGBA[1];
  381. view->Topview->fisheyeParams.srcColor.B = (float) cl.u.RGBA[2];
  382. colorxlate(get_attribute_value
  383. ("topologicalfisheyecoarsestcolor", view,
  384. view->g[view->activeGraph]), &cl, RGBA_DOUBLE);
  385. view->Topview->fisheyeParams.tarColor.R = (float) cl.u.RGBA[0];
  386. view->Topview->fisheyeParams.tarColor.G = (float) cl.u.RGBA[1];
  387. view->Topview->fisheyeParams.tarColor.B = (float) cl.u.RGBA[2];
  388. sscanf(agget
  389. (view->g[view->activeGraph],
  390. "topologicalfisheyedistortionfactor"), "%lf",
  391. &view->Topview->fisheyeParams.repos.distortion);
  392. sscanf(agget
  393. (view->g[view->activeGraph], "topologicalfisheyefinenodes"),
  394. "%d", &view->Topview->fisheyeParams.level.num_fine_nodes);
  395. sscanf(agget
  396. (view->g[view->activeGraph],
  397. "topologicalfisheyecoarseningfactor"), "%lf",
  398. &view->Topview->fisheyeParams.level.coarsening_rate);
  399. sscanf(agget
  400. (view->g[view->activeGraph], "topologicalfisheyedist2limit"),
  401. "%d", &view->Topview->fisheyeParams.hier.dist2_limit);
  402. sscanf(agget(view->g[view->activeGraph], "topologicalfisheyeanimate"),
  403. "%d", &view->Topview->fisheyeParams.animate);
  404. set_active_levels(hp, fs->foci_nodes, fs->num_foci, &(t->fisheyeParams.level));
  405. positionAllItems(hp, fs, &(t->fisheyeParams.repos));
  406. view->Topview->fisheyeParams.animate = 1;
  407. if (t->fisheyeParams.animate) {
  408. view->active_frame = 0;
  409. g_timer_start(view->timer);
  410. }
  411. }