6 * $Date: 2012-07-07 17:14:54 +0200 (Sa, 07. Jul 2012) $
7 ***************************************************************/
10 * \brief Computes an embedding of a graph with minimum depth.
11 * See paper "Graph Embedding with Minimum Depth and Maximum External
12 * Face" by C. Gutwenger and P. Mutzel (2004) for details.
14 * \author Thorsten Kerkhof
17 * This file is part of the Open Graph Drawing Framework (OGDF).
21 * See README.txt in the root directory of the OGDF installation for details.
24 * This program is free software; you can redistribute it and/or
25 * modify it under the terms of the GNU General Public License
26 * Version 2 or 3 as published by the Free Software Foundation;
27 * see the file LICENSE.txt included in the packaging of this file
31 * This program is distributed in the hope that it will be useful,
32 * but WITHOUT ANY WARRANTY; without even the implied warranty of
33 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
34 * GNU General Public License for more details.
37 * You should have received a copy of the GNU General Public
38 * License along with this program; if not, write to the Free
39 * Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
40 * Boston, MA 02110-1301, USA.
42 * \see http://www.gnu.org/copyleft/gpl.html
43 ***************************************************************/
45 #include <ogdf/planarity/EmbedderMinDepth.h>
46 #include <ogdf/internal/planarity/EmbedderMaxFaceBiconnectedGraphs.h>
47 #include <ogdf/internal/planarity/ConnectedSubgraph.h>
51 void EmbedderMinDepth::call(Graph
& G
, adjEntry
& adjExternal
)
54 pAdjExternal
= &adjExternal
;
57 if (G
.numberOfNodes() <= 1)
60 if (G
.numberOfEdges() == 1)
62 edge e
= G
.firstEdge();
63 adjExternal
= e
->adjSource();
67 //HINT: Edges are directed from child to parent in BC-trees
68 pBCTree
= new BCTree(G
);
70 //base case of biconnected graph:
71 if (pBCTree
->bcTree().numberOfNodes() == 1)
73 NodeArray
<int> m_nodeLength(G
, 0);
74 EdgeArray
<int> m_edgeLength(G
, 0);
75 adjEntry m_adjExternal
;
76 EmbedderMaxFaceBiconnectedGraphs
<int>::embed(G
, m_adjExternal
, m_nodeLength
, m_edgeLength
);
77 adjExternal
= m_adjExternal
->twin();
84 //***************************************************************************/
85 //First step: calculate min depth and node lengths
86 //***************************************************************************/
87 //Find root Block (only node with out-degree of 0):
90 forall_nodes(n
, pBCTree
->bcTree())
99 //compute block graphs:
100 blockG
.init(pBCTree
->bcTree());
101 nBlockEmbedding_to_nH
.init(pBCTree
->bcTree());
102 eBlockEmbedding_to_eH
.init(pBCTree
->bcTree());
103 nH_to_nBlockEmbedding
.init(pBCTree
->bcTree());
104 eH_to_eBlockEmbedding
.init(pBCTree
->bcTree());
105 nodeLength
.init(pBCTree
->bcTree());
106 spqrTrees
.init(pBCTree
->bcTree(),0);
107 computeBlockGraphs(rootBlockNode
, 0);
109 //Edge lengths of BC-tree, values m_{c, B} for all (c, B) \in bcTree:
110 m_cB
.init(pBCTree
->bcTree(), 0);
112 //Bottom-up traversal: (set m_cB for all {c, B} \in bcTree)
113 nodeLength
[rootBlockNode
].init(blockG
[rootBlockNode
], 0);
115 forall_adj_edges(e
, rootBlockNode
)
117 node cT
= e
->source();
118 //node cH = pBCTree->cutVertex(cT, rootBlockNode);
120 //set length of c in block graph of root block node:
122 forall_adj_edges(e2
, cT
)
124 if (e2
->target() != cT
)
127 node blockNode
= e2
->source();
128 node cutVertex
= pBCTree
->cutVertex(cT
, blockNode
);
131 m_cB
[e2
] = bottomUpTraversal(blockNode
, cutVertex
);
135 //Top-down traversal: (set m_cB for all {B, c} \in bcTree and get min depth
137 int maxint
= 2147483647;
138 minDepth
.init(pBCTree
->bcTree(), maxint
);
139 M_B
.init(pBCTree
->bcTree());
140 M2
.init(pBCTree
->bcTree());
141 topDownTraversal(rootBlockNode
);
146 forall_nodes(n
, pBCTree
->bcTree())
148 if (pBCTree
->typeOfBNode(n
) != BCTree::BComp
)
150 if (minDepth
[n
] < depth
)
157 //****************************************************************************
158 //Second step: Embed G by expanding a maximum face in bT_opt
159 //****************************************************************************
161 treeNodeTreated
.init(pBCTree
->bcTree(), false);
165 G
.sort(n
, newOrder
[n
]);
167 forall_nodes(n
, pBCTree
->bcTree())
174 void EmbedderMinDepth::computeBlockGraphs(const node
& bT
, const node
& cH
)
178 forall_adj_edges(e
, bT
)
180 if (e
->source() == bT
)
183 node cT
= e
->source();
185 forall_adj_edges(e2
, cT
)
187 if (e2
->source() == cT
)
189 node cH2
= pBCTree
->cutVertex(cT
, e2
->source());
190 computeBlockGraphs(e2
->source(), cH2
);
197 m_cH
= pBCTree
->cutVertex(bT
->firstAdj()->twinNode(), bT
);
198 ConnectedSubgraph
<int>::call(pBCTree
->auxiliaryGraph(), blockG
[bT
], m_cH
,
199 nBlockEmbedding_to_nH
[bT
], eBlockEmbedding_to_eH
[bT
],
200 nH_to_nBlockEmbedding
[bT
], eH_to_eBlockEmbedding
[bT
]);
202 if ( !blockG
[bT
].empty()
203 && blockG
[bT
].numberOfNodes() != 1
204 && blockG
[bT
].numberOfEdges() > 2)
206 spqrTrees
[bT
] = new StaticSPQRTree(blockG
[bT
]);
211 int EmbedderMinDepth::bottomUpTraversal(const node
& bT
, const node
& cH
)
213 int m_B
= 0; //max_{c \in B} m_B(c)
214 List
<node
> M_B
; //{c \in B | m_B(c) = m_B}
218 forall_adj_edges(e
, bT
)
220 if (e
->target() != bT
)
222 node cT
= e
->source();
223 //node c_in_bT = pBCTree->cutVertex(cT, bT);
225 //set length of c in block graph of root block node:
227 forall_adj_edges(e_cT_bT2
, cT
)
232 node bT2
= e_cT_bT2
->source();
233 node c_in_bT2
= pBCTree
->cutVertex(cT
, bT2
);
234 m_cB
[e_cT_bT2
] = bottomUpTraversal(bT2
, c_in_bT2
);
236 //update m_B and M_B:
237 if (m_B
< m_cB
[e_cT_bT2
])
239 node cV_in_bT
= pBCTree
->cutVertex(cT
, bT
);
240 m_B
= m_cB
[e_cT_bT2
];
242 M_B
.pushBack(cV_in_bT
);
244 else if (m_B
== m_cB
[e_cT_bT2
] && M_B
.search(pBCTree
->cutVertex(cT
, bT
)) == -1)
246 node cV_in_bT
= pBCTree
->cutVertex(cT
, bT
);
247 M_B
.pushBack(cV_in_bT
);
252 //set vertex length for all vertices in bH to 1 if vertex is in M_B:
253 nodeLength
[bT
].init(blockG
[bT
], 0);
254 for (ListIterator
<node
> iterator
= M_B
.begin(); iterator
.valid(); iterator
++)
255 nodeLength
[bT
][nH_to_nBlockEmbedding
[bT
][*iterator
]] = 1;
261 //set edge length for all edges in block graph to 0:
262 EdgeArray
<int> edgeLength(blockG
[bT
], 0);
264 //compute maximum external face of block graph and get its size:
265 int cstrLength_B_c
= EmbedderMaxFaceBiconnectedGraphs
<int>::computeSize(
267 nH_to_nBlockEmbedding
[bT
][cH
],
272 if (cstrLength_B_c
== M_B
.size())
279 void EmbedderMinDepth::topDownTraversal(const node
& bT
)
281 //m_B(c) = max {0} \cup {m_{c, B'} | c \in B', B' \neq B}
282 int m_B
= 0; //max_{c \in B} m_B(c)
284 //Compute m_B and M_B:
288 forall_adj_edges(e_bT_cT
, bT
)
290 if (e_bT_cT
->source() == bT
)
291 cT_parent
= e_bT_cT
->target();
292 node cT
= (e_bT_cT
->source() == bT
) ? e_bT_cT
->target() : e_bT_cT
->source();
294 forall_adj_edges(e_cT_bT2
, cT
)
296 if (e_cT_bT2
== e_bT_cT
)
299 //update m_B and M_B:
300 if (m_B
< m_cB
[e_cT_bT2
])
302 m_B
= m_cB
[e_cT_bT2
];
304 M_B
[bT
].pushBack(pBCTree
->cutVertex(cT
, bT
));
306 else if ( m_B
== m_cB
[e_cT_bT2
] && M_B
[bT
].search(pBCTree
->cutVertex(cT
, bT
)) == -1)
308 M_B
[bT
].pushBack(pBCTree
->cutVertex(cT
, bT
));
310 }//forall_adj_edges(e_cT_bT2, cT)
311 }//forall_adj_edges(e_bT_cT, bT)
313 //set vertex length for all vertices in bH to 1 if vertex is in M_B:
314 nodeLength
[bT
].fill(0);
315 NodeArray
<int> m_nodeLength(blockG
[bT
], 0);
316 for (ListIterator
<node
> iterator
= M_B
[bT
].begin(); iterator
.valid(); iterator
++)
318 nodeLength
[bT
][nH_to_nBlockEmbedding
[bT
][*iterator
]] = 1;
319 m_nodeLength
[nH_to_nBlockEmbedding
[bT
][*iterator
]] = 1;
322 //set edge length for all edges in block graph to 0:
323 EdgeArray
<int> edgeLengthBlock(blockG
[bT
], 0);
325 //compute size of a maximum external face of block graph:
326 NodeArray
< EdgeArray
<int> > edgeLengthSkel
;
327 int cstrLength_B_c
= EmbedderMaxFaceBiconnectedGraphs
<int>::computeSize(
334 //Prepare recursion by setting m_{c, B} for all edges {B, c} \in bcTree:
335 if (M_B
[bT
].size() > 0)
337 node cT1
= pBCTree
->bcproper(pBCTree
->original(*(M_B
[bT
].begin())));
338 bool calculateNewNodeLengths
;
339 if (M_B
[bT
].size() == 1 && cT1
== cT_parent
)
340 calculateNewNodeLengths
= true;
342 calculateNewNodeLengths
= false;
343 forall_adj_edges(e_bT_cT
, bT
)
345 if (e_bT_cT
->target() != bT
)
347 node cT
= e_bT_cT
->source();
348 node cH
= pBCTree
->cutVertex(cT
, bT
);
350 if (M_B
[bT
].size() == 1 && cT1
== cT
)
352 //Compute new vertex lengths according to
353 //m2 = max_{v \in V_B, v != c} m_B(v) and
354 //M2 = {c \in V_B \ {v} | m_B(c) = m2}.
359 forall_adj_edges(e_bT_cT2
, bT
)
361 node cT2
= (e_bT_cT2
->source() == bT
) ? e_bT_cT2
->target() : e_bT_cT2
->source();
365 forall_adj_edges(e_cT2_bT2
, cT2
)
367 if (e_cT2_bT2
== e_bT_cT2
)
370 //update m_B and M_B:
371 if (m2
< m_cB
[e_cT2_bT2
])
373 m2
= m_cB
[e_cT2_bT2
];
375 M2
[bT
].pushBack(pBCTree
->cutVertex(cT2
, bT
));
377 else if ( m2
== m_cB
[e_cT2_bT2
] && M2
[bT
].search(pBCTree
->cutVertex(cT2
, bT
)) == -1)
379 M2
[bT
].pushBack(pBCTree
->cutVertex(cT2
, bT
));
381 }//forall_adj_edges(e_cT2_bT2, cT2)
382 }//forall_adj_edges(e_bT_cT2, bT)
384 //set vertex length for all vertices in bH to 1 if vertex is in M2 and
386 nodeLength
[bT
][nH_to_nBlockEmbedding
[bT
][*(M_B
[bT
].begin())]] = 0;
387 for (ListIterator
<node
> iterator
= M2
[bT
].begin(); iterator
.valid(); iterator
++)
388 nodeLength
[bT
][nH_to_nBlockEmbedding
[bT
][*iterator
]] = 1;
390 //set edge length for all edges in block graph to 0:
391 EdgeArray
<int> edgeLength(blockG
[bT
], 0);
393 //compute a maximum external face size of a face containing c in block graph:
394 int maxFaceSize
= EmbedderMaxFaceBiconnectedGraphs
<int>::computeSize(
396 nH_to_nBlockEmbedding
[bT
][cH
],
400 if (M2
[bT
].size() == 0)
404 if (maxFaceSize
== M2
[bT
].size())
407 m_cB
[e_bT_cT
] = m2
+ 2;
410 if (calculateNewNodeLengths
)
411 calculateNewNodeLengths
= false;
414 //reset node lengths:
415 for (ListIterator
<node
> iterator
= M2
[bT
].begin(); iterator
.valid(); iterator
++)
416 nodeLength
[bT
][nH_to_nBlockEmbedding
[bT
][*iterator
]] = 0;
417 nodeLength
[bT
][nH_to_nBlockEmbedding
[bT
][*(M_B
[bT
].begin())]] = 1;
420 else //M_B.size() != 1
422 //Compute a maximum face in block B containing c using the vertex lengths
425 //set edge length for all edges in block graph to 0:
426 EdgeArray
<int> edgeLength(blockG
[bT
], 0);
428 //compute a maximum external face size of a face containing c in block graph:
429 int maxFaceSize
= EmbedderMaxFaceBiconnectedGraphs
<int>::computeSize(
431 nH_to_nBlockEmbedding
[bT
][cH
],
436 if (M_B
[bT
].size() == 0)
440 if (maxFaceSize
== M_B
[bT
].size())
443 m_cB
[e_bT_cT
] = m_B
+ 2;
446 }//forall_adj_edges(e_bT_cT, bT)
448 if (calculateNewNodeLengths
)
450 //Compute new vertex lengths according to
451 //m2 = max_{v \in V_B, v != c} m_B(v) and
452 //M2 = {c \in V_B \ {v} | m_B(c) = m2}.
457 forall_adj_edges(e_bT_cT2
, bT
)
459 node cT2
= (e_bT_cT2
->source() == bT
) ? e_bT_cT2
->target() : e_bT_cT2
->source();
463 forall_adj_edges(e_cT2_bT2
, cT2
)
465 if (e_cT2_bT2
== e_bT_cT2
)
468 //update m_B and M_B:
469 if (m2
< m_cB
[e_cT2_bT2
])
471 m2
= m_cB
[e_cT2_bT2
];
473 M2
[bT
].pushBack(pBCTree
->cutVertex(cT2
, bT
));
475 else if ( m2
== m_cB
[e_cT2_bT2
] && M2
[bT
].search(pBCTree
->cutVertex(cT2
, bT
)) == -1)
477 M2
[bT
].pushBack(pBCTree
->cutVertex(cT2
, bT
));
479 }//forall_adj_edges(e_cT2_bT2, cT2)
480 }//forall_adj_edges(e_bT_cT2, bT)
482 //set vertex length for all vertices in bH to 1 if vertex is in M2 and
484 nodeLength
[bT
][nH_to_nBlockEmbedding
[bT
][*(M_B
[bT
].begin())]] = 0;
485 for (ListIterator
<node
> iterator
= M2
[bT
].begin(); iterator
.valid(); iterator
++)
486 nodeLength
[bT
][nH_to_nBlockEmbedding
[bT
][*iterator
]] = 1;
487 } //if (calculateNewNodeLengths
488 else if (M_B
[bT
].size() == 1)
490 //Compute M2 = {c \in V_B \ {v} | m_B(c) = m2} with
491 //m2 = max_{v \in V_B, v != c} m_B(v).
494 forall_adj_edges(e_bT_cT2
, bT
)
496 node cT2
= (e_bT_cT2
->source() == bT
) ? e_bT_cT2
->target() : e_bT_cT2
->source();
500 forall_adj_edges(e_cT2_bT2
, cT2
)
502 if (e_cT2_bT2
== e_bT_cT2
)
505 //update m_B and M_B:
506 if (m2
< m_cB
[e_cT2_bT2
])
508 m2
= m_cB
[e_cT2_bT2
];
510 M2
[bT
].pushBack(pBCTree
->cutVertex(cT2
, bT
));
512 else if ( m2
== m_cB
[e_cT2_bT2
] && M2
[bT
].search(pBCTree
->cutVertex(cT2
, bT
)) == -1)
514 M2
[bT
].pushBack(pBCTree
->cutVertex(cT2
, bT
));
516 }//forall_adj_edges(e_cT2_bT2, cT2)
517 }//forall_adj_edges(e_bT_cT2, bT)
522 forall_adj_edges(e_bT_cT
, bT
)
524 if (e_bT_cT
->target() != bT
)
527 node cT
= e_bT_cT
->source();
529 forall_adj_edges(e_cT_bT2
, cT
)
531 if (e_cT_bT2
== e_bT_cT
)
534 topDownTraversal(e_cT_bT2
->source());
538 //Compute M_B and M2 for embedBlock-function:
544 forall_adj_edges(e_bT_cT
, bT
)
546 node cT
= (e_bT_cT
->source() == bT
) ? e_bT_cT
->target() : e_bT_cT
->source();
548 forall_adj_edges(e_cT_bT2
, cT
)
550 if (e_bT_cT
== e_cT_bT2
)
553 //update m_B and M_B:
554 if (m_B
< m_cB
[e_cT_bT2
])
556 m_B
= m_cB
[e_cT_bT2
];
558 M_B
[bT
].pushBack(pBCTree
->cutVertex(cT
, bT
));
560 else if ( m_B
== m_cB
[e_cT_bT2
] && M_B
[bT
].search(pBCTree
->cutVertex(cT
, bT
)) == -1)
562 M_B
[bT
].pushBack(pBCTree
->cutVertex(cT
, bT
));
564 }//forall_adj_edges(e_cT_bT2, cT)
565 }//forall_adj_edges(e_bT_cT, bT)
567 if (M_B
[bT
].size() == 1)
569 node cT1
= pBCTree
->bcproper(pBCTree
->original(*(M_B
[bT
].begin())));
570 forall_adj_edges(e_bT_cT
, bT
)
572 node cT2
= (e_bT_cT
->source() == bT
) ? e_bT_cT
->target() : e_bT_cT
->source();
575 node cT
= (e_bT_cT
->source() == bT
) ? e_bT_cT
->target() : e_bT_cT
->source();
577 forall_adj_edges(e_cT_bT2
, cT
)
580 if (m2
< m_cB
[e_cT_bT2
])
584 M2
[bT
].pushBack(pBCTree
->cutVertex(cT
, bT
));
586 else if ( m2
== m_cB
[e_cT_bT2
]
587 && M2
[bT
].search(pBCTree
->cutVertex(cT
, bT
)) == -1)
589 M2
[bT
].pushBack(pBCTree
->cutVertex(cT
, bT
));
591 }//forall_adj_edges(e_cT_bT2, cT)
592 }//forall_adj_edges(e_bT_cT, bT)
596 if (cstrLength_B_c
== M_B
[bT
].size())
599 minDepth
[bT
] = m_B
+ 2;
603 void EmbedderMinDepth::embedBlock(const node
& bT
)
605 ListIterator
<adjEntry
> after
;
607 embedBlock(bT
, cT
, after
);
611 void EmbedderMinDepth::embedBlock(
614 ListIterator
<adjEntry
>& after
)
616 treeNodeTreated
[bT
] = true;
619 cH
= pBCTree
->cutVertex(cT
, bT
);
621 //***************************************************************************
622 // 1. Compute node lengths depending on M_B, M2 and cT
623 //***************************************************************************
624 nodeLength
[bT
].fill(0);
625 if (!(cT
== 0) && M_B
[bT
].size() == 1 && *(M_B
[bT
].begin()) == cH
)
627 //set node length to 1 if node is in M2 and 0 otherwise
628 for (ListIterator
<node
> iterator
= M2
[bT
].begin(); iterator
.valid(); iterator
++)
629 nodeLength
[bT
][nH_to_nBlockEmbedding
[bT
][*iterator
]] = 1;
633 //set node length to 1 if node is in M_B and 0 otherwise
634 for (ListIterator
<node
> iterator
= M_B
[bT
].begin(); iterator
.valid(); iterator
++)
635 nodeLength
[bT
][nH_to_nBlockEmbedding
[bT
][*iterator
]] = 1;
638 //***************************************************************************
639 // 2. Compute embedding of block
640 //***************************************************************************
641 EdgeArray
<int> edgeLength(blockG
[bT
], 0);
642 adjEntry m_adjExternal
= 0;
644 EmbedderMaxFaceBiconnectedGraphs
<int>::embed(blockG
[bT
], m_adjExternal
, nodeLength
[bT
], edgeLength
);
646 EmbedderMaxFaceBiconnectedGraphs
<int>::embed(blockG
[bT
], m_adjExternal
, nodeLength
[bT
], edgeLength
,
647 nH_to_nBlockEmbedding
[bT
][cH
]);
649 //***************************************************************************
650 // 3. Copy block embedding into graph embedding and call recursively
651 // embedBlock for all cut vertices in bT
652 //***************************************************************************
653 CombinatorialEmbedding
CE(blockG
[bT
]);
654 face f
= CE
.leftFace(m_adjExternal
);
656 if (*pAdjExternal
== 0)
658 node on
= pBCTree
->original(nBlockEmbedding_to_nH
[bT
][m_adjExternal
->theNode()]);
659 adjEntry ae1
= on
->firstAdj();
660 for (adjEntry ae
= ae1
; ae
; ae
= ae
->succ())
662 if (ae
->theEdge() == pBCTree
->original(eBlockEmbedding_to_eH
[bT
][m_adjExternal
->theEdge()]))
664 *pAdjExternal
= ae
->twin();
671 forall_nodes(nSG
, blockG
[bT
])
673 node nH
= nBlockEmbedding_to_nH
[bT
][nSG
];
674 node nG
= pBCTree
->original(nH
);
675 adjEntry ae
= nSG
->firstAdj();
676 ListIterator
<adjEntry
>* pAfter
;
677 if (pBCTree
->bcproper(nG
) == cT
)
680 pAfter
= OGDF_NEW ListIterator
<adjEntry
>();
682 if (pBCTree
->typeOfGNode(nG
) == BCTree::CutVertex
)
684 node cT2
= pBCTree
->bcproper(nG
);
685 bool no_recursion
= false;
688 node parent_bT_of_cT2
;
690 forall_adj_edges(e_cT2_to_bT2
, cT2
)
692 if (e_cT2_to_bT2
->source() == cT2
)
694 parent_bT_of_cT2
= e_cT2_to_bT2
->target();
698 if (treeNodeTreated
[parent_bT_of_cT2
])
704 //find adjacency entry of nSG which lies on external face f:
705 adjEntry aeFace
= f
->firstAdj();
708 if (aeFace
->theNode() == nSG
)
713 ae
= nSG
->firstAdj();
716 aeFace
= aeFace
->faceCycleSucc();
717 } while(aeFace
!= f
->firstAdj());
721 //(if exists) find adjacency entry of nSG which lies on external face f:
722 //bool aeExtExists = false;
723 adjEntry aeFace
= f
->firstAdj();
724 //List<edge> extFaceEdges;
727 //extFaceEdges.pushBack(aeFace->theEdge());
728 if (aeFace
->theNode() == nSG
)
733 ae
= nSG
->firstAdj();
734 //aeExtExists = true;
737 aeFace
= aeFace
->faceCycleSucc();
738 } while(aeFace
!= f
->firstAdj());
743 forall_adj_edges(e_cT2_to_bT2
, cT2
)
746 if (e_cT2_to_bT2
->source() == cT2
)
747 bT2
= e_cT2_to_bT2
->target();
749 bT2
= e_cT2_to_bT2
->source();
750 if (!treeNodeTreated
[bT2
])
751 embedBlock(bT2
, cT2
, *pAfter
);
756 // //cannot embed block into external face, so find a face with an adjacent
757 // //edge of the external face:
758 // bool foundIt = false;
760 // forall_adj_edges(adjEdge, nSG)
762 // face m_f = CE.leftFace(adjEdge->adjSource());
763 // adjEntry aeF = m_f->firstAdj();
766 // if (extFaceEdges.search(aeF->theEdge()) != -1)
768 // ae = adjEdge->adjSource();
772 // aeF = aeF->faceCycleSucc();
773 // } while(aeF != m_f->firstAdj());
781 //embed all edges of block bT:
782 bool after_ae
= true;
783 for (adjEntry aeNode
= ae
;
784 after_ae
|| aeNode
!= ae
;
785 after_ae
= (!after_ae
|| !aeNode
->succ()) ? false : true,
786 aeNode
= aeNode
->succ() ? aeNode
->succ() : nSG
->firstAdj())
788 edge eG
= pBCTree
->original(eBlockEmbedding_to_eH
[bT
][aeNode
->theEdge()]);
789 if (nG
== eG
->source())
791 if (!pAfter
->valid())
792 *pAfter
= newOrder
[nG
].pushBack(eG
->adjSource());
794 *pAfter
= newOrder
[nG
].insertAfter(eG
->adjSource(), *pAfter
);
796 else //!(nG == eG->source())
798 if (!pAfter
->valid())
799 *pAfter
= newOrder
[nG
].pushBack(eG
->adjTarget());
801 *pAfter
= newOrder
[nG
].insertAfter(eG
->adjTarget(), *pAfter
);
803 } //for (adjEntry aeNode = ae; aeNode; aeNode = aeNode->succ())
805 if (!(*pAfter
== after
))
807 } //forall_nodes(nSG, blockG[bT])
810 } // end namespace ogdf