// sets the positions of the nodes in a largest face of G in the form // of a regular k-gon. The corresponding nodes and their positions are // stored in nodes and pos, respectively. void TutteLayout::setFixedNodes( const Graph &G, List<node>& nodes, List<DPoint>& pos, double radius) { // compute faces of a copy of G GraphCopy GC(G); PlanarModule pm; // compute a planar embedding if \a G is planar if(pm.planarityTest(G)) pm.planarEmbed(GC); CombinatorialEmbedding E(GC); E.computeFaces(); // search for largest face face maxFace = E.maximalFace(); // delete possible old entries in nodes and pos nodes.clear(); pos.clear(); // set nodes and pos NodeArray<bool> addMe(GC,true); adjEntry adj; List<node> maxNodes; forall_face_adj(adj,maxFace) { maxNodes.pushBack(adj->theNode()); }
void ExpandedGraph2::expand(node v, node vPred, node vSucc) { m_exp.clear(); while (!m_nodesG.empty()) m_GtoExp[m_nodesG.popBackRet()] = 0; edge eInS = 0; if (vPred != 0) { eInS = m_BC.dynamicSPQRForest().virtualEdge(vPred,v); m_eS = insertEdge(eInS->source(),eInS->target(),0); } edge eOutS = 0; if (vSucc != 0) { eOutS = m_BC.dynamicSPQRForest().virtualEdge(vSucc,v); m_eT = insertEdge(eOutS->source(),eOutS->target(),0); } expandSkeleton(v, eInS, eOutS); PlanarModule pm; pm.planarEmbed(m_exp); m_E.init(m_exp); }
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 planarTriconnectedGraph(Graph &G, int n, int m) { if (n < 4) n = 4; if(n % 2) ++n; // need an even number // start with K_4 completeGraph(G,4); PlanarModule pm; pm.planarEmbed(G); // nodes[0],...,nodes[i-1] is array of all nodes Array<node> nodes(n); node v; int i = 0; forall_nodes(v,G) nodes[i++] = v; // create planar triconnected 3-graph for(; i < n; ) { // pick a random node v = nodes[randomNumber(0,i-1)]; adjEntry adj2 = v->firstAdj(); int r = randomNumber(0,2); switch(r) { case 2: adj2 = adj2->succ(); // fall through to next case case 1: adj2 = adj2->succ(); } adjEntry adj1 = adj2->cyclicSucc(); nodes[i++] = G.splitNode(adj1,adj2); r = randomNumber(0,1); if(r == 0) { adjEntry adj = adj1->twin(); G.newEdge(adj2,adj); nodes[i++] = G.splitNode(adj,adj->cyclicSucc()->cyclicSucc()); } else { adjEntry adj = adj1->cyclicSucc()->twin(); G.newEdge(adj2,adj,ogdf::before); nodes[i++] = G.splitNode(adj->cyclicPred(),adj->cyclicSucc()); } } nodes.init(); Array<edge> edges(m); CombinatorialEmbedding E(G); Array<face> faces(2*n); i = 0; face f; forall_faces(f,E) { if(f->size() >= 4) faces[i++] = f; } while(G.numberOfEdges() < m && i > 0) { int r = randomNumber(0,i-1); f = faces[r]; faces[r] = faces[--i]; int p = randomNumber(0,f->size()-1); int j = 0; adjEntry adj, adj2; for(adj = f->firstAdj(); j < p; adj = adj->faceCycleSucc(), ++j) ; p = randomNumber(2, f->size()-2); for(j = 0, adj2 = adj; j < p; adj2 = adj2->faceCycleSucc(), ++j) ; edge e = E.splitFace(adj,adj2); f = E.rightFace(e->adjSource()); if(f->size() >= 4) faces[i++] = f; f = E.rightFace(e->adjTarget()); if(f->size() >= 4) faces[i++] = f; } }
void planarTriconnectedGraph(Graph &G, int n, double p1, double p2) { if (n < 4) n = 4; // start with K_4 completeGraph(G,4); PlanarModule pm; pm.planarEmbed(G); // nodes[0],...,nodes[i-1] is array of all nodes Array<node> nodes(n); node v; int i = 0; forall_nodes(v,G) nodes[i++] = v; for(; i < n; ++i) { // pick a random node v = nodes[randomNumber(0,i-1)]; int m = v->degree(); int a1 = randomNumber(0,m-1); int a2 = randomNumber(0,m-2); int j; adjEntry adj1, adj2; for(adj1 = v->firstAdj(), j = 0; j < a1; adj1 = adj1->succ(), ++j) ; for(adj2 = adj1->cyclicSucc(), j = 0; j < a2; adj2 = adj2->cyclicSucc(), ++j) ; adjEntry adj_b1 = adj2->cyclicPred(); adjEntry adj_b2 = adj1->cyclicPred(); nodes[i] = G.splitNode(adj1, adj2); if(adj1 == adj_b1) G.newEdge(adj_b1, adj2->twin()); else if(adj2 == adj_b2) G.newEdge(adj2, adj_b1->twin(), ogdf::before); else { double r = randomDouble(0.0,1.0); if(r <= p1) { int s = randomNumber(0,1); if(s == 0) G.newEdge(adj_b1, adj2->twin()); else G.newEdge(adj2, adj_b1->twin(), ogdf::before); } } double r = randomDouble(0.0,1.0); if(r <= p2) { int s = randomNumber(0,1); if(s == 0) G.newEdge(adj1, adj_b2->twin(), ogdf::before); else G.newEdge(adj_b2, adj1->twin()); } } }