GridLayouter.cpp 39 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752
  1. #include "GridLayouter.h"
  2. GridLayouter::GridLayouter()
  3. {
  4. }
  5. void GridLayouter::gridLayouterForClusteredGraph(SubGraph & gCurrentClusteredGraph,
  6. SubGraph & gRootClusteredGraph)
  7. {
  8. BoostGraphWrapper boostGraphWrapper;
  9. //Construct a non-clustered graph newG for given clustered graph--------------------------------------------
  10. //where, all clusters are replaced by nodes with same size
  11. //create newG
  12. SubGraph gNewGraph;
  13. //define data structures to store mapping between nodes of newG and originalG
  14. QMap <int, bool> isCluster;
  15. QMap <int, VertexIterator> originalVertexForNewVertex;
  16. QMap <int, ChildrenIterator> childrenList;
  17. //add nodes to newG
  18. this->addVerticesToNewGraph(gCurrentClusteredGraph, gNewGraph, gRootClusteredGraph,
  19. isCluster, originalVertexForNewVertex, childrenList);
  20. int nv = boost::num_vertices(gNewGraph);
  21. // XXX old LAYOUT_ASSERT((size_t)boost::num_vertices(gNewGraph) == isCluster.size(),
  22. Q_UNUSED(nv);
  23. LAYOUT_ASSERT(nv == isCluster.size(),
  24. LayoutException("gridLayouterForClusteredGraph",
  25. LayoutExceptionEnum::INCONSISTENT_DATASTRUCTURE,
  26. "isCluster",
  27. "after adding node to NewGraph"));
  28. //if nothing added to newG, it means that current clustered graph doesnot contain anything
  29. //(neither vertex nor another cluster)
  30. //in such case, add a dummy invisible node with some fixed size and location and return
  31. if(boost::num_vertices(gNewGraph) == 0)
  32. {
  33. //add a dummy invisible vertex of some fixed size
  34. VertexDescriptor vDummyInvisibleVertex = add_vertex(gCurrentClusteredGraph);
  35. boostGraphWrapper.setVertexCenterCoordX(vDummyInvisibleVertex, gCurrentClusteredGraph, 0);
  36. boostGraphWrapper.setVertexCenterCoordY(vDummyInvisibleVertex, gCurrentClusteredGraph, 0);
  37. boostGraphWrapper.setVertexHeight(vDummyInvisibleVertex, gCurrentClusteredGraph, 40);
  38. boostGraphWrapper.setVertexWidth(vDummyInvisibleVertex, gCurrentClusteredGraph, 40);
  39. boostGraphWrapper.setVertexIsInvisible(vDummyInvisibleVertex, gCurrentClusteredGraph, true);
  40. //Update properties of current clustered graph
  41. Reingold reingold;
  42. int iMargine = 10;
  43. reingold.setCompartMentProps(gCurrentClusteredGraph, iMargine);
  44. return;
  45. }
  46. //define data structures to store edges to be added to newG and their corres. original edges
  47. std::vector<GraphPreProcessor::VertexOrderType> oEdgesToRemove;
  48. std::vector<GridLayouter::edgeType> oEdgesToAdd;
  49. std::vector<GraphPreProcessor::VertexOrderType> oInnerEdgesToRemove;
  50. //find edges to be added and removed
  51. this->findEdgesToBeAddedRemoved(gCurrentClusteredGraph, gNewGraph,
  52. oEdgesToRemove,
  53. oEdgesToAdd,
  54. oInnerEdgesToRemove,
  55. childrenList);
  56. LAYOUT_ASSERT(oEdgesToRemove.size() == oEdgesToAdd.size(),
  57. LayoutException("gridLayouterForClusteredGraph",
  58. LayoutExceptionEnum::INCONSISTENT_DATASTRUCTURE,
  59. "oEdgesToRemove-oEdgesToAdd",
  60. "after finding edges to be added/removed"));
  61. //add edges to newG
  62. this->addEdgesToNewGraph(gCurrentClusteredGraph, gNewGraph,
  63. oEdgesToRemove,
  64. oEdgesToAdd,
  65. oInnerEdgesToRemove,
  66. originalVertexForNewVertex);
  67. //---------------------------------------------------------------------------------------------------------
  68. //call gridLayouterForNonClusteredGraph() for newG---------------------------------------------------------
  69. //Remove parallel edges
  70. GraphPreProcessor graphPreProcessor;
  71. GraphPreProcessor::EdgeOrderType oParallelEdges;
  72. std::vector<QString> oParallelEdgeIDs;
  73. graphPreProcessor.removeParallelEdges(gNewGraph, oParallelEdges, oParallelEdgeIDs);
  74. //NEED TO REMOVE PARALLEL EDGES since they may be introdiced when adding edges between nodes-for-clusters
  75. this->gridLayouterForNonClusteredGraph(gNewGraph);
  76. // //Add parallel edges back
  77. // graphPreProcessor.addParallelEdges(gNewGraph, oParallelEdges);
  78. //NO NEED TO ADD PARALLEL EDGES BACK since we use only coordinates of vertices of newG
  79. //---------------------------------------------------------------------------------------------------------
  80. //copy back the coordinates to original graph
  81. this->copyBackCoordinates(gCurrentClusteredGraph, gNewGraph, gRootClusteredGraph,
  82. isCluster,
  83. originalVertexForNewVertex,
  84. childrenList);
  85. //Update properties of current clustered graph
  86. Reingold reingold;
  87. int iMargine = 10;
  88. reingold.setCompartMentProps(gCurrentClusteredGraph, iMargine);
  89. }
  90. void GridLayouter::addVerticesToNewGraph(SubGraph & gCurrentClusteredGraph, SubGraph & gNewGraph,
  91. SubGraph & gRootClusteredGraph,
  92. QMap <int, bool> & isCluster,
  93. QMap <int, VertexIterator> & originalVertexForNewVertex,
  94. QMap <int, ChildrenIterator> & childrenList)
  95. {
  96. BoostGraphWrapper boostGraphWrapper;
  97. int iGraphClusterId = boostGraphWrapper.getGraphClusterID(gCurrentClusteredGraph);
  98. //add normal nodes from current graph to newG-----------------------------------------------------------
  99. VertexIterator itrVert, itrEndVert;
  100. for(boost::tie(itrVert, itrEndVert) = vertices(gCurrentClusteredGraph); itrVert != itrEndVert; itrVert++)
  101. {
  102. VertexDescriptor vCurrentVertexInClusteredGraph = *itrVert;
  103. int iVertexClusterId = boostGraphWrapper.getVertexClusterID(*itrVert, gCurrentClusteredGraph);
  104. if(iVertexClusterId == iGraphClusterId)
  105. {
  106. VertexDescriptor vNew = add_vertex(gNewGraph);
  107. //set size of new node same as the original node
  108. int iVertexHeight = boostGraphWrapper.getVertexHeight(vCurrentVertexInClusteredGraph, gCurrentClusteredGraph);
  109. int iVertexWidth = boostGraphWrapper.getVertexWidth(vCurrentVertexInClusteredGraph, gCurrentClusteredGraph);
  110. boostGraphWrapper.setVertexHeight(vNew, gNewGraph, iVertexHeight);
  111. boostGraphWrapper.setVertexWidth(vNew, gNewGraph, iVertexWidth);
  112. int iNewVertexIndex = get(vertex_index, gNewGraph, vNew);
  113. isCluster.insert(iNewVertexIndex, false);
  114. originalVertexForNewVertex.insert(iNewVertexIndex, itrVert);
  115. }
  116. }
  117. //--------------------------------------------------------------------------------------------------------
  118. //for each child, call gridLayouterForClusteredGraph() and add newNode to newG----------------------------
  119. ChildrenIterator itrChild, itrEndChild;
  120. for(boost::tie(itrChild, itrEndChild) = gCurrentClusteredGraph.children(); itrChild != itrEndChild; ++itrChild)
  121. {
  122. this->gridLayouterForClusteredGraph(*itrChild, gRootClusteredGraph);
  123. VertexDescriptor vNew = add_vertex(gNewGraph);
  124. //set size of new node same as the child graph
  125. int iChildHeight, iChildWidth;
  126. iChildHeight = boostGraphWrapper.getGraphHeight(*itrChild);
  127. iChildWidth = boostGraphWrapper.getGraphWidth(*itrChild);
  128. boostGraphWrapper.setVertexHeight(vNew, gNewGraph, iChildHeight);
  129. boostGraphWrapper.setVertexWidth(vNew, gNewGraph, iChildWidth);
  130. int iNewVertexIndex = get(vertex_index, gNewGraph, vNew);
  131. isCluster.insert(iNewVertexIndex, true);
  132. childrenList.insert(iNewVertexIndex, itrChild);
  133. }
  134. //---------------------------------------------------------------------------------------------------------
  135. }
  136. void GridLayouter::findEdgesToBeAddedRemoved(SubGraph & gCurrentClusteredGraph, SubGraph & gNewGraph,
  137. std::vector<GraphPreProcessor::VertexOrderType> & oEdgesToRemove,
  138. std::vector<GridLayouter::edgeType> & oEdgesToAdd,
  139. std::vector<GraphPreProcessor::VertexOrderType> & oInnerEdgesToRemove,
  140. QMap <int, ChildrenIterator> & childrenList)
  141. {
  142. std::vector<VertexDescriptor> oEndPointsOfEdgeToRemove(2);
  143. GridLayouter::edgeType oEndPointsOfEdgeToAdd(2);
  144. std::vector<VertexDescriptor> oEndPointsOfInnerEdge(2);
  145. //find edges in/out of each child and their corresponding newEdges
  146. //for each child in currentG-----------------------------------------------------------------------------
  147. ChildrenIterator itrChild, itrEndChild;
  148. for(boost::tie(itrChild, itrEndChild) = gCurrentClusteredGraph.children(); itrChild != itrEndChild; ++itrChild)
  149. {
  150. //find newNode (in newG) corresponding to this child
  151. // XXX need init
  152. VertexDescriptor vCorresVertInNewG = 0;
  153. bool bFound = false;
  154. QMapIterator<int, ChildrenIterator> itrChildrenListMap(childrenList);
  155. // XXX unused
  156. Q_UNUSED(bFound);
  157. while (itrChildrenListMap.hasNext())
  158. {
  159. itrChildrenListMap.next();
  160. if(itrChild == itrChildrenListMap.value())
  161. {
  162. vCorresVertInNewG = vertex(itrChildrenListMap.key(), gNewGraph);
  163. bFound = true;
  164. break;
  165. }
  166. }
  167. // XXX vCorresVertInNewG can be un-inited, see below
  168. LAYOUT_ASSERT(bFound,
  169. LayoutException("findEdgesToBeAddedRemoved",
  170. LayoutExceptionEnum::INCONSISTENT_DATASTRUCTURE,
  171. "childrenList",
  172. ""));
  173. //for each vertex in this child----------------------------------------------------------------------
  174. VertexIterator itrVert, itrEndVert;
  175. for(boost::tie(itrVert, itrEndVert) = vertices(*itrChild); itrVert != itrEndVert; ++itrVert)
  176. {
  177. //get its global descriptor
  178. VertexDescriptor vGlobalOfVert = (*itrChild).local_to_global(*itrVert);
  179. //for each edge in currentG----------------------------------------------------------------------
  180. EdgeIterator itrEdge, itrEndEdge;
  181. for(boost::tie(itrEdge, itrEndEdge) = edges(gCurrentClusteredGraph); itrEdge != itrEndEdge; ++itrEdge)
  182. {
  183. //Find the type of edge----------------------------------------------------------------------
  184. GridLayouter::EdgeType enumEdgeStatus;
  185. //find src and tgt of edge (in currentG)
  186. VertexDescriptor vSrcOfEdgeInCurrentG, vTgtOfEdgeInCurrentG;
  187. vSrcOfEdgeInCurrentG = source(*itrEdge, gCurrentClusteredGraph);
  188. vTgtOfEdgeInCurrentG = target(*itrEdge, gCurrentClusteredGraph);
  189. //find global of src and tgt
  190. VertexDescriptor vGlobalOfSrc, vGlobalOfTgt;
  191. vGlobalOfSrc = gCurrentClusteredGraph.local_to_global(vSrcOfEdgeInCurrentG);
  192. vGlobalOfTgt = gCurrentClusteredGraph.local_to_global(vTgtOfEdgeInCurrentG);
  193. //find if the edge is incident on current vertex or not
  194. if(vGlobalOfVert == vGlobalOfSrc) //if current vertex is src; E(v --> tgt)
  195. {
  196. if(!(*itrChild).find_vertex(vGlobalOfTgt).second) //if tgt lies outside current child
  197. {
  198. //save the type of edge
  199. enumEdgeStatus = GOING_OUT;
  200. //remember the egde as 'to be removed'
  201. oEndPointsOfEdgeToRemove[0] = vSrcOfEdgeInCurrentG;
  202. oEndPointsOfEdgeToRemove[1] = vTgtOfEdgeInCurrentG;
  203. //remenber its corresponding edge 'to be added' in newG
  204. oEndPointsOfEdgeToAdd[0].vNode = vCorresVertInNewG;
  205. oEndPointsOfEdgeToAdd[0].vertexType = NEW_VERTEX;
  206. oEndPointsOfEdgeToAdd[1].vNode = vTgtOfEdgeInCurrentG;
  207. oEndPointsOfEdgeToAdd[1].vertexType = ORIGINAL_VERTEX;
  208. }
  209. else //if tgt also lies inside current child
  210. {
  211. //save the type of edge
  212. enumEdgeStatus = LIES_IN;
  213. //remember the egde as 'inner edge'; not added in newG
  214. oEndPointsOfInnerEdge[0] = vSrcOfEdgeInCurrentG;
  215. oEndPointsOfInnerEdge[1] = vTgtOfEdgeInCurrentG;
  216. }
  217. }
  218. else if(vGlobalOfVert == vGlobalOfTgt) //if current vertex is tgt; E(src --> v)
  219. {
  220. if(!(*itrChild).find_vertex(vGlobalOfSrc).second) //if src lies outside current child
  221. {
  222. //save the type of edge
  223. enumEdgeStatus = COMMING_IN;
  224. //remember the egde as 'to be removed'
  225. oEndPointsOfEdgeToRemove[0] = vSrcOfEdgeInCurrentG;
  226. oEndPointsOfEdgeToRemove[1] = vTgtOfEdgeInCurrentG;
  227. //remenber its corresponding edge 'to be added' in newG
  228. oEndPointsOfEdgeToAdd[0].vNode = vSrcOfEdgeInCurrentG;
  229. oEndPointsOfEdgeToAdd[0].vertexType = ORIGINAL_VERTEX;
  230. oEndPointsOfEdgeToAdd[1].vNode = vCorresVertInNewG;
  231. oEndPointsOfEdgeToAdd[1].vertexType = NEW_VERTEX;
  232. }
  233. else //if src also lies inside current child
  234. {
  235. //save the type of edge
  236. enumEdgeStatus = LIES_IN;
  237. //remember the egde as 'inner edge'; not added in newG
  238. oEndPointsOfInnerEdge[0] = vSrcOfEdgeInCurrentG;
  239. oEndPointsOfInnerEdge[1] = vTgtOfEdgeInCurrentG;
  240. }
  241. }
  242. else //if current vertex is neither src, nor tgt of this edge (edge not incident on current vertex)
  243. {
  244. //save the type of edge
  245. enumEdgeStatus = NOT_INCIDENT;
  246. }
  247. //---------------------------------------------------------------------------------------------
  248. //Remember the edges added and/or removed depending on type of current edge--------------------
  249. //if one end is in child and other out
  250. if(enumEdgeStatus == GOING_OUT || enumEdgeStatus == COMMING_IN)
  251. {
  252. //search in Removed[]
  253. bool bIsInRemoved = false;
  254. for(size_t iIndexOfEdgesToRemove = 0; iIndexOfEdgesToRemove < oEdgesToRemove.size(); ++iIndexOfEdgesToRemove)
  255. {
  256. //if already in Removed[]
  257. // XXX updated
  258. // if(vSrcOfEdgeInCurrentG == oEdgesToRemove[iIndexOfEdgesToRemove][0] &
  259. // vTgtOfEdgeInCurrentG == oEdgesToRemove[iIndexOfEdgesToRemove][1])
  260. if((vSrcOfEdgeInCurrentG == oEdgesToRemove[iIndexOfEdgesToRemove][0]) &&
  261. (vTgtOfEdgeInCurrentG == oEdgesToRemove[iIndexOfEdgesToRemove][1]))
  262. {
  263. //compare ToRemove and ToAdd, find common node, replace it in Removed[]
  264. //if src is common
  265. if(oEdgesToRemove[iIndexOfEdgesToRemove][0] == oEdgesToAdd[iIndexOfEdgesToRemove][0].vNode)
  266. {
  267. // XXX uninited vCorresVertInNewG
  268. oEdgesToAdd[iIndexOfEdgesToRemove][0].vNode = vCorresVertInNewG;
  269. oEdgesToAdd[iIndexOfEdgesToRemove][0].vertexType = NEW_VERTEX;
  270. bIsInRemoved = true;
  271. break;
  272. }
  273. //if tgt is common
  274. else if(oEdgesToRemove[iIndexOfEdgesToRemove][1] == oEdgesToAdd[iIndexOfEdgesToRemove][1].vNode)
  275. {
  276. oEdgesToAdd[iIndexOfEdgesToRemove][1].vNode = vCorresVertInNewG;
  277. oEdgesToAdd[iIndexOfEdgesToRemove][1].vertexType = NEW_VERTEX;
  278. bIsInRemoved = true;
  279. break;
  280. }
  281. else //if no common node found
  282. {
  283. throw LayoutException("findEdgesToBeAddedRemoved",
  284. LayoutExceptionEnum::NOT_FOUND_IN_CONTAINER,
  285. "edes to remove/add",
  286. "common vertex");
  287. }
  288. }
  289. }
  290. //if not in Removed[]
  291. if(!bIsInRemoved)
  292. {
  293. //save it in Removed[], and corresponding new edge in Added[]
  294. oEdgesToRemove.push_back(oEndPointsOfEdgeToRemove);
  295. oEdgesToAdd.push_back(oEndPointsOfEdgeToAdd);
  296. }
  297. }
  298. else if(enumEdgeStatus == LIES_IN) //if both ends are in child
  299. {
  300. //search in InnerEdges[]
  301. bool bIsInInnerEdgesToRemove = false;
  302. for(size_t iInnerEdgeIndex = 0; iInnerEdgeIndex < oInnerEdgesToRemove.size(); ++iInnerEdgeIndex)
  303. {
  304. //if already in InnerEdges[]
  305. //if(vSrcOfEdgeInCurrentG == oInnerEdgesToRemove[iInnerEdgeIndex][0] &
  306. // vTgtOfEdgeInCurrentG == oInnerEdgesToRemove[iInnerEdgeIndex][1])
  307. // XXX updated
  308. if((vSrcOfEdgeInCurrentG == oInnerEdgesToRemove[iInnerEdgeIndex][0]) &&
  309. (vTgtOfEdgeInCurrentG == oInnerEdgesToRemove[iInnerEdgeIndex][1]))
  310. {
  311. bIsInInnerEdgesToRemove = true;
  312. break;
  313. }
  314. }
  315. if(!bIsInInnerEdgesToRemove)//if not in InnerEdges[]
  316. {
  317. //save it in InnerEdges[]
  318. oInnerEdgesToRemove.push_back(oEndPointsOfInnerEdge);
  319. }
  320. }
  321. //else NOT_INCIDENT; ignore
  322. //-------------------------------------------------------------------------------------------
  323. }
  324. //--------------------------------------------------------------------------------------EOFL edge
  325. }
  326. //--------------------------------------------------------------------------------------EOFL vertices
  327. }
  328. //---------------------------------------------------------------------------------------------EOFL child
  329. }
  330. void GridLayouter::addEdgesToNewGraph(SubGraph & gCurrentClusteredGraph, SubGraph & gNewGraph,
  331. std::vector<GraphPreProcessor::VertexOrderType> & oEdgesToRemove,
  332. std::vector<GridLayouter::edgeType> & oEdgesToAdd,
  333. std::vector<GraphPreProcessor::VertexOrderType> & oInnerEdgesToRemove,
  334. QMap <int, VertexIterator> & originalVertexForNewVertex)
  335. {
  336. //for each edge in currentG------------------------------------------------------------------------------
  337. EdgeIterator itrEdge, itrEndEdge;
  338. for(boost::tie(itrEdge, itrEndEdge) = edges(gCurrentClusteredGraph); itrEdge != itrEndEdge; ++itrEdge)
  339. {
  340. EdgeDescriptor eCurrentEdge = *itrEdge;
  341. VertexDescriptor vSourceOfCurrentEdge;
  342. VertexDescriptor vTargetOfCurrentEdge;
  343. VertexDescriptor vSourceOfNewEdge;
  344. VertexDescriptor vTargetOfNewEdge;
  345. //get its src and tgt
  346. vSourceOfCurrentEdge = source(eCurrentEdge, gCurrentClusteredGraph);
  347. vTargetOfCurrentEdge = target(eCurrentEdge, gCurrentClusteredGraph);
  348. // XXX unused
  349. Q_UNUSED(vSourceOfCurrentEdge);
  350. Q_UNUSED(vTargetOfCurrentEdge);
  351. Q_UNUSED(vSourceOfNewEdge);
  352. Q_UNUSED(vTargetOfNewEdge);
  353. //search the edge in InnerEdges[]
  354. bool bIsInnerEdge = false;
  355. size_t iInnerEdgeIndex;
  356. for(iInnerEdgeIndex = 0; iInnerEdgeIndex < oInnerEdgesToRemove.size(); ++iInnerEdgeIndex)
  357. {
  358. // if(vSourceOfCurrentEdge == oInnerEdgesToRemove[iInnerEdgeIndex][0] &
  359. // vTargetOfCurrentEdge == oInnerEdgesToRemove[iInnerEdgeIndex][1])
  360. // XXX updated
  361. if((vSourceOfCurrentEdge == oInnerEdgesToRemove[iInnerEdgeIndex][0]) &&
  362. (vTargetOfCurrentEdge == oInnerEdgesToRemove[iInnerEdgeIndex][1]))
  363. {
  364. bIsInnerEdge = true;
  365. break;
  366. }
  367. }
  368. if(bIsInnerEdge) //if edge is in InnerEdges[]
  369. {
  370. //don't add it to NewG
  371. }
  372. else //if edge is not in InnerEdges[]----------------------------------------------------------------
  373. {
  374. //search the edge in Removed[]
  375. bool bIsToBeRemoved = false;
  376. size_t iRemovedEdgeIndex;
  377. for(iRemovedEdgeIndex = 0; iRemovedEdgeIndex < oEdgesToRemove.size(); ++iRemovedEdgeIndex)
  378. {
  379. // if(vSourceOfCurrentEdge == oEdgesToRemove[iRemovedEdgeIndex][0] &
  380. // vTargetOfCurrentEdge == oEdgesToRemove[iRemovedEdgeIndex][1])
  381. // XXX updated
  382. if((vSourceOfCurrentEdge == oEdgesToRemove[iRemovedEdgeIndex][0]) &&
  383. (vTargetOfCurrentEdge == oEdgesToRemove[iRemovedEdgeIndex][1]))
  384. {
  385. bIsToBeRemoved = true;
  386. break;
  387. }
  388. }
  389. if(bIsToBeRemoved) //edge is in Removed[]
  390. {
  391. //get its corresponding edge in Added[]
  392. if(oEdgesToAdd[iRemovedEdgeIndex][0].vertexType == ORIGINAL_VERTEX) //if source of this edge is from original graph
  393. {
  394. //search src of 'Added' in originalVerticesList
  395. bool bHasFound = false;
  396. QMapIterator<int, VertexIterator> itroriginalVertexForNewVertexMap(originalVertexForNewVertex);
  397. while (itroriginalVertexForNewVertexMap.hasNext())
  398. {
  399. itroriginalVertexForNewVertexMap.next();
  400. if(oEdgesToAdd[iRemovedEdgeIndex][0].vNode
  401. == *itroriginalVertexForNewVertexMap.value()) //if found in list
  402. {
  403. //get its corresponding new vertex
  404. vSourceOfNewEdge = vertex(itroriginalVertexForNewVertexMap.key(), gNewGraph);
  405. bHasFound = true;
  406. break;
  407. }
  408. }
  409. // LAYOUT_ASSERT(bHasFound,
  410. // LayoutException("addEdgesToNewGraph",
  411. // LayoutExceptionEnum::NOT_FOUND_IN_CONTAINER,
  412. // "originalVertexForNewVertex",
  413. // "source of edge to be replaced"));
  414. if(!bHasFound)
  415. {
  416. goto label_SkipTheEdge;
  417. }
  418. }
  419. else //if source of this edge is from new graph (NEW_VERTEX)
  420. {
  421. vSourceOfNewEdge = oEdgesToAdd[iRemovedEdgeIndex][0].vNode;
  422. }
  423. if(oEdgesToAdd[iRemovedEdgeIndex][1].vertexType == ORIGINAL_VERTEX) //if target of this edge is from original graph
  424. {
  425. //search src of 'Added' in originalVerticesList
  426. bool bHasFound = false;
  427. QMapIterator<int, VertexIterator> itroriginalVertexForNewVertexMap(originalVertexForNewVertex);
  428. while (itroriginalVertexForNewVertexMap.hasNext())
  429. {
  430. itroriginalVertexForNewVertexMap.next();
  431. if(oEdgesToAdd[iRemovedEdgeIndex][1].vNode
  432. == *itroriginalVertexForNewVertexMap.value())
  433. {
  434. //get its corresponding new vertex
  435. vTargetOfNewEdge = vertex(itroriginalVertexForNewVertexMap.key(), gNewGraph);
  436. bHasFound = true;
  437. break;
  438. }
  439. }
  440. // LAYOUT_ASSERT(bHasFound,
  441. // LayoutException("addEdgesToNewGraph",
  442. // LayoutExceptionEnum::NOT_FOUND_IN_CONTAINER,
  443. // "originalVertexForNewVertex",
  444. // "target of edge to be replaced"));
  445. if(!bHasFound)
  446. {
  447. goto label_SkipTheEdge;
  448. }
  449. }
  450. else //if target of this edge is from new graph (NEW_VERTEX)
  451. {
  452. vTargetOfNewEdge = oEdgesToAdd[iRemovedEdgeIndex][1].vNode;
  453. }
  454. //add edge to newG
  455. LAYOUT_ASSERT(add_edge(vSourceOfNewEdge, vTargetOfNewEdge, gNewGraph).second,
  456. LayoutException("addEdgesToNewGraph",
  457. LayoutExceptionEnum::INVALID_OPERATION,
  458. "add_edge(replace)",
  459. "addEdgesToNewGraph"));
  460. label_SkipTheEdge:
  461. continue;
  462. }
  463. else //if edge not in Removed[], it is to be added as it is
  464. {
  465. //search its src in originalVerticesList
  466. bool bHasFound = false;
  467. // XXX unused
  468. Q_UNUSED(bHasFound);
  469. QMapIterator<int, VertexIterator> itroriginalVertexForNewVertexMap1(originalVertexForNewVertex);
  470. while (itroriginalVertexForNewVertexMap1.hasNext())
  471. {
  472. itroriginalVertexForNewVertexMap1.next();
  473. if(vSourceOfCurrentEdge
  474. == *itroriginalVertexForNewVertexMap1.value())
  475. {
  476. //get its corresponding new vertex
  477. vSourceOfNewEdge = vertex(itroriginalVertexForNewVertexMap1.key(), gNewGraph);
  478. bHasFound = true;
  479. break;
  480. }
  481. }
  482. LAYOUT_ASSERT(bHasFound,
  483. LayoutException("addEdgesToNewGraph",
  484. LayoutExceptionEnum::NOT_FOUND_IN_CONTAINER,
  485. "originalVertexForNewVertex",
  486. "source of edge to be add"));
  487. //search its tgt in originalVerticesList
  488. bHasFound = false;
  489. QMapIterator<int, VertexIterator> itroriginalVertexForNewVertexMap2(originalVertexForNewVertex);
  490. while (itroriginalVertexForNewVertexMap2.hasNext())
  491. {
  492. itroriginalVertexForNewVertexMap2.next();
  493. if(vTargetOfCurrentEdge
  494. == *itroriginalVertexForNewVertexMap2.value())
  495. {
  496. //get its corresponding new vertex
  497. vTargetOfNewEdge = vertex(itroriginalVertexForNewVertexMap2.key(), gNewGraph);
  498. bHasFound = true;
  499. break;
  500. }
  501. }
  502. LAYOUT_ASSERT(bHasFound,
  503. LayoutException("addEdgesToNewGraph",
  504. LayoutExceptionEnum::NOT_FOUND_IN_CONTAINER,
  505. "originalVertexForNewVertex",
  506. "target of edge to be add"));
  507. //add edge to newG
  508. LAYOUT_ASSERT(add_edge(vSourceOfNewEdge, vTargetOfNewEdge, gNewGraph).second,
  509. LayoutException("addEdgesToNewGraph",
  510. LayoutExceptionEnum::INVALID_OPERATION,
  511. "add_edge(as it is)",
  512. "addEdgesToNewGraph"));
  513. }
  514. }
  515. //---------------------------------------------------------------------------------------------------
  516. }
  517. //-------------------------------------------------------------------------------------------------------
  518. }
  519. void GridLayouter::gridLayouterForNonClusteredGraph(SubGraph & gCurrentNonClusteredGraph)
  520. {
  521. LAYOUT_ASSERT(num_vertices(gCurrentNonClusteredGraph) > 0,
  522. LayoutException("gridLayouterForNonClusteredGraph",
  523. LayoutExceptionEnum::EMPTY_CONTAINER,
  524. "zero vertices",
  525. "NonClusteredGraph"));
  526. GraphPreProcessor graphPreProcessor;
  527. GridBasedLayout gridBasedLayout;
  528. BoostGraphWrapper boostGraphWrapper;
  529. GraphPreProcessor::VertexOrderType oDummyVertices;
  530. std::vector<GraphPreProcessor::EdgePairType> oCrossingEdges;
  531. GraphPreProcessor::EdgeOrderType oDummyEdges;
  532. std::vector<int> oCanonicalOrder;
  533. std::vector< GridBasedLayout::Position > oVertexPossition;
  534. if(boost::num_vertices(gCurrentNonClusteredGraph) > 2)
  535. {
  536. //CONVERT NON-PLANAR GRAPH TO PLANAR
  537. //In this process, some extra vertices (at edge crossings) and edges may be added to the graph
  538. //We also store the crossing edges, which a DummyVertex replaces, in m_oCrossingEdges
  539. graphPreProcessor.toPlanar(gCurrentNonClusteredGraph, oDummyVertices, oCrossingEdges);
  540. //CONVERT PLANAR GRAPH TO MAXIMAL PLANAR
  541. //In this process, some extra edges may be added to the graph
  542. graphPreProcessor.toMaximalPlanar(gCurrentNonClusteredGraph, oDummyEdges);
  543. //FIND CANONICAL ORDER OF VERTICES
  544. gridBasedLayout.findCanonicalOrder(gCurrentNonClusteredGraph, oCanonicalOrder);
  545. //APPLY GRID BASED LAYOUT
  546. //findGridBasedLayout() requires the graph to be MAXIMAL PLANAR ONLY
  547. gridBasedLayout.findGridBasedLayout(gCurrentNonClusteredGraph, oCanonicalOrder, oVertexPossition);
  548. //REMOVE DUMMY EDGES
  549. //This section removes the extra edges added during conversion from planar graph to maximal planar graph
  550. graphPreProcessor.removeDummyEdges(gCurrentNonClusteredGraph, oDummyEdges);
  551. //REMOVE DUMMY VERTICES
  552. //This section removes the extra vertices and edges added
  553. //during conversion from non-planar graph to planar graph
  554. graphPreProcessor.removeDummyVertices(gCurrentNonClusteredGraph, oDummyVertices, oCrossingEdges);
  555. }
  556. else //if(boost::num_vertices(gCurrentNonClusteredGraph) <= 2)
  557. {
  558. std::vector< GridBasedLayout::Position > PositionVector(boost::num_vertices(gCurrentNonClusteredGraph));
  559. int iXCoordInSmallGraph = 0;
  560. int iSeparation = 1;
  561. //if there are 2 vertices, find separation needed to avoid overlap
  562. if(boost::num_vertices(gCurrentNonClusteredGraph) == 2)
  563. {
  564. VertexDescriptor v0, v1;
  565. v0 = vertex(0, gCurrentNonClusteredGraph);
  566. v1 = vertex(1, gCurrentNonClusteredGraph);
  567. int iWidthOfV0 = boostGraphWrapper.getVertexWidth(v0, gCurrentNonClusteredGraph);
  568. int iWidthOfV1 = boostGraphWrapper.getVertexWidth(v1, gCurrentNonClusteredGraph);
  569. iSeparation = std::ceil((iWidthOfV0/2) + (iWidthOfV1/2)) + (2*SEPARATION);
  570. }
  571. //set positions of vertices
  572. VertexIterator itrVertex, itrVertexEnd;
  573. for(boost::tie(itrVertex, itrVertexEnd) = vertices(gCurrentNonClusteredGraph); itrVertex != itrVertexEnd; ++itrVertex)
  574. {
  575. int iVertexIndex = get(vertex_index, gCurrentNonClusteredGraph, *itrVertex);
  576. PositionVector[iVertexIndex].iCoordX = iXCoordInSmallGraph;
  577. PositionVector[iVertexIndex].iCoordY = 0;
  578. iXCoordInSmallGraph += iSeparation; //++iXCoordInSmallGraph;
  579. }
  580. oVertexPossition = PositionVector;
  581. }
  582. //set coordinates of vertices-------------------------------------------------------------------------------
  583. VertexIterator iterVertex, iterVertexEnd;
  584. VertexDescriptor descVertex;
  585. int iVertexIndex, iXCoordinate, iYCoordinate;
  586. LAYOUT_ASSERT(oVertexPossition.size() == boost::num_vertices(gCurrentNonClusteredGraph),
  587. LayoutException("gridLayouterForNonClusteredGraph",
  588. LayoutExceptionEnum::INCONSISTENT_DATASTRUCTURE,
  589. "oVertexPosition",
  590. ""));
  591. //for each vertex
  592. for(boost::tie(iterVertex, iterVertexEnd) = vertices(gCurrentNonClusteredGraph); iterVertex != iterVertexEnd; ++iterVertex)
  593. {
  594. descVertex = *iterVertex;
  595. iVertexIndex = get(vertex_index, gCurrentNonClusteredGraph, descVertex);
  596. iXCoordinate = oVertexPossition[iVertexIndex].iCoordX;
  597. iYCoordinate = oVertexPossition[iVertexIndex].iCoordY;
  598. //set coordinates
  599. boostGraphWrapper.setVertexCenterCoordX(descVertex, gCurrentNonClusteredGraph, iXCoordinate);
  600. boostGraphWrapper.setVertexCenterCoordY(descVertex, gCurrentNonClusteredGraph, iYCoordinate);
  601. }
  602. //----------------------------------------------------------------------------------------------------------
  603. }
  604. void GridLayouter::copyBackCoordinates(SubGraph & gCurrentClusteredGraph, SubGraph & gNewGraph,
  605. SubGraph & gRootClusteredGraph,
  606. QMap <int, bool> & isCluster,
  607. QMap <int, VertexIterator> & originalVertexForNewVertex,
  608. QMap <int, ChildrenIterator> & childrenList)
  609. {
  610. int nv = boost::num_vertices(gNewGraph);
  611. Q_UNUSED(nv);
  612. // XXX old LAYOUT_ASSERT(isCluster.count() <= (size_t)boost::num_vertices(gNewGraph),
  613. LAYOUT_ASSERT(isCluster.count() <= nv,
  614. LayoutException("copyBackCoordinates",
  615. LayoutExceptionEnum::INVALID_PARAMETER,
  616. "isCluster",
  617. " "));
  618. BoostGraphWrapper boostGraphWrapper;
  619. //for each vertex in newG
  620. VertexIterator itrNewVertex, itrEndNewVertex;
  621. for(boost::tie(itrNewVertex, itrEndNewVertex) = vertices(gNewGraph); itrNewVertex != itrEndNewVertex; ++itrNewVertex)
  622. {
  623. int iIndexOfNewVertex = get(vertex_index, gNewGraph, *itrNewVertex);
  624. VertexDescriptor vCurrentVertex = *itrNewVertex;
  625. bool bIsInvisible = boostGraphWrapper.getVertexIsInvisible(vCurrentVertex, gNewGraph);
  626. if(!bIsInvisible)
  627. {
  628. //get cooridinates of current NewVertex
  629. int iXCoordOfNewVertex = boostGraphWrapper.getVertexCenterCoordX(vCurrentVertex, gNewGraph);
  630. int iYCoordOfNewVertex = boostGraphWrapper.getVertexCenterCoordY(vCurrentVertex, gNewGraph);
  631. LAYOUT_ASSERT(isCluster.contains(iIndexOfNewVertex),
  632. LayoutException("copyBackCoordinates",
  633. LayoutExceptionEnum::NOT_FOUND_IN_CONTAINER,
  634. "isCluster",
  635. "NewVertex"));
  636. if(isCluster.value(iIndexOfNewVertex)) //if current NewVertex is a cluster
  637. {
  638. //calculate offset coordinates
  639. int iHeightOfNewVertex = boostGraphWrapper.getVertexHeight(vCurrentVertex, gNewGraph);
  640. int iWidthOfNewVertex = boostGraphWrapper.getVertexWidth(vCurrentVertex, gNewGraph);
  641. int iOffsetXCoord = iXCoordOfNewVertex - (iWidthOfNewVertex / 2) + 35;
  642. int iOffsetYCoord = iYCoordOfNewVertex - (iHeightOfNewVertex / 2) + 35;
  643. //get corres child
  644. LAYOUT_ASSERT(childrenList.contains(iIndexOfNewVertex),
  645. LayoutException("copyBackCoordinates",
  646. LayoutExceptionEnum::NOT_FOUND_IN_CONTAINER,
  647. "childrenList",
  648. "NewVertex"));
  649. ChildrenIterator itrCurrentChild = childrenList.value(iIndexOfNewVertex);
  650. //for each vertex in child
  651. VertexIterator itrVertexInChild, itrEndVertexInChild;
  652. for(boost::tie(itrVertexInChild, itrEndVertexInChild) = vertices(*itrCurrentChild); itrVertexInChild != itrEndVertexInChild; ++itrVertexInChild)
  653. {
  654. //get its global vertex
  655. VertexDescriptor vGlobalOfVertexInChild = (*itrCurrentChild).local_to_global(*itrVertexInChild);
  656. //update X coord of global vertex
  657. int iXCoordOfGlobalVertex = boostGraphWrapper.getVertexCenterCoordX(vGlobalOfVertexInChild, gRootClusteredGraph);
  658. boostGraphWrapper.setVertexCenterCoordX(vGlobalOfVertexInChild, gRootClusteredGraph, (iOffsetXCoord + iXCoordOfGlobalVertex));
  659. //update Y coord of global vertex
  660. int iYCoordOfGlobalVertex = boostGraphWrapper.getVertexCenterCoordY(vGlobalOfVertexInChild, gRootClusteredGraph);
  661. boostGraphWrapper.setVertexCenterCoordY(vGlobalOfVertexInChild, gRootClusteredGraph, (iOffsetYCoord + iYCoordOfGlobalVertex));
  662. }
  663. }
  664. else //if current NewVertex is a simple node
  665. {
  666. //get corres original vertex, get its global vertex
  667. LAYOUT_ASSERT(originalVertexForNewVertex.contains(iIndexOfNewVertex),
  668. LayoutException("copyBackCoordinates",
  669. LayoutExceptionEnum::NOT_FOUND_IN_CONTAINER,
  670. "originalVertexForNewVertex",
  671. "NewVertex"));
  672. VertexDescriptor vOriginalVertex = *originalVertexForNewVertex.value(iIndexOfNewVertex);
  673. VertexDescriptor vGlobalOfCurrentVertex = gCurrentClusteredGraph.local_to_global(vOriginalVertex);
  674. //update X coord of global vertex
  675. boostGraphWrapper.setVertexCenterCoordX(vGlobalOfCurrentVertex, gRootClusteredGraph, iXCoordOfNewVertex);
  676. //update Y coord of global vertex
  677. boostGraphWrapper.setVertexCenterCoordY(vGlobalOfCurrentVertex, gRootClusteredGraph, iYCoordOfNewVertex);
  678. }
  679. }
  680. }
  681. }