sfgdemo.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500
  1. /*
  2. * Copyright t lefering
  3. * parts are (C) Universitaet Passau 1986-1991
  4. * parts are Copyright (C) 1998-2021 Free Software Foundation, Inc.
  5. * parts are Copyright (C) Felix von Leitner from dietlibc
  6. *
  7. * https://notabug.org/mooigraph/sfgraph
  8. *
  9. * This program is free software: you can redistribute it and/or modify
  10. * it under the terms of the GNU General Public License as published by
  11. * the Free Software Foundation, either version 3 of the License, or
  12. * (at your option) any later version.
  13. *
  14. * This program is distributed in the hope that it will be useful,
  15. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  16. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  17. * GNU General Public License for more details.
  18. *
  19. * You should have received a copy of the GNU General Public License
  20. * along with this program. If not, see <http://www.gnu.org/licenses/>.
  21. *
  22. * These are the four essential freedoms with GNU GPL software:
  23. * 1: freedom to run the program, for any purpose
  24. * 2: freedom to study how the program works, and change it to make it do what you wish
  25. * 3: freedom to redistribute copies to help your Free Software friends
  26. * 4: freedom to distribute copies of your modified versions to your Free Software friends
  27. * , ,
  28. * / \
  29. * ((__-^^-,-^^-__))
  30. * `-_---' `---_-'
  31. * `--|o` 'o|--'
  32. * \ ` /
  33. * ): :(
  34. * :o_o:
  35. * "-"
  36. *
  37. * SPDX-License-Identifier: GPL-3.0+
  38. * License-Filename: LICENSE
  39. */
  40. /* demo program how to use the sfg.c Single File Graph layout file
  41. * compile with gcc sfgdemo.c sfg.c -o sfgdemo
  42. * usage:
  43. * ./sfgdemo
  44. * ./sfgdemo input.txt output.ps
  45. */
  46. #include <stdio.h>
  47. #include <string.h>
  48. #include "sfg.h"
  49. static char *namein = NULL;
  50. static char *nameout = NULL;
  51. static FILE *fin = NULL;
  52. static FILE *fos = NULL;
  53. static char lbuf[1024];
  54. static void readfile(void);
  55. static void head(void);
  56. static void tail(void);
  57. /* this gets the node data after layout */
  58. static int getnodedata(int num, int level, int pos, int xpos, int ypos, int tx, int ty, int nselfedges, int type,
  59. int indegree, int outdegree, int ly0, int ly1);
  60. /* this gets the node data after layout */
  61. static int getnodedataps(int num, int level, int pos, int xpos, int ypos, int tx, int ty, int nselfedges, int type,
  62. int indegree, int outdegree, int ly0, int ly1);
  63. /* this gets the edge data after layout */
  64. static int getedgedata(int num, int from, int to, int type, int rev);
  65. /* this gets the edge data after layout */
  66. static int getedgedataps(int num, int from, int to, int type, int rev);
  67. int main(int argc, char *argv[])
  68. {
  69. int status = 0;
  70. int nn = 0;
  71. int ne = 0;
  72. if (argc == 1) {
  73. namein = "sfgdemo.txt";
  74. nameout = "sfgdemo.svg";
  75. } else if (argc == 3) {
  76. namein = argv[1];
  77. nameout = argv[2];
  78. } else {
  79. printf("Usage: ./sfgdemo input.txt output.svg or ./sfgdemo\n");
  80. return (0);
  81. }
  82. if (argc == 1) {
  83. printf("demo of sfg Single File Graph layout library version %d\n", sfg_version());
  84. /* init to start */
  85. status = sfg_init();
  86. if (status < 0) { /* error */
  87. }
  88. /* add few nodes starting at 1, no user data, small texlabel area */
  89. for (nn = 1; nn < 4; nn++) {
  90. status = sfg_addnode(nn, 25, 20);
  91. if (status < 0) { /* error */
  92. break;
  93. }
  94. }
  95. /* add few edges with number starting at 1 */
  96. ne++;
  97. status = sfg_addedge(ne, /* from */ 1, /* to */ 2, 0, 0);
  98. if (status < 0) { /* error */
  99. }
  100. ne++;
  101. status = sfg_addedge(ne, /* from */ 1, /* to */ 3, 10, 10);
  102. if (status < 0) { /* error */
  103. }
  104. /* set min (x,y) spacing of nodes */
  105. status = sfg_xspacing(5);
  106. if (status < 0) { /* error */
  107. }
  108. status = sfg_yspacing(15);
  109. if (status < 0) { /* error */
  110. }
  111. /* run layout */
  112. status = sfg_layout();
  113. if (status < 0) { /* error */
  114. }
  115. printf("drawing has size (%d,%d) with %d levels\n", sfg_maxx(), sfg_maxy(), sfg_nlevels());
  116. /* get node data */
  117. status = sfg_node_foreach(getnodedata);
  118. if (status < 0) { /* error */
  119. }
  120. /* get edge data */
  121. status = sfg_edge_foreach(getedgedata);
  122. if (status < 0) { /* error */
  123. }
  124. /* de-init to finish */
  125. status = sfg_deinit();
  126. if (status < 0) { /* error */
  127. }
  128. }
  129. /* now run it on file */
  130. fin = fopen(namein, "r");
  131. fos = fopen(nameout, "w");
  132. if (fin == NULL) {
  133. printf("cannot open file %s for reading\n", namein);
  134. return (0);
  135. }
  136. if (fos == NULL) {
  137. printf("cannot open file %s for writing\n", nameout);
  138. return (0);
  139. }
  140. fflush(stdout);
  141. /* re-init and read input file, then generate postscript */
  142. /* init to start */
  143. status = sfg_init();
  144. if (status < 0) { /* error */
  145. }
  146. readfile();
  147. /* run layout */
  148. status = sfg_layout();
  149. if (status < 0) { /* error */
  150. }
  151. printf("drawing has size (%d,%d) with %d levels and %d nodes with %d edges\n", sfg_maxx(), sfg_maxy(), sfg_nlevels(),
  152. sfg_nnodes(), sfg_nedges());
  153. head();
  154. /* get node data */
  155. status = sfg_node_foreach(getnodedataps);
  156. if (status < 0) { /* error */
  157. }
  158. /* get edge data */
  159. status = sfg_edge_foreach(getedgedataps);
  160. if (status < 0) { /* error */
  161. }
  162. tail();
  163. /* de-init to finish */
  164. status = sfg_deinit();
  165. if (status < 0) { /* error */
  166. }
  167. return (0);
  168. }
  169. /* this gets the node data after layout */
  170. static int getnodedata(int num, int level, int pos, int xpos, int ypos, int tx, int ty, int nselfedges, int type,
  171. int indegree, int outdegree, int ly0, int ly1)
  172. {
  173. /* return(1); to stop the callback */
  174. if (xpos) {
  175. }
  176. if (ypos) {
  177. }
  178. if (tx) {
  179. }
  180. if (ty) {
  181. }
  182. if (nselfedges) {
  183. }
  184. if (type) {
  185. }
  186. if (indegree) {
  187. }
  188. if (outdegree) {
  189. }
  190. if (ly0) {
  191. }
  192. if (ly1) {
  193. }
  194. printf("node %d relative pos (%d,%d) in/outdegree %d:%d final pos (%d,%d)\n", num, pos, level, indegree, outdegree, xpos,
  195. ypos);
  196. /* return 0 to continue callbacks */
  197. return (0);
  198. }
  199. /* this gets the edge data after layout */
  200. static int getedgedata(int num, int from, int to, int type, int rev)
  201. {
  202. /* return(1); to stop the callback */
  203. if (type) {
  204. }
  205. printf("edge %d from node %d to %d reversed=%d\n", num, from, to, rev);
  206. /* return 0 to continue callbacks */
  207. return (0);
  208. }
  209. static void readfile(void)
  210. {
  211. int ch = 0;
  212. int i = 0;
  213. int n = 0;
  214. int fn = 0;
  215. int tn = 0;
  216. int status = 0;
  217. int ne = 0;
  218. for (;;) {
  219. /* fill buffer */
  220. memset(lbuf, 0, 1024);
  221. i = 0;
  222. for (;;) {
  223. ch = fgetc(fin);
  224. if (ch == EOF) {
  225. break;
  226. }
  227. if (ch == '\n') {
  228. break;
  229. }
  230. lbuf[i] = ch;
  231. if (i > 1023) {
  232. break;
  233. }
  234. i++;
  235. }
  236. /* check data in buffer */
  237. if (strlen(lbuf)) {
  238. if (lbuf[0] == '#') {
  239. /* comment line */ } else {
  240. n = sscanf(lbuf, "%d %d", &fn, &tn);
  241. if (n == 1) {
  242. /* node */
  243. printf("parsed node number %d\n", fn);
  244. status = sfg_addnode(fn, 25, 20);
  245. if (status < 0) { /* error */
  246. break;
  247. }
  248. } else if (n == 2) {
  249. /* edge */
  250. printf("parsed edge from node %d to node %d\n", fn, tn);
  251. ne++;
  252. status = sfg_addedge(ne, /* from */ fn, /* to */ tn, 0, 0);
  253. if (status < 0) { /* error */
  254. }
  255. } else {
  256. /* skip line */
  257. }
  258. }
  259. }
  260. if (ch == EOF) {
  261. break;
  262. }
  263. }
  264. /* testing add few single nodes */
  265. if (0) {
  266. status = sfg_addnode(100, 25, 20);
  267. if (status < 0) { /* error */
  268. }
  269. status = sfg_addnode(101, 25, 40);
  270. if (status < 0) { /* error */
  271. }
  272. status = sfg_addnode(102, 25, 30);
  273. if (status < 0) { /* error */
  274. }
  275. }
  276. return;
  277. }
  278. /* this gets the node data after layout, see sfg.h */
  279. static int getnodedataps(int num, int level, int pos, int xpos, int ypos, int tx, int ty, int nselfedges, int type,
  280. int indegree, int outdegree, int ly0, int ly1)
  281. {
  282. /* return(1); to stop the callback */
  283. if (num) {
  284. }
  285. if (level) {
  286. }
  287. if (pos) {
  288. }
  289. if (xpos) {
  290. }
  291. if (ypos) {
  292. }
  293. if (nselfedges) {
  294. /* self edges at the node must be drawn here */
  295. }
  296. if (type) {
  297. }
  298. if (indegree) {
  299. }
  300. if (outdegree) {
  301. }
  302. if (ly0) {
  303. }
  304. if (ly1) {
  305. }
  306. fprintf(fos,
  307. " <rect id=\"node_%d\" height=\"%d\" width=\"%d\" y=\"%d\" x=\"%d\" stroke-linecap=\"null\" stroke-linejoin=\"null\" stroke-dasharray=\"null\" stroke=\"#000000\" fill=\"#7fff00\"/>\n",
  308. num, ty, tx, ypos, xpos);
  309. if (tx && ty) {
  310. fprintf(fos, " <text x=\"%d\" y=\"%d\" class=\"small\">%d</text>\n", xpos, ypos + ty, num);
  311. }
  312. /* return 0 to continue callbacks */
  313. return (0);
  314. }
  315. /* this gets the edge data after layout, see sfg.h */
  316. static int getedgedataps(int num, int from, int to, int type, int rev)
  317. {
  318. int fx = 0;
  319. int fy = 0;
  320. int tx = 0;
  321. int ty = 0;
  322. int typef = 0;
  323. int typet = 0;
  324. int szxf = 0;
  325. int szyf = 0;
  326. int szxt = 0;
  327. int szyt = 0;
  328. int ly = 0;
  329. int ryf = 0;
  330. int ryt = 0;
  331. char *scolor = "";
  332. /* todo this should also guide the dummy nodes to get a better drawing */
  333. if (num) {
  334. }
  335. if (rev) {
  336. /* draw arrow at from-node */
  337. scolor = "#0f0fff";
  338. } else {
  339. /* draw arrow at to-node */
  340. scolor = "#000000";
  341. }
  342. /* return(1); to stop the callback */
  343. /* get type of nodes */
  344. typef = sfg_nodetype(from);
  345. typet = sfg_nodetype(to);
  346. /* get (x,y) pos of nodes */
  347. fx = sfg_nodexpos(from);
  348. fy = sfg_nodeypos(from);
  349. tx = sfg_nodexpos(to);
  350. ty = sfg_nodeypos(to);
  351. /* get sizes of nodes */
  352. szxf = sfg_nodexsize(from);
  353. szyf = sfg_nodeysize(from);
  354. szxt = sfg_nodexsize(to);
  355. szyt = sfg_nodeysize(to);
  356. /* relative y positions of from/to node */
  357. ryf = sfg_noderelypos(from);
  358. ryt = sfg_noderelypos(to);
  359. if (ryf) {
  360. }
  361. if (ryt) {
  362. }
  363. /* type of edge */
  364. if (type == 3) {
  365. /* this horizontal edge must be drawn different */
  366. if (fy + szyf > ty + szyt) {
  367. ly = fy + szyf;
  368. } else {
  369. ly = ty + szyt;
  370. }
  371. ly = ly + 4;
  372. fx = fx + (szxf / 2);
  373. fy = fy + szyf;
  374. tx = tx + (szxt / 2);
  375. ty = ty + szyt;
  376. fprintf(fos,
  377. " <line id=\"edge_%d\" y2=\"%d\" x2=\"%d\" y1=\"%d\" x1=\"%d\" stroke-linecap=\"null\" stroke-linejoin=\"null\" stroke-dasharray=\"null\" stroke-width=\"2\" stroke=\"%s\" fill=\"none\"/>\n",
  378. num, ly, fx, fy, fx, scolor);
  379. fprintf(fos,
  380. " <line id=\"edge_%d\" y2=\"%d\" x2=\"%d\" y1=\"%d\" x1=\"%d\" stroke-linecap=\"null\" stroke-linejoin=\"null\" stroke-dasharray=\"null\" stroke-width=\"2\" stroke=\"%s\" fill=\"none\"/>\n",
  381. num, ly, tx, ly, fx, scolor);
  382. fprintf(fos,
  383. " <line id=\"edge_%d\" y2=\"%d\" x2=\"%d\" y1=\"%d\" x1=\"%d\" stroke-linecap=\"null\" stroke-linejoin=\"null\" stroke-dasharray=\"null\" stroke-width=\"2\" stroke=\"%s\" fill=\"none\"/>\n",
  384. num, ty, tx, ly, tx, scolor);
  385. } else {
  386. /* if from node is regular, tune the edge conn. point */
  387. if (typef == 1) {
  388. fx = fx + (szxf / 2);
  389. fy = fy + szyf;
  390. }
  391. /* if to node is regular, tune the edge conn. point */
  392. if (typet == 1) {
  393. tx = tx + (szxt / 2);
  394. if (szyt) {
  395. }
  396. }
  397. fprintf(fos,
  398. " <line id=\"edge_%d\" y2=\"%d\" x2=\"%d\" y1=\"%d\" x1=\"%d\" stroke-linecap=\"null\" stroke-linejoin=\"null\" stroke-dasharray=\"null\" stroke-width=\"2\" stroke=\"%s\" fill=\"none\"/>\n",
  399. num, ty, tx, fy, fx, scolor);
  400. }
  401. /* return 0 to continue callbacks */
  402. return (0);
  403. }
  404. /* header */
  405. static void head(void)
  406. {
  407. /* make image +5 y pixels larger to allow for horizontal edge */
  408. fprintf(fos,
  409. "<svg width=\"%d\" height=\"%d\" xmlns=\"http://www.w3.org/2000/svg\" xmlns:svg=\"http://www.w3.org/2000/svg\">\n",
  410. sfg_maxx() + 1, sfg_maxy() + 5);
  411. fprintf(fos, "%s\n", " <g>");
  412. fprintf(fos, "%s\n", " <title>sfgdemo</title>");
  413. fprintf(fos, "%s\n", " <style>");
  414. fprintf(fos, "%s\n", " .small { font: italic 15px sans-serif; }");
  415. fprintf(fos, "%s\n", " </style>");
  416. return;
  417. }
  418. /* footer */
  419. static void tail(void)
  420. {
  421. fprintf(fos, "%s\n", " </g>");
  422. fprintf(fos, "%s\n", "</svg>");
  423. return;
  424. }
  425. /* end */