GridLayouter.cpp 37 KB

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