fdpinit.c 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165
  1. /**
  2. * @file
  3. * @brief API fdpgen/fdp.h: @ref fdp_init_node_edge, @ref fdp_cleanup
  4. */
  5. /*************************************************************************
  6. * Copyright (c) 2011 AT&T Intellectual Property
  7. * All rights reserved. This program and the accompanying materials
  8. * are made available under the terms of the Eclipse Public License v1.0
  9. * which accompanies this distribution, and is available at
  10. * https://www.eclipse.org/legal/epl-v10.html
  11. *
  12. * Contributors: Details at https://graphviz.org
  13. *************************************************************************/
  14. /* fdpinit.c:
  15. * Written by Emden R. Gansner
  16. *
  17. * Mostly boilerplate initialization and cleanup code.
  18. */
  19. /* uses PRIVATE interface */
  20. #define FDP_PRIVATE 1
  21. #include <fdpgen/tlayout.h>
  22. #include <neatogen/neatoprocs.h>
  23. #include <stdbool.h>
  24. #include <util/agxbuf.h>
  25. #include <util/alloc.h>
  26. static void initialPositions(graph_t * g)
  27. {
  28. int i;
  29. node_t *np;
  30. attrsym_t *possym;
  31. attrsym_t *pinsym;
  32. double *pvec;
  33. char *p;
  34. char c;
  35. possym = agattr(g,AGNODE, "pos", NULL);
  36. if (!possym)
  37. return;
  38. pinsym = agattr(g,AGNODE, "pin", NULL);
  39. for (i = 0; (np = GD_neato_nlist(g)[i]); i++) {
  40. p = agxget(np, possym);
  41. if (p[0]) {
  42. pvec = ND_pos(np);
  43. c = '\0';
  44. if (sscanf(p, "%lf,%lf%c", pvec, pvec + 1, &c) >= 2) {
  45. if (PSinputscale > 0.0) {
  46. int j;
  47. for (j = 0; j < NDIM; j++)
  48. pvec[j] = pvec[j] / PSinputscale;
  49. }
  50. ND_pinned(np) = P_SET;
  51. if (c == '!'
  52. || (pinsym && mapbool(agxget(np, pinsym))))
  53. ND_pinned(np) = P_PIN;
  54. } else
  55. fprintf(stderr,
  56. "Warning: node %s, position %s, expected two floats\n",
  57. agnameof(np), p);
  58. }
  59. }
  60. }
  61. /* init_edge:
  62. */
  63. static void init_edge(edge_t * e, attrsym_t * E_len)
  64. {
  65. agbindrec(e, "Agedgeinfo_t", sizeof(Agedgeinfo_t), true); //node custom data
  66. ED_factor(e) = late_double(e, E_weight, 1.0, 0.0);
  67. ED_dist(e) = late_double(e, E_len, fdp_parms->K, 0.0);
  68. common_init_edge(e);
  69. }
  70. static void init_node(node_t * n)
  71. {
  72. common_init_node(n);
  73. ND_pos(n) = gv_calloc(GD_ndim(agraphof(n)), sizeof(double));
  74. gv_nodesize(n, GD_flip(agraphof(n)));
  75. }
  76. void fdp_init_node_edge(graph_t * g)
  77. {
  78. attrsym_t *E_len;
  79. node_t *n;
  80. edge_t *e;
  81. int nn;
  82. int i;
  83. aginit(g, AGNODE, "Agnodeinfo_t", sizeof(Agnodeinfo_t), true);
  84. processClusterEdges(g);
  85. /* Get node count after processClusterEdges(), as this function may
  86. * add new nodes.
  87. */
  88. nn = agnnodes(g);
  89. GD_neato_nlist(g) = gv_calloc(nn + 1, sizeof(node_t*));
  90. for (i = 0, n = agfstnode(g); n; n = agnxtnode(g, n)) {
  91. init_node (n);
  92. GD_neato_nlist(g)[i] = n;
  93. ND_id(n) = i++;
  94. }
  95. E_len = agattr(g,AGEDGE, "len", NULL);
  96. for (n = agfstnode(g); n; n = agnxtnode(g, n)) {
  97. for (e = agfstout(g, n); e; e = agnxtout(g, e)) {
  98. init_edge(e, E_len);
  99. }
  100. }
  101. initialPositions(g);
  102. }
  103. static void cleanup_subgs(graph_t * g)
  104. {
  105. graph_t *subg;
  106. int i;
  107. for (i = 1; i <= GD_n_cluster(g); i++) {
  108. subg = GD_clust(g)[i];
  109. free_label(GD_label(subg));
  110. if (GD_alg(subg)) {
  111. free(PORTS(subg));
  112. free(GD_alg(subg));
  113. }
  114. cleanup_subgs(subg);
  115. }
  116. free (GD_clust(g));
  117. }
  118. static void fdp_cleanup_graph(graph_t * g)
  119. {
  120. cleanup_subgs(g);
  121. free(GD_neato_nlist(g));
  122. free(GD_alg(g));
  123. }
  124. void fdp_cleanup(graph_t * g)
  125. {
  126. node_t *n;
  127. edge_t *e;
  128. for (n = agfstnode(g); n; n = agnxtnode(g, n)) {
  129. for (e = agfstout(g, n); e; e = agnxtout(g, e)) {
  130. gv_cleanup_edge(e);
  131. }
  132. gv_cleanup_node(n);
  133. }
  134. fdp_cleanup_graph(g);
  135. }
  136. /**
  137. * @dir lib/fdpgen
  138. * @brief [Force-Directed Placement](https://en.wikipedia.org/wiki/Force-directed_graph_drawing) layout engine, API fdpgen/fdp.h
  139. * @ingroup engines
  140. *
  141. * [FDP layout user manual](https://graphviz.org/docs/layouts/fdp/)
  142. *
  143. * Other @ref engines
  144. */