GridBasedLayout.cpp 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520
  1. #include "GridBasedLayout.h"
  2. GridBasedLayout::GridBasedLayout()
  3. {
  4. }
  5. void GridBasedLayout::findCanonicalOrder(SubGraph & gInputGraph, std::vector<int> & oVertexIndexCanonicalOrder)
  6. {
  7. // change graph format:
  8. // gInputGraph is a bidirectedS graph, whereas the Canonical Ordering algorithm accepts undirectedS graphs.
  9. // To map our graph to undirected one, we create a local undirected graph and copy the edges and vertices
  10. // in our graph to this local graph; and pass this to the algorithm.
  11. VertexDescriptor descVertexSource, descVertexTarget;
  12. EdgeIterator itrEdge, itrEdgeEnd;
  13. EdgeDescriptor descEdge;
  14. int iVertexSource, iVertexTarget, iNumVertices;
  15. BoostGraphWrapper graphWrapper;
  16. iNumVertices = boost::num_vertices(gInputGraph);
  17. GridBasedLayout::graph g(iNumVertices); //create a local undirected graph with same no. of vertices
  18. VertexOrderType oCanonicalOrder;
  19. LayoutUtility layoutUtility;
  20. // copy each edge one by one
  21. for(boost::tie(itrEdge, itrEdgeEnd) = edges(gInputGraph); itrEdge != itrEdgeEnd; itrEdge++)
  22. {
  23. //get its src and tgt
  24. descEdge = *itrEdge;
  25. descVertexSource = graphWrapper.getEdgeSource(descEdge, gInputGraph);
  26. descVertexTarget = graphWrapper.getEdgeTarget(descEdge, gInputGraph);
  27. //get indices of src and tgt
  28. iVertexSource = graphWrapper.getVertexIndex(descVertexSource);
  29. iVertexTarget = graphWrapper.getVertexIndex(descVertexTarget);
  30. //add edge between corresponding vertices in local graph
  31. add_edge(iVertexSource, iVertexTarget, g);
  32. }
  33. // Initialize the interior edge index
  34. layoutUtility.reinitializeEdgeIndices(g);
  35. // Test for planarity - we know it is planar, we just want to
  36. // compute the planar embedding as a side-effect
  37. typedef std::vector< graph_traits< graph >::edge_descriptor > vec_t;
  38. std::vector<vec_t> embedding(num_vertices(g));
  39. if (boyer_myrvold_planarity_test(boyer_myrvold_params::graph = g,
  40. boyer_myrvold_params::embedding = make_iterator_property_map(embedding.begin(),
  41. get(vertex_index,
  42. g))))
  43. {
  44. //std::cout << "Input graph is planar2" << std::endl;
  45. }
  46. else
  47. {
  48. throw LayoutException("findCanonicalOrder",
  49. LayoutExceptionEnum::INVALID_GRAPH_TYPE,
  50. "inputGraph",
  51. "non-planar");
  52. //std::cout << "Input graph is not planar2" << std::endl;
  53. }
  54. //find the Canonical Order
  55. planar_canonical_ordering(g, make_iterator_property_map(embedding.begin(), get(vertex_index, g)),
  56. std::back_inserter(oCanonicalOrder));
  57. //copy the canonical order of indices to the supplied parameter
  58. for(int i = 0; i < oCanonicalOrder.size(); ++i)
  59. oVertexIndexCanonicalOrder.push_back(get(vertex_index, g, oCanonicalOrder[i]));
  60. }
  61. void GridBasedLayout::findGridBasedLayout(SubGraph & gInputGraph, std::vector<int> & oCanonicalOrder, std::vector< GridBasedLayout::Position > & oVertexPosition)
  62. {
  63. int iNumVertices = boost::num_vertices( gInputGraph );
  64. LAYOUT_ASSERT(oCanonicalOrder.size() == iNumVertices,
  65. LayoutException("findGridBasedLayout",
  66. LayoutExceptionEnum::INVALID_PARAMETER,
  67. "canonicalOrder",
  68. "size of")); //size_of(canonical_order) = #nodes
  69. //initialize set of associated vertices such that: Associated Vertices of V = {V}
  70. std::vector< std::vector<VertexDescriptor> > AssociatedVertices(iNumVertices);
  71. for(int iCount=0; iCount < iNumVertices ; iCount++)
  72. {
  73. AssociatedVertices[iCount].push_back(vertex(iCount, gInputGraph));
  74. }
  75. //INITIALIZE for first 2 vertices-------------------------------------------------------------------------
  76. BoostGraphWrapper graphWrapper;
  77. int iTempararyIndex;
  78. std::vector<VertexDescriptor> oContour;
  79. std::vector< Position > PositionVector( iNumVertices );
  80. //set positions of first 2 vertices as (0,0)
  81. iTempararyIndex = oCanonicalOrder[0];
  82. PositionVector[iTempararyIndex].iCoordX = 0;
  83. PositionVector[iTempararyIndex].iCoordY = 0;
  84. iTempararyIndex = oCanonicalOrder[1];
  85. PositionVector[iTempararyIndex].iCoordX = 0;
  86. PositionVector[iTempararyIndex].iCoordY = 0;
  87. //initial contour contains vertices 0-1
  88. oContour.push_back(vertex(oCanonicalOrder[0], gInputGraph));
  89. oContour.push_back(vertex(oCanonicalOrder[1], gInputGraph));
  90. //Find the initial overlap and shift the node horizontally
  91. VertexDescriptor v0, v1;
  92. v0 = vertex(oCanonicalOrder[0], gInputGraph);
  93. v1 = vertex(oCanonicalOrder[1], gInputGraph);
  94. int iWidthOfV0 = graphWrapper.getVertexWidth(v0, gInputGraph);
  95. int iWidthOfV1 = graphWrapper.getVertexWidth(v1, gInputGraph);
  96. int iInitialOverlapLeft = std::ceil((iWidthOfV0/2) + (iWidthOfV1/2)) + SEPARATION;
  97. int iInitialOverlapRight = 0;
  98. int iInitialP = 0; //index of left neighbour of the node to be shifted (in current contour)
  99. this->secondShiftRight(iInitialOverlapLeft, iInitialOverlapRight, gInputGraph,
  100. PositionVector, AssociatedVertices,
  101. oContour, iInitialP);
  102. //--------------------------------------------------------------------------------------------------------
  103. //REPEATE for 3rd vertex in canonical vertex onward-------------------------------------------------------
  104. for(int k = 2; k < oCanonicalOrder.size(); ++k)
  105. {
  106. int iP, iQ, iOverlapLeft, iOverlapRight;
  107. iP = 0;
  108. iQ = 0;
  109. //FIND EXTREME NEIGHBOURS of kth vertex in contour
  110. this->findNeighbours(gInputGraph, oContour, oCanonicalOrder[k], iP, iQ);
  111. LAYOUT_ASSERT((0<=iP) & (iP<=iQ) & (iQ<=oContour.size()),
  112. LayoutException("findGridBasedLayout",
  113. LayoutExceptionEnum::INCONSISTENT_DATASTRUCTURE,
  114. "contour",
  115. "P-Q"));
  116. //REARRANGE GRAPH by shifting some vertices right by 1 or 2 places
  117. this->shiftRight(TWO, gInputGraph, PositionVector, AssociatedVertices, oContour, iP, iQ);
  118. this->shiftRight(ONE, gInputGraph, PositionVector, AssociatedVertices, oContour, iP, iQ);
  119. //FIND POSITION of kth vertex
  120. this->findNewPosition(oCanonicalOrder[k], iP, iQ, gInputGraph, PositionVector, oContour);
  121. //FIND TOPMOST POINT under this new vertex
  122. int iIndexOfTopmostVertex;
  123. this->findTopmostVertex(iP, iQ, oContour, gInputGraph, PositionVector, iIndexOfTopmostVertex);
  124. //UPDATE ASSOCIATED VERTICES for kth vertex
  125. this->updateAssociaedVertices(AssociatedVertices, gInputGraph, oContour, oCanonicalOrder[k], iP, iQ);
  126. //UPDATE CONTOUR to reflect change after adding new vertex
  127. this->updateContour(oContour, gInputGraph, oCanonicalOrder[k], iP, iQ);
  128. //FIND OVERLAPS for newly added vertex
  129. this->findOverlaps(iP, oContour, gInputGraph, PositionVector, iOverlapLeft, iOverlapRight);
  130. //REARRANGE GRAPH by shifting some vertices right if overlapping
  131. this->secondShiftRight(iOverlapLeft, iOverlapRight, gInputGraph, PositionVector, AssociatedVertices,
  132. oContour, iP);
  133. //Find NEW POSITION
  134. int iR = iP+2;
  135. this->findNewPosition(oCanonicalOrder[k], iP, iR, gInputGraph, PositionVector, oContour);
  136. //SHIFT VERTICALLY if needed
  137. this->shiftVertically(iIndexOfTopmostVertex, oCanonicalOrder[k], gInputGraph, PositionVector);
  138. }
  139. //---------------------------------------------------------------------------------------------------------
  140. oVertexPosition = PositionVector;
  141. }
  142. void GridBasedLayout::findNeighbours(SubGraph &gInputGraph, std::vector<VertexDescriptor> & oContour,
  143. int & iNewVertexIndex, int& p, int& q)
  144. {
  145. //This method goes through the contour and checks whether the current vertex in the contour
  146. //is adjecent to vNewVertex in gInputGraph
  147. bool bHasFoundNeighbour = false; //reflects whether vNewVertex has started encountering neighbours in contour
  148. EdgeBoolPair pairEdgeBoolVtoC, pairEdgeBoolCtoV, pairEdgeBoolUndirected;
  149. VertexDescriptor vNewVertex = vertex(iNewVertexIndex, gInputGraph);
  150. //traverse contour sequentially
  151. for(int iContourIndex = 0; iContourIndex < oContour.size(); ++iContourIndex)
  152. {
  153. //check whether edge exists between vNewVertex and current vertex in contour
  154. pairEdgeBoolVtoC = lookup_edge(vNewVertex, oContour[iContourIndex], gInputGraph);
  155. pairEdgeBoolCtoV = lookup_edge(oContour[iContourIndex], vNewVertex, gInputGraph);
  156. pairEdgeBoolUndirected = edge(vNewVertex, oContour[iContourIndex], gInputGraph);
  157. bool bIsEdge = false;
  158. bIsEdge = pairEdgeBoolVtoC.second || pairEdgeBoolCtoV.second || pairEdgeBoolUndirected.second;
  159. //find first and last neighbour in contour
  160. if( bIsEdge && !bHasFoundNeighbour) //if found first neighbour
  161. {
  162. p = iContourIndex;
  163. bHasFoundNeighbour = true;
  164. if(iContourIndex == (oContour.size() - 1)) //if end of contour, it is also the last neighbour
  165. {
  166. q = iContourIndex;
  167. break;
  168. }
  169. //else continue;
  170. }
  171. else if( bIsEdge && bHasFoundNeighbour) //if found another neighbour
  172. {
  173. if(iContourIndex == (oContour.size() - 1)) //if end of contour, it is the last neighbour
  174. {
  175. q = iContourIndex;
  176. break;
  177. }
  178. //else continue;
  179. }
  180. else if( !bIsEdge && !bHasFoundNeighbour) //if not found a neighbour yet
  181. continue;
  182. else if( !bIsEdge && bHasFoundNeighbour) //if found last neighbour
  183. {
  184. q = iContourIndex - 1;
  185. break;
  186. }
  187. else //invalid condition
  188. {
  189. throw LayoutException("findNeighbours",
  190. LayoutExceptionEnum::UNKNOWNLAYOUTEXCEPTION,
  191. " ",
  192. " ");
  193. //break;
  194. }
  195. }
  196. }
  197. void GridBasedLayout::shiftRight(int iShiftBy, SubGraph & gInputGraph,
  198. std::vector< Position > & vecPositon,
  199. std::vector< std::vector<VertexDescriptor> > & vecAssociated,
  200. std::vector<VertexDescriptor> & oContour,
  201. int& p, int& q)
  202. {
  203. //This method rearranges current layout to accomodate new vertex
  204. //It is called twice; first with iShiftBy = 2 and then with iShiftBy = 1
  205. //shifts all vertices associated to (Wq.....Wm) by 2 to their right
  206. //shifts all vertices associated to (Wp+1.....Wq-1) by 1 to their right
  207. //LAYOUT_ASSERT
  208. VertexDescriptor vWi;
  209. int iIndexOfWi, iIndexOfAssociatedVertex;
  210. switch (iShiftBy)
  211. {
  212. case 2:
  213. //for vertices (Wq.....Wm) in contour
  214. for(int i = q; i < oContour.size(); i++)
  215. {
  216. vWi = oContour[i];
  217. iIndexOfWi = get(vertex_index, gInputGraph, vWi);
  218. //for all of its associated vertices
  219. for(int j = 0; j < vecAssociated[iIndexOfWi].size(); j++)
  220. {
  221. iIndexOfAssociatedVertex = get(vertex_index, gInputGraph, vecAssociated[iIndexOfWi][j]);
  222. //shift by 2
  223. vecPositon[iIndexOfAssociatedVertex].iCoordX = vecPositon[iIndexOfAssociatedVertex].iCoordX + 2;
  224. }
  225. }
  226. break;
  227. case 1:
  228. //for vertices (Wp+1.....Wq-1) in contour
  229. for(int i = p+1; i < q; i++)
  230. {
  231. vWi = oContour[i];
  232. iIndexOfWi = get(vertex_index, gInputGraph, vWi);
  233. //for all of its associated vertices
  234. for(int j = 0; j < vecAssociated[iIndexOfWi].size(); j++)
  235. {
  236. iIndexOfAssociatedVertex = get(vertex_index, gInputGraph, vecAssociated[iIndexOfWi][j]);
  237. //shift by 1
  238. vecPositon[iIndexOfAssociatedVertex].iCoordX = vecPositon[iIndexOfAssociatedVertex].iCoordX + 1;
  239. }
  240. }
  241. break;
  242. default:
  243. //THROW
  244. std::cout << "Invalid value of shiftBy:" << iShiftBy << std::endl;
  245. break;
  246. }
  247. }
  248. void GridBasedLayout::findNewPosition(int & vNewVertexIntex, int& p, int& q, SubGraph & gInputGraph,
  249. std::vector< Position > & vecPositon,
  250. std::vector<VertexDescriptor> & oContour)
  251. {
  252. //This method calculates coordinates of vNewVertex on the grid layout
  253. //new vertex is plotted at intersection of lines with slopes +1 and -1,
  254. //passing through first and last neighbours (Wp,Wq), respectively
  255. //new position given by formula P(Wp,Wq) = (x1-y1+x2+y2, -x1+y1+x2+y2) / 2
  256. //read Wp and Wq
  257. VertexDescriptor vWp, vWq;
  258. vWp = oContour[p];
  259. vWq = oContour[q];
  260. //get their indices
  261. int iIndexP, iIndexQ;
  262. iIndexP = get(vertex_index, gInputGraph, vWp);
  263. iIndexQ = get(vertex_index, gInputGraph, vWq);
  264. //read coordinates of Wp and Wq
  265. int iX1, iY1, iX2, iY2;
  266. iX1 = vecPositon[iIndexP].iCoordX;
  267. iY1 = vecPositon[iIndexP].iCoordY;
  268. iX2 = vecPositon[iIndexQ].iCoordX;
  269. iY2 = vecPositon[iIndexQ].iCoordY;
  270. //calculate coordinates of vNewVertex and update them
  271. vecPositon[vNewVertexIntex].iCoordX = (int)((iX1 - iY1 + iX2 + iY2) / 2);
  272. vecPositon[vNewVertexIntex].iCoordY = (int)((iY1 - iX1 + iX2 + iY2) / 2);
  273. }
  274. void GridBasedLayout::updateAssociaedVertices(std::vector< std::vector<VertexDescriptor> > & vecAssociated,
  275. SubGraph & gInputGraph,
  276. std::vector<VertexDescriptor> & oContour,
  277. int & iNewVertexIndex,
  278. int& p, int& q)
  279. {
  280. //This method updates Associated Vertices' List for the new vertex
  281. //This is done as: Associated Vertices's List of Vk = Union of Associated Vertices' Lists of (Wp+1....Wq-1)
  282. //for each vertex between (Wp+1....Wq-1) in contour
  283. for(int iIndexInContour = p + 1; iIndexInContour < q; iIndexInContour++)
  284. {
  285. VertexDescriptor vWi = oContour[iIndexInContour];
  286. //get its index
  287. int iIndexW = get(vertex_index, gInputGraph, vWi);
  288. //for each vertex in Associated Vertices' List of Wi
  289. for(int iIndexInAssociatedList = 0; iIndexInAssociatedList < vecAssociated[iIndexW].size(); iIndexInAssociatedList++)
  290. {
  291. //copy it to Associated Vertices' List of NewVertex
  292. vecAssociated[iNewVertexIndex].push_back(vecAssociated[iIndexW][iIndexInAssociatedList]);
  293. }
  294. }
  295. }
  296. void GridBasedLayout::updateContour(std::vector<VertexDescriptor> & oContour, SubGraph & gInputGraph,
  297. int & iNewVertexIndex,
  298. int& p, int& q)
  299. {
  300. //This method updates contour after adding new vertex
  301. //It removes all the vertices in contour inbetween Wp and Wq
  302. //and replaces them with vNewVertex; say Vk
  303. //thus contour (W1-...-Wp-...-Wq-...-Wm) becomes (W1-...-Wp-Vk-Wq-...-Wm)
  304. //declare temporary contour
  305. std::vector<VertexDescriptor> oTempararyContour;
  306. //push (W1-...-Wp) to temporary contour
  307. for(int i = 0; i <= p; i++)
  308. oTempararyContour.push_back(oContour[i]);
  309. //push NewVertex to temporary contour
  310. oTempararyContour.push_back(vertex(iNewVertexIndex, gInputGraph));
  311. //push (Wq-...-Wm) to temporary contour
  312. for(int i = q; i < oContour.size(); i++)
  313. oTempararyContour.push_back(oContour[i]);
  314. //copy temporary contour to original contour
  315. oContour = oTempararyContour;
  316. }
  317. void GridBasedLayout::findOverlaps(int &p, std::vector<VertexDescriptor> &oContour, SubGraph &gInputGraph,
  318. std::vector<Position> &vecPositon, int &iOverlapLeft, int &iOverlapRight)
  319. {
  320. LAYOUT_ASSERT((p+2) < oContour.size(),
  321. LayoutException("findOverlaps",
  322. LayoutExceptionEnum::INVALID_PARAMETER,
  323. "contour",
  324. "P"));
  325. //Read new vertex and vertices at its left and right in current contour
  326. VertexDescriptor vLeftVertex, vNewVertex, vRightVertex;
  327. vLeftVertex = oContour[p];
  328. vNewVertex = oContour[p + 1];
  329. vRightVertex = oContour[p + 2];
  330. //Find distance between them and their widths--------------------------------------------------------------
  331. BoostGraphWrapper boostGraphWrapper;
  332. int iCoordXOfLeft, iCoordXOfRight,iCoordXOfNew;
  333. int iDistanceAtLeft, iDistanceAtRight, iWidthOfLeftVertex, iWidthOfRightVertex, iWidthOfNewVertex;
  334. //get centre coordinates
  335. iCoordXOfLeft = vecPositon[get(vertex_index, gInputGraph, vLeftVertex)].iCoordX;
  336. iCoordXOfNew = vecPositon[get(vertex_index, gInputGraph, vNewVertex)].iCoordX;
  337. iCoordXOfRight = vecPositon[get(vertex_index, gInputGraph, vRightVertex)].iCoordX;
  338. //get distance between centres
  339. iDistanceAtLeft = std::abs(iCoordXOfNew - iCoordXOfLeft);
  340. iDistanceAtRight = std::abs(iCoordXOfRight - iCoordXOfNew);
  341. //get widths
  342. iWidthOfLeftVertex = boostGraphWrapper.getVertexWidth(vLeftVertex, gInputGraph);
  343. iWidthOfNewVertex = boostGraphWrapper.getVertexWidth(vNewVertex, gInputGraph);
  344. iWidthOfRightVertex = boostGraphWrapper.getVertexWidth(vRightVertex, gInputGraph);
  345. //---------------------------------------------------------------------------------------------------------
  346. //If they overlap, find the amount by which they overlap---------------------------------------------------
  347. //get separation between centres needed to avoid overlap
  348. int iSeparationLeft, iSeparationRight;
  349. iSeparationLeft = std::ceil((iWidthOfLeftVertex / 2) + (iWidthOfNewVertex / 2));
  350. iSeparationRight = std::ceil((iWidthOfRightVertex / 2) + (iWidthOfNewVertex / 2));
  351. if(iSeparationLeft >= iDistanceAtLeft) //if NewNode overlaps with node at left
  352. iOverlapLeft = (iSeparationLeft - iDistanceAtLeft) + SEPARATION;
  353. else
  354. iOverlapLeft = 5;
  355. if(iSeparationRight >= iDistanceAtRight) //if NewNode overlaps with node at right
  356. iOverlapRight = (iSeparationRight - iDistanceAtRight) + SEPARATION;
  357. else
  358. iOverlapRight = 5;
  359. //---------------------------------------------------------------------------------------------------------
  360. }
  361. void GridBasedLayout::secondShiftRight(int &iOverlapLeft, int &iOverlapRight, SubGraph &gInputGraph,
  362. std::vector<Position> &vecPositon,
  363. std::vector<std::vector<VertexDescriptor> > &vecAssociated,
  364. std::vector<VertexDescriptor> &oContour, int &p)
  365. {
  366. LAYOUT_ASSERT((p+2) <= oContour.size(),
  367. LayoutException("secondShiftRight",
  368. LayoutExceptionEnum::INVALID_PARAMETER,
  369. "contour",
  370. "P"));
  371. //for vertices associated to new node, shift by iOverlapLeft-----------------------------------------------
  372. VertexDescriptor vNewVertex = oContour[p + 1];
  373. int iIndexOfNewVertex = get(vertex_index, gInputGraph, vNewVertex);
  374. //for each vertex associated to NewVertex
  375. for(int iAssociatedIndex = 0; iAssociatedIndex < vecAssociated[iIndexOfNewVertex].size(); iAssociatedIndex++)
  376. {
  377. int iVertIndex = get(vertex_index, gInputGraph, vecAssociated[iIndexOfNewVertex][iAssociatedIndex]);
  378. //shift by iOverlapLeft
  379. vecPositon[iVertIndex].iCoordX = vecPositon[iVertIndex].iCoordX + iOverlapLeft;
  380. }
  381. //---------------------------------------------------------------------------------------------------------
  382. //for vertices associated to Wq onwords, shift by iOverlapLeft + iOverlapRight-----------------------------
  383. //for each vertex (Wq.....) on contour
  384. for(int iIndexInContour = p+2; iIndexInContour < oContour.size(); iIndexInContour++)
  385. {
  386. VertexDescriptor vVertexOnContour = oContour[iIndexInContour];
  387. int iContourVertIndex = get(vertex_index, gInputGraph, vVertexOnContour);
  388. //for each of its associated vertex
  389. for(int iAssociatedIndex = 0; iAssociatedIndex < vecAssociated[iContourVertIndex].size(); iAssociatedIndex++)//for associated vertices
  390. {
  391. int iVertIndex = get(vertex_index, gInputGraph, vecAssociated[iContourVertIndex][iAssociatedIndex]);
  392. //shift by iOverlapLeft + iOverlapRight
  393. vecPositon[iVertIndex].iCoordX = vecPositon[iVertIndex].iCoordX + iOverlapLeft + iOverlapRight;
  394. }
  395. }
  396. //---------------------------------------------------------------------------------------------------------
  397. }
  398. void GridBasedLayout::findTopmostVertex(int &p, int &q, std::vector<VertexDescriptor> &oContour,
  399. SubGraph &gInputGraph, std::vector<Position> &vecPositon,
  400. int &iIndexOfTopmostVertex)
  401. {
  402. BoostGraphWrapper boostGrapgWrapper;
  403. int iHighestPoint = -2147483648; // initialize to smallest int value
  404. //initially, set contour[p] as topmost vertex
  405. iIndexOfTopmostVertex = get(vertex_index, gInputGraph, oContour[p]);
  406. //linearly search through contour in range p...q
  407. for(int iContourIndex = p; iContourIndex <= q; ++iContourIndex)
  408. {
  409. //calculate topmost point of current vertex
  410. int iHeightOfCurrentVertex, iYCoordOfCentreOfCurrentVertex, iTopmostPointOfCurrentVertex;
  411. iHeightOfCurrentVertex = boostGrapgWrapper.getVertexHeight(oContour[iContourIndex], gInputGraph);
  412. iYCoordOfCentreOfCurrentVertex = vecPositon[get(vertex_index, gInputGraph, oContour[iContourIndex])].iCoordY;
  413. iTopmostPointOfCurrentVertex = iYCoordOfCentreOfCurrentVertex + (iHeightOfCurrentVertex / 2);
  414. //update the topmost vertex
  415. if(iTopmostPointOfCurrentVertex > iHighestPoint)
  416. {
  417. iHighestPoint = iTopmostPointOfCurrentVertex;
  418. iIndexOfTopmostVertex = get(vertex_index, gInputGraph, oContour[iContourIndex]);
  419. }
  420. //else continue
  421. }
  422. }
  423. void GridBasedLayout::shiftVertically(int &iIndexOfTopmostVertex, int &iNewVertexIndex,
  424. SubGraph &gInputGraph, std::vector<Position> &vecPositon)
  425. {
  426. BoostGraphWrapper boostGraphWrapper;
  427. //Find whether topmost vertex and new vertex overlap
  428. int iDistanceBetweenCentres, iSeparation;
  429. int iYCoordOfCentreOfTopmoostVertex, iYCoordOfCentreOfNewVertex;
  430. int iHeightOfTopmostVertex, iHeightOfNewVertex;
  431. VertexDescriptor vTopmostVertex = vertex(iIndexOfTopmostVertex, gInputGraph);
  432. VertexDescriptor vNewVertex = vertex(iNewVertexIndex, gInputGraph);
  433. //get coordinates of centres
  434. iYCoordOfCentreOfTopmoostVertex = vecPositon[iIndexOfTopmostVertex].iCoordY;
  435. iYCoordOfCentreOfNewVertex = vecPositon[iNewVertexIndex].iCoordY;
  436. //get distance between centres
  437. iDistanceBetweenCentres = iYCoordOfCentreOfNewVertex - iYCoordOfCentreOfTopmoostVertex;
  438. //get heights
  439. iHeightOfTopmostVertex = boostGraphWrapper.getVertexHeight(vTopmostVertex, gInputGraph);
  440. iHeightOfNewVertex = boostGraphWrapper.getVertexHeight(vNewVertex, gInputGraph);
  441. //get separation between centres needed to avoid overlap
  442. iSeparation = std::ceil((iHeightOfNewVertex / 2) + (iHeightOfTopmostVertex / 2));
  443. int iAmountOfVerticalOverlap = 5;
  444. if(iSeparation >= iDistanceBetweenCentres) //if there is overlap
  445. iAmountOfVerticalOverlap = std::abs(iSeparation - iDistanceBetweenCentres) + SEPARATION;
  446. //shift new vertex vertically
  447. vecPositon[iNewVertexIndex].iCoordY += iAmountOfVerticalOverlap;
  448. }