pos3.c 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816
  1. /*
  2. * Copyright 2021
  3. * (C) Universitaet Passau 1986-1991
  4. *
  5. * This program is free software: you can redistribute it and/or modify
  6. * it under the terms of the GNU General Public License as published by
  7. * the Free Software Foundation, either version 3 of the License, or
  8. * (at your option) any later version.
  9. *
  10. * This program is distributed in the hope that it will be useful,
  11. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. * GNU General Public License for more details.
  14. *
  15. * You should have received a copy of the GNU General Public License
  16. * along with this program. If not, see <http://www.gnu.org/licenses/>.
  17. *
  18. * These are the four essential freedoms with GNU GPL software:
  19. * 1: freedom to run the program, for any purpose
  20. * 2: freedom to study how the program works, and change it to make it do what you wish
  21. * 3: freedom to redistribute copies to help your Free Software friends
  22. * 4: freedom to distribute copies of your modified versions to your Free Software friends
  23. * , ,
  24. * / \
  25. * ((__-^^-,-^^-__))
  26. * `-_---' `---_-'
  27. * `--|o` 'o|--'
  28. * \ ` /
  29. * ): :(
  30. * :o_o:
  31. * "-"
  32. *
  33. * SPDX-License-Identifier: GPL-3.0+
  34. * License-Filename: LICENSE
  35. */
  36. #include "config.h"
  37. #include <stdio.h>
  38. #include <stdlib.h>
  39. #include <math.h>
  40. #include "splay-tree.h"
  41. #include "main.h"
  42. #include "hier.h"
  43. #include "pos.h"
  44. #include "pos3.h"
  45. #include "dpmem.h"
  46. /* min. distance between 2 nodes */
  47. static int xmindist = 1;
  48. static int ymindist = 1;
  49. /* level step size, 1 or 2 */
  50. static int ssize = 1;
  51. struct node_data {
  52. struct gml_node *node;
  53. int priority;
  54. int done;
  55. };
  56. /* */
  57. static struct node_data *nl = NULL;
  58. /* */
  59. static struct node_data **dl = NULL;
  60. /* index in in dl */
  61. static int *cix = NULL;
  62. /* y size of levels */
  63. static int *szy = NULL;
  64. /* how many connection edges from previous level */
  65. static int upper_connectivity(struct gml_node *node)
  66. {
  67. return (node->indegree);
  68. }
  69. /* how many connection edges to next level */
  70. static int lower_connectivity(struct gml_node *node)
  71. {
  72. return (node->outdegree);
  73. }
  74. /* avg x pos of incoming edges */
  75. static int upper_barycenter(struct gml_node *node)
  76. {
  77. struct gml_elist *el = NULL;
  78. int result = 0;
  79. double r = 0.0;
  80. int abx = 0;
  81. /* incoming edges x sum for_targetlist(node,edge) */
  82. el = node->incoming_e;
  83. while (el) {
  84. if (ssize == 1) {
  85. /* todo testing +bbx/2 */
  86. abx = el->edge->from_node->absx + (el->edge->from_node->bbx / 2);
  87. } else {
  88. abx = el->edge->from_node->incoming_e->edge->from_node->absx;
  89. }
  90. result = result + abx;
  91. el = el->next;
  92. }
  93. if (result == 0) {
  94. r = (0.0);
  95. } else {
  96. r = (result / upper_connectivity(node));
  97. }
  98. if (1) {
  99. r = round(r);
  100. }
  101. return ((int)r);
  102. }
  103. /* avg x pos of outgoing edges */
  104. static int lower_barycenter(struct gml_node *node)
  105. {
  106. struct gml_elist *el = NULL;
  107. int result = 0;
  108. double r = 0.0;
  109. int abx = 0;
  110. /* get avg. x pos of outgoing edges for_sourcelist(node,edge) */
  111. el = node->outgoing_e;
  112. while (el) {
  113. if (ssize == 1) {
  114. /* todo testing +bbx/2 */
  115. abx = el->edge->to_node->absx + (el->edge->to_node->bbx / 2);
  116. } else {
  117. abx = el->edge->to_node->outgoing_e->edge->to_node->absx;
  118. }
  119. result = result + abx;
  120. el = el->next;
  121. }
  122. if (result == 0) {
  123. r = (0.0);
  124. } else {
  125. r = (result / lower_connectivity(node));
  126. }
  127. if (1) {
  128. r = round(r);
  129. }
  130. return ((int)r);
  131. }
  132. static void sort(int n)
  133. {
  134. int i = 0;
  135. int j = 0;
  136. struct node_data h;
  137. for (j = n - 1; j > 0; j--) {
  138. for (i = 0; i < j; i++) {
  139. /* issue here */
  140. if (nl[i].node && nl[i + 1].node) {
  141. if (nl[i].node->relx > nl[i + 1].node->relx) {
  142. /* swap */
  143. h = nl[i];
  144. nl[i] = nl[i + 1];
  145. nl[i + 1] = h;
  146. }
  147. } else {
  148. printf("%s(): nil nodes nl[i].node=%p nl[i + 1].node=%p\n", __func__, (void *)nl[i].node, (void *)nl[i + 1].node);
  149. }
  150. }
  151. }
  152. return;
  153. }
  154. /* prepare level */
  155. static void make_node_list_up(struct gml_graph *g, int l)
  156. {
  157. int i = 0;
  158. nl = dl[l];
  159. if (nl == NULL) {
  160. printf("%s(): nil nl at level %d\n", __func__, l);
  161. return;
  162. }
  163. for (i = 0; i < g->nnodes_of_level[l]; i++) {
  164. nl[i].done = 0;
  165. if (nl[i].node->dummy) {
  166. nl[i].priority = 1000 * nl[i].node->relx; // (100000 + nl[i].node->relx);
  167. // nl[i].priority = (1000 * (g->nnodes_of_level[l+2] + 1));
  168. } else {
  169. nl[i].priority = lower_connectivity(nl[i].node);
  170. }
  171. }
  172. return;
  173. }
  174. /* prepare level */
  175. static void make_node_list_down(struct gml_graph *g, int l)
  176. {
  177. int i = 0;
  178. nl = dl[l];
  179. if (nl == NULL) {
  180. printf("%s(): nil nl at level %d\n", __func__, l);
  181. fflush(stdout);
  182. return;
  183. }
  184. for (i = 0; i < g->nnodes_of_level[l]; i++) {
  185. nl[i].done = 0;
  186. if (nl[i].node->dummy) {
  187. nl[i].priority = 1000 * nl[i].node->relx; //(100000 + nl[i].node->relx);
  188. } else {
  189. nl[i].priority = upper_connectivity(nl[i].node);
  190. }
  191. }
  192. return;
  193. }
  194. /* get number of node with highest prio which is not done yet */
  195. static int find_next(int n)
  196. {
  197. int nindex = 0;
  198. int i = 0;
  199. int highest_priority = 0;
  200. for (i = 0; i < n; i++) {
  201. if (nl) {
  202. if (nl[i].priority >= highest_priority) {
  203. if (nl[i].done == 0) {
  204. nindex = i;
  205. highest_priority = nl[i].priority;
  206. }
  207. }
  208. }
  209. }
  210. return (nindex);
  211. }
  212. static void do_down(struct gml_graph *g, int l)
  213. {
  214. int i = 0;
  215. int index = 0;
  216. int j = 0;
  217. int optimal_position = 0;
  218. int distance = 0;
  219. int possible_distance = 0;
  220. if (nl == NULL) { /*shuldnothappen */
  221. return;
  222. }
  223. for (i = 0; i < g->nnodes_of_level[l]; i++) {
  224. index = find_next(g->nnodes_of_level[l]);
  225. optimal_position = upper_barycenter(nl[index].node);
  226. if (optimal_position == 0) {
  227. optimal_position = nl[index].node->absx;
  228. }
  229. if (optimal_position < nl[index].node->absx) {
  230. distance = nl[index].node->absx - optimal_position;
  231. possible_distance = 0;
  232. j = index;
  233. do {
  234. if (j > 0) {
  235. possible_distance += nl[j].node->absx - (nl[j - 1].node->absx + nl[j - 1].node->bbx) - xmindist;
  236. } else {
  237. /* j==0, no nodes at left */
  238. possible_distance += (nl[j].node->absx + nl[j].node->bbx) /* XXX +bbx? */ -xmindist;
  239. }
  240. j--;
  241. }
  242. while ((j >= 0) && (nl[j].done == 0));
  243. if (possible_distance < distance) {
  244. distance = possible_distance;
  245. }
  246. j = index;
  247. while (distance > 0) {
  248. int d = 0;
  249. int k = 0;
  250. if (j == 0) {
  251. d = distance;
  252. } else {
  253. if (nl[j].node->absx - (nl[j - 1].node->absx + nl[j - 1].node->bbx) - xmindist < distance) {
  254. d = nl[j].node->absx - (nl[j - 1].node->absx + nl[j - 1].node->bbx) - xmindist;
  255. } else {
  256. d = distance;
  257. }
  258. }
  259. for (k = j; k <= index; k++) {
  260. nl[k].node->absx -= d;
  261. }
  262. j--;
  263. distance -= d;
  264. }
  265. } else {
  266. distance = optimal_position - nl[index].node->absx;
  267. possible_distance = 0;
  268. j = index;
  269. do {
  270. if (j < g->nnodes_of_level[l] - 1) {
  271. possible_distance += nl[j + 1].node->absx - (nl[j].node->absx + nl[j].node->bbx) - xmindist;
  272. } else {
  273. /* j == g->nnodes_of_level[l]-1, no nodes rechts */
  274. possible_distance += distance;
  275. }
  276. j++;
  277. }
  278. while ((j < g->nnodes_of_level[l]) && (nl[j].done == 0));
  279. if (possible_distance < distance) {
  280. distance = possible_distance;
  281. }
  282. j = index;
  283. while (distance > 0) {
  284. int d = 0;
  285. int k = 0;
  286. if (j == g->nnodes_of_level[l] - 1) {
  287. d = distance;
  288. } else {
  289. if (nl[j + 1].node->absx - (nl[j].node->absx + nl[j].node->bbx) - xmindist < distance) {
  290. d = nl[j + 1].node->absx - (nl[j].node->absx + nl[j].node->bbx) - xmindist;
  291. } else {
  292. d = distance;
  293. }
  294. }
  295. for (k = index; k <= j; k++) {
  296. nl[k].node->absx += d;
  297. }
  298. j++;
  299. distance -= d;
  300. }
  301. }
  302. nl[index].done = 1; /* TRUE */
  303. }
  304. return;
  305. }
  306. static void do_up(struct gml_graph *g, int l)
  307. {
  308. int i = 0;
  309. int index = 0;
  310. int j = 0;
  311. int optimal_position = 0;
  312. int distance = 0;
  313. int possible_distance = 0;
  314. for (i = 0; i < g->nnodes_of_level[l]; i++) {
  315. index = find_next(g->nnodes_of_level[l]);
  316. optimal_position = lower_barycenter(nl[index].node);
  317. if (optimal_position == 0) {
  318. optimal_position = nl[index].node->absx;
  319. }
  320. if (optimal_position < nl[index].node->absx) {
  321. distance = nl[index].node->absx - optimal_position;
  322. possible_distance = 0;
  323. j = index;
  324. do {
  325. if (j > 0) {
  326. possible_distance += nl[j].node->absx - (nl[j - 1].node->absx + nl[j - 1].node->bbx) - xmindist;
  327. } else {
  328. /* j == 0, no nodes links */
  329. possible_distance += (nl[0].node->absx + nl[0].node->bbx) /* XXX +bbx? */ -xmindist;
  330. }
  331. j--;
  332. }
  333. while ((j >= 0) && (nl[j].done == 0));
  334. if (possible_distance < distance) {
  335. distance = possible_distance;
  336. }
  337. j = index;
  338. while (distance > 0) {
  339. int d = 0;
  340. int k = 0;
  341. if (j == 0) {
  342. d = distance;
  343. } else {
  344. if (nl[j].node->absx - (nl[j - 1].node->absx + nl[j - 1].node->bbx) - xmindist < distance) {
  345. d = nl[j].node->absx - (nl[j - 1].node->absx + nl[j - 1].node->bbx) - xmindist;
  346. } else {
  347. d = distance;
  348. }
  349. }
  350. for (k = j; k <= index; k++) {
  351. nl[k].node->absx -= d;
  352. }
  353. j--;
  354. distance -= d;
  355. }
  356. } else {
  357. /* optimal_position >= nl[index].node->absx */
  358. distance = optimal_position - nl[index].node->absx;
  359. possible_distance = 0;
  360. j = index;
  361. do {
  362. if (j < g->nnodes_of_level[l] - 1) {
  363. possible_distance += nl[j + 1].node->absx - (nl[j].node->absx + nl[j].node->bbx) - xmindist;
  364. } else {
  365. /* j == g->nnodes_of_level[l]-1, no nodes rechts */
  366. possible_distance += distance;
  367. }
  368. j++;
  369. }
  370. while ((j < g->nnodes_of_level[l]) && (nl[j].done == 0));
  371. if (possible_distance < distance) {
  372. distance = possible_distance;
  373. }
  374. j = index;
  375. while (distance > 0) {
  376. int d = 0;
  377. int k = 0;
  378. if (j == g->nnodes_of_level[l] - 1) {
  379. d = distance;
  380. } else {
  381. if (nl[j + 1].node->absx - (nl[j].node->absx + nl[j].node->bbx) - xmindist < distance) {
  382. d = nl[j + 1].node->absx - (nl[j].node->absx + nl[j].node->bbx) - xmindist;
  383. } else {
  384. d = distance;
  385. }
  386. }
  387. for (k = index; k <= j; k++) {
  388. nl[k].node->absx += d;
  389. }
  390. j++;
  391. distance -= d;
  392. }
  393. }
  394. nl[index].done = 1; /* TRUE */
  395. }
  396. return;
  397. }
  398. /* build data */
  399. static void pos3init(struct gml_graph *g)
  400. {
  401. struct node_data *pnl = NULL;
  402. struct gml_nlist *gnl = NULL;
  403. struct gml_node *n = NULL;
  404. int i = 0;
  405. int j = 0;
  406. int my = 0;
  407. int yoff = 0;
  408. dl = dp_calloc(1, ((g->maxlevel + 1) * sizeof(struct node_data *)));
  409. if (dl == NULL) {
  410. return;
  411. }
  412. for (i = 0; i <= g->maxlevel; i++) {
  413. dl[i] = dp_calloc(1, ((g->nnodes_of_level[i] + 1) * sizeof(struct node_data)));
  414. if (dl[i] == NULL) {
  415. return;
  416. }
  417. }
  418. cix = dp_calloc(1, ((g->maxlevel + 1) * sizeof(int)));
  419. if (cix == NULL) {
  420. return;
  421. }
  422. /* for_all_nodes(g,n) */
  423. gnl = g->nodelist;
  424. while (gnl) {
  425. n = gnl->node;
  426. pnl = dl[n->rely];
  427. pnl[cix[n->rely]].node = n;
  428. pnl[cix[n->rely]].done = 0;
  429. pnl[cix[n->rely]].priority = 0;
  430. cix[n->rely]++;
  431. gnl = gnl->next;
  432. }
  433. for (i = 0; i <= g->maxlevel; i++) {
  434. nl = dl[i];
  435. if (g->nnodes_of_level[i]) {
  436. sort(g->nnodes_of_level[i]);
  437. }
  438. }
  439. /* calc max y-size at every level */
  440. szy = dp_calloc(1, ((g->maxlevel + 1) * sizeof(int)));
  441. if (szy == NULL) {
  442. return;
  443. }
  444. /* y offset */
  445. yoff = 0;
  446. for (i = 0; i <= g->maxlevel; i++) {
  447. nl = dl[i];
  448. my = 0;
  449. /* determine needed y size of this level */
  450. for (j = 0; j < g->nnodes_of_level[i]; j++) {
  451. if (nl[j].node->bby > my) {
  452. /* node with largest y size */
  453. my = nl[j].node->bby;
  454. }
  455. }
  456. /* set this max. y as y size of this level */
  457. szy[i] = my;
  458. /* place the nodes */
  459. for (j = 0; j < g->nnodes_of_level[i]; j++) {
  460. /* node places centered halfway of level */
  461. nl[j].node->absy = yoff + ((szy[i] / 2) - (nl[j].node->bby / 2));
  462. nl[j].node->ly0 = yoff;
  463. nl[j].node->ly1 = (yoff + szy[i] /* XXX + ymindist */ );
  464. if (nl[j].node->dummy) {
  465. nl[j].node->bby = szy[i] + ymindist;
  466. }
  467. }
  468. yoff = yoff + my + ymindist;
  469. }
  470. return;
  471. }
  472. /* clear data */
  473. static void pos3clear(struct gml_graph *g)
  474. {
  475. struct node_data *pnl = NULL;
  476. int i = 0;
  477. if (dl) {
  478. for (i = 0; i <= g->maxlevel; i++) {
  479. pnl = dl[i];
  480. if (pnl) {
  481. dp_free(pnl);
  482. dl[i] = NULL;
  483. }
  484. }
  485. dp_free(dl);
  486. }
  487. if (cix) {
  488. dp_free(cix);
  489. }
  490. cix = NULL;
  491. if (szy) {
  492. dp_free(szy);
  493. }
  494. szy = NULL;
  495. dl = NULL;
  496. nl = NULL;
  497. return;
  498. }
  499. /* left most layout */
  500. static void pos3leftmost(struct gml_graph *g)
  501. {
  502. int i = 0;
  503. int j = 0;
  504. int mx = 0;
  505. /* left most layout setting all node x pos. to minimum needed value */
  506. for (i = 0; i < g->maxlevel; i++) {
  507. nl = dl[i];
  508. if (nl) {
  509. mx = 0;
  510. for (j = 0; j < g->nnodes_of_level[i]; j++) {
  511. if (nl[j].node) {
  512. nl[j].node->absx = mx;
  513. mx = mx + xmindist + nl[j].node->bbx;
  514. }
  515. }
  516. }
  517. }
  518. return;
  519. }
  520. /* fix dummy nodes */
  521. static void pos3fixdummy(struct gml_graph *g, int level)
  522. {
  523. int j = 0;
  524. int x0 = 0;
  525. int x1 = 0;
  526. nl = dl[level];
  527. if (nl == NULL) {
  528. return;
  529. }
  530. for (j = 0; j < g->nnodes_of_level[level]; j++) {
  531. /* do not move edge labels, only dummy nodes */
  532. if (nl[j].node->elabel == 0) {
  533. /* do not move if hor. edges */
  534. if (nl[j].node->incoming_e && nl[j].node->outgoing_e) {
  535. if (nl[j].node->incoming_e->edge->hedge == 0 && nl[j].node->outgoing_e->edge->hedge == 0) {
  536. /* this is a vertical edge */
  537. x0 = nl[j].node->incoming_e->edge->from_node->absx + (nl[j].node->incoming_e->edge->from_node->bbx / 2);
  538. x1 = nl[j].node->outgoing_e->edge->to_node->absx + (nl[j].node->outgoing_e->edge->to_node->bbx / 2);
  539. nl[j].node->absx = ((x0 + x1) / 2);
  540. }
  541. }
  542. }
  543. }
  544. return;
  545. }
  546. /* XXX todo this does not work as expected */
  547. /* determine relative node pos. from the barycenter rel. node pos. */
  548. static void improve_positions_3(struct gml_graph *g)
  549. {
  550. struct gml_nlist *gnl = NULL;
  551. int i = 0;
  552. int count = 0;
  553. int ii = 0;
  554. int sl = 0;
  555. int mx = 0;
  556. int mylevel = 0;
  557. /* step size */
  558. ssize = 1;
  559. /* min. node dist, minimum 1 */
  560. xmindist = xspacing;
  561. ymindist = yspacing;
  562. if (g->nsinglenodes) {
  563. /* single nodes in level 0 and skip this level */
  564. sl = 1;
  565. } else {
  566. /* start level is 0 */
  567. sl = 0;
  568. }
  569. /* copy the rel(x,y) pos into abs(x,y) and modify the absx pos here */
  570. gnl = g->nodelist;
  571. while (gnl) {
  572. gnl->node->absx = gnl->node->relx;
  573. gnl->node->absy = gnl->node->rely;
  574. gnl->node->finx = 0;
  575. gnl->node->finy = 0;
  576. gnl->node->ly0 = 0;
  577. gnl->node->ly1 = 0;
  578. if (gnl->node->dummy) {
  579. gnl->node->bbx = 0;
  580. gnl->node->bby = 0;
  581. }
  582. gnl = gnl->next;
  583. }
  584. /* build data */
  585. pos3init(g);
  586. /* left most layout */
  587. pos3leftmost(g);
  588. /* number of up/down sweeps */
  589. count = 2;
  590. for (ii = 0; ii < count; ii++) {
  591. /* from to of drawing to bottom */
  592. for (i = sl; i < g->maxlevel; i = i + ssize) {
  593. mylevel = i;
  594. if (g->nnodes_of_level[i]) {
  595. make_node_list_down(g, i);
  596. do_down(g, i);
  597. }
  598. }
  599. /* from bottom of drawing to top */
  600. for (i = mylevel; i > sl; i = i - ssize) {
  601. if (g->nnodes_of_level[i]) {
  602. make_node_list_up(g, i);
  603. do_up(g, i);
  604. }
  605. }
  606. }
  607. if ((sl + 2) < g->maxlevel) {
  608. for (i = sl; i < g->maxlevel; i = i + ssize) {
  609. if (g->nnodes_of_level[i]) {
  610. make_node_list_up(g, i);
  611. do_up(g, i);
  612. }
  613. }
  614. }
  615. /* left-align the image */
  616. /* find min. x pos in-use */
  617. mx = 1024 * 1024; /* just some high value */
  618. if (g->nsinglenodes) {
  619. /* single nodes in level 0 and skip this level */
  620. gnl = g->nodelist;
  621. while (gnl) {
  622. /* only level 1...n */
  623. if (gnl->node->rely) {
  624. if (gnl->node->absx < mx) {
  625. mx = gnl->node->absx;
  626. }
  627. }
  628. gnl = gnl->next;
  629. }
  630. /* move whole drawing to the left */
  631. gnl = g->nodelist;
  632. while (gnl) {
  633. /* only level 1...n */
  634. if (gnl->node->rely) {
  635. gnl->node->absx = (gnl->node->absx - mx);
  636. }
  637. gnl = gnl->next;
  638. }
  639. } else {
  640. /* no single nodes and level 0 is in use for the drawing */
  641. gnl = g->nodelist;
  642. while (gnl) {
  643. if (gnl->node->absx < mx) {
  644. mx = gnl->node->absx;
  645. }
  646. gnl = gnl->next;
  647. }
  648. /* move whole drawing to the left */
  649. gnl = g->nodelist;
  650. while (gnl) {
  651. gnl->node->absx = (gnl->node->absx - mx);
  652. gnl = gnl->next;
  653. }
  654. }
  655. /* tune in-between levels with dummy nodes */
  656. if (ssize == 2 || 0) {
  657. ssize = 2;
  658. for (i = sl; i < g->maxlevel; i = i + ssize) {
  659. pos3fixdummy(g, (i + 1));
  660. }
  661. }
  662. /* clear all data */
  663. pos3clear(g);
  664. return;
  665. }
  666. /* switched between different modes */
  667. void improve_positions3(struct gml_graph *g)
  668. {
  669. printf("%s(): positioning mode is %d\n", __func__, postype);
  670. fflush(stdout);
  671. /* this can happen */
  672. if (g->nnodes_of_level == NULL) {
  673. return;
  674. }
  675. improve_positions_3(g);
  676. return;
  677. }
  678. /* end */