void DynamicSPQRForest::createSPQR (node vB) const { Graph GC; NodeArray<node> origNode(GC,0); EdgeArray<edge> origEdge(GC,0); SListConstIterator<edge> iH; for (iH=m_bNode_hEdges[vB].begin(); iH.valid(); ++iH) m_htogc[(*iH)->source()] = m_htogc[(*iH)->target()] = 0; for (iH=m_bNode_hEdges[vB].begin(); iH.valid(); ++iH) { edge eH = *iH; node sH = eH->source(); node tH = eH->target(); node& sGC = m_htogc[sH]; node& tGC = m_htogc[tH]; if (!sGC) { sGC = GC.newNode(); origNode[sGC] = sH; } if (!tGC) { tGC = GC.newNode(); origNode[tGC] = tH; } origEdge[GC.newEdge(sGC,tGC)] = eH; } TricComp tricComp(GC); const GraphCopySimple& GCC = *tricComp.m_pGC; EdgeArray<node> partnerNode(GCC,0); EdgeArray<edge> partnerEdge(GCC,0); for (int i=0; i<tricComp.m_numComp; ++i) { const TricComp::CompStruct &C = tricComp.m_component[i]; if (C.m_edges.empty()) continue; node vT = m_T.newNode(); m_tNode_owner[vT] = vT; switch(C.m_type) { case TricComp::bond: m_tNode_type[vT] = PComp; m_bNode_numP[vB]++; break; case TricComp::polygon: m_tNode_type[vT] = SComp; m_bNode_numS[vB]++; break; case TricComp::triconnected: m_tNode_type[vT] = RComp; m_bNode_numR[vB]++; break; } for (ListConstIterator<edge> iGCC=C.m_edges.begin(); iGCC.valid(); ++iGCC) { edge eGCC = *iGCC; edge eH = GCC.original(eGCC); if (eH) eH = origEdge[eH]; else { node uH = origNode[GCC.original(eGCC->source())]; node vH = origNode[GCC.original(eGCC->target())]; eH = m_H.newEdge(uH,vH); if (!partnerNode[eGCC]) { partnerNode[eGCC] = vT; partnerEdge[eGCC] = eH; } else { m_T.newEdge(partnerNode[eGCC],vT); m_hEdge_twinEdge[eH] = partnerEdge[eGCC]; m_hEdge_twinEdge[partnerEdge[eGCC]] = eH; } } m_hEdge_position[eH] = m_tNode_hEdges[vT].pushBack(eH); m_hEdge_tNode[eH] = vT; } } m_bNode_SPQR[vB] = m_hEdge_tNode[origEdge[GC.firstEdge()]]; m_tNode_hRefEdge[m_bNode_SPQR[vB]] = 0; SList<node> lT; lT.pushBack(m_bNode_SPQR[vB]); lT.pushBack(0); while (!lT.empty()) { node vT = lT.popFrontRet(); node wT = lT.popFrontRet(); for (ListConstIterator<edge> iH=m_tNode_hEdges[vT].begin(); iH.valid(); ++iH) { edge eH = *iH; edge fH = m_hEdge_twinEdge[eH]; if (!fH) continue; node uT = m_hEdge_tNode[fH]; if (uT==wT) m_tNode_hRefEdge[vT] = eH; else { lT.pushBack(uT); lT.pushBack(vT); } } } }
void StaticSPQRTree::init(edge eRef, TricComp &tricComp) { m_cpV = nullptr; const GraphCopySimple &GC = *tricComp.m_pGC; m_type.init(m_tree,SNode); m_sk.init(m_tree,nullptr); m_skEdgeSrc.init(m_tree,nullptr); m_skEdgeTgt.init(m_tree,nullptr); NodeArray<node> mapV(GC,nullptr); BoundedStack<node> inMapV(GC.numberOfNodes()); EdgeArray<node> partnerNode(GC,nullptr); EdgeArray<edge> partnerEdge(GC,nullptr); m_numS = m_numP = m_numR = 0; for (int i = 0; i < tricComp.m_numComp; i++) { const TricComp::CompStruct &C = tricComp.m_component[i]; if (C.m_edges.empty()) continue; node vT = m_tree.newNode(); switch(C.m_type) { case TricComp::bond: m_type[vT] = PNode; m_numP++; break; case TricComp::polygon: m_type[vT] = SNode; m_numS++; break; case TricComp::triconnected: m_type[vT] = RNode; m_numR++; break; } m_sk[vT] = OGDF_NEW StaticSkeleton(this,vT); StaticSkeleton &S = *m_sk[vT]; for(edge e : C.m_edges) { edge eG = GC.original(e); node uGC = e->source(), vGC = e->target(); node uM = mapV[uGC], vM = mapV[vGC]; if (uM == nullptr) { uM = mapV[uGC] = S.m_M.newNode(); inMapV.push(uGC); S.m_orig[uM] = GC.original(uGC); } if (vM == nullptr) { vM = mapV[vGC] = S.m_M.newNode(); inMapV.push(vGC); S.m_orig[vM] = GC.original(vGC); } // normalize direction of virtual edges if(eG == nullptr && GC.original(vGC) < GC.original(uGC)) swap(uM,vM); edge eM = S.m_M.newEdge(uM,vM); if (eG == nullptr) { if (partnerNode[e] == nullptr) { partnerNode[e] = vT; partnerEdge[e] = eM; } else { edge eT = m_tree.newEdge(partnerNode[e],vT); StaticSkeleton &pS = *m_sk[partnerNode[e]]; pS.m_treeEdge[partnerEdge[e]] = S.m_treeEdge[eM] = eT; m_skEdgeSrc[eT] = partnerEdge[e]; m_skEdgeTgt[eT] = eM; } } else { S.m_real[eM] = eG; m_copyOf[eG] = eM; if (eG->source() != S.original(eM->source())) S.m_M.reverseEdge(eM); m_skOf [eG] = &S; } } while(!inMapV.empty()) mapV[inMapV.pop()] = nullptr; } rootTreeAt(eRef); }