void VisibilityLayout::constructVisibilityRepresentation(UpwardPlanRep &UPR) { constructDualGraph(UPR); //makeSimple(D); //if (t_D->degree() <= 1) // D.newEdge(s_D, t_D); // make biconnected //OGDF_ASSERT(isSimple(UPR)); //OGDF_ASSERT(isBiconnected(UPR)); //OGDF_ASSERT(isSimple(D)); //OGDF_ASSERT(isBiconnected(D)); //compute top. numbering NodeArray<int> topNumberUPR(UPR); NodeArray<int> topNumberD(D); topologicalNumbering(UPR, topNumberUPR); topologicalNumbering(D, topNumberD); nodeToVis.init(UPR); edgeToVis.init(UPR); for(node v : UPR.nodes) { NodeSegment vVis; //cout << "node : " << v << " stNum: " << topNumberUPR[v] << endl; if (v == UPR.getSuperSource() || v == UPR.getSuperSink()) { vVis.y = topNumberUPR[v]; vVis.x_l = topNumberD[s_D]; vVis.x_r = topNumberD[t_D]-1; nodeToVis[v] =vVis; continue; } vVis.y = topNumberUPR[v]; face f_v = leftFace_node[v]; node vD = faceToNode[f_v]; vVis.x_l = topNumberD[vD]; f_v = rightFace_node[v]; vD = faceToNode[f_v]; vVis.x_r = topNumberD[vD]-1; nodeToVis[v] =vVis; } for(edge e : UPR.edges) { EdgeSegment eVis; face f_v = leftFace_edge[e]; node vD = faceToNode[f_v]; eVis.x = topNumberD[vD]; eVis.y_b = topNumberUPR[e->source()]; eVis.y_t = topNumberUPR[e->target()]; edgeToVis[e] = eVis; } }
void VisibilityLayout::call(GraphAttributes &GA) { if (GA.constGraph().numberOfNodes() <= 1) return; //call upward planarizer UpwardPlanRep UPR; UPR.createEmpty(GA.constGraph()); m_upPlanarizer.get().call(UPR); layout(GA, UPR); }
void DominanceLayout::call(GraphAttributes &GA) { if (GA.constGraph().numberOfNodes() <= 1) return; OGDF_ASSERT(isSimpleUndirected(GA.constGraph())); //call upward planarizer UpwardPlanRep UPR; UPR.createEmpty(GA.constGraph()); m_upPlanarizer->call(UPR); layout(GA, UPR); }
void UPRSupplier::supply(Graph& graph, UpwardPlanRep& retVal){ node addedSource = graph.newNode(); node addedSink = graph.newNode(); if (outputDebug){ cout << "\tAdded super source (" << addedSource->index() << ") and super sink (" << addedSink->index() << ")." << endl; cout << endl; } vector<edge> addedEdges; node n; forall_nodes(n, graph){ if (n->indeg() == 0 && n != addedSource && n != addedSink) { edge e = graph.newEdge(addedSource, n); addedEdges.push_back(e); } } forall_nodes(n, graph){ if (n->outdeg() == 0 && n != addedSource && n != addedSink) { edge e = graph.newEdge(n, addedSink); addedEdges.push_back(e); } } retVal.createEmpty(graph); assert(&retVal.original() == &graph); EdgeArray<int> cost (graph, this->normalCost); if (outputDebug) cout << "\tAssigning cost " << this->normalCost << " as default cost per edge" << endl; EdgeArray<bool> forbid (graph, false); for (vector<edge>::iterator it = addedEdges.begin(); it != addedEdges.end(); ++it){ cost[*it] = this->sourceSinkCost; if (outputDebug) cout << "\tAssigning cost " << cost[*it] << " to " << *it << endl; } if (outputDebug) cout << endl; SubgraphUpwardPlanarizer sup; FUPSSourceSink* fups = new FUPSSourceSink(); fups->runs(this->runs); sup.setSubgraph(fups); sup.setInserter(new OutputUpwardEdgeInserter()); sup.runs(this->runs); sup.call(retVal, &cost, &forbid); }
void UPRSupplier::revertUPR(UpwardPlanRep& upr, GraphAttributes& uga){ upr.delNode(getSource(upr)); upr.delNode(getSink(upr)); upr.delNode(getSink(upr)); node source = getSource(upr); node sink = getSink(upr); vector<edge> edgesToDelete; edge e; forall_edges(e, upr){ if (upr.original(e)->source() == upr.original(source) || upr.original(e)->target() == upr.original(sink)) edgesToDelete.push_back(e); } for (vector<edge>::iterator it = edgesToDelete.begin(); it != edgesToDelete.end(); ++it){ upr.delEdge(*it); } upr.delNode(source); upr.delNode(sink); vector<node> nodesToUnsplit; node n; forall_nodes(n, upr){ if (n->indeg() == 1 && n->outdeg() == 1 && upr.isDummy(n)){ nodesToUnsplit.push_back(n); } } for (vector<node>::iterator it = nodesToUnsplit.begin(); it != nodesToUnsplit.end(); ++it){ edge in = (*it)->firstAdj()->theEdge(); edge out = (*it)->lastAdj()->theEdge(); if (in->source() == *it) swap(in, out); DPolyline& inBends = uga.bends(in); DPolyline& outBends = uga.bends(out); inBends.popBack(); double x = inBends.back().m_x; int counter = 0; for (ListIterator<DPoint> it = outBends.begin(); it != outBends.end(); ++it){ if (counter < 2){ DPoint p(x, (*it).m_y); inBends.pushBack(p); counter++; } else { inBends.pushBack(*it); } } upr.unsplit(in, out); } }
void DominanceLayout::findTransitiveEdges(const UpwardPlanRep &UPR, List<edge> &edges) { // for st-graphs: // e = (u,v) transitive <=> ex. face f: e in f and u source-switch and v = sink-switch for(face f : UPR.getEmbedding().faces) { if (f == UPR.getEmbedding().externalFace()) continue; for(adjEntry adj : f->entries) { node src = adj->theEdge()->source(); node tgt = adj->theEdge()->target(); if ( (adj->faceCycleSucc()->theEdge()->source() == src && adj->faceCyclePred()->theEdge()->target() == tgt) || (adj->faceCycleSucc()->theEdge()->target() == tgt && adj->faceCyclePred()->theEdge()->source() == src)) { edges.pushBack(adj->theEdge()); break; } } } }
void DominanceLayout::labelY(const UpwardPlanRep &UPR, node v, int &count) { yNodes.pushBack(v); yPreCoord[v] = count; count++; if (v != UPR.getSuperSink()) { adjEntry adj = lastout[v]->adjSource(); do { node w = adj->theEdge()->target(); if (adj->theEdge() == firstin[w]) labelY(UPR, w, count); adj = adj->cyclicPred(); } while (adj->cyclicSucc()->theEdge() != firstout[v]); } }
Module::ReturnType OutputUpwardEdgeInserter::insertAll(UpwardPlanRep &UPR, List<edge> &toInsert, EdgeArray<int> &costOrig) { if (toInsert.empty()) return Module::retFeasible; List<edge> l; int size_new = toInsert.size(); int size_old = 0; while (size_old != size_new) { size_old = size_new; while (!toInsert.empty()) { edge e_orig = toInsert.popFrontRet(); SList<adjEntry> path; /* //debug cout << endl; cout << " insertion path for e_orig :" << e_orig << "; e_UPR: (" << UPR.copy(e_orig->source()) << "," << UPR.copy(e_orig->target()) << ")" << endl; */ minFIP(UPR, toInsert, costOrig, e_orig, path); /* //--------------------------------------debug forall_slistiterators(adjEntry, it, path) { cout << (*it)->theEdge() << "; node: " << (*it)->theNode() << endl; } //--------------------------------------end debug */ List<edge> lEdges = toInsert, lTmp = l; lEdges.conc(lTmp); bool ok = isConstraintFeasible(UPR, lEdges, e_orig, path); if (ok) { UPR.insertEdgePathEmbedded(e_orig, path, costOrig); OGDF_ASSERT(isUpwardPlanar(UPR)); OGDF_ASSERT(isSimple(UPR)); OGDF_ASSERT(isConnected(UPR)); OGDF_ASSERT(hasSingleSource(UPR)); } else l.pushBack(e_orig); /* if (false) { //---------------------------------------------------debug //UPR.outputFaces(UPR.getEmbedding()); //UPR.writeGML("c:/temp/bug5.gml"); LayerBasedUPRLayout uprLayout; Graph GTmp( (const Graph &) UPR); CombinatorialEmbedding embTmp(GTmp); node tTmp = 0; //GTmp.writeGML("c:/temp/bug4.gml"); hasSingleSink(GTmp, tTmp); OGDF_ASSERT(tTmp != 0); embTmp.setExternalFace(embTmp.rightFace(tTmp->firstAdj())); //adjEntry adjTmp = GCTmp.copy(UPR.extFaceHandle->theEdge())->adjTarget(); UpwardPlanRep upr_bug(embTmp); adjEntry adj_bug = upr_bug.getAdjEntry(upr_bug.getEmbedding(), upr_bug.getSuperSource(), upr_bug.getEmbedding().externalFace()); node s_upr_bug = upr_bug.newNode(); upr_bug.getEmbedding().splitFace(s_upr_bug, adj_bug); upr_bug.m_isSourceArc.init(upr_bug, false); upr_bug.m_isSourceArc[s_upr_bug->firstAdj()->theEdge()] = true; upr_bug.s_hat = s_upr_bug; upr_bug.augment(); GraphAttributes GA_UPR_tmp(GTmp, GraphAttributes::nodeGraphics| GraphAttributes::edgeGraphics| GraphAttributes::nodeColor| GraphAttributes::edgeColor| GraphAttributes::nodeLabel| GraphAttributes::edgeLabel ); GA_UPR_tmp.setAllHeight(30.0); GA_UPR_tmp.setAllWidth(30.0); uprLayout.call(upr_bug, GA_UPR_tmp); // label the nodes with their index node z; forall_nodes(z, GA_UPR_tmp.constGraph()) { char str[255]; sprintf_s(str, 255, "%d", z->index()); // convert to string GA_UPR_tmp.labelNode(z) = str; GA_UPR_tmp.y(z)=-GA_UPR_tmp.y(z); GA_UPR_tmp.x(z)=-GA_UPR_tmp.x(z); } edge eee; forall_edges(eee, GA_UPR_tmp.constGraph()) { DPolyline &line = GA_UPR_tmp.bends(eee); ListIterator<DPoint> it; for(it = line.begin(); it.valid(); it++) { (*it).m_y = -(*it).m_y; (*it).m_x = -(*it).m_x; } } GA_UPR_tmp.writeGML("c:/temp/UPR_int.gml"); //cout << "face of UPR_int :" << endl; //upr_bug.outputFaces(upr_bug.getEmbedding()); //end -----------------------------------------------debug } */ } size_new = l.size(); toInsert = l; l.clear(); } /* * some edges cannot be inserted, so use heuristic insertion methods */ if (!toInsert.empty()) { //cout << endl << "\a\a\a\a\aheuristical call!! " << endl; edge e_orig = toInsert.popFrontRet(); /* cout << endl; cout << "heuristical insertion path for e_orig :" << e_orig << "; e_UPR: (" << UPR.copy(e_orig->source()) << "," << UPR.copy(e_orig->target()) << ")" << endl; */ /* if (false) { //---------------------------------------------------debug //UPR.outputFaces(UPR.getEmbedding()); //UPR.writeGML("c:/temp/bug5.gml"); LayerBasedUPRLayout uprLayout; Graph GTmp( (const Graph &) UPR); CombinatorialEmbedding embTmp(GTmp); node tTmp = 0; //GTmp.writeGML("c:/temp/bug4.gml"); hasSingleSink(GTmp, tTmp); OGDF_ASSERT(tTmp != 0); embTmp.setExternalFace(embTmp.rightFace(tTmp->firstAdj())); //adjEntry adjTmp = GCTmp.copy(UPR.extFaceHandle->theEdge())->adjTarget(); UpwardPlanRep upr_bug(embTmp); adjEntry adj_bug = upr_bug.getAdjEntry(upr_bug.getEmbedding(), upr_bug.getSuperSource(), upr_bug.getEmbedding().externalFace()); node s_upr_bug = upr_bug.newNode(); upr_bug.getEmbedding().splitFace(s_upr_bug, adj_bug); upr_bug.m_isSourceArc.init(upr_bug, false); upr_bug.m_isSourceArc[s_upr_bug->firstAdj()->theEdge()] = true; upr_bug.s_hat = s_upr_bug; upr_bug.augment(); GraphAttributes GA_UPR_tmp(GTmp, GraphAttributes::nodeGraphics| GraphAttributes::edgeGraphics| GraphAttributes::nodeColor| GraphAttributes::edgeColor| GraphAttributes::nodeLabel| GraphAttributes::edgeLabel ); GA_UPR_tmp.setAllHeight(30.0); GA_UPR_tmp.setAllWidth(30.0); uprLayout.call(upr_bug, GA_UPR_tmp); // label the nodes with their index node z; forall_nodes(z, GA_UPR_tmp.constGraph()) { char str[255]; sprintf_s(str, 255, "%d", z->index()); // convert to string GA_UPR_tmp.labelNode(z) = str; GA_UPR_tmp.y(z)=-GA_UPR_tmp.y(z); GA_UPR_tmp.x(z)=-GA_UPR_tmp.x(z); } edge eee; forall_edges(eee, GA_UPR_tmp.constGraph()) { DPolyline &line = GA_UPR_tmp.bends(eee); ListIterator<DPoint> it; for(it = line.begin(); it.valid(); it++) { (*it).m_y = -(*it).m_y; (*it).m_x = -(*it).m_x; } } GA_UPR_tmp.writeGML("c:/temp/UPR_int.gml"); //cout << "face of UPR_int :" << endl; //upr_bug.outputFaces(upr_bug.getEmbedding()); //end -----------------------------------------------debug } */ SList<adjEntry> path; constraintFIP(UPR, toInsert, costOrig, e_orig, path); /* //--------------------------------------debug forall_slistiterators(adjEntry, it, path) { cout << (*it)->theEdge() << "; node: " << (*it)->theNode() << endl;; } //--------------------------------------end debug */ UPR.insertEdgePathEmbedded(e_orig, path, costOrig); OGDF_ASSERT(isUpwardPlanar(UPR)); return insertAll(UPR, toInsert, costOrig); } return Module::retFeasible; }
void FUPSSimple::computeFUPS(UpwardPlanRep &UPR, List<edge> &delEdges) { const Graph &G = UPR.original(); GraphCopy FUPS(G); node s_orig; hasSingleSource(G, s_orig); List<edge> nonTreeEdges_orig; bool random = (m_nRuns != 0); getSpanTree(FUPS, nonTreeEdges_orig, random); CombinatorialEmbedding Gamma(FUPS); if (random) nonTreeEdges_orig.permute(); // random order adjEntry extFaceHandle = nullptr; //insert nonTreeEdges while (!nonTreeEdges_orig.empty()) { /* //------------------------------------debug GraphAttributes AG(FUPS, GraphAttributes::nodeGraphics| GraphAttributes::edgeGraphics| GraphAttributes::nodeColor| GraphAttributes::edgeColor| GraphAttributes::nodeLabel| GraphAttributes::edgeLabel ); // label the nodes with their index for(node v : AG.constGraph().nodes) { AG.label(v) = to_string(v->index()); } AG.writeGML("c:/temp/spannTree.gml"); */ // make identical copy FUPSCopy of FUPS //and insert e_orig in FUPSCopy GraphCopy FUPSCopy((const GraphCopy &) FUPS); edge e_orig = nonTreeEdges_orig.popFrontRet(); FUPSCopy.newEdge(e_orig); if (UpwardPlanarity::upwardPlanarEmbed_singleSource(FUPSCopy)) { //upward embedded the fups and check feasibility CombinatorialEmbedding Beta(FUPSCopy); //choose a arbitrary feasibel ext. face FaceSinkGraph fsg(Beta, FUPSCopy.copy(s_orig)); SList<face> ext_faces; fsg.possibleExternalFaces(ext_faces); OGDF_ASSERT(!ext_faces.empty()); Beta.setExternalFace(ext_faces.front()); #if 0 //*************************** debug ******************************** cout << endl << "FUPS : " << endl; for(face ff : Beta.faces) { cout << "face " << ff->index() << ": "; adjEntry adjNext = ff->firstAdj(); do { cout << adjNext->theEdge() << "; "; adjNext = adjNext->faceCycleSucc(); } while(adjNext != ff->firstAdj()); cout << endl; } if (Beta.externalFace() != 0) cout << "ext. face of the graph is: " << Beta.externalFace()->index() << endl; else cout << "no ext. face set." << endl; #endif GraphCopy M((const GraphCopy &) FUPSCopy); // use a identical copy of FUPSCopy to construct the merge graph of FUPSCopy adjEntry extFaceHandle_cur = getAdjEntry(Beta, FUPSCopy.copy(s_orig), Beta.externalFace()); adjEntry adj_orig = FUPSCopy.original(extFaceHandle_cur->theEdge())->adjSource(); List<edge> missingEdges = nonTreeEdges_orig, listTmp = delEdges; missingEdges.conc(listTmp); if (constructMergeGraph(M, adj_orig, missingEdges)) { FUPS = FUPSCopy; extFaceHandle = FUPS.copy(FUPSCopy.original(extFaceHandle_cur->theEdge()))->adjSource(); continue; } else { //Beta is not feasible delEdges.pushBack(e_orig); } } else { // not ok, GC is not feasible delEdges.pushBack(e_orig); } } UpwardPlanRep fups_tmp (FUPS, extFaceHandle); UPR = fups_tmp; }
Module::ReturnType SubgraphUpwardPlanarizer::doCall(UpwardPlanRep &UPR, const EdgeArray<int> &cost, const EdgeArray<bool> &forbid) { const Graph &G = UPR.original(); GraphCopy GC(G); //reverse some edges in order to obtain a DAG List<edge> feedBackArcSet; m_acyclicMod.get().call(GC, feedBackArcSet); for(edge e : feedBackArcSet) { GC.reverseEdge(e); } OGDF_ASSERT(isSimple(G)); //mapping cost EdgeArray<int> cost_GC(GC); for(edge e : GC.edges) { if (forbid[GC.original(e)]) cost_GC[e] = numeric_limits<int>::max(); else cost_GC[e] = cost[GC.original(e)]; } // tranform to single source graph by adding a super source s_hat and connect it with the other sources EdgeArray<bool> sourceArcs(GC, false); node s_hat = GC.newNode(); for(node v : GC.nodes) { if (v->indeg() == 0 && v != s_hat) { edge e_tmp = GC.newEdge(s_hat, v); cost_GC[e_tmp] = 0; // crossings source arcs cause not cost sourceArcs[e_tmp] = true; } } /* //------------------------------------------------debug GraphAttributes AG_GC(GC, GraphAttributes::nodeGraphics| GraphAttributes::edgeGraphics| GraphAttributes::nodeColor| GraphAttributes::edgeColor| GraphAttributes::nodeLabel| GraphAttributes::edgeLabel ); AG_GC.setAllHeight(30.0); AG_GC.setAllWidth(30.0); for(node z : AG_GC.constGraph().nodes) { AG_GC.label(z) = to_string(z->index()); } AG_GC.writeGML("c:/temp/GC.gml"); // --------------------------------------------end debug */ BCTree BC(GC); const Graph &bcTree = BC.bcTree(); GraphCopy G_dummy; G_dummy.createEmpty(G); NodeArray<GraphCopy> biComps(bcTree, G_dummy); // bicomps of G; init with an empty graph UpwardPlanRep UPR_dummy; UPR_dummy.createEmpty(G); NodeArray<UpwardPlanRep> uprs(bcTree, UPR_dummy); // the upward planarized representation of the bicomps; init with an empty UpwarPlanRep constructComponentGraphs(BC, biComps); for(node v : bcTree.nodes) { if (BC.typeOfBNode(v) == BCTree::CComp) continue; GraphCopy &block = biComps[v]; OGDF_ASSERT(m_subgraph.valid()); // construct a super source for this block node s, s_block; hasSingleSource(block, s); s_block = block.newNode(); block.newEdge(s_block, s); //connect s UpwardPlanRep bestUPR; //upward planarize if not upward planar if (!UpwardPlanarity::upwardPlanarEmbed_singleSource(block)) { for (int i = 0; i < m_runs; i++) {// i multistarts UpwardPlanRep UPR_tmp; UPR_tmp.createEmpty(block); List<edge> delEdges; m_subgraph.get().call(UPR_tmp, delEdges); OGDF_ASSERT( isSimple(UPR_tmp) ); UPR_tmp.augment(); //mark the source arcs of block UPR_tmp.m_isSourceArc[UPR_tmp.copy(s_block->firstAdj()->theEdge())] = true; for (adjEntry adj_tmp : UPR_tmp.copy(s_block->firstAdj()->theEdge()->target())->adjEntries) { edge e_tmp = UPR_tmp.original(adj_tmp->theEdge()); if (e_tmp != nullptr && block.original(e_tmp) != nullptr && sourceArcs[block.original(e_tmp)]) UPR_tmp.m_isSourceArc[adj_tmp->theEdge()] = true; } //assign "crossing cost" EdgeArray<int> cost_Block(block); for (edge e : block.edges) { if (block.original(e) == nullptr || GC.original(block.original(e)) == nullptr) cost_Block[e] = 0; else cost_Block[e] = cost_GC[block.original(e)]; } /* if (false) { //---------------------------------------------------debug LayerBasedUPRLayout uprLayout; UpwardPlanRep upr_bug(UPR_tmp.getEmbedding()); adjEntry adj_bug = upr_bug.getAdjEntry(upr_bug.getEmbedding(), upr_bug.getSuperSource(), upr_bug.getEmbedding().externalFace()); node s_upr_bug = upr_bug.newNode(); upr_bug.getEmbedding().splitFace(s_upr_bug, adj_bug); upr_bug.m_isSourceArc.init(upr_bug, false); upr_bug.m_isSourceArc[s_upr_bug->firstAdj()->theEdge()] = true; upr_bug.s_hat = s_upr_bug; upr_bug.augment(); GraphAttributes GA_UPR_tmp(UPR_tmp, GraphAttributes::nodeGraphics| GraphAttributes::edgeGraphics| GraphAttributes::nodeColor| GraphAttributes::edgeColor| GraphAttributes::nodeLabel| GraphAttributes::edgeLabel ); GA_UPR_tmp.setAllHeight(30.0); GA_UPR_tmp.setAllWidth(30.0); uprLayout.call(upr_bug, GA_UPR_tmp); // label the nodes with their index for(node z : GA_UPR_tmp.constGraph().nodes) { GA_UPR_tmp.label(z) = to_string(z->index()); GA_UPR_tmp.y(z)=-GA_UPR_tmp.y(z); GA_UPR_tmp.x(z)=-GA_UPR_tmp.x(z); } for(edge eee : GA_UPR_tmp.constGraph().edges) { DPolyline &line = GA_UPR_tmp.bends(eee); ListIterator<DPoint> it; for(it = line.begin(); it.valid(); it++) { (*it).m_y = -(*it).m_y; (*it).m_x = -(*it).m_x; } } GA_UPR_tmp.writeGML("c:/temp/UPR_tmp_fups.gml"); cout << "UPR_tmp/fups faces:"; UPR_tmp.outputFaces(UPR_tmp.getEmbedding()); //end -----------------------------------------------debug } */ delEdges.permute(); m_inserter.get().call(UPR_tmp, cost_Block, delEdges); if (i != 0) { if (UPR_tmp.numberOfCrossings() < bestUPR.numberOfCrossings()) { //cout << endl << "new cr_nr:" << UPR_tmp.numberOfCrossings() << " old cr_nr : " << bestUPR.numberOfCrossings() << endl; bestUPR = UPR_tmp; } } else bestUPR = UPR_tmp; }//for } else { //block is upward planar CombinatorialEmbedding Gamma(block); FaceSinkGraph fsg((const CombinatorialEmbedding &) Gamma, s_block); SList<face> faceList; fsg.possibleExternalFaces(faceList); Gamma.setExternalFace(faceList.front()); UpwardPlanRep UPR_tmp(Gamma); UPR_tmp.augment(); //mark the source arcs of block UPR_tmp.m_isSourceArc[UPR_tmp.copy(s->firstAdj()->theEdge())] = true; for (adjEntry adj_tmp : UPR_tmp.copy(s->firstAdj()->theEdge()->target())->adjEntries) { edge e_tmp = UPR_tmp.original(adj_tmp->theEdge()); if (e_tmp != nullptr && block.original(e_tmp) != nullptr && sourceArcs[block.original(e_tmp)]) UPR_tmp.m_isSourceArc[adj_tmp->theEdge()] = true; } bestUPR = UPR_tmp; /* //debug //---------------------------------------------------debug GraphAttributes GA_UPR_tmp(UPR_tmp, GraphAttributes::nodeGraphics| GraphAttributes::edgeGraphics| GraphAttributes::nodeColor| GraphAttributes::edgeColor| GraphAttributes::nodeLabel| GraphAttributes::edgeLabel ); GA_UPR_tmp.setAllHeight(30.0); GA_UPR_tmp.setAllWidth(30.0); // label the nodes with their index for(node z : GA_UPR_tmp.constGraph().nodes) { GA_UPR_tmp.label(z) = to_string(z->index()); GA_UPR_tmp.y(z)=-GA_UPR_tmp.y(z); GA_UPR_tmp.x(z)=-GA_UPR_tmp.x(z); } for(edge eee : GA_UPR_tmp.constGraph().edges) { DPolyline &line = GA_UPR_tmp.bends(eee); ListIterator<DPoint> it; for(it = line.begin(); it.valid(); it++) { (*it).m_y = -(*it).m_y; (*it).m_x = -(*it).m_x; } } GA_UPR_tmp.writeGML("c:/temp/UPR_tmp_fups.gml"); cout << "UPR_tmp/fups faces:"; UPR_tmp.outputFaces(UPR_tmp.getEmbedding()); //end -----------------------------------------------debug */ } uprs[v] = bestUPR; } // compute the number of crossings int nr_cr = 0; for(node v : bcTree.nodes) { if (BC.typeOfBNode(v) != BCTree::CComp) nr_cr = nr_cr + uprs[v].numberOfCrossings(); } //merge all component to a graph node parent_BC = BC.bcproper(s_hat); NodeArray<bool> nodesDone(bcTree, false); dfsMerge(GC, BC, biComps, uprs, UPR, nullptr, parent_BC, nodesDone); // start with the component which contains the super source s_hat //augment to single sink graph UPR.augment(); //set crossings UPR.crossings = nr_cr; //------------------------------------------------debug /* LayerBasedUPRLayout uprLayout; UpwardPlanRep upr_bug(UPR.getEmbedding()); adjEntry adj_bug = upr_bug.getAdjEntry(upr_bug.getEmbedding(), upr_bug.getSuperSource(), upr_bug.getEmbedding().externalFace()); node s_upr_bug = upr_bug.newNode(); upr_bug.getEmbedding().splitFace(s_upr_bug, adj_bug); upr_bug.m_isSourceArc.init(upr_bug, false); upr_bug.m_isSourceArc[s_upr_bug->firstAdj()->theEdge()] = true; upr_bug.s_hat = s_upr_bug; upr_bug.augment(); GraphAttributes AG(UPR, GraphAttributes::nodeGraphics| GraphAttributes::edgeGraphics| GraphAttributes::nodeColor| GraphAttributes::edgeColor| GraphAttributes::nodeLabel| GraphAttributes::edgeLabel ); AG.setAllHeight(30.0); AG.setAllWidth(30.0); uprLayout.call(upr_bug, AG); for(node v : AG.constGraph().nodes) { int idx; idx = v->index(); if (UPR.original(v) != 0) idx = UPR.original(v)->index(); AG.label(v) = to_string(idx); if (UPR.isDummy(v)) AG.fillColor(v) = "#ff0000"; AG.y(v)=-AG.y(v); } // label the edges with their index for(edge e : AG.constGraph().edges) { AG.label(e) = to_string(e->index()); if (UPR.isSourceArc(e)) AG.strokeColor(e) = "#00ff00"; if (UPR.isSinkArc(e)) AG.strokeColor(e) = "#ff0000"; DPolyline &line = AG.bends(e); ListIterator<DPoint> it; for(it = line.begin(); it.valid(); it++) { (*it).m_y = -(*it).m_y; } } AG.writeGML("c:/temp/upr_res.gml"); //cout << "UPR_RES"; //UPR.outputFaces(UPR.getEmbedding()); //cout << "Mapping :" << endl; //for(node v : UPR.nodes) { // if (UPR.original(v) != 0) { // cout << "node UPR " << v << " node G " << UPR.original(v) << endl; // } //} // --------------------------------------------end debug */ OGDF_ASSERT(hasSingleSource(UPR)); OGDF_ASSERT(isSimple(UPR)); OGDF_ASSERT(isAcyclic(UPR)); OGDF_ASSERT(UpwardPlanarity::isUpwardPlanar_singleSource(UPR)); /* for(edge eee : UPR.original().edges) { if (UPR.isReversed(eee)) cout << endl << eee << endl; } */ return Module::retFeasible; }
void SubgraphUpwardPlanarizer::merge( const GraphCopy &GC, UpwardPlanRep &UPR_res, const GraphCopy &block, UpwardPlanRep &UPR) { node startUPR = UPR.getSuperSource()->firstAdj()->theEdge()->target(); node startRes; node startG = GC.original(block.original(UPR.original(startUPR))); bool empty = UPR_res.empty(); if (empty) { OGDF_ASSERT(startG == 0); // contruct a node in UPR_res assocciated with startUPR startRes = UPR_res.newNode(); UPR_res.m_isSinkArc.init(UPR_res, false); UPR_res.m_isSourceArc.init(UPR_res, false); UPR_res.s_hat = startRes; } else { startRes = UPR_res.copy(startG); } OGDF_ASSERT(startRes != 0); // compute the adjEntry position (in UPR_res) of the cutvertex startRes adjEntry pos = nullptr; if (!empty) { adjEntry adj_ext = nullptr, adj_int = nullptr; for(adjEntry run : startRes->adjEntries) { if (UPR_res.getEmbedding().rightFace(run) == UPR_res.getEmbedding().externalFace()) { adj_ext = run; break; } if (run->theEdge()->source() == startRes) adj_int = run; } // cutvertex is a sink in UPR_res if (adj_ext == nullptr && adj_int == nullptr) { pos = UPR_res.sinkSwitchOf(startRes); } else { if (adj_ext == nullptr) pos = adj_int; else pos = adj_ext; } OGDF_ASSERT(pos != 0); } // construct for each node (except the two super sink and the super source) of UPR a associated of UPR to UPR_res NodeArray<node> nodeUPR2UPR_res(UPR, nullptr); nodeUPR2UPR_res[startUPR] = startRes; for(node v : UPR.nodes) { // allready constructed or is super sink or super source if (v == startUPR || v == UPR.getSuperSink() || v == UPR.getSuperSink()->firstAdj()->theEdge()->source() || v == UPR.getSuperSource()) continue; node vNew; if (UPR.original(v) != nullptr ) { node vG = GC.original(block.original((UPR.original(v)))); if (vG != nullptr) vNew = UPR_res.newNode(vG); else vNew = UPR_res.newNode(); //vG is the super source } else // crossing dummy, no original node vNew = UPR_res.newNode(); nodeUPR2UPR_res[v] = vNew; } //add edges of UPR to UPR_res EdgeArray<edge> edgeUPR2UPR_res(UPR, nullptr); for(edge e : block.edges) { if (e->source()->indeg()==0) // the artificial edge with the super source continue; List<edge> chains = UPR.chain(e); edge eG = nullptr, eGC = block.original(e); eG = GC.original(eGC); OGDF_ASSERT(!chains.empty()); //construct new edges in UPR_res for(edge eChain : chains) { node tgt = nodeUPR2UPR_res[eChain->target()]; node src = nodeUPR2UPR_res[eChain->source()]; edge eNew = UPR_res.newEdge(src, tgt); edgeUPR2UPR_res[eChain] = eNew; if (UPR.isSinkArc(UPR.copy(e))) UPR_res.m_isSinkArc[eNew] = true; if (UPR.isSourceArc(UPR.copy(e))) UPR_res.m_isSourceArc[eNew] = true; if (eG == nullptr) { // edge is associated with a sink arc UPR_res.m_eOrig[eNew] = nullptr; continue; } UPR_res.m_eOrig[eNew] = eG; if (chains.size() == 1) { // e is not split UPR_res.m_eCopy[eG].pushBack(eNew); UPR_res.m_eIterator[eNew] = UPR_res.m_eCopy[eG].begin(); break; } UPR_res.m_eCopy[eG].pushBack(eNew); UPR_res.m_eIterator[eNew] = UPR_res.m_eCopy[eG].rbegin(); } } ///* //* embed the new component in UPR_res with respect to the embedding of UPR //*/ // for the cut vertex if (!empty) { adjEntry run = UPR.getAdjEntry(UPR.getEmbedding(), startUPR, UPR.getEmbedding().externalFace()); run = run->cyclicSucc(); adjEntry adjStart = run; do { if (edgeUPR2UPR_res[run->theEdge()] != nullptr) { adjEntry adj_UPR_res = edgeUPR2UPR_res[run->theEdge()]->adjSource(); UPR_res.moveAdjAfter(adj_UPR_res, pos); pos = adj_UPR_res; } run = run->cyclicSucc(); } while(run != adjStart); } for(node v : UPR.nodes) { if (v == startUPR && !empty) continue; node v_UPR_res = nodeUPR2UPR_res[v]; List<adjEntry> adj_UPR, adj_UPR_res; v->allAdjEntries(adj_UPR); // convert adj_UPR of v to adj_UPR_res of v_UPR_res for(adjEntry adj : adj_UPR) { edge e_res = edgeUPR2UPR_res[adj->theEdge()]; if (e_res == nullptr) // associated edges in UPR_res continue; adjEntry adj_res = e_res->adjSource(); if (adj_res->theNode() != v_UPR_res) adj_res = adj_res->twin(); adj_UPR_res.pushBack(adj_res); } UPR_res.sort(v_UPR_res, adj_UPR_res); } /* //---------------------------------------------------debug if (!UPR_res.empty()) { GraphAttributes GA_UPR_res(UPR_res, GraphAttributes::nodeGraphics| GraphAttributes::edgeGraphics| GraphAttributes::nodeColor| GraphAttributes::edgeColor| GraphAttributes::nodeLabel| GraphAttributes::edgeLabel ); GA_UPR_res.setAllHeight(30.0); GA_UPR_res.setAllWidth(30.0); // label the nodes with their index for(node z : GA_UPR_res.constGraph().nodes) { GA_UPR_res.label(z) = to_string(z->index()); } GA_UPR_res.writeGML("c:/temp/UPR_res_tmp.gml"); cout << "UPR_res_tmp faces:"; UPR_res.outputFaces(UPR_res.getEmbedding()); } GraphAttributes GA_UPR(UPR, GraphAttributes::nodeGraphics| GraphAttributes::edgeGraphics| GraphAttributes::nodeColor| GraphAttributes::edgeColor| GraphAttributes::nodeLabel| GraphAttributes::edgeLabel ); GA_UPR.setAllHeight(30.0); GA_UPR.setAllWidth(30.0); // label the nodes with their index for(node z : GA_UPR.constGraph().nodes) { GA_UPR.label(z) = to_string(z->index()); } GA_UPR.writeGML("c:/temp/UPR_tmp.gml"); cout << "UPR_tmp faces:"; UPR.outputFaces(UPR.getEmbedding()); //end -----------------------------------------------debug */ // update UPR_res UPR_res.initMe(); }
void UpwardPlanRep::copyMe(const UpwardPlanRep &UPR) { NodeArray<node> vCopy; EdgeArray<edge> eCopy; Graph::construct(UPR, vCopy, eCopy); // initGC m_pGraph = UPR.m_pGraph; m_vOrig.init(*this, nullptr); m_eOrig.init(*this, nullptr); m_vCopy.init(*m_pGraph, nullptr); m_eCopy.init(*m_pGraph); m_eIterator.init(*this, nullptr); for (node v : UPR.nodes) m_vOrig[vCopy[v]] = UPR.m_vOrig[v]; for (edge e : UPR.edges) m_eOrig[eCopy[e]] = UPR.m_eOrig[e]; for (node v : nodes) { node w = m_vOrig[v]; if (w != nullptr) m_vCopy[w] = v; } for(edge e : m_pGraph->edges) { ListConstIterator<edge> it; for (it = UPR.m_eCopy[e].begin(); it.valid(); ++it) m_eIterator[eCopy[*it]] = m_eCopy[e].pushBack(eCopy[*it]); } //GraphCopy::initGC(UPR,vCopy,eCopy); m_Gamma.init(*this); m_isSinkArc.init(*this, false); m_isSourceArc.init(*this, false); if (UPR.numberOfNodes() == 0) return; s_hat = vCopy[UPR.getSuperSource()]; if (UPR.augmented()) t_hat = vCopy[UPR.getSuperSink()]; OGDF_ASSERT(UPR.extFaceHandle != nullptr); edge eC = eCopy[UPR.extFaceHandle->theEdge()]; node vC = vCopy[UPR.extFaceHandle->theNode()]; if (eC->adjSource()->theNode() == vC) extFaceHandle = eC->adjSource(); else extFaceHandle = eC->adjTarget(); m_Gamma.setExternalFace(m_Gamma.rightFace(extFaceHandle)); for(edge e : UPR.edges) { edge a = eCopy[e]; if (UPR.isSinkArc(e)) m_isSinkArc[a] = true; if (UPR.isSourceArc(e)) m_isSourceArc[a] = true; } computeSinkSwitches(); }
void VisibilityLayout::layout(GraphAttributes &GA, const UpwardPlanRep &UPROrig) { UpwardPlanRep UPR = UPROrig; //clear some data for(edge e : GA.constGraph().edges) { GA.bends(e).clear(); } int minGridDist = 1; for(node v : GA.constGraph().nodes) { if (minGridDist < max(GA.height(v), GA.width(v))) minGridDist = (int) max(GA.height(v), GA.width(v)); } minGridDist = max(minGridDist*2+1, m_grid_dist); CombinatorialEmbedding &gamma = UPR.getEmbedding(); //add edge (s,t) adjEntry adjSrc = nullptr; for(adjEntry adj : UPR.getSuperSource()->adjEntries) { if (gamma.rightFace(adj) == gamma.externalFace()) adjSrc = adj; break; } OGDF_ASSERT(adjSrc != nullptr); edge e_st = UPR.newEdge(adjSrc, UPR.getSuperSink()); // on the right gamma.computeFaces(); gamma.setExternalFace(gamma.rightFace(e_st->adjSource())); constructVisibilityRepresentation(UPR); // the preliminary postion NodeArray<int> xPos(UPR); NodeArray<int> yPos(UPR); // node Position for(node v : UPR.nodes) { NodeSegment vVis = nodeToVis[v]; int x = (int) (vVis.x_l + vVis.x_r)/2 ; // median positioning xPos[v] = x; yPos[v] = vVis.y; if (UPR.original(v) != nullptr) { node vOrig = UPR.original(v); //final position GA.x(vOrig) = x * minGridDist; GA.y(vOrig) = vVis.y * minGridDist; } } //compute bendpoints for(edge e : GA.constGraph().edges) { const List<edge> &chain = UPR.chain(e); for(edge eUPR : chain) { EdgeSegment eVis = edgeToVis[eUPR]; if (chain.size() == 1) { if ((yPos[eUPR->target()] - yPos[eUPR->source()]) > 1) { DPoint p1(eVis.x*minGridDist, (yPos[eUPR->source()]+1)*minGridDist); DPoint p2(eVis.x*minGridDist, (yPos[eUPR->target()]-1)*minGridDist); GA.bends(e).pushBack(p1); if (yPos[eUPR->source()]+1 != yPos[eUPR->target()]-1) GA.bends(e).pushBack(p2); } } else { //short edge if ((yPos[eUPR->target()] - yPos[eUPR->source()]) == 1) { if (UPR.original(eUPR->target()) == nullptr) { node tgtUPR = eUPR->target(); DPoint p(xPos[tgtUPR]*minGridDist, yPos[tgtUPR]*minGridDist); GA.bends(e).pushBack(p); } } //long edge else { DPoint p1(eVis.x*minGridDist, (yPos[eUPR->source()]+1)*minGridDist); DPoint p2(eVis.x*minGridDist, (yPos[eUPR->target()]-1)*minGridDist); GA.bends(e).pushBack(p1); if (yPos[eUPR->source()]+1 != yPos[eUPR->target()]-1) GA.bends(e).pushBack(p2); if (UPR.original(eUPR->target()) == nullptr) { node tgtUPR = eUPR->target(); DPoint p(xPos[tgtUPR]*minGridDist, yPos[tgtUPR]*minGridDist); GA.bends(e).pushBack(p); } } } } DPolyline &poly = GA.bends(e); DPoint pSrc(GA.x(e->source()), GA.y(e->source())); DPoint pTgt(GA.x(e->target()), GA.y(e->target())); poly.normalize(pSrc, pTgt); } }
void VisibilityLayout::constructDualGraph(UpwardPlanRep &UPR) { CombinatorialEmbedding &gamma = UPR.getEmbedding(); faceToNode.init(gamma, nullptr); leftFace_node.init(UPR, nullptr); rightFace_node.init(UPR, nullptr); leftFace_edge.init(UPR, nullptr); rightFace_edge.init(UPR, nullptr); //construct a node for each face f for(face f : gamma.faces) { faceToNode[f] = D.newNode(); if (f == gamma.externalFace()) s_D = faceToNode[f] ; //compute face switches node s = nullptr, t = nullptr; for(adjEntry adj : f->entries) { adjEntry adjNext = adj->faceCycleSucc(); if (adjNext->theEdge()->source() == adj->theEdge()->source()) s = adjNext->theEdge()->source(); if (adjNext->theEdge()->target() == adj->theEdge()->target()) t = adjNext->theEdge()->target(); } OGDF_ASSERT(s); OGDF_ASSERT(t); //compute left and right face bool passSource = false; adjEntry adj; if (f == gamma.externalFace()) { adj = UPR.getSuperSink()->firstAdj(); if (gamma.rightFace(adj) != gamma.externalFace()) adj = adj->cyclicSucc(); } else adj = UPR.getAdjEntry(gamma, t, f); adjEntry adjBegin = adj; do { node v = adj->theEdge()->source(); if (!passSource) { if (v != s) leftFace_node[v] = f; leftFace_edge[adj->theEdge()] = f; } else { if (v != s) rightFace_node[v] = f; rightFace_edge[adj->theEdge()] = f; } if (adj->theEdge()->source() == s) passSource = true; adj = adj->faceCycleSucc(); } while(adj != adjBegin); } t_D = D.newNode(); // the second (right) node associated with the external face //construct dual edges for(edge e : UPR.edges) { face f_r = rightFace_edge[e]; face f_l = leftFace_edge[e]; node u = faceToNode[f_l]; node v = faceToNode[f_r]; if (f_r == gamma.externalFace() || f_r == f_l) D.newEdge(u, t_D); else D.newEdge(u,v); } OGDF_ASSERT(isConnected(D)); }
void DominanceLayout::layout(GraphAttributes &GA, const UpwardPlanRep &UPROrig) { UpwardPlanRep UPR = UPROrig; //clear some data for(edge e : GA.constGraph().edges) { GA.bends(e).clear(); } //compute and splite transitiv edges List<edge> splitMe; findTransitiveEdges(UPR, splitMe); for(edge eSplit : splitMe) { UPR.getEmbedding().split(eSplit); } // set up first-/lastout, first-/lastin firstout.init(UPR, nullptr); lastout.init(UPR, nullptr); firstin.init(UPR, nullptr); lastin.init(UPR, nullptr); node s = UPR.getSuperSource(); node t = UPR.getSuperSink(); firstout[t] = lastout[t] = nullptr; firstin[s] = lastin[s] = nullptr; firstin[t] = lastin[t] =t->firstAdj()->theEdge(); adjEntry adjRun = s->firstAdj(); while (UPR.getEmbedding().rightFace(adjRun) != UPR.getEmbedding().externalFace()) { adjRun = adjRun->cyclicSucc(); } lastout[s] = adjRun->theEdge(); firstout[s] = adjRun->cyclicSucc()->theEdge(); for(node v : UPR.nodes) { if (v == t || v == s) continue; adjEntry adj = UPR.leftInEdge(v); firstin[v] = adj->theEdge(); firstout[v] = adj->cyclicSucc()->theEdge(); adjEntry adjRightIn = adj; while (adjRightIn->cyclicPred()->theEdge()->source() != v) adjRightIn = adjRightIn->cyclicPred(); lastin[v] = adjRightIn->theEdge(); lastout[v] = adjRightIn->cyclicPred()->theEdge(); } //compute m_L and m_R for min. area drawing m_L = 0; m_R = 0; for(edge e : UPR.edges) { node src = e->source(); node tgt = e->target(); if (lastin[tgt] == e && firstout[src] == e) m_L++; if (firstin[tgt] == e && lastout[src] == e) m_R++; } // compute preleminary coordinate xPreCoord.init(UPR); yPreCoord.init(UPR); int count = 0; labelX(UPR, s, count); count = 0; labelY(UPR, s, count); // compaction compact(UPR, GA); // map coordinate to GA for(node v : GA.constGraph().nodes) { node vUPR = UPR.copy(v); GA.x(v) = xCoord[vUPR]; GA.y(v) = yCoord[vUPR]; } // add bends to original edges for(edge e : GA.constGraph().edges) { const List<edge> &chain = UPR.chain(e); for(edge eChain : chain) { node tgtUPR = eChain->target(); if (tgtUPR != chain.back()->target()) { DPoint p(xCoord[tgtUPR], yCoord[tgtUPR]); GA.bends(e).pushBack(p); } } } //rotate the drawing for(node v : GA.constGraph().nodes) { double r = sqrt(GA.x(v)*GA.x(v) + GA.y(v)*GA.y(v)); if (r == 0) continue; double alpha = asin(GA.y(v)/r); double yNew = sin(alpha + m_angle)*r; double xNew = cos(alpha + m_angle)*r; GA.x(v) = xNew; GA.y(v) = yNew; } for(edge e : GA.constGraph().edges) { DPolyline &poly = GA.bends(e); DPoint pSrc(GA.x(e->source()), GA.y(e->source())); DPoint pTgt(GA.x(e->target()), GA.y(e->target())); poly.normalize(pSrc, pTgt); for(DPoint &p : poly) { double r = p.distance(DPoint(0,0)); if (r == 0) continue; double alpha = asin( p.m_y/r); double yNew = sin(alpha + m_angle)*r; double xNew = cos(alpha + m_angle)*r; p.m_x = xNew; p.m_y = yNew; } } }