LGraph.cpp 62 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947
  1. /** \file
  2. * \brief routines
  3. *
  4. * \par
  5. * Copyright (C)<br>
  6. * See README.md in the root directory for details.
  7. *
  8. * \par
  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. * \par
  15. * This program is distributed in the hope that it will be useful,
  16. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  17. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  18. * GNU General Public License for more details.
  19. *
  20. * \par
  21. * You should have received a copy of the GNU General Public
  22. * License along with this program; if not, see
  23. * http://www.gnu.org/copyleft/gpl.html
  24. *
  25. * SPDX-License-Identifier: GPL-3.0+
  26. * License-Filename: LICENSE
  27. */
  28. /**
  29. * @file: LGraph.cpp
  30. */
  31. #include "Layout.h"
  32. /**
  33. * determine layout
  34. * \param number_of_iterations how many times
  35. * \param do_transpose if true do phase-II
  36. * \param transpose_range how many nodes to swap
  37. * \param verbose if true print messages
  38. * \parm usebary if true use barycenter values
  39. */
  40. void LGraph::Layout(unsigned long int number_of_iterations,
  41. bool do_transpose,
  42. int transpose_range,
  43. bool verbose, bool usebary)
  44. {
  45. bool changed = false;
  46. int nsame = 0; // same crossings count
  47. int curc = 0; // current crossings
  48. int bestc = 0; // best crossings
  49. bool status = false; // median status
  50. list<pLEdge> ReverseEdges; // edges which are reversed
  51. if (layouted > 0) {
  52. // graph is already layouted
  53. // option here and todo
  54. return;
  55. }
  56. // avoid crash when graph has no nodes
  57. if (m_total_nodes_num == 0) {
  58. // The graph is layouted
  59. layouted++;
  60. return;
  61. }
  62. // clear db
  63. nodesplay = splay_tree_delete(nodesplay);
  64. edgesplay = splay_tree_delete(edgesplay);
  65. nodesplay = splay_tree_new(splay_tree_compare_ints, (splay_tree_delete_key_fn)0, (splay_tree_delete_value_fn)0);
  66. edgesplay = splay_tree_new(splay_tree_compare_ints, (splay_tree_delete_key_fn)0, (splay_tree_delete_value_fn)0);
  67. // nothing to layout if there are no edges but there can be self-edges at nodes
  68. if (m_total_edges_num == 0) {
  69. // special layout mode to set the single nodes
  70. // The graph is layouted
  71. layouted++;
  72. // init vertical levels
  73. InitRank();
  74. // create array for node ordering in the levels
  75. order = new Ordering();
  76. // create node lists of every rank level
  77. order->order_vector = InitOrder();
  78. // give nodes relative x position
  79. InitPos(order);
  80. // center graph and give nodes absolute node position
  81. InitCoordinates(order);
  82. FinalCoordinates(order);
  83. // copy nodes in db
  84. for (list<pLNode>::iterator node_iter = nodes_list()->begin();
  85. node_iter != nodes_list()->end();
  86. node_iter++) {
  87. splay_tree_insert(nodesplay, (splay_tree_key)((LNode*)(*node_iter))->id(), (splay_tree_value)((LNode*)(*node_iter)));
  88. }
  89. // there are zero crossings
  90. if (verbose == true) {
  91. printf("Graph has %d starter nodes and %d ranks\n", m_nstarter_num, (maxrank + 1));
  92. order->Dump();
  93. printf("Final Crossings: %d\n", countCrossing(order));
  94. }
  95. delete order;
  96. return;
  97. }
  98. // find cycles in the graph, reverse few edges if needed
  99. changed = FindReverseEdges(ReverseEdges);
  100. if (changed == true) {
  101. // number of reversed edges changed
  102. if (verbose == true) {
  103. std::printf("Reversed edges changed to %d\n", nreversededges());
  104. }
  105. }
  106. // reverse edges to get cyclic graph
  107. ReverseReverseEdges(ReverseEdges);
  108. // at this point the graph is acyclic with reversed edges
  109. // double space the graph then same edges are multiple edges
  110. // set node rank levels and get max rank y level in the graph
  111. InitRank();
  112. // list for longer edges to split
  113. list<pLEdge> LongEdges;
  114. // add long edges to list
  115. FindLongEdges(LongEdges);
  116. // split long edges in short edges connected with dummy nodes
  117. AddDummyNodes(LongEdges);
  118. // free list of reversed edges
  119. ReverseEdges.clear();
  120. // create array for node ordering in the levels
  121. order = new Ordering();
  122. // create node lists of every rank level
  123. order->order_vector = InitOrder();
  124. order->m_crossings_num = InitOrder2();
  125. order->m_iicrossings_num = InitOrder2();
  126. order->m_ircrossings_num = InitOrder2();
  127. order->m_rrcrossings_num = InitOrder2();
  128. // Check nodes in order data
  129. CheckOrder(order);
  130. // The graph is layouted
  131. layouted++;
  132. nsame = 0;
  133. bestc = 0;
  134. // improve edge crossings
  135. for (unsigned int i = 0; i < number_of_iterations; i++) {
  136. // relative x position nodes on median value
  137. status = WeightedMedianHeuristic(i, verbose, usebary);
  138. curc = countCrossing(order);
  139. if (curc == 0) {
  140. break;
  141. }
  142. // true status if crossings did not change
  143. if (status == true) {
  144. if (curc < bestc) {
  145. bestc = curc;
  146. nsame = 0;
  147. } else {
  148. nsame++;
  149. }
  150. } else {
  151. nsame = 0;
  152. }
  153. // stop when layout does not change and n times same crossings
  154. if (nsame > 5) {
  155. if (verbose == true) {
  156. printf("%s(): graph does not change anymore at %d crossings\n", __func__, curc);
  157. }
  158. break;
  159. }
  160. // swap nodes at all levels optional
  161. // Ususal is to swap nodes with same barycenter value
  162. if (do_transpose) {
  163. Transpose(i + transpose_range, verbose);
  164. curc = countCrossing(order);
  165. if (curc == 0) {
  166. break;
  167. }
  168. }
  169. }
  170. // give nodes relative x position
  171. InitPos(order);
  172. // center graph and give nodes absolute node position
  173. InitCoordinates(order);
  174. // get statistics too and count crossings
  175. curc = FinalcountCrossing(order);
  176. // center graph and give nodes absolute node position
  177. FinalCoordinates(order);
  178. // copy nodes in db
  179. for (list<pLNode>::iterator node_iter = nodes_list()->begin();
  180. node_iter != nodes_list()->end();
  181. node_iter++) {
  182. splay_tree_insert(nodesplay, (splay_tree_key)((LNode*)(*node_iter))->id(), (splay_tree_value)((LNode*)(*node_iter)));
  183. }
  184. // copy edges in db
  185. for (list<pLEdge>::iterator edge_iter = edges_list()->begin();
  186. edge_iter != edges_list()->end();
  187. edge_iter++) {
  188. splay_tree_insert(edgesplay, (splay_tree_key)((pLEdge)(*edge_iter))->id(), (splay_tree_value)((pLEdge)(*edge_iter)));
  189. }
  190. // this prints the node order in the levels
  191. if (verbose == true) {
  192. printf("Graph has %u starter nodes\n", m_nstarter_num);
  193. order->Dump();
  194. printf("Final Crossings: %d\n", curc);
  195. }
  196. // free to avoid memleak
  197. delete order;
  198. return;
  199. }
  200. /**
  201. * get how many rank y levels there are in the graph
  202. * at this point the graph is acyclic with reversed edges
  203. * double space the graph then same edges are multiple edges
  204. */
  205. void LGraph::InitRank()
  206. {
  207. m_nstarter_num = 0;
  208. maxrank = 0;
  209. unsigned int rank = 0;
  210. // Calculating the rank for all Nodes
  211. for (list<pLNode>::iterator node_iter = nodes_list()->begin();
  212. node_iter != nodes_list()->end();
  213. node_iter++) {
  214. // determine the rank of the node
  215. rank = ((LNode*)(*node_iter))->Rank();
  216. if (rank) {
  217. // silence unused warning
  218. }
  219. }
  220. // Calculating the rank for all Nodes
  221. for (list<pLNode>::iterator node_iter = nodes_list()->begin();
  222. node_iter != nodes_list()->end();
  223. node_iter++) {
  224. // get rank level of this node
  225. rank = ((LNode*)(*node_iter))->Rank();
  226. // double space the graph
  227. // this is needed to make sure same edges are in drawing multiple edges
  228. // instead of one bundled edge
  229. ((LNode*)(*node_iter))->setrank(2 * rank);
  230. rank = ((LNode*)(*node_iter))->Rank();
  231. if (rank > maxrank) {
  232. maxrank = rank;
  233. }
  234. // check if this node starts a graph
  235. if (((LNode*)(*node_iter))->entry) {
  236. m_nstarter_num++;
  237. }
  238. }
  239. return;
  240. }
  241. /**
  242. * create list of nodes in every rank level
  243. * \todo add nodes initial order using dfs
  244. * that seems to improve the barycenter algorithm
  245. */
  246. vector<vector<pLNode>>
  247. LGraph::InitOrder()
  248. {
  249. pLNode curnode;
  250. // reserve space for maxrank levels + 1
  251. vector<vector<pLNode>> order(maxrank + 1);
  252. // scan all nodes
  253. // todo run dfs and in order of visited push
  254. for (list<pLNode>::iterator node_iter = nodes_list()->begin();
  255. node_iter != nodes_list()->end();
  256. node_iter++) {
  257. // get current node
  258. curnode = ((pLNode)(*node_iter));
  259. if (curnode->in_edges_list()->size() == 0) {
  260. // this is a starter node
  261. // todo run dfs at this starter node to fill order[]
  262. }
  263. // add node at rank level to list of nodes at that rank level
  264. order[((pLNode)(*node_iter))->Rank()].push_back((pLNode)(*node_iter));
  265. }
  266. return order;
  267. }
  268. /**
  269. * reserve space for maxrank levels + 1
  270. */
  271. vector<int>
  272. LGraph::InitOrder2()
  273. {
  274. // reserve space for maxrank levels + 1
  275. vector<int> order(maxrank + 1);
  276. return order;
  277. }
  278. /**
  279. * reverse edges to get acyclic graph
  280. */
  281. void LGraph::ReverseReverseEdges(list<pLEdge>& ReverseEdges)
  282. {
  283. // all reversed edges as normal direction edge
  284. // avoids a looping in node rank()
  285. for (list<pLEdge>::iterator edge_iter = ReverseEdges.begin();
  286. edge_iter != ReverseEdges.end();
  287. edge_iter++) {
  288. ((pLEdge)(*edge_iter))->Reverse();
  289. }
  290. return;
  291. }
  292. /**
  293. * find edges which are longer then 1 vertical rank level
  294. */
  295. void LGraph::FindLongEdges(list<pLEdge>& LongEdges)
  296. {
  297. int nhedges = 0;
  298. int delta = 0;
  299. pLEdge curedge;
  300. pLNode fn;
  301. pLNode tn;
  302. // scan all edges
  303. for (list<pLEdge>::iterator edge_iter = edges_list()->begin();
  304. edge_iter != edges_list()->end();
  305. edge_iter++) {
  306. curedge = (*edge_iter);
  307. fn = curedge->from();
  308. tn = curedge->to();
  309. if (fn == NULL) {
  310. printf("nil fn\n");
  311. }
  312. if (tn == NULL) {
  313. printf("nil tn\n");
  314. }
  315. // delta = ((*edge_iter)->to())->Rank() - ((*edge_iter)->from())->Rank();
  316. delta = tn->Rank() - fn->Rank();
  317. // check for wrong value
  318. if (delta < 0) {
  319. // todo
  320. printf("%s() delta is %d shouldnothappen\n", __func__, delta);
  321. }
  322. // check if edge is too long
  323. if (delta > 1) {
  324. // this is a edge spanning multiple levels
  325. LongEdges.push_back(*edge_iter);
  326. }
  327. // check horizontal edge
  328. if (delta == 0) {
  329. nhedges++;
  330. (*edge_iter)->SetHedge(true);
  331. } else {
  332. (*edge_iter)->SetHedge(false);
  333. }
  334. }
  335. // set number of hor. edges
  336. Set_Nhoredges(nhedges);
  337. return;
  338. }
  339. /**
  340. * split long edges with dummy nodes
  341. */
  342. void LGraph::AddDummyNodes(list<pLEdge>& LongEdges)
  343. {
  344. // scan all edges, skip self-edges
  345. for (list<pLEdge>::iterator edge_iter = LongEdges.begin();
  346. edge_iter != LongEdges.end();
  347. edge_iter++) {
  348. ((pLEdge)(*edge_iter))->BreakLongEdge();
  349. }
  350. return;
  351. }
  352. /**
  353. * Comparator to work with pointers to pLNode
  354. * comparing the median values and called from stable_sort()
  355. */
  356. bool ComparePointer(pLNode node1, pLNode node2)
  357. {
  358. double median1 = node1->getMedian();
  359. double median2 = node2->getMedian();
  360. double diff = median1 - median2;
  361. // numbers close to 0 are same as 0
  362. if (diff > -0.1) {
  363. return true;
  364. }
  365. if (diff >= 0) {
  366. return true;
  367. }
  368. if (diff < 0) {
  369. return false;
  370. }
  371. // old and not used
  372. return node1->getMedian() < node2->getMedian();
  373. }
  374. /**
  375. * scan graph and calculate barycenter values
  376. * then sort the new node order and check
  377. * if edge crossings reduced.
  378. * using stable_sort() keeps the elements with same value unchanged
  379. * \param if usebary is true use barycenter values
  380. * \return true if number of crossings did not change
  381. */
  382. bool LGraph::WeightedMedianHeuristic(int iter, bool verbose, bool usebary)
  383. {
  384. bool eq = false;
  385. Ordering temp_order;
  386. temp_order.order_vector = order->order_vector;
  387. // go from top to bottom or reversed
  388. if ((iter % 2) == 0) {
  389. // scan from top to bottom of drawing
  390. for (unsigned int r = 1; r <= maxrank; r++) {
  391. // get median barycenter value for every node at this level
  392. for (unsigned int i = 0; i < temp_order.order_vector[r].size(); i++) {
  393. temp_order.order_vector[r][i]->median = temp_order.order_vector[r][i]->Median(*order, MEDIAN_IN, usebary);
  394. }
  395. // Sort temp_order using ComparePointer comparator on the barycenter value of the nodes
  396. stable_sort(temp_order.order_vector[r].begin(),
  397. temp_order.order_vector[r].end(),
  398. ComparePointer);
  399. }
  400. } else {
  401. // scan from bottom to top of drawing
  402. for (int r = maxrank - 1; r >= 0; r--) {
  403. // get median barycenter value for every node at this level
  404. for (unsigned int i = 0; i < temp_order.order_vector[r].size(); i++) {
  405. temp_order.order_vector[r][i]->median = temp_order.order_vector[r][i]->Median(*order, MEDIAN_OUT, usebary);
  406. }
  407. // Sort temp_order using ComparePointer comparator on the barycenter value of the nodes
  408. // use stable sort to keep equal values at same position
  409. stable_sort(temp_order.order_vector[r].begin(),
  410. temp_order.order_vector[r].end(),
  411. ComparePointer);
  412. }
  413. }
  414. // give nodes x pos based on pos in temp_order
  415. InitPos(&temp_order);
  416. // count edge crossings in whole graph
  417. int cross_temp_order = countCrossing(&temp_order);
  418. // give nodes x pos based on pos in order
  419. InitPos(order);
  420. // count edge crossings in whole graph
  421. int cross_order = countCrossing(order);
  422. // if edge crossings reduced, set order to temp_order
  423. // different order can have same amount of edge crossings
  424. // using <= is needed to keep the layout moving
  425. // this must be <= to get best results of the barycenter
  426. eq = false;
  427. if (cross_temp_order <= cross_order) {
  428. order->order_vector = temp_order.order_vector;
  429. if (verbose == true) {
  430. printf("%s(): edge crossings reduced from %d to %d\n", __func__, cross_order, cross_temp_order);
  431. }
  432. // return true if did not change
  433. if (cross_order == cross_temp_order) {
  434. eq = true;
  435. }
  436. } else {
  437. // did not improve, keep graph unchanged
  438. if (verbose == true) {
  439. if (0) {
  440. printf("%s(): edge crossings did not reduce from current %d to %d\n", __func__, cross_order, cross_temp_order);
  441. }
  442. }
  443. }
  444. return (eq);
  445. }
  446. /**
  447. * Count edge crossings of the whole graph
  448. */
  449. int LGraph::countCrossing(Ordering* order)
  450. {
  451. int crossing = 0; // total number of crossings returned
  452. int rankcrossing = 0; // crossings at this rank level
  453. int maxcrossing = 0; // max. crossings at certain level
  454. // int maxcrossingrank = 0; level with most crossings
  455. // if only single nodes
  456. if (maxrank < 2) {
  457. return 0;
  458. }
  459. // count crossings at every level
  460. for (unsigned int rank = 0; rank < maxrank - 1; rank++) {
  461. rankcrossing = countCrossingOnRank(order, rank);
  462. if (rankcrossing > maxcrossing) {
  463. maxcrossing = rankcrossing;
  464. // maxcrossingrank = rank;
  465. }
  466. crossing += rankcrossing;
  467. }
  468. return crossing;
  469. }
  470. /**
  471. * Count edge crossings of the whole graph and get statistics
  472. */
  473. int LGraph::FinalcountCrossing(Ordering* order)
  474. {
  475. int crossing = 0; // total number of crossings returned
  476. int rankcrossing = 0; // crossings at this rank level
  477. int maxcrossing = 0; // max. crossings at certain level
  478. // int maxcrossingrank = 0; level with most crossings
  479. // if only single nodes
  480. if (maxrank < 2) {
  481. return 0;
  482. }
  483. // count crossings at every level
  484. for (unsigned int rank = 0; rank < maxrank - 1; rank++) {
  485. rankcrossing = FinalcountCrossingOnRank(order, rank);
  486. if (rankcrossing > maxcrossing) {
  487. maxcrossing = rankcrossing;
  488. // maxcrossingrank = rank;
  489. }
  490. crossing += rankcrossing;
  491. }
  492. return crossing;
  493. }
  494. /**
  495. * Count edge crossings between rank level rank and rank+1
  496. */
  497. int LGraph::countCrossingOnRank(Ordering* order, int rank)
  498. {
  499. int crossing = 0;
  500. pLEdge curedge;
  501. // Making list of all outgoing edges between rank and rank+1 level
  502. vector<pLEdge> edge_list;
  503. // scan node at this rank level
  504. for (unsigned int i = 0; i < order->order_vector[rank].size(); i++) {
  505. // select the outgoing edges at a node
  506. for (list<pLEdge>::iterator edge_iter = order->order_vector[rank][i]->out_edges_list()->begin();
  507. edge_iter != order->order_vector[rank][i]->out_edges_list()->end();
  508. edge_iter++) {
  509. curedge = (*edge_iter);
  510. edge_list.push_back(curedge);
  511. }
  512. }
  513. // scan the edges in just created edge list
  514. for (unsigned int i = 0; i < edge_list.size(); i++) {
  515. // scan the next edges after current edge
  516. for (unsigned int j = i + 1; j < edge_list.size(); j++) {
  517. // Criterion of crossing edge_list[i] and edge_list[j]
  518. // check relative position of to nodes in edge
  519. int cmp1 = ((pLNode)edge_list[i]->to())->pos - ((pLNode)edge_list[j]->to())->pos;
  520. // check relative position of from nodes in edge
  521. int cmp2 = ((pLNode)edge_list[i]->from())->pos - ((pLNode)edge_list[j]->from())->pos;
  522. // cmp1 is delto to pos, cmp2 is delta from pos
  523. if ((cmp1 > 0 && cmp2 < 0) || (cmp1 < 0 && cmp2 > 0)) {
  524. // edges did cross
  525. crossing++;
  526. } else {
  527. // edges did not cross
  528. }
  529. }
  530. }
  531. edge_list.clear();
  532. return crossing;
  533. }
  534. /**
  535. * Count edge crossings between rank level rank and rank+1
  536. */
  537. int LGraph::FinalcountCrossingOnRank(Ordering* order, int rank)
  538. {
  539. int crossing = 0;
  540. int iicrossings = 0;
  541. int ircrossings = 0;
  542. int rrcrossings = 0;
  543. pLEdge curedgei = NULL;
  544. pLEdge curedgej = NULL;
  545. // Making list of all outgoing edges between rank and rank+1 level
  546. vector<pLEdge> edge_list;
  547. // scan node at this rank level
  548. for (unsigned int i = 0; i < order->order_vector[rank].size(); i++) {
  549. // select the outgoing edges at a node and reset edge crossing count data
  550. for (list<pLEdge>::iterator edge_iter = order->order_vector[rank][i]->out_edges_list()->begin();
  551. edge_iter != order->order_vector[rank][i]->out_edges_list()->end();
  552. edge_iter++) {
  553. edge_list.push_back((pLEdge)(*edge_iter));
  554. // no crossings at this edge
  555. ((pLEdge)(*edge_iter))->iicross = 0;
  556. ((pLEdge)(*edge_iter))->ircross = 0;
  557. ((pLEdge)(*edge_iter))->rrcross = 0;
  558. // not a conflict type 1 edge
  559. ((pLEdge)(*edge_iter))->conflict = false;
  560. }
  561. }
  562. // scan the out going edges in just created edge list and set type of edge crossing
  563. for (unsigned int i = 0; i < edge_list.size(); i++) {
  564. // scan the next edges after current edge
  565. curedgei = (pLEdge)edge_list[i];
  566. for (unsigned int j = i + 1; j < edge_list.size(); j++) {
  567. curedgej = (pLEdge)edge_list[j];
  568. // Criterion of crossing edge_list[i] and edge_list[j]
  569. // check relative position of to nodes in edge
  570. int cmp1 = ((pLNode)edge_list[i]->to())->pos - ((pLNode)edge_list[j]->to())->pos;
  571. // check relative position of from nodes in edge
  572. int cmp2 = ((pLNode)edge_list[i]->from())->pos - ((pLNode)edge_list[j]->from())->pos;
  573. // cmp1 is delto to pos, cmp2 is delta from pos
  574. if ((cmp1 > 0 && cmp2 < 0) || (cmp1 < 0 && cmp2 > 0)) {
  575. // edges did cross
  576. crossing++;
  577. // set type of edge crossing
  578. if ((curedgei->inner == true) || (curedgej->inner == true)) {
  579. if ((curedgei->inner == true) && (curedgej->inner == true)) {
  580. // these edges are inner crossing edges
  581. curedgei->iicross++;
  582. curedgej->iicross++;
  583. iicrossings++;
  584. } else {
  585. /* i is a non-inner, j a inner edge */
  586. curedgei->ircross++;
  587. curedgej->ircross++;
  588. // this are the edge type 1 conflicta
  589. ircrossings++;
  590. }
  591. } else {
  592. // both are not inner edges
  593. curedgei->rrcross++;
  594. curedgej->rrcross++;
  595. rrcrossings++;
  596. }
  597. } else {
  598. // edges did not cross
  599. }
  600. }
  601. }
  602. // crossing counts for this level
  603. order->m_crossings_num[rank] = crossing;
  604. order->m_iicrossings_num[rank] = iicrossings;
  605. order->m_ircrossings_num[rank] = ircrossings;
  606. order->m_rrcrossings_num[rank] = rrcrossings;
  607. edge_list.clear();
  608. return crossing;
  609. }
  610. /**
  611. * Give nodes initial x position based on index in order
  612. * does extra check on the in/out edges of the nodes in the order
  613. */
  614. void LGraph::InitPos(Ordering* order)
  615. {
  616. pLNode curnode;
  617. pLNode fromnode;
  618. pLNode tonode;
  619. pLNode leftnode;
  620. pLNode rightnode;
  621. // scan all vertical rank levels
  622. for (unsigned int rank = 0; rank <= maxrank; rank++) {
  623. // extra check
  624. if (order->order_vector[rank].size() <= 0) {
  625. printf("%s(): wrong number of nodes at level %d with %lu nodes\n", __func__, rank, order->order_vector[rank].size());
  626. }
  627. // scan all nodes at this level
  628. for (unsigned int i = 0; i < order->order_vector[rank].size(); i++) {
  629. // give node relative x position based on position in order
  630. // order->order_vector[rank][i]->pos = i;
  631. curnode = order->order_vector[rank][i];
  632. // set relative x postion
  633. curnode->pos = i;
  634. // scan outgoing edges and check if to node is one level more
  635. for (list<pLEdge>::iterator edge_iter = curnode->out_edges_list()->begin();
  636. edge_iter != order->order_vector[rank][i]->out_edges_list()->end();
  637. edge_iter++) {
  638. fromnode = (pLNode)(pLEdge)(*edge_iter)->from();
  639. tonode = (pLNode)(pLEdge)(*edge_iter)->to();
  640. if ((tonode->Rank() - fromnode->Rank()) != 1) {
  641. printf("%s(): delta at outgoing edges should be 1\n", __func__);
  642. }
  643. }
  644. // same incoming edges
  645. for (list<pLEdge>::iterator edge_iter = curnode->in_edges_list()->begin();
  646. edge_iter != order->order_vector[rank][i]->in_edges_list()->end();
  647. edge_iter++) {
  648. fromnode = (pLNode)(pLEdge)(*edge_iter)->from();
  649. tonode = (pLNode)(pLEdge)(*edge_iter)->to();
  650. if ((tonode->Rank() - fromnode->Rank()) != 1) {
  651. printf("%s(): delta at incoming edges should be 1\n", __func__);
  652. }
  653. }
  654. }
  655. }
  656. // set left/right nodes at every node
  657. // scan all vertical rank levels
  658. for (unsigned int rank = 0; rank <= maxrank; rank++) {
  659. // scan all nodes at this level
  660. leftnode = NULL;
  661. rightnode = NULL;
  662. for (unsigned int i = 0; i < order->order_vector[rank].size(); i++) {
  663. curnode = order->order_vector[rank][i];
  664. // set node at left of node or NULL at first node
  665. curnode->lnode = leftnode;
  666. if ((i + 1) < order->order_vector[rank].size()) {
  667. rightnode = order->order_vector[rank][i + 1];
  668. } else {
  669. rightnode = NULL;
  670. }
  671. // set node at right of node or NULL at last node
  672. curnode->rnode = rightnode;
  673. leftnode = curnode;
  674. }
  675. }
  676. return;
  677. }
  678. /**
  679. * Check node in order data
  680. */
  681. void LGraph::CheckOrder(Ordering* order)
  682. {
  683. pLNode curnode;
  684. pLNode fromnode;
  685. pLNode tonode;
  686. int delta = 0;
  687. // scan all vertical rank levels
  688. for (unsigned int rank = 0; rank <= maxrank; rank++) {
  689. // extra check
  690. if (order->order_vector[rank].size() <= 0) {
  691. printf("%s(): wrong number of nodes at level %d\n", __func__, rank);
  692. }
  693. // scan all nodes at this level
  694. for (unsigned int i = 0; i < order->order_vector[rank].size(); i++) {
  695. // current node to check
  696. curnode = order->order_vector[rank][i];
  697. // scan outgoing edges and check if to node is one level more
  698. for (list<pLEdge>::iterator edge_iter = curnode->out_edges_list()->begin();
  699. edge_iter != order->order_vector[rank][i]->out_edges_list()->end();
  700. edge_iter++) {
  701. fromnode = (pLNode)(pLEdge)(*edge_iter)->from();
  702. tonode = (pLNode)(pLEdge)(*edge_iter)->to();
  703. delta = (tonode->Rank() - fromnode->Rank());
  704. if (delta != 1) {
  705. printf("%s(): delta at outgoing edges should be 1 but it is %d\n", __func__, delta);
  706. }
  707. }
  708. // same incoming edges
  709. for (list<pLEdge>::iterator edge_iter = curnode->in_edges_list()->begin();
  710. edge_iter != order->order_vector[rank][i]->in_edges_list()->end();
  711. edge_iter++) {
  712. fromnode = (pLNode)(pLEdge)(*edge_iter)->from();
  713. tonode = (pLNode)(pLEdge)(*edge_iter)->to();
  714. delta = (tonode->Rank() - fromnode->Rank());
  715. if (delta != 1) {
  716. printf("%s(): delta at incoming edges should be 1 but it is %d\n", __func__, delta);
  717. }
  718. }
  719. }
  720. }
  721. return;
  722. }
  723. /**
  724. *
  725. * \param orient is 0..3 orientation mode
  726. */
  727. // upper_left=0, lower_left=1, upper_right=2, lower_right=3
  728. static void FinalCoordinates_horizontal_compaction(Ordering* order, int orient)
  729. {
  730. }
  731. //static bool FinalCoordinates_vertical_align_is_type1_edge(node u, node v)
  732. // scan edge list for this edge and return if it is type1 edge
  733. // or scan outgoing edges of node for this edge and check
  734. /**
  735. * for every node choose the node it will be vertical aligned to
  736. * \param orient is 0..3 orientation mode
  737. initialize root[v] = v;
  738. initialize align[v] = v;
  739. for i=1 to lastlayer do
  740. {
  741. r←0;
  742. for k=1 to last_node_in_layer do
  743. {
  744. if node v(i) k has_upper_neighbors u1 ≺ ... ≺ ud with d > 0 then
  745. {
  746. // slice
  747. for m median of node v(i) k do
  748. {
  749. if align[v(i)k] = v(i)k then
  750. {
  751. if (um,v(i)k) not marked and r < pos[um] then
  752. {
  753. align[um] ← v(i)k;
  754. root[v(i)k] ← root[um];
  755. align[v(i)k] ← root[v(i)k];
  756. r = pos[um];
  757. }
  758. }
  759. }
  760. }
  761. }
  762. }
  763. */
  764. // upper_left=0, lower_left=1, upper_right=2, lower_right=3
  765. void LGraph::FinalCoordinates_vertical_align(Ordering* order, int dir)
  766. {
  767. pLNode curnode;
  768. int mp = 0;
  769. int d = 0;
  770. // init the 4 connecting nodes possible at node
  771. // upper_left=0, lower_left=1, upper_right=2, lower_right=3
  772. // init_medians() has configured the node medians
  773. // scan all levels
  774. if (dir == orient::upper_left || dir == orient::upper_right) {
  775. // scan from top of drawing to bottom
  776. mp = 0;
  777. d = 1;
  778. for (unsigned int rank = 0; rank < maxrank; rank++) {
  779. // scan all nodes at this level
  780. for (unsigned int i = 0; i < order->order_vector[rank].size(); i++) {
  781. // current node to check
  782. curnode = order->order_vector[rank][i];
  783. }
  784. }
  785. } else if (dir == orient::lower_left || dir == orient::lower_right) {
  786. // scan from bottom of drawing to top
  787. for (unsigned int rank = maxrank; rank > 0; rank--) {
  788. mp = 0;
  789. d = 1;
  790. // scan all nodes at this level
  791. for (unsigned int i = 0; i < order->order_vector[rank].size(); i++) {
  792. // current node to check
  793. curnode = order->order_vector[rank][i];
  794. }
  795. }
  796. } else {
  797. // shouldnothappen
  798. printf("%s(): unknown dir shouldnothappen\n", __func__);
  799. }
  800. return;
  801. }
  802. /**
  803. * sort in/out edges of a node
  804. */
  805. static void FinalCoordinates_init_sortededges(pLNode node)
  806. {
  807. size_t nconn = 0;
  808. int needed = 0;
  809. int prevfrom = 0;
  810. int prevto = 0;
  811. pLEdge curedge;
  812. pLNode fromnode;
  813. pLNode tonode;
  814. nconn = node->in_edges_list()->size();
  815. // only sort needed at 2 or more nodes
  816. if (nconn > 1) {
  817. needed = 0;
  818. prevfrom = -1;
  819. // check if sort is needed
  820. for (list<pLEdge>::iterator edge_iter = node->in_edges_list()->begin(); edge_iter != node->in_edges_list()->end(); edge_iter++) {
  821. curedge = (*edge_iter);
  822. fromnode = curedge->from();
  823. if (fromnode->getPos() < prevfrom) {
  824. needed = 1;
  825. break;
  826. }
  827. prevfrom = fromnode->getPos();
  828. }
  829. if (needed > 0) {
  830. // sort of in edges is needed
  831. node->NodeSortIn();
  832. }
  833. }
  834. nconn = node->out_edges_list()->size();
  835. // only sort needed at 2 or more nodes
  836. if (nconn > 1) {
  837. needed = 0;
  838. prevto = -1;
  839. // check if sort is needed
  840. for (list<pLEdge>::iterator edge_iter = node->out_edges_list()->begin(); edge_iter != node->out_edges_list()->end(); edge_iter++) {
  841. curedge = (*edge_iter);
  842. tonode = curedge->to();
  843. if (tonode->getPos() < prevto) {
  844. needed = 1;
  845. break;
  846. }
  847. prevto = tonode->getPos();
  848. }
  849. if (needed > 0) {
  850. // sort of out edge is needed
  851. node->NodeSortOut();
  852. }
  853. }
  854. return;
  855. }
  856. /**
  857. *
  858. */
  859. void LGraph::FinalCoordinates_init_medians(Ordering* order)
  860. {
  861. list<pLEdge>::iterator edge_iter;
  862. pLNode curnode;
  863. pLNode c1node;
  864. pLNode c2node;
  865. pLEdge curedge;
  866. int i = 0;
  867. int j = 0;
  868. int nconn = 0;
  869. // init the sizes for the node data
  870. // m_total_nodes_num is > 0 and is number of real + dummy nodes
  871. for (i = 0; i < 4; i++) {
  872. // root node of block the node belongs to
  873. root[i] = vector<pLNode>(m_total_nodes_num);
  874. // node to align with of the node
  875. align[i] = vector<pLNode>(m_total_nodes_num);
  876. // node
  877. sink[i] = vector<pLNode>(m_total_nodes_num);
  878. // node
  879. medians[i] = vector<pLNode>(m_total_nodes_num);
  880. // movement
  881. shift[i] = vector<double>(m_total_nodes_num);
  882. }
  883. // scan all nodes to set the median nodes
  884. for (list<pLNode>::iterator node_iter = nodes_list()->begin();
  885. node_iter != nodes_list()->end();
  886. node_iter++) {
  887. curnode = (*node_iter);
  888. j = curnode->id();
  889. // in/out edges of node must be sorted for median
  890. FinalCoordinates_init_sortededges(curnode);
  891. // init the 4 connecting nodes possible at node
  892. // upper_left=0, lower_left=1, upper_right=2, lower_right=3
  893. root[orient::lower_left][j] = curnode;
  894. align[orient::lower_left][j] = curnode;
  895. sink[orient::lower_left][j] = curnode;
  896. medians[orient::lower_left][j] = curnode;
  897. shift[orient::lower_left][j] = 0.0;
  898. root[orient::lower_right][j] = curnode;
  899. align[orient::lower_right][j] = curnode;
  900. sink[orient::lower_right][j] = curnode;
  901. medians[orient::lower_right][j] = curnode;
  902. shift[orient::lower_right][j] = 0.0;
  903. root[orient::upper_left][j] = curnode;
  904. align[orient::upper_left][j] = curnode;
  905. sink[orient::upper_left][j] = curnode;
  906. medians[orient::upper_left][j] = curnode;
  907. shift[orient::upper_left][j] = 0.0;
  908. root[orient::upper_right][j] = curnode;
  909. align[orient::upper_right][j] = curnode;
  910. sink[orient::upper_right][j] = curnode;
  911. medians[orient::upper_right][j] = curnode;
  912. shift[orient::upper_right][j] = 0.0;
  913. // preset
  914. medians[orient::lower_left][j] = curnode; // left;
  915. medians[orient::lower_right][j] = curnode; // right;
  916. // check the out going edges of this node
  917. nconn = (int)curnode->out_edges_list()->size();
  918. if (nconn == 0) {
  919. // no out edges
  920. medians[orient::lower_left][j] = curnode; // left;
  921. medians[orient::lower_right][j] = curnode; // right;
  922. } else if (nconn == 1) {
  923. // find median of out edges
  924. // with 1 edge both are the to node.
  925. edge_iter = curnode->out_edges_list()->begin();
  926. c1node = (pLNode)(pLEdge)(*edge_iter)->to();
  927. medians[orient::lower_left][j] = c1node; // left;
  928. medians[orient::lower_right][j] = c1node; // right;
  929. } else if (nconn == 2) {
  930. // find median of out edges
  931. edge_iter = curnode->out_edges_list()->begin();
  932. c1node = (*edge_iter)->to();
  933. edge_iter++;
  934. c2node = (*edge_iter)->to();
  935. medians[orient::lower_left][j] = c1node; // left;
  936. medians[orient::lower_right][j] = c2node; // right;
  937. } else {
  938. // find median of out edges
  939. i = 0;
  940. for (list<pLEdge>::iterator edge_iter = curnode->out_edges_list()->begin();
  941. edge_iter != curnode->out_edges_list()->end();
  942. edge_iter++) {
  943. curedge = (*edge_iter);
  944. if (i == ((nconn / 2) - 1)) {
  945. c1node = (*edge_iter)->to();
  946. edge_iter++;
  947. c2node = (*edge_iter)->to();
  948. medians[orient::lower_left][j] = c1node; // left;
  949. medians[orient::lower_right][j] = c2node; // right;
  950. break;
  951. }
  952. i++;
  953. }
  954. }
  955. // check the in coming edges to this node
  956. nconn = (int)curnode->in_edges_list()->size();
  957. // preset default
  958. medians[orient::upper_left][j] = curnode; // left;
  959. medians[orient::upper_right][j] = curnode; // right;
  960. if (nconn == 0) {
  961. // no in edges
  962. medians[orient::upper_left][j] = curnode; // left;
  963. medians[orient::upper_right][j] = curnode; // right;
  964. } else if (nconn == 1) {
  965. // find median of in edges
  966. edge_iter = curnode->in_edges_list()->begin();
  967. c1node = (*edge_iter)->from();
  968. medians[orient::upper_left][j] = c1node; // left;
  969. medians[orient::upper_right][j] = c1node; // right;
  970. } else if (nconn == 2) {
  971. // find median of in edges
  972. edge_iter = curnode->in_edges_list()->begin();
  973. c1node = (*edge_iter)->from();
  974. edge_iter++;
  975. c2node = (*edge_iter)->from();
  976. medians[orient::upper_left][j] = c1node; // left;
  977. medians[orient::upper_right][j] = c2node; // right;
  978. } else {
  979. // find median of in edges
  980. i = 0;
  981. for (list<pLEdge>::iterator edge_iter = curnode->in_edges_list()->begin();
  982. edge_iter != curnode->in_edges_list()->end();
  983. edge_iter++) {
  984. curedge = (*edge_iter);
  985. if (i == ((nconn / 2) - 1)) {
  986. c1node = (*edge_iter)->from();
  987. edge_iter++;
  988. c2node = (*edge_iter)->from();
  989. medians[orient::upper_left][j] = c1node; // left;
  990. medians[orient::upper_right][j] = c2node; // right;
  991. break;
  992. }
  993. i++;
  994. }
  995. }
  996. }
  997. return;
  998. }
  999. /**
  1000. * set nodes at final (x,y) position in the graph
  1001. * (x2,y2) have same values as (x,y) at start
  1002. * this set new (x2,y2) coordinates for the nodes
  1003. */
  1004. void LGraph::FinalCoordinates(Ordering* order)
  1005. {
  1006. bool verbose = true;
  1007. int ntype1 = 0;
  1008. int rc = 0;
  1009. vector<pLEdge> edge_list;
  1010. // print the levels with the orders of the nodes
  1011. if (verbose == true) {
  1012. order->Dump();
  1013. }
  1014. // mark crossing edge conflicts
  1015. // this is the crossing count routine but only checks where non-inner segment and a inner segment cross
  1016. // there can only dummynodes when maxrank >1
  1017. // with levels 0, 1 and 2 with at least dummy nodes at level 1
  1018. // This phase of the node placer marks all type 1 and type 2 conflicts.
  1019. // The conflict types base on the distinction of inner segments and non-inner segments of edges.
  1020. // A inner segment is present if an edge is drawn between two dummy nodes and thus is part of
  1021. // a long edge.
  1022. // A non-inner segment is present if one of the connected nodes is not a dummy node.
  1023. // Type 0 conflicts occur if two non-inner segments cross each other.
  1024. // Type 1 conflicts happen when a non-inner segment and a inner segment cross.
  1025. // Type 2 conflicts are present if two inner segments cross.
  1026. // The markers are later used to solve conflicts in favor of long edges.
  1027. // In case of type 2 conflicts, the marker favors the earlier node in layout order.
  1028. // In case of type 1 conflict the non-inner edge is marked as conflicting edge.
  1029. if (maxrank > 1) {
  1030. // here if maxrank is 2 or more with levels 0, 1, 2 ...
  1031. // there can only be inner edges below level 2 because level 0 has start nodes
  1032. // and level 1 has dummy nodes with only non-inner edges
  1033. // the last level only has end nodes with (last-level-1) dummy nodes
  1034. // at that level are only non-inner edges
  1035. for (unsigned int rank = 2; rank < maxrank - 2; rank++) {
  1036. rc = 0;
  1037. // only if there are crossings at this level with a dummy node involved
  1038. // edge type 1 conflicts when inner edge crosses non-inner edge
  1039. if (verbose == true) {
  1040. std::printf("between level %d and level %d are %d crossings", rank, rank + 1, order->m_crossings_num[rank]);
  1041. if (order->m_crossings_num[rank] > 0) {
  1042. std::printf(", %d local-nonlocal Type 1 conflict, %d local-local Type 2 conflict, %d nonlocal-nonlocal crossings type 0 conflict",
  1043. order->m_ircrossings_num[rank],
  1044. order->m_iicrossings_num[rank],
  1045. order->m_rrcrossings_num[rank]);
  1046. }
  1047. std::printf("\n");
  1048. }
  1049. if (order->m_ircrossings_num[rank] > 0) {
  1050. if (verbose == true) {
  1051. std::printf("between level %d and level %d are %d Type 1 edge conflicts\n", (int)rank, (int)(rank + 1), (int)order->m_ircrossings_num[rank]);
  1052. }
  1053. // check nodes at level (rank) and the out edges to level rank+1
  1054. // find the Type 1 conflict edges and mark them
  1055. // if curedge->ircross > 0 then it is a Type 1 conflict edge
  1056. // check if edge is inner or non-inner segment
  1057. // mark non-inner segment as conflict edge
  1058. // Making list of all outgoing edges between rank and rank+1 level
  1059. edge_list.clear();
  1060. // scan node at this rank level
  1061. for (unsigned int i = 0; i < order->order_vector[rank].size(); i++) {
  1062. // select the outgoing edges at a node and reset edge crossing count data
  1063. for (list<pLEdge>::iterator edge_iter = order->order_vector[rank][i]->out_edges_list()->begin();
  1064. edge_iter != order->order_vector[rank][i]->out_edges_list()->end();
  1065. edge_iter++) {
  1066. edge_list.push_back((pLEdge)(*edge_iter));
  1067. // not a conflict type 1 edge
  1068. ((pLEdge)(*edge_iter))->conflict = false;
  1069. }
  1070. }
  1071. // scan the edges in just created edge list
  1072. for (unsigned int i = 0; i < edge_list.size(); i++) {
  1073. if (edge_list[i]->n_ircross() > 0) {
  1074. // scan the next edges after current edge
  1075. for (unsigned int j = i + 1; j < edge_list.size(); j++) {
  1076. if (edge_list[j]->n_ircross() > 0) {
  1077. // Criterion of crossing edge_list[i] and edge_list[j]
  1078. // check relative position of to nodes in edge
  1079. int cmp1 = ((pLNode)edge_list[i]->to())->pos - ((pLNode)edge_list[j]->to())->pos;
  1080. // check relative position of from nodes in edge
  1081. int cmp2 = ((pLNode)edge_list[i]->from())->pos - ((pLNode)edge_list[j]->from())->pos;
  1082. // cmp1 is delto to pos, cmp2 is delta from pos
  1083. if ((cmp1 > 0 && cmp2 < 0) || (cmp1 < 0 && cmp2 > 0)) {
  1084. rc++;
  1085. // edges did cross
  1086. if (verbose == true) {
  1087. std::printf("edge crossing inner status %d and %d\n", edge_list[i]->inner, edge_list[j]->inner);
  1088. }
  1089. if (edge_list[i]->inner == true && edge_list[j]->inner == true) {
  1090. // inner inner edge crossings
  1091. } else if (edge_list[i]->inner == false && edge_list[j]->inner == false) {
  1092. // should not happen
  1093. } else if (edge_list[i]->inner == false && edge_list[j]->inner == true) {
  1094. // noninner inner crossing
  1095. if (edge_list[i]->conflict == false) {
  1096. // set the noninner edge as conflict edge
  1097. edge_list[i]->setconflict(true);
  1098. ntype1++;
  1099. }
  1100. } else {
  1101. // inner noninner crossing
  1102. if (edge_list[j]->conflict == false) {
  1103. // set the noninner edge as conflict edge
  1104. edge_list[j]->setconflict(true);
  1105. ntype1++;
  1106. }
  1107. }
  1108. } else {
  1109. // edges did not cross
  1110. }
  1111. } // end of if (edge_list[j]->n_ircross() > 0)
  1112. } // end of for (unsigned int j = i + 1; j < edge_list.size(); j++)
  1113. } // end of if (edge_list[i]->n_ircross() > 0)
  1114. } // end of for (unsigned int i = 0; i < edge_list.size(); i++)
  1115. } // end of if (order->m_ircrossings_num[rank] > 0)
  1116. // todo here
  1117. std::printf("at rank %d found %d crossings and expected %d crossings\n", rank, order->m_ircrossings_num[rank], rc);
  1118. } // end of for (unsigned int rank = 0; rank < maxrank - 1; rank++)
  1119. } // end of if (maxrank > 1)
  1120. edge_list.clear();
  1121. if (verbose == true) {
  1122. if (ntype1 > 0) {
  1123. std::printf("total %d type 1 conflict edges in the graph\n", ntype1);
  1124. // output it as dot graph
  1125. std::printf("// conflict type 1 edge is noninner edge colored red and crossing between inner and noninner edge\n");
  1126. std::printf("// inner edge is blue\n");
  1127. std::printf("// noninner edge is green\n");
  1128. std::printf("digraph conflict1edges {\n");
  1129. // scan all edges
  1130. for (list<pLEdge>::iterator edge_iter = edges_list()->begin();
  1131. edge_iter != edges_list()->end();
  1132. edge_iter++) {
  1133. std::printf(" %d -> %d [color=\"", (*edge_iter)->from()->id(), (*edge_iter)->to()->id());
  1134. if (((pLEdge)(*edge_iter))->conflict == true) {
  1135. // this is a conflict 1 edge and a noninner edge
  1136. std::printf("red");
  1137. } else {
  1138. // colorize inner/noninner edges
  1139. if (((pLEdge)(*edge_iter))->inner == true) {
  1140. std::printf("blue");
  1141. } else {
  1142. std::printf("green");
  1143. }
  1144. }
  1145. std::printf("\"];\n");
  1146. }
  1147. }
  1148. std::printf("}\n");
  1149. }
  1150. // init arrays with the node data
  1151. FinalCoordinates_init_medians(order);
  1152. // check the 4 connecting nodes possible at node
  1153. // upper_left=0, lower_left=1, upper_right=2, lower_right=3
  1154. FinalCoordinates_vertical_align(order, orient::upper_left);
  1155. FinalCoordinates_horizontal_compaction(order, orient::upper_left);
  1156. FinalCoordinates_vertical_align(order, orient::lower_left);
  1157. FinalCoordinates_horizontal_compaction(order, orient::lower_left);
  1158. FinalCoordinates_vertical_align(order, orient::upper_right);
  1159. FinalCoordinates_horizontal_compaction(order, orient::upper_right);
  1160. FinalCoordinates_vertical_align(order, orient::lower_right);
  1161. FinalCoordinates_horizontal_compaction(order, orient::lower_right);
  1162. return;
  1163. }
  1164. /**
  1165. * set nodes at final (x,y) position in this level
  1166. * \param normalwide is x size for a node
  1167. * \param dummy wide is x sie for a dummy node
  1168. * \param vertical_size is y distance between y rank levels
  1169. */
  1170. void LGraph::InitCoordinates(Ordering* order,
  1171. int normalwide,
  1172. int dummywide,
  1173. int vertical_size)
  1174. {
  1175. vector<unsigned int> wides(maxrank + 1);
  1176. // Getting Max Size;
  1177. unsigned int maxwide = 0;
  1178. // Calculating wide of each rank.
  1179. for (unsigned int rank = 0; rank <= maxrank; rank++) {
  1180. // scan nodes at this level
  1181. for (unsigned int i = 0; i < order->order_vector[rank].size(); i++) {
  1182. // adjust xsize depending on node type
  1183. if (order->order_vector[rank][i]->dummy == false) {
  1184. // regular node
  1185. wides[rank] += normalwide;
  1186. } else {
  1187. // dummy node
  1188. wides[rank] += dummywide;
  1189. }
  1190. }
  1191. // check if this level is wider
  1192. if (wides[rank] > maxwide) {
  1193. maxwide = wides[rank];
  1194. }
  1195. }
  1196. // Centering graph
  1197. for (unsigned int rank = 0; rank <= maxrank; rank++) {
  1198. // check all nodes in this level rank
  1199. // wides[rank] is the x size of this rank
  1200. // maxwide is largest x size of the drawing
  1201. for (unsigned int i = 0; i < order->order_vector[rank].size(); i++) {
  1202. if (i == 0) {
  1203. // put first node
  1204. order->order_vector[rank][i]->x = (maxwide / 2) - (wides[rank] / 2) + 20;
  1205. } else if (order->order_vector[rank][i]->dummy == false) {
  1206. // regular node
  1207. order->order_vector[rank][i]->x = order->order_vector[rank][i - 1]->x + normalwide;
  1208. } else {
  1209. // dummy node
  1210. order->order_vector[rank][i]->x = order->order_vector[rank][i - 1]->x + dummywide;
  1211. }
  1212. // y spacing
  1213. order->order_vector[rank][i]->y = rank * vertical_size;
  1214. // set a value for the second (x,y) pos
  1215. order->order_vector[rank][i]->x2 = order->order_vector[rank][i]->x;
  1216. order->order_vector[rank][i]->y2 = order->order_vector[rank][i]->y;
  1217. }
  1218. }
  1219. // now priority layout setting (x2,y2)
  1220. return;
  1221. }
  1222. /**
  1223. * try different graph lyouts to find the one with lowest edge crossings
  1224. * \param maxtry try limited number of times
  1225. */
  1226. void LGraph::Transpose(unsigned long int maxtry, bool verbose)
  1227. {
  1228. bool improved = true;
  1229. for (unsigned long int j = 1; j < maxtry; j++) {
  1230. improved = true;
  1231. // try another layout
  1232. while (improved == true) {
  1233. improved = false;
  1234. // scan all rank levels
  1235. for (unsigned int r = 1; r < order->order_vector.size(); r++) {
  1236. // scan nodes at levels
  1237. for (unsigned long int i = 0; (order->order_vector[r].size() > j) && (i < order->order_vector[r].size() - (j + 1));
  1238. i++) {
  1239. // get nodes
  1240. pLNode v = order->order_vector[r][i];
  1241. pLNode w = order->order_vector[r][i + j];
  1242. // Give nodes initial x position based on index in order
  1243. InitPos(order);
  1244. // count crossings between level r and r+1, and level r-1 and r
  1245. int cross0 = countCrossingOnRank(order, r) + countCrossingOnRank(order, r - 1);
  1246. // change node positions
  1247. v->pos += j;
  1248. w->pos -= j;
  1249. // after node swapping count crossings between level r and r+1, and level r-1 and r
  1250. int cross1 = countCrossingOnRank(order, r) + countCrossingOnRank(order, r - 1);
  1251. // check if reduced crossings, use < and not <= here
  1252. if (cross1 < cross0) {
  1253. // swapping nodes improved edge crossings
  1254. improved = true;
  1255. // put nodes at new locations
  1256. order->order_vector[r][i] = w;
  1257. order->order_vector[r][i + j] = v;
  1258. if (verbose == true) {
  1259. printf("%s(): edge crossings reduced from %d to %d at try %lu rank %lu\n", __func__, cross0, cross1, j, i);
  1260. }
  1261. } else {
  1262. if (verbose == true) {
  1263. if (0) {
  1264. printf("%s(): edge crossings did not reduce from current %d to %d at try %lu rank %lu\n", __func__, cross0, cross1, j, i);
  1265. }
  1266. }
  1267. }
  1268. // end of nodes at level
  1269. }
  1270. }
  1271. // end of rank levels
  1272. }
  1273. // end of maxtry
  1274. }
  1275. return;
  1276. }
  1277. /**
  1278. * free node
  1279. */
  1280. void LGraph::FreeNode(pLNode p)
  1281. {
  1282. assert(p != NULL);
  1283. delete p; // todo warning here
  1284. }
  1285. /**
  1286. * free edge
  1287. */
  1288. void LGraph::FreeEdge(pLEdge p)
  1289. {
  1290. assert(p != NULL);
  1291. delete (pLEdge)p; // todo warning here
  1292. }
  1293. /**
  1294. * add edge between from and to nodes
  1295. */
  1296. pLEdge
  1297. LGraph::AddEdge(pLNode from, pLNode to, void* usrdata)
  1298. {
  1299. pLEdge new_edge = new LEdge(from, to);
  1300. new_edge->usrdata = usrdata;
  1301. return new_edge;
  1302. }
  1303. /**
  1304. * find node with given id number
  1305. */
  1306. pLNode LGraph::FindNode(int num)
  1307. {
  1308. pLNode curnode = NULL;
  1309. splay_tree_node spn = NULL;
  1310. spn = splay_tree_lookup(nodesplay, (splay_tree_key)num);
  1311. if (spn) {
  1312. curnode = (pLNode)spn->value;
  1313. }
  1314. return (curnode);
  1315. }
  1316. /**
  1317. * find edge with given id number
  1318. */
  1319. pLEdge LGraph::FindEdge(int num)
  1320. {
  1321. pLEdge curedge = NULL;
  1322. splay_tree_node spn = NULL;
  1323. spn = splay_tree_lookup(edgesplay, (splay_tree_key)num);
  1324. if (spn) {
  1325. curedge = (pLEdge)spn->value;
  1326. }
  1327. return (curedge);
  1328. }
  1329. /**
  1330. * create graph
  1331. */
  1332. LGraph::LGraph()
  1333. {
  1334. maxrank = 0;
  1335. m_nstarter_num = 0;
  1336. layouted = false;
  1337. order = (Ordering*)0;
  1338. nodesplay = (splay_tree)0;
  1339. edgesplay = (splay_tree)0;
  1340. m_total_nodes_num = 0;
  1341. m_total_dummynodes_num = 0;
  1342. m_total_edges_num = 0;
  1343. m_total_horedges_num = 0;
  1344. m_total_selfedges_num = 0;
  1345. m_total_reversededges_num = 0;
  1346. next_node_id = 0;
  1347. next_edge_id = 0;
  1348. m_id = 0;
  1349. m_xspacing_num = 20;
  1350. m_yspacing_num = 40;
  1351. }
  1352. /**
  1353. * delete graph
  1354. */
  1355. LGraph::~LGraph()
  1356. {
  1357. nodesplay = splay_tree_delete(nodesplay);
  1358. edgesplay = splay_tree_delete(edgesplay);
  1359. Destroy();
  1360. }
  1361. /**
  1362. * create node
  1363. */
  1364. pLNode LGraph::AddNode()
  1365. {
  1366. pLNode new_node = new LNode(this);
  1367. return new_node;
  1368. }
  1369. /**
  1370. * clear graph
  1371. * \todo check
  1372. */
  1373. void LGraph::Destroy()
  1374. {
  1375. // list<pNode>::iterator node_iter;
  1376. // list<pEdge>::iterator edge_iter;
  1377. while (m_nodes_list.empty() == false) {
  1378. pLNode pn = m_nodes_list.front();
  1379. // delete node and it in/out edges
  1380. DeleteNode(pn);
  1381. }
  1382. assert(m_nodes_list.empty());
  1383. assert(m_edges_list.empty());
  1384. assert(m_total_edges_num == 0);
  1385. assert(m_total_nodes_num == 0);
  1386. nodesplay = splay_tree_delete(nodesplay);
  1387. edgesplay = splay_tree_delete(edgesplay);
  1388. return;
  1389. }
  1390. /**
  1391. * return false if some integrity error of graph data
  1392. */
  1393. bool LGraph::Verify(void)
  1394. {
  1395. // error if no nodes, but there are edges.
  1396. if (m_edges_list.size() > 0 && m_nodes_list.size() == 0) {
  1397. return false;
  1398. }
  1399. map<pLEdge, bool> edge_map;
  1400. // scan all nodes
  1401. for (list<pLNode>::iterator node_iter = m_nodes_list.begin();
  1402. node_iter != m_nodes_list.end();
  1403. node_iter++) {
  1404. // error if node does not belong to this graph
  1405. if ((*node_iter)->m_graph != this) {
  1406. return false;
  1407. }
  1408. // scan incoming edges at this node
  1409. for (list<pLEdge>::iterator edge_iter = (*node_iter)->m_in_edges_list.begin();
  1410. edge_iter != (*node_iter)->m_in_edges_list.end();
  1411. edge_iter++) {
  1412. // error if edge does not belong to this graph
  1413. if ((*node_iter)->m_graph != (*edge_iter)->m_graph) {
  1414. return false;
  1415. }
  1416. }
  1417. // scan outgoing edges at this node
  1418. for (list<pLEdge>::iterator edge_iter = (*node_iter)->m_out_edges_list.begin();
  1419. edge_iter != (*node_iter)->m_out_edges_list.end();
  1420. edge_iter++) {
  1421. // error if edge does not belong to this graph
  1422. if ((*node_iter)->m_graph != (*edge_iter)->m_graph) {
  1423. return false;
  1424. }
  1425. }
  1426. }
  1427. // scan all edges
  1428. for (list<pLEdge>::iterator edge_iter = m_edges_list.begin();
  1429. edge_iter != m_edges_list.end();
  1430. edge_iter++) {
  1431. edge_map[(*edge_iter)] = true;
  1432. }
  1433. // scan all edges
  1434. for (list<pLEdge>::iterator edge_iter = m_edges_list.begin();
  1435. edge_iter != m_edges_list.end();
  1436. edge_iter++) {
  1437. // error if edge has no from node or no end node
  1438. if ((*edge_iter)->m_from == NULL || (*edge_iter)->m_to == NULL) {
  1439. return false;
  1440. }
  1441. // error if edge does not belong to a graph
  1442. if ((*edge_iter)->m_graph == NULL) {
  1443. return false;
  1444. }
  1445. // error if one of nodes does not belong to a graph
  1446. if ((*edge_iter)->m_from->m_graph == NULL || (*edge_iter)->m_to->m_graph == NULL) {
  1447. return false;
  1448. }
  1449. // error if edge does not belong to this graph
  1450. if ((*edge_iter)->m_graph != this) {
  1451. return false;
  1452. }
  1453. // error if iter does not belong to this graph
  1454. if (!((*edge_iter)->m_graph == (*edge_iter)->m_to->m_graph && (*edge_iter)->m_graph == (*edge_iter)->m_from->m_graph)) {
  1455. return false;
  1456. }
  1457. bool flag = false;
  1458. // Check for list of incoming edges.
  1459. for (list<pLEdge>::iterator edge_local = (*edge_iter)->m_to->m_in_edges_list.begin();
  1460. edge_local != (*edge_iter)->m_to->m_in_edges_list.end();
  1461. edge_local++) {
  1462. // Sets if this is exist incoming edge
  1463. if ((*edge_iter) == (*edge_local)) {
  1464. flag = true; // named edge_iter.
  1465. }
  1466. // If there are some edges without declaration
  1467. if (edge_map[(*edge_iter)] == false) {
  1468. return false; // in m_edges_list, graph isn't correct.
  1469. }
  1470. }
  1471. /* stop at error */
  1472. if (flag == false) {
  1473. return false;
  1474. }
  1475. flag = false;
  1476. // The same check for list of outgoing edges.
  1477. for (list<pLEdge>::iterator edge_local = (*edge_iter)->m_from->m_out_edges_list.begin();
  1478. edge_local != (*edge_iter)->m_from->m_out_edges_list.end();
  1479. edge_local++) {
  1480. // Sets if this is exist outgoing edge
  1481. if ((*edge_iter) == (*edge_local)) {
  1482. flag = true;
  1483. }
  1484. // If there are some edges without declaration
  1485. if (edge_map[(*edge_iter)] == false) {
  1486. return false;
  1487. }
  1488. }
  1489. // stop at error
  1490. if (flag == false) {
  1491. return false;
  1492. }
  1493. }
  1494. // graph data is correct
  1495. return true;
  1496. }
  1497. /**
  1498. * run dfs to assing node dfs number
  1499. */
  1500. void LGraph::DFS(pLNode node,
  1501. map<pLNode, bool>* isused,
  1502. map<pLNode, int>* dfs,
  1503. int* num)
  1504. {
  1505. pLEdge curedge;
  1506. pLNode ton;
  1507. if ((*isused)[node] == true) {
  1508. // return if node has already set
  1509. return;
  1510. }
  1511. (*isused)[node] = true;
  1512. // set dfs count
  1513. (*dfs)[node] = ++(*num);
  1514. // follow outgoing edges of this node
  1515. for (list<pLEdge>::iterator edge_iter = node->m_out_edges_list.begin();
  1516. edge_iter != node->m_out_edges_list.end();
  1517. edge_iter++) {
  1518. curedge = (*edge_iter);
  1519. ton = curedge->to();
  1520. if (ton) {
  1521. // if to edge is not done, recurse
  1522. // if (((*isused)[(*edge_iter)->m_to]) == false) {
  1523. // DFS((*edge_iter)->m_to, isused, dfs, num);
  1524. // }
  1525. if (((*isused)[ton]) == false) {
  1526. DFS(ton, isused, dfs, num);
  1527. }
  1528. }
  1529. }
  1530. return;
  1531. }
  1532. /**
  1533. * return true if revesed edges count changed
  1534. * find cycles in the graph and reverse edge
  1535. */
  1536. bool LGraph::FindReverseEdges(list<pLEdge>& ReverseEdges)
  1537. {
  1538. map<pLNode, int>* dfs = new map<pLNode, int>; // dfs count numbers
  1539. map<pLNode, bool>* isused = new map<pLNode, bool>; // dfs flags
  1540. int num = 0; // Current dfs counter is 0
  1541. size_t count_rev_edges = ReverseEdges.size();
  1542. int rank = 0;
  1543. // clear dfs
  1544. for (list<pLNode>::iterator node_iter = m_nodes_list.begin();
  1545. node_iter != m_nodes_list.end();
  1546. node_iter++) {
  1547. (*dfs)[*node_iter] = 0;
  1548. }
  1549. // clear used
  1550. for (list<pLNode>::iterator node_iter = m_nodes_list.begin();
  1551. node_iter != m_nodes_list.end();
  1552. node_iter++) {
  1553. (*isused)[(*node_iter)] = false;
  1554. }
  1555. for (list<pLNode>::iterator node_iter = m_nodes_list.begin();
  1556. node_iter != m_nodes_list.end();
  1557. node_iter++) {
  1558. if ((*isused)[*node_iter] == false) {
  1559. // Starts from every new node.
  1560. DFS((*node_iter), isused, dfs, &num);
  1561. }
  1562. }
  1563. delete isused;
  1564. // detect cycles
  1565. for (list<pLEdge>::iterator edge_iter = m_edges_list.begin();
  1566. edge_iter != m_edges_list.end();
  1567. edge_iter++) {
  1568. if ((*dfs)[(*edge_iter)->m_to] < (*dfs)[(*edge_iter)->m_from]) {
  1569. // this is a cycle
  1570. ReverseEdges.push_back((*edge_iter));
  1571. }
  1572. }
  1573. delete dfs;
  1574. // total number of reversed edges without self-edges
  1575. m_total_reversededges_num = ReverseEdges.size();
  1576. if (ReverseEdges.size() == count_rev_edges) {
  1577. return false; // No changes
  1578. }
  1579. /* reversed edges changed */
  1580. return true;
  1581. }
  1582. /**
  1583. * set uniq graph id as int number
  1584. */
  1585. void LGraph::Setid(int id)
  1586. {
  1587. m_id = id;
  1588. return;
  1589. }
  1590. /**
  1591. * increase count of dummy nodes
  1592. */
  1593. void LGraph::AddDummyNode()
  1594. {
  1595. m_total_dummynodes_num++;
  1596. return;
  1597. }
  1598. /**
  1599. * delete node and it in/out edges
  1600. */
  1601. void LGraph::DeleteNode(pLNode p)
  1602. {
  1603. bool found = false;
  1604. // todo if dummy node, update graph dummy node count
  1605. // clear incoming edges
  1606. while (p->m_in_edges_list.empty() == false) {
  1607. found = DeleteEdge(p->m_in_edges_list.front()->m_from, p);
  1608. if (found == false) { // edge not found
  1609. }
  1610. }
  1611. // clear outgoing edges
  1612. while (p->m_out_edges_list.empty() == false) {
  1613. found = DeleteEdge(p, p->m_out_edges_list.front()->m_to);
  1614. if (found == false) { // edge not found
  1615. }
  1616. }
  1617. // remove node from nodelist
  1618. m_nodes_list.remove(p);
  1619. // decr. number of total nodes
  1620. if (m_total_nodes_num > 0) {
  1621. m_total_nodes_num--;
  1622. }
  1623. // clear node
  1624. FreeNode(p);
  1625. return;
  1626. }
  1627. /**
  1628. * remove edge between node from and node to
  1629. * return tru if edge deleted, false when edge not found
  1630. */
  1631. bool LGraph::DeleteEdge(pLNode from, pLNode to)
  1632. {
  1633. assert(from && from->m_graph == this);
  1634. assert(to && to->m_graph == this);
  1635. // delete self edge if specified
  1636. if (from->id() == to->id()) {
  1637. // this is a self edge
  1638. if (from->nselfedges() <= 0) {
  1639. // shouldnothappen
  1640. from->m_selfedges = 0;
  1641. return false;
  1642. }
  1643. from->m_selfedges--;
  1644. // update in graph data
  1645. if (from->m_graph->m_total_selfedges_num > 0) {
  1646. from->m_graph->m_total_selfedges_num--;
  1647. }
  1648. return true;
  1649. }
  1650. list<pLEdge>::iterator edge_iter;
  1651. // scan edge list
  1652. for (edge_iter = m_edges_list.begin();
  1653. edge_iter != m_edges_list.end();
  1654. edge_iter++) {
  1655. pLEdge pe = *edge_iter;
  1656. // if this is edge with from/to number
  1657. if (pe->m_from == from && pe->m_to == to) {
  1658. m_edges_list.erase(edge_iter);
  1659. // remove as outgoing edge at from node
  1660. pe->m_from->m_out_edges_list.remove(pe);
  1661. // remove as incoming edge at to node
  1662. pe->m_to->m_in_edges_list.remove(pe);
  1663. pe->m_from = NULL;
  1664. pe->m_to = NULL;
  1665. m_total_edges_num--;
  1666. FreeEdge(pe);
  1667. // edge is found and deleted
  1668. return true;
  1669. }
  1670. }
  1671. // return false if edge not found.
  1672. return false;
  1673. }
  1674. /**
  1675. * print graph data
  1676. */
  1677. void LGraph::Dump()
  1678. {
  1679. list<pLNode>::iterator node_iter;
  1680. list<pLEdge>::iterator edge_iter;
  1681. printf("Dumping graph id:%d (%d nodes, %d real nodes, %d dummy nodes, %d edges, %d horizontal edges, %d selfedges %d reversed edges)\n", id(), nnodes(), nrealnodes(), ndummynodes(), nedges(), nhoredges(), nselfedges(), nreversededges());
  1682. printf("Nodes:\n");
  1683. for (node_iter = m_nodes_list.begin();
  1684. node_iter != m_nodes_list.end();
  1685. node_iter++) {
  1686. pLNode pn = *node_iter;
  1687. if (pn) {
  1688. /* print single node */
  1689. pn->Dump();
  1690. }
  1691. }
  1692. // edge list does not have self edges
  1693. printf("Edges:\n");
  1694. for (edge_iter = m_edges_list.begin();
  1695. edge_iter != m_edges_list.end();
  1696. edge_iter++) {
  1697. pLEdge pe = *edge_iter;
  1698. if (pe) {
  1699. /* print single edge */
  1700. pe->Dump();
  1701. }
  1702. }
  1703. return;
  1704. }
  1705. /* end. */