rhp.h 9.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215
  1. /*
  2. * Copyright 2021
  3. *
  4. * This program is free software: you can redistribute it and/or modify
  5. * it under the terms of the GNU General Public License as published by
  6. * the Free Software Foundation, either version 3 of the License, or
  7. * (at your option) any later version.
  8. *
  9. * This program is distributed in the hope that it will be useful,
  10. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. * GNU General Public License for more details.
  13. *
  14. * You should have received a copy of the GNU General Public License
  15. * along with this program. If not, see <http://www.gnu.org/licenses/>.
  16. *
  17. * SPDX-License-Identifier: GPL-3.0+
  18. * License-Filename: LICENSE
  19. */
  20. /* relative horizontal positioning in a single c source file.
  21. * this is used to draw structure and organisation in data but
  22. * the spring-embedders are good at density and change in data.
  23. * during layout memory usage may almost double and all that
  24. * extra memory is free()'ed at deinit().
  25. * at drawing the memory usage is much lower.
  26. * this can also be compiled as a lib.
  27. * this barycenter is also a trial-and-error algo and nobody knows
  28. * how to steer it to get good resuls. It may find good solutions
  29. * which are difficult to understand for humans in a drawing.
  30. * cpu temperature goes up 60% with large graph data.
  31. * theoretical limit is 2G nodes + 2G edges
  32. * practical limit is 2M nodes + 2M edges
  33. * current average graph has 1000-10000 nodes+edges
  34. * The layout theory is described in this book :
  35. * Graph Drawing And Applications For Software And Knowledge Engineers
  36. * ISBN10 9810248792 or ISBN13 9789810248796
  37. * Kozo Sugiyama, World Scientific Publishing Co Pte Ltd
  38. */
  39. #ifndef RHP_H
  40. #define RHP_H 1
  41. /* stdint is used for the int64_t data type or use (long long int) 64 bits */
  42. #include <stdint.h>
  43. /* version info example "1.0" */
  44. extern char *rhp_version (void);
  45. /* init layouter
  46. * this must be done before any of the other routines below.
  47. * when the logname is NULL or (char *)0 no log output file is created.
  48. * when there is a logname specified a file with that name is created
  49. * and log messages are written to it. at deinit() the file is closed.
  50. * the log file is a human readable descriprion what the layouter is doing.
  51. * log messages with a '!' are error messages and always put on stderr.
  52. * if loglevel has a value then log messages are generated if there
  53. * is a logname and if loglevel > 1 then memory log messages are generated.
  54. * if logname is "" then output is stdout
  55. */
  56. extern void rhp_init (char *logname, int loglevel);
  57. /* de-init lyouter and free() all memory and close optional logfile.
  58. * after deinit() routines below do not react anymore until init() is done.
  59. */
  60. extern void rhp_deinit (void);
  61. /* add node at level
  62. * the num must be a uniq node number in 32bits int range
  63. * the level must be the relative vertical level of the node
  64. * the data can be used to pass additional data casted on
  65. * this data is not used by layouter but presented again
  66. * at calls done via rhp_node_foreach()
  67. * this routine returns 0 if everything is oke
  68. * this routine returns 1 at error
  69. * errors are num or level is below zero or too high
  70. * or node did already exist with given node number
  71. */
  72. extern int rhp_addnode (int num, int level, void *data);
  73. /* add edge from node number fnode to tnode
  74. * the fnode and tnode numbers are the from and to nodes
  75. * to create a directed edge between and both must have
  76. * been defined earlir with rhp_addnode().
  77. * the num must be a uniq edge number to identify this edge.
  78. * the data can be used to pass additional data casted on
  79. * this data is not used by layouter but presented again
  80. * at calls done via rhp_edge_foreach()
  81. * the to-node must be 1 one level more the the from-node.
  82. * if all oke then this return status (int) 0
  83. * this returns 1 if node numbers are out of range,
  84. * or nodes are not defined earlier or if the lenght
  85. * of the edge is longer then 1 one relative level.
  86. * when edges or nodes are rejected the the layout()
  87. * can continue with the nodes+edges passed on.
  88. */
  89. extern int rhp_addedge (int num, int fnode, int tnode, void *data);
  90. /* run layouter
  91. * the options can be 0 - not implemented yet
  92. * runs the barycenter to determine relative horzintal position
  93. * with lowest edge crossing count but there must be at least
  94. * one node in the graph data.
  95. * when there are 0 or 1 edges the crossing count is zero.
  96. * when there are 1 or 2 nodes the crossing count is zero.
  97. * to get the result node posions use rhp_node_foreach()
  98. * int nodeweightadjust = 0 for left node weight adjust
  99. * int nodeweightadjust = 1 for average node weight adjust
  100. */
  101. extern void rhp_layout (int options, int nodeweightadjust);
  102. /* get layouter data during iteration
  103. * this runs the supplied callback() routine at every iteration
  104. * of the layout. When the initial edge crossing count is zero
  105. * then this routine is never called.
  106. * the callback must return 0 to continue layouting or can
  107. * return 1 to stop the layouter algorithm.
  108. * when the callback() function runs the layouter pauses
  109. * and waits for the callback() to finish.
  110. * the callback routine gets the current iteration in iter,
  111. * the max. number of iterarion in maxiter, the current
  112. * edge crossings in ncross and the previous edge crossings
  113. * count in previous_ncross. the reduction number is the
  114. * amount of edge crossing reduction in percentage or
  115. * greater then 100% when there was an edge cross increase.
  116. * with this data the callback() routine can decide to stop
  117. * the layouer.
  118. * the better parameter is 1 if new drawing improved on
  119. * edge crossings or 0 if not improved.
  120. * the numbers improvements and notimprovements are the
  121. * number of times the drawing did improve or not-improve.
  122. * bot these numbers can be 0 and stay zero during layout.
  123. * the ratio of these improvement numbers can indicate if
  124. * it makes sense to continue layout similar as the difference
  125. * between crossing improvement numbers when that gets low.
  126. * the callback() routine can run rhp_node_foreach() and
  127. * rhp_edge_foreach() to get the details of the current
  128. * graph drawing status and use it to snapshot or draw it
  129. * as a continuous changing drawing during layout to see
  130. * the layout algorithm lowering the number of edge crossings.
  131. * if there is no callback() routine supplied (NULL) then
  132. * error message is printed and the routine call is ignored.
  133. */
  134. extern void
  135. rhp_layout_callback (int (*getlayoutdata)
  136. (int iter, int maxiter, uint64_t ncross, uint64_t previous_ncross, uint64_t reduction, int better, int improvements, int notimprovements));
  137. /* get node data and the calculated positions
  138. * this runs a supplied callback routine for every node
  139. * the callback routine gets the node number as supplied,
  140. * the level as supplied and the calculated pos position.
  141. * the data is the supplied data and can be used similar.
  142. * when the callback function needs to stop the iteration
  143. * over the node list then it must return a non-zero status
  144. * and that status is returned by rho_node_foreach()
  145. * return is 0 from this routine if everything is oke or no data.
  146. */
  147. extern int rhp_node_foreach (int (*getnodedata) (int num, int level, int pos, void *data));
  148. /* instead of foreach() get level of given node or -1 at error */
  149. extern int rhp_node_get_level (int num);
  150. /* instead of foreach() get position of given node or -1 at error */
  151. extern int rhp_node_get_position (int num);
  152. /* instead of foreach() get data of given node or -1 at error */
  153. extern void *rhp_node_get_data (int num);
  154. /* get edge data
  155. * this runs a supplied callback routine for every edge
  156. * the callback routine gets the edge number as supplied,
  157. * with the from-node number, level and position in fnum,
  158. * flevel and fpos and same for the to-node in tnum, tlevel
  159. * and tpos and the 64-bits signed int number of edge cossings
  160. * of this edge with other edges and the supplied data to use.
  161. * when the callback function needs to stop the iteration
  162. * over the edge list then it must return a non-zero status
  163. * and that status is returned by rho_node_foreach()
  164. * return is 0 from this routine if everything is oke or no data.
  165. */
  166. extern int rhp_edge_foreach (int (*getedgedata) (int num, int fnum, int flevel, int fpos, int tnum, int tlevel, int tpos, int64_t ecross, void *data));
  167. /* calculate initial crossings
  168. * this returns the initial graph edge crossings as 64bits number
  169. */
  170. extern int64_t rhp_initial_crossings (void);
  171. /* calculate crossings
  172. * this returns the current graph edge crossings as 64bits number
  173. */
  174. extern int64_t rhp_current_crossings (void);
  175. /* calculate crossings at level
  176. * this returns the graph edge crossings as 64bits number for specified level
  177. */
  178. extern int64_t rhp_current_crossings_at_level (int level);
  179. /* get number of nodes in specified level */
  180. extern int rhp_nodes_in_level (int level);
  181. /* get number of nodes in layouter for all levels */
  182. extern int rhp_nodes_in_layout (void);
  183. /* get number of edges in layouter for all levels */
  184. extern int rhp_edges_in_layout (void);
  185. /* emscripten can cross compile llvm to javascript as this source.
  186. * node-ffi can interface this to javascript using node.js
  187. */
  188. #endif
  189. /* End. */