CircularLayoutGenerator.cpp 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323
  1. #include "CircularLayoutGenerator.h"
  2. #include "Common/LayoutEnum.h"
  3. CircularLayoutGenerator::CircularLayoutGenerator()
  4. {
  5. m_iCenterX = 0;
  6. m_iCenterY = 0;
  7. }
  8. void CircularLayoutGenerator::applyCircularLayout(SubGraph& gInputGraph, LayoutEnum::VertexOrderCriteria enVertexOrder)
  9. {
  10. // enVertexOrder = LayoutEnum::VertexOrderCriteria::DefaultOrder;
  11. // qDebug("Circular layout applied");
  12. bool isSubgraph = true; // root will always be a subgraph
  13. // XXX seems to be obselete
  14. // LAYOUT_ASSERT(&gInputGraph != NULL, LayoutMemoryException(__FUNCTION__, LayoutExceptionEnum::NULL_POINTER_EXCEPTION, NULL_GRAPH_FOUND));
  15. // XXX seems obselete
  16. // LAYOUT_ASSERT((LayoutEnum::isValidVertexOrderingCriteria(enVertexOrder)) == true,
  17. // LayoutException(__FUNCTION__, LayoutExceptionEnum::INVALID_TYPE, TYPE_ENUM_VERTEXORDER_TYPE, ORDERING_CRITERIA));
  18. // construct container of subgraph lists in the vector
  19. m_vecSubgraphContainer.push_back(&gInputGraph);
  20. try
  21. {
  22. // iterate the subgraph hierarchy and get the list of subgraphs in the container
  23. m_vecBFSOrderedSubgraphs.push_back(&gInputGraph);
  24. iterateChildrenGraphs(m_vecBFSOrderedSubgraphs);
  25. }
  26. catch(LayoutException& eException)
  27. {
  28. LayoutException(__FUNCTION__, LayoutExceptionEnum::EMPTY_CONTAINER, eException.getEntityValue());
  29. }
  30. catch(boost::exception& eBoostException)
  31. {
  32. throw *boost::get_error_info<errmsg_info>(eBoostException);
  33. }
  34. // There should be atleast one subgraph, if there is none, throw an exception so that caller functions can take appropriate decision.
  35. // XXX seems obselete
  36. // LAYOUT_ASSERT(!(m_vecSubgraphContainer.empty()),
  37. // LayoutMemoryException(__FUNCTION__,
  38. // LayoutExceptionEnum::NULL_POINTER_EXCEPTION,
  39. // NULL_SUBGRAPH_CONTAINER_FOUND));
  40. // preprocessing for the circular layout
  41. for(vector<SubGraph*>::iterator itrSubgraph = m_vecSubgraphContainer.begin();
  42. itrSubgraph != m_vecSubgraphContainer.end();
  43. ++itrSubgraph)
  44. {
  45. // for empty graph add dummy node to that graph
  46. int iNumVertices = num_vertices(**itrSubgraph);
  47. if(iNumVertices == 0)
  48. {
  49. VertexDescriptor vVertex = m_boostGraphWrapper.addVertex(**itrSubgraph, LayoutEnum::InvisibleNode);
  50. // This dummy node will set the size of cluster
  51. // set height = 80 nd width = 80;
  52. int iDummyNodeHeight = 80;
  53. int iDummyNodeWidth = 80;
  54. m_boostGraphWrapper.setVertexHeight(vVertex,**itrSubgraph, iDummyNodeHeight);
  55. m_boostGraphWrapper.setVertexWidth(vVertex, **itrSubgraph, iDummyNodeWidth);
  56. }
  57. }
  58. // iterate the list of subgraphs from the container and apply circle layout
  59. for(vector<SubGraph*>::iterator itrSubgraph = m_vecSubgraphContainer.begin();
  60. itrSubgraph != m_vecSubgraphContainer.end();
  61. ++itrSubgraph)
  62. {
  63. // find center
  64. VertexIterPair vIterVerticesPair = vertices(**itrSubgraph);
  65. if(!isSubgraph)
  66. {
  67. // calculating middle vertex index for subgraph
  68. VertexDescriptor vMidVertexIndex;
  69. if((vIterVerticesPair.second - vIterVerticesPair.first) == 1)
  70. {
  71. // if single vertex is present in the subgraph then median should be that vertex only.
  72. vMidVertexIndex = vIterVerticesPair.first[0];
  73. }
  74. else
  75. {
  76. // for more than 1 vertex in the subgraph then median should be (diff + 1)/2.
  77. vMidVertexIndex = (vIterVerticesPair.second - vIterVerticesPair.first +1)/2;
  78. }
  79. // get the middle vertex's global index
  80. VertexDescriptor vGlobalMidVertex = (**itrSubgraph).local_to_global(vMidVertexIndex);
  81. // get the x and y coordinates of middle vertex as the center cooordinates of the graph
  82. m_iCenterX = m_boostGraphWrapper.getVertexCenterCoordX(vGlobalMidVertex ,gInputGraph);
  83. m_iCenterY = m_boostGraphWrapper.getVertexCenterCoordY(vGlobalMidVertex, gInputGraph);
  84. }
  85. else
  86. {
  87. isSubgraph = false;
  88. }
  89. // calculating radius for cluster using radius share factor
  90. // get total vertex present in the graph
  91. int iTotalVertex = num_vertices(**itrSubgraph);
  92. // get number of dummy vertices present in the graph
  93. int iDummyVertices = (**itrSubgraph).num_children();
  94. // calculate real vertices present in the graph
  95. int iVertexCount = iTotalVertex - iDummyVertices;
  96. // calculate the radius for real vertices considering the radius share factor
  97. double dRadiusUsingShare = ((iVertexCount) * RADIUS_SHARE);
  98. // calculate size considered radius from diagonal
  99. double dRadiusFromNodeDetails;
  100. dRadiusFromNodeDetails = calculateRadius(**itrSubgraph);
  101. // add size considered radius and radius with radius share
  102. m_dRadius = dRadiusUsingShare + dRadiusFromNodeDetails;
  103. // Check the order specified by caller function
  104. MapOrderVertex mapOrderVertex;
  105. bool bIsValidVertexOrder = LayoutEnum::isValidVertexOrderingCriteria(enVertexOrder);
  106. if(bIsValidVertexOrder == true)
  107. {
  108. if(enVertexOrder == LayoutEnum::TopologicalOrder)
  109. {
  110. // topological Ordering Criteria
  111. VectorEdgeDescriptor vectBackEdges;
  112. GraphCycleHandler graphCycleHandler;
  113. graphCycleHandler.detectBackEdges(**itrSubgraph,vectBackEdges);
  114. graphCycleHandler.reverseEdges(**itrSubgraph,vectBackEdges);
  115. // Apply vertex ordering methods and get ordered map
  116. m_boostGraphWrapper.applyTopologicalVertexOrdering(**itrSubgraph,mapOrderVertex);
  117. }
  118. else if(enVertexOrder == LayoutEnum::ConnectedComponentOrder)
  119. {
  120. // connected Component ordering criteria
  121. m_boostGraphWrapper.applyConnectedComponent(**itrSubgraph,mapOrderVertex);
  122. }
  123. else
  124. {
  125. // default Ordering
  126. PGL_MAP_VERTEX_ORDER(mapVertexOrder,**itrSubgraph);
  127. mapOrderVertex = m_boostGraphWrapper.getMapOrderedVertices(**itrSubgraph
  128. ,mapVertexOrder);
  129. }
  130. }
  131. else
  132. {
  133. // if order is not valid then we are keeping it as the default vertex ordering
  134. PGL_MAP_VERTEX_ORDER(mapVertexOrder,**itrSubgraph);
  135. mapOrderVertex = m_boostGraphWrapper.getMapOrderedVertices(**itrSubgraph
  136. , mapVertexOrder);
  137. }
  138. // apply circle layout to this graph
  139. CircleLayouter circleLayouter;
  140. try
  141. {
  142. circleLayouter.applyCircleGraphLayout(**itrSubgraph, get(vertex_position,**itrSubgraph),
  143. m_dRadius, m_iCenterX, m_iCenterY, mapOrderVertex);
  144. }
  145. catch(boost::exception& eBoostException)
  146. {
  147. throw *boost::get_error_info<errmsg_info>(eBoostException);
  148. }
  149. // set the radius for this graph in its GraphProperty
  150. m_boostGraphWrapper.setGraphRadius(m_dRadius, (**itrSubgraph));
  151. // set center coordinates in the GraphProperty of this graph
  152. m_boostGraphWrapper.setGraphCenterCoordX(m_iCenterX, (**itrSubgraph));
  153. m_boostGraphWrapper.setGraphCenterCoordY(m_iCenterY, (**itrSubgraph));
  154. }
  155. // size Manager Functionality
  156. // calculate the subgraph size and set respective parameters in its properties
  157. m_sizeManager.processSizeManager(gInputGraph);
  158. // space utilizer functionality
  159. m_spaceUtilizer.addSubgraphDummyVerticesAndMap(gInputGraph, VERTEX_START_INDEX);
  160. // apply second pass of circle layout on the graph which will provide uniform space on the circumference of circle
  161. m_spaceUtilizer.processSecondPassCircularLayout(gInputGraph, CENTERCOORDINATEX_START, CENTERCOORDINATEY_START);
  162. // apply size manager functinality to update propertis with respect to second pass circle layout
  163. m_sizeManager.processSizeManager(gInputGraph);
  164. }
  165. void CircularLayoutGenerator::iterateChildrenGraphs(vector<SubGraph *> &subgraphQueue)
  166. {
  167. /*
  168. we have used queue because it will contain reference of subgraphs.
  169. Adding all the subgraphs in queue to iterate one by one in circular way.
  170. */
  171. // XXX seems obselete
  172. // LAYOUT_ASSERT(!subgraphQueue.empty(),
  173. // LayoutException(__FUNCTION__,LayoutExceptionEnum::EMPTY_CONTAINER,VECTOR_CONTENTS));
  174. // define local queue which will contain the childrens of main graph
  175. vector<SubGraph*> subgraphSequence;
  176. try
  177. {
  178. // To iterate input queue which will contain graph reference
  179. for( vector<SubGraph*>::iterator itrSubgraphQueue = subgraphQueue.begin();
  180. itrSubgraphQueue != subgraphQueue.end();
  181. itrSubgraphQueue++)
  182. {
  183. // Finding the children upto deep level
  184. SubGraph::children_iterator itrSubgraph, itrSubgraphEnd;
  185. for (boost::tie(itrSubgraph, itrSubgraphEnd) = (**itrSubgraphQueue).children();
  186. itrSubgraph != itrSubgraphEnd;
  187. ++itrSubgraph)
  188. {
  189. // Add children in the global queue container
  190. m_vecSubgraphContainer.push_back(&(*itrSubgraph));
  191. // Add children in the local queue conatainer
  192. subgraphSequence.push_back(&(*itrSubgraph));
  193. }
  194. }
  195. }
  196. catch(boost::exception& eBoostException)
  197. {
  198. throw *boost::get_error_info<errmsg_info>(eBoostException);
  199. }
  200. catch(...)
  201. {
  202. throw;
  203. }
  204. // To iterarte the local queue again if ant children is present
  205. if(!subgraphSequence.empty())
  206. {
  207. // Recursive call to iterate children
  208. iterateChildrenGraphs(subgraphSequence);
  209. }
  210. }
  211. double CircularLayoutGenerator::calculateRadius(SubGraph &gSubgraph)
  212. {
  213. // XXX seems to be obselete
  214. // LAYOUT_ASSERT(&gSubgraph != NULL,
  215. // LayoutMemoryException(__FUNCTION__,
  216. // LayoutExceptionEnum::NULL_POINTER_EXCEPTION,
  217. // GRAPH));
  218. CircleLayouter circleLayouter;
  219. double dCircumference;
  220. try
  221. {
  222. dCircumference = circleLayouter.calculateCircumference(gSubgraph);
  223. }
  224. catch(LayoutMemoryException& eException)
  225. {
  226. throw LayoutMemoryException(__FUNCTION__,
  227. LayoutExceptionEnum::NULL_POINTER_EXCEPTION,
  228. eException.getObjectName());
  229. }
  230. catch(LayoutException& eException)
  231. {
  232. throw LayoutException(__FUNCTION__,
  233. LayoutExceptionEnum::INVALID_PARAMETER,
  234. eException.getEntityValue(),eException.getEntityType());
  235. }
  236. catch(boost::exception& eBoostException)
  237. {
  238. throw *boost::get_error_info<errmsg_info>(eBoostException);
  239. }
  240. // XXX seems obselet
  241. // LAYOUT_ASSERT(dCircumference > 0,
  242. // LayoutException(__FUNCTION__,
  243. // LayoutExceptionEnum::INVALID_PARAMETER,
  244. // INVALID_CIRCUMFERENCE_VALUE));
  245. double dRadius = (dCircumference / (2 * PI));
  246. m_boostGraphWrapper.setGraphRadius(dRadius, gSubgraph);
  247. return dRadius;
  248. }
  249. void CircularLayoutGenerator::addDummyEdgesForTopologicalOrder(SubGraph &gSubgraph)
  250. {
  251. /*
  252. This fumction adds the edges which will be treated as a dummy edges in the graph for getting
  253. the nodes for topological ordering in the consecutive mannar. Hence we will add edges between
  254. dummy subgraph nodes and nodes of that subgraph.
  255. */
  256. // XXX seems to be obselete
  257. // LAYOUT_ASSERT(&gSubgraph != NULL,
  258. // LayoutMemoryException(__FUNCTION__,
  259. // LayoutExceptionEnum::NULL_POINTER_EXCEPTION,
  260. // GRAPH));
  261. ChildrenIterator itrSubgraph, itrSubgraphEnd;
  262. for(boost::tie(itrSubgraph, itrSubgraphEnd) = gSubgraph.children();
  263. itrSubgraph != itrSubgraphEnd;
  264. itrSubgraph++)
  265. {
  266. size_t iDummyNodeIndex;
  267. iDummyNodeIndex = m_boostGraphWrapper.getGraphDummyNodeIndex(*itrSubgraph);
  268. m_boostGraphWrapper.printGraph(*itrSubgraph);
  269. BGL_FORALL_VERTICES(vVertex, gSubgraph, SubGraph)
  270. {
  271. size_t iVertexIndex = m_boostGraphWrapper.getVertexIndex(vVertex);
  272. if((iVertexIndex == iDummyNodeIndex))
  273. {
  274. VertexDescriptor vGlobalDummyVertex = (*itrSubgraph).local_to_global(vVertex);
  275. BGL_FORALL_VERTICES(vSubVertex, *itrSubgraph, SubGraph)
  276. {
  277. VertexDescriptor vGlobalSubVertex = (*itrSubgraph).local_to_global(vSubVertex);
  278. if(vGlobalDummyVertex != vGlobalSubVertex)
  279. {
  280. m_boostGraphWrapper.addEdge(vGlobalDummyVertex, vGlobalSubVertex,gSubgraph);
  281. }
  282. }
  283. }
  284. }
  285. }
  286. }