void PlanarDrawLayout::doCall( const Graph &G, adjEntry adjExternal, GridLayout &gridLayout, IPoint &boundingBox, bool fixEmbedding) { // require to have a planar graph without multi-edges and self-loops; // planarity is checked below OGDF_ASSERT(isSimple(G) && isLoopFree(G)); // handle special case of graphs with less than 3 nodes if(G.numberOfNodes() < 3) { node v1, v2; switch(G.numberOfNodes()) { case 0: boundingBox = IPoint(0,0); return; case 1: v1 = G.firstNode(); gridLayout.x(v1) = gridLayout.y(v1) = 0; boundingBox = IPoint(0,0); return; case 2: v1 = G.firstNode(); v2 = G.lastNode (); gridLayout.x(v1) = gridLayout.y(v1) = gridLayout.y(v2) = 0; gridLayout.x(v2) = 1; boundingBox = IPoint(1,0); return; } } // we make a copy of G since we use planar biconnected augmentation GraphCopySimple GC(G); if(fixEmbedding) { PlanarAugmentationFix augmenter; augmenter.call(GC); } else { // augment graph planar biconnected m_augmenter.get().call(GC); // embed augmented graph PlanarModule pm; bool isPlanar = pm.planarEmbed(GC); if(isPlanar == false) OGDF_THROW_PARAM(PreconditionViolatedException, pvcPlanar); } // compute shelling order m_computeOrder.get().baseRatio(m_baseRatio); ShellingOrder order; m_computeOrder.get().call(GC,order,adjExternal); // compute grid coordinates for GC NodeArray<int> x(GC), y(GC); computeCoordinates(GC,order,x,y); boundingBox.m_x = x[order(1,order.len(1))]; boundingBox.m_y = 0; node v; forall_nodes(v,GC) if(y[v] > boundingBox.m_y) boundingBox.m_y = y[v]; // copy coordinates from GC to G forall_nodes(v,G) { node vCopy = GC.copy(v); gridLayout.x(v) = x[vCopy]; gridLayout.y(v) = y[vCopy]; }
void PlanarStraightLayout::doCall( const Graph &G, adjEntry adjExternal, GridLayout &gridLayout, IPoint &boundingBox, bool fixEmbedding) { // require to have a planar graph without multi-edges and self-loops; // planarity is checked below OGDF_ASSERT(isSimple(G) && isLoopFree(G)); // handle special case of graphs with less than 3 nodes if(G.numberOfNodes() < 3) { node v1, v2; switch(G.numberOfNodes()) { case 0: boundingBox = IPoint(0,0); return; case 1: v1 = G.firstNode(); gridLayout.x(v1) = gridLayout.y(v1) = 0; boundingBox = IPoint(0,0); return; case 2: v1 = G.firstNode(); v2 = G.lastNode (); gridLayout.x(v1) = gridLayout.y(v1) = gridLayout.y(v2) = 0; gridLayout.x(v2) = 1; boundingBox = IPoint(1,0); return; } } // we make a copy of G since we use planar biconnected augmentation GraphCopySimple GC(G); if(fixEmbedding) { // determine adjacency entry on external face of GC (if required) if(adjExternal != 0) { edge eG = adjExternal->theEdge(); edge eGC = GC.copy(eG); adjExternal = (adjExternal == eG->adjSource()) ? eGC->adjSource() : eGC->adjTarget(); } PlanarAugmentationFix augmenter; augmenter.call(GC); } else { adjExternal = 0; // augment graph planar biconnected m_augmenter.get().call(GC); // embed augmented graph m_embedder.get().call(GC,adjExternal); } // compute shelling order with shelling order module m_computeOrder.get().baseRatio(m_baseRatio); ShellingOrder order; m_computeOrder.get().callLeftmost(GC,order,adjExternal); // compute grid coordinates for GC NodeArray<int> x(GC), y(GC); computeCoordinates(GC,order,x,y); boundingBox.m_x = x[order(1,order.len(1))]; boundingBox.m_y = 0; node v; forall_nodes(v,GC) if(y[v] > boundingBox.m_y) boundingBox.m_y = y[v]; // copy coordinates from GC to G forall_nodes(v,G) { node vCopy = GC.copy(v); gridLayout.x(v) = x[vCopy]; gridLayout.y(v) = y[vCopy]; }