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 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; } } }