// 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()); }
bool CconnectClusterPlanar::preProcess(ClusterGraph &C,Graph &G) { if (!isCConnected(C)) { ogdf::sprintf(errorCode,124,"Graph is not C-connected \n"); m_errorCode = nonCConnected; return false; } PlanarModule Pm; if (!Pm.planarityTest(C)) { ogdf::sprintf(errorCode,124,"Graph is not planar\n"); m_errorCode = nonPlanar; return false; } cluster c; SListPure<node> selfLoops; makeLoopFree(G,selfLoops); c = C.rootCluster(); bool cPlanar = planarityTest(C,c,G); return cPlanar; }
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]; }
Module::ReturnType SubgraphPlanarizer::doCall(PlanRep &PG, int cc, const EdgeArray<int> &cost, const EdgeArray<bool> &forbid, const EdgeArray<unsigned int> &subgraphs, int& crossingNumber) { OGDF_ASSERT(m_permutations >= 1); OGDF_ASSERT(!(useSubgraphs()) || useCost()); // ersetze durch exception handling double startTime; usedTime(startTime); if(m_setTimeout) m_subgraph.get().timeLimit(m_timeLimit); List<edge> deletedEdges; PG.initCC(cc); EdgeArray<int> costPG(PG); edge e; forall_edges(e,PG) costPG[e] = cost[PG.original(e)]; ReturnType retValue = m_subgraph.get().call(PG, costPG, deletedEdges); if(isSolution(retValue) == false) return retValue; for(ListIterator<edge> it = deletedEdges.begin(); it.valid(); ++it) *it = PG.original(*it); bool foundSolution = false; CrossingStructure cs; for(int i = 1; i <= m_permutations; ++i) { const int nG = PG.numberOfNodes(); for(ListConstIterator<edge> it = deletedEdges.begin(); it.valid(); ++it) PG.delCopy(PG.copy(*it)); deletedEdges.permute(); if(m_setTimeout) m_inserter.get().timeLimit( (m_timeLimit >= 0) ? max(0.0,m_timeLimit - usedTime(startTime)) : -1); ReturnType ret; if(useForbid()) { if(useCost()) { if(useSubgraphs()) ret = m_inserter.get().call(PG, cost, forbid, deletedEdges, subgraphs); else ret = m_inserter.get().call(PG, cost, forbid, deletedEdges); } else ret = m_inserter.get().call(PG, forbid, deletedEdges); } else { if(useCost()) { if(useSubgraphs()) ret = m_inserter.get().call(PG, cost, deletedEdges, subgraphs); else ret = m_inserter.get().call(PG, cost, deletedEdges); } else ret = m_inserter.get().call(PG, deletedEdges); } if(isSolution(ret) == false) continue; // no solution found, that's bad... if(!useCost()) crossingNumber = PG.numberOfNodes() - nG; else { crossingNumber = 0; node n; forall_nodes(n, PG) { if(PG.original(n) == 0) { // dummy found -> calc cost edge e1 = PG.original(n->firstAdj()->theEdge()); edge e2 = PG.original(n->lastAdj()->theEdge()); if(useSubgraphs()) { int subgraphCounter = 0; for(int i=0; i<32; i++) { if(((subgraphs[e1] & (1<<i))!=0) && ((subgraphs[e2] & (1<<i)) != 0)) subgraphCounter++; } crossingNumber += (subgraphCounter*cost[e1] * cost[e2]); } else crossingNumber += cost[e1] * cost[e2]; } } } if(i == 1 || crossingNumber < cs.weightedCrossingNumber()) { foundSolution = true; cs.init(PG, crossingNumber); } if(localLogMode() == LM_STATISTIC) { if(m_permutations <= 200 || i <= 10 || (i <= 30 && (i % 2) == 0) || (i > 30 && i <= 100 && (i % 5) == 0) || ((i % 10) == 0)) sout() << "\t" << cs.weightedCrossingNumber(); } PG.initCC(cc); if(m_timeLimit >= 0 && usedTime(startTime) >= m_timeLimit) { if(foundSolution == false) return retTimeoutInfeasible; // not able to find a solution... break; } } cs.restore(PG,cc); // restore best solution in PG crossingNumber = cs.weightedCrossingNumber(); PlanarModule pm; OGDF_ASSERT(pm.planarityTest(PG) == true); return retFeasible; }
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()); } } }