6 * $Date: 2012-07-07 17:14:54 +0200 (Sa, 07. Jul 2012) $
7 ***************************************************************/
10 * \brief Implementation of FixedEmbeddingUpwardInserter class.
12 * \author Hoi-Ming Wong
15 * This file is part of the Open Graph Drawing Framework (OGDF).
19 * See README.txt in the root directory of the OGDF installation for details.
22 * This program is free software; you can redistribute it and/or
23 * modify it under the terms of the GNU General Public License
24 * Version 2 or 3 as published by the Free Software Foundation;
25 * see the file LICENSE.txt included in the packaging of this file
29 * This program is distributed in the hope that it will be useful,
30 * but WITHOUT ANY WARRANTY; without even the implied warranty of
31 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
32 * GNU General Public License for more details.
35 * You should have received a copy of the GNU General Public
36 * License along with this program; if not, write to the Free
37 * Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
38 * Boston, MA 02110-1301, USA.
40 * \see http://www.gnu.org/copyleft/gpl.html
41 ***************************************************************/
43 #include <ogdf/basic/Queue.h>
44 #include <ogdf/basic/BinaryHeap.h>
45 #include <ogdf/basic/simple_graph_alg.h>
46 #include <ogdf/upward/UpwardPlanRep.h>
47 #include <ogdf/upward/FixedEmbeddingUpwardEdgeInserter.h>
51 #include <ogdf/upward/LayerBasedUPRLayout.h>
56 Module::ReturnType
FixedEmbeddingUpwardEdgeInserter::doCall(
58 const List
<edge
> &origEdges
,
59 const EdgeArray
<int> *costOrig
,
60 const EdgeArray
<bool> *forbiddenEdgeOrig
)
62 if (origEdges
.empty())
63 return Module::retFeasible
;
65 List
<edge
> toInsert
= origEdges
;
74 cost
.init(UPR
.original(), 1);
76 if (forbiddenEdgeOrig
!= 0) {
78 forall_edges(e
, UPR
.original()) {
79 if ((*forbiddenEdgeOrig
)[e
])
87 //cout << endl << endl << "edge to insert " << toInsert.size() << " : " << endl;
88 //forall_listiterators(edge, it, toInsert) {
89 // cout << "edge : " << *it << endl;
91 //cout << endl << endl << "number of edges to insert: " << toInsert.size() << endl;
93 return insertAll(UPR
, toInsert
, cost
);
98 Module::ReturnType
FixedEmbeddingUpwardEdgeInserter::insertAll(
100 List
<edge
> &toInsert
,
101 EdgeArray
<int> &costOrig
)
103 if (toInsert
.empty())
104 return Module::retFeasible
;
107 int size_new
= toInsert
.size();
109 while (size_old
!= size_new
) {
111 while (!toInsert
.empty()) {
112 edge e_orig
= toInsert
.popFrontRet();
113 SList
<adjEntry
> path
;
118 cout << " insertion path for e_orig :" << e_orig << "; e_UPR: (" << UPR.copy(e_orig->source()) << ","
119 << UPR.copy(e_orig->target()) << ")" << endl;
122 minFIP(UPR
, toInsert
, costOrig
, e_orig
, path
);
126 //--------------------------------------debug
127 forall_slistiterators(adjEntry, it, path) {
128 cout << (*it)->theEdge() << "; node: " << (*it)->theNode() << endl;
130 //--------------------------------------end debug
133 List
<edge
> lEdges
= toInsert
, lTmp
= l
;
135 bool ok
= isConstraintFeasible(UPR
, lEdges
, e_orig
, path
);
137 UPR
.insertEdgePathEmbedded(e_orig
, path
, costOrig
);
139 OGDF_ASSERT(isUpwardPlanar(UPR
));
140 OGDF_ASSERT(isSimple(UPR
));
141 OGDF_ASSERT(isConnected(UPR
));
142 OGDF_ASSERT(hasSingleSource(UPR
));
150 //---------------------------------------------------debug
151 //UPR.outputFaces(UPR.getEmbedding());
152 //UPR.writeGML("c:/temp/bug5.gml");
154 LayerBasedUPRLayout uprLayout;
155 Graph GTmp( (const Graph &) UPR);
156 CombinatorialEmbedding embTmp(GTmp);
158 //GTmp.writeGML("c:/temp/bug4.gml");
159 hasSingleSink(GTmp, tTmp);
160 OGDF_ASSERT(tTmp != 0);
161 embTmp.setExternalFace(embTmp.rightFace(tTmp->firstAdj()));
162 //adjEntry adjTmp = GCTmp.copy(UPR.extFaceHandle->theEdge())->adjTarget();
163 UpwardPlanRep upr_bug(embTmp);
164 adjEntry adj_bug = upr_bug.getAdjEntry(upr_bug.getEmbedding(), upr_bug.getSuperSource(), upr_bug.getEmbedding().externalFace());
165 node s_upr_bug = upr_bug.newNode();
166 upr_bug.getEmbedding().splitFace(s_upr_bug, adj_bug);
167 upr_bug.m_isSourceArc.init(upr_bug, false);
168 upr_bug.m_isSourceArc[s_upr_bug->firstAdj()->theEdge()] = true;
169 upr_bug.s_hat = s_upr_bug;
172 GraphAttributes GA_UPR_tmp(GTmp, GraphAttributes::nodeGraphics|
173 GraphAttributes::edgeGraphics|
174 GraphAttributes::nodeColor|
175 GraphAttributes::edgeColor|
176 GraphAttributes::nodeLabel|
177 GraphAttributes::edgeLabel
179 GA_UPR_tmp.setAllHeight(30.0);
180 GA_UPR_tmp.setAllWidth(30.0);
182 uprLayout.call(upr_bug, GA_UPR_tmp);
184 // label the nodes with their index
186 forall_nodes(z, GA_UPR_tmp.constGraph()) {
188 sprintf_s(str, 255, "%d", z->index()); // convert to string
189 GA_UPR_tmp.labelNode(z) = str;
190 GA_UPR_tmp.y(z)=-GA_UPR_tmp.y(z);
191 GA_UPR_tmp.x(z)=-GA_UPR_tmp.x(z);
194 forall_edges(eee, GA_UPR_tmp.constGraph()) {
195 DPolyline &line = GA_UPR_tmp.bends(eee);
196 ListIterator<DPoint> it;
197 for(it = line.begin(); it.valid(); it++) {
198 (*it).m_y = -(*it).m_y;
199 (*it).m_x = -(*it).m_x;
202 GA_UPR_tmp.writeGML("c:/temp/UPR_int.gml");
203 //cout << "face of UPR_int :" << endl;
204 //upr_bug.outputFaces(upr_bug.getEmbedding());
205 //end -----------------------------------------------debug
216 * some edges cannot be inserted, so use heuristic insertion methods
218 if (!toInsert
.empty()) {
220 //cout << endl << "\a\a\a\a\aheuristical call!! " << endl;
222 edge e_orig
= toInsert
.popFrontRet();
226 cout << "heuristical insertion path for e_orig :" << e_orig << "; e_UPR: (" << UPR.copy(e_orig->source()) << ","
227 << UPR.copy(e_orig->target()) << ")" << endl;
233 //---------------------------------------------------debug
234 //UPR.outputFaces(UPR.getEmbedding());
235 //UPR.writeGML("c:/temp/bug5.gml");
237 LayerBasedUPRLayout uprLayout;
238 Graph GTmp( (const Graph &) UPR);
239 CombinatorialEmbedding embTmp(GTmp);
241 //GTmp.writeGML("c:/temp/bug4.gml");
242 hasSingleSink(GTmp, tTmp);
243 OGDF_ASSERT(tTmp != 0);
244 embTmp.setExternalFace(embTmp.rightFace(tTmp->firstAdj()));
245 //adjEntry adjTmp = GCTmp.copy(UPR.extFaceHandle->theEdge())->adjTarget();
246 UpwardPlanRep upr_bug(embTmp);
247 adjEntry adj_bug = upr_bug.getAdjEntry(upr_bug.getEmbedding(), upr_bug.getSuperSource(), upr_bug.getEmbedding().externalFace());
248 node s_upr_bug = upr_bug.newNode();
249 upr_bug.getEmbedding().splitFace(s_upr_bug, adj_bug);
250 upr_bug.m_isSourceArc.init(upr_bug, false);
251 upr_bug.m_isSourceArc[s_upr_bug->firstAdj()->theEdge()] = true;
252 upr_bug.s_hat = s_upr_bug;
255 GraphAttributes GA_UPR_tmp(GTmp, GraphAttributes::nodeGraphics|
256 GraphAttributes::edgeGraphics|
257 GraphAttributes::nodeColor|
258 GraphAttributes::edgeColor|
259 GraphAttributes::nodeLabel|
260 GraphAttributes::edgeLabel
262 GA_UPR_tmp.setAllHeight(30.0);
263 GA_UPR_tmp.setAllWidth(30.0);
265 uprLayout.call(upr_bug, GA_UPR_tmp);
267 // label the nodes with their index
269 forall_nodes(z, GA_UPR_tmp.constGraph()) {
271 sprintf_s(str, 255, "%d", z->index()); // convert to string
272 GA_UPR_tmp.labelNode(z) = str;
273 GA_UPR_tmp.y(z)=-GA_UPR_tmp.y(z);
274 GA_UPR_tmp.x(z)=-GA_UPR_tmp.x(z);
277 forall_edges(eee, GA_UPR_tmp.constGraph()) {
278 DPolyline &line = GA_UPR_tmp.bends(eee);
279 ListIterator<DPoint> it;
280 for(it = line.begin(); it.valid(); it++) {
281 (*it).m_y = -(*it).m_y;
282 (*it).m_x = -(*it).m_x;
285 GA_UPR_tmp.writeGML("c:/temp/UPR_int.gml");
286 //cout << "face of UPR_int :" << endl;
287 //upr_bug.outputFaces(upr_bug.getEmbedding());
288 //end -----------------------------------------------debug
292 SList
<adjEntry
> path
;
293 constraintFIP(UPR
, toInsert
, costOrig
, e_orig
, path
);
296 //--------------------------------------debug
298 forall_slistiterators(adjEntry, it, path) {
299 cout << (*it)->theEdge() << "; node: " << (*it)->theNode() << endl;;
301 //--------------------------------------end debug
304 UPR
.insertEdgePathEmbedded(e_orig
, path
, costOrig
);
306 OGDF_ASSERT(isUpwardPlanar(UPR
));
308 return insertAll(UPR
, toInsert
, costOrig
);
310 return Module::retFeasible
;
315 void FixedEmbeddingUpwardEdgeInserter::staticLock(
317 EdgeArray
<bool> &locked
,
318 const List
<edge
> &origEdges
,
321 // construct merge graph M
322 GraphCopy
M((const Graph
&) UPR
);
324 // add deleted edges to M
325 forall_listiterators(edge
, it
, origEdges
) {
327 node u
= M
.copy(UPR
.copy(e
->source()));
328 node v
= M
.copy(UPR
.copy(e
->target()));
332 EdgeArray
<bool> markedEdges(M
, false);
333 markUp(M
, M
.copy(UPR
.copy(e_orig
->target())), markedEdges
);
334 markDown(M
, M
.copy(UPR
.copy(e_orig
->source())), markedEdges
);
338 if (markedEdges
[e
] && M
.original(e
) != 0) {
339 locked
[M
.original(e
)] = true;
346 void FixedEmbeddingUpwardEdgeInserter::getPath(
348 List
<edge
> &origEdges
,
349 EdgeArray
<int> &cost
,
351 SList
<adjEntry
> &path
,
355 node x_1
= UPR
.copy(e_orig
->source());
356 node y_1
= UPR
.copy(e_orig
->target());
357 const CombinatorialEmbedding
&Gamma
= UPR
.getEmbedding();
359 EdgeArray
<bool> locked(UPR
, false);
360 staticLock(UPR
, locked
, origEdges
, e_orig
);
362 //locked the adjacent edges of x_1 and y_1
364 forall_adj(adjTmp
, x_1
)
365 locked
[adjTmp
->theEdge()] = true;
366 forall_adj(adjTmp
, y_1
)
367 locked
[adjTmp
->theEdge()] = true;
369 EdgeArray
<adjEntry
> predAdj(UPR
, 0); // for path reconstruction
370 EdgeArray
<int> dist(UPR
, INT_MAX
); // current distance to an edge
371 EdgeArray
<adjEntry
> toAdjEntry(UPR
, 0);
375 * compute the adjEntry of the adjacent edges of x_1
376 * this is necessary for the initiliazation of priorQ
379 List
<adjEntry
> adjOut
;
380 UPR
.outEdges(x_1
, outEdges
);
381 forall_listiterators(edge
, it
, outEdges
) {
382 adjEntry adj
= (*it
)->adjSource();
383 adjOut
.pushBack(adj
);
384 if (adj
->cyclicPred()->theEdge()->target() == x_1
)
385 adjOut
.pushBack(adj
->cyclicPred()); // right face of the left in edge of x_1
388 List
<adjEntry
> initEdges
;
389 forall_listiterators(adjEntry
, it
, adjOut
) {
390 feasibleEdges(UPR
, Gamma
.rightFace(*it
), *it
, locked
, initEdges
, heuristic
);
391 forall_listiterators(adjEntry
, iu
, initEdges
) {
392 edge ee
= (*iu
)->theEdge();
394 if (UPR
.isSinkArc(ee
) || UPR
.isSourceArc(ee
))
399 // mappe ee to the "correct" adjEntry
400 toAdjEntry
[ee
] = *iu
;
403 //check if ee contains the target source y_1
404 if ((*iu
)->twin()->theNode() == y_1
) {
405 adjEntry adjTgt
= UPR
.getAdjEntry(UPR
.getEmbedding(), y_1
, UPR
.getEmbedding().rightFace(*it
));
407 //for the case if there are two adjEntry of y_1 which right face is the external face
408 if (Gamma
.rightFace(*it
) == Gamma
.externalFace()) {
409 //we have to compute the correct adjEntry
410 adjEntry tgtLeft
= 0, tgtRight
= 0, runAdj
;
411 forall_adj(runAdj
, y_1
) {
412 if (Gamma
.rightFace(runAdj
) == Gamma
.externalFace()) {
413 if (runAdj
->theEdge()->target() == y_1
)
419 if ((*it
)->theNode() == (*it
)->theEdge()->source())
420 adjTgt
= tgtRight
; // *it->theEdge() is on the right face side
422 adjTgt
= tgtLeft
; // *it->theEdge() is on the left face side
425 if (Gamma
.rightFace(*it
) != Gamma
.rightFace(adjTgt
))
426 adjTgt
= adjTgt
->cyclicPred();
427 path
.pushFront((*it
));
428 path
.pushBack(adjTgt
);
430 OGDF_ASSERT(Gamma
.rightFace(*it
) == Gamma
.rightFace(adjTgt
));
435 if (path
.size() == 2) // edge can be inserted without crossing
436 break; //leave forall_listiterators(adjEntry, it, adjOut) loop
441 // if path.size == 2 then we can insert e_orig without crossing (the path is not necessary constrain feasible)
442 if (path
.size() != 2) {
443 // init the priority queque
444 BinaryHeap
<edge
, int> priorQ(UPR
.numberOfEdges());
445 EdgeArray
< const BinaryHeap
<edge
, int>::Element
* > elemArray(UPR
, 0); // reference to the elements of priorQ
447 forall_edges(e
, UPR
) {
449 int priority
= dist
[e
];
450 elemArray
[e
] = &(priorQ
.insert(e
, priority
));
453 adjEntry adjLast
= 0;
454 while (!priorQ
.empty()) {
456 adjEntry adj_cur
= toAdjEntry
[priorQ
.pop()];
458 OGDF_ASSERT(adj_cur
!= 0);
460 face f
= Gamma
.rightFace(adj_cur
); //current face f
461 List
<adjEntry
> nextAdjs
;
462 feasibleEdges(UPR
, f
, adj_cur
, locked
, nextAdjs
, heuristic
);
464 bool reached
= false;
465 forall_listiterators(adjEntry
, it
, nextAdjs
) {
466 adjEntry adjNext
= *it
;
468 if (adjNext
->theNode() == y_1
) { // y_1 reached ?
470 adjLast
= UPR
.getAdjEntry(UPR
.getEmbedding(), y_1
, f
);
473 if (Gamma
.rightFace(adj_cur
) == Gamma
.externalFace()) {
474 //we have to compute the correct adjEntry
475 adjEntry tgtLeft
= 0, tgtRight
= 0, runAdj
;
476 forall_adj(runAdj
, y_1
) {
477 if (Gamma
.rightFace(runAdj
) == Gamma
.externalFace()) {
478 if (runAdj
->theEdge()->target() == y_1
)
484 if (adj_cur
->theNode() == adj_cur
->theEdge()->source())
485 adjLast
= tgtRight
; // adj_cur->theEdge() is on the right face side
487 adjLast
= tgtLeft
; // adj_cur->theEdge() is on the left face side
490 OGDF_ASSERT(adjLast
!= 0)
492 predAdj
[adjLast
->theEdge()] = adj_cur
;
493 break; // leave forall-loop
496 bool ok
= !locked
[adjNext
->theEdge()];
498 //use heuristic to check curent path
500 ok
= isConstraintFeasible(UPR
, origEdges
, e_orig
, adj_cur
, adjNext
, predAdj
);
505 if (UPR
.original(adjNext
->theEdge()) != 0)
506 c
= cost
[UPR
.original(adjNext
->theEdge())];
508 int new_dist
= dist
[adj_cur
->theEdge()] + c
;
509 if (dist
[adjNext
->theEdge()] > new_dist
) {
510 const BinaryHeap
<edge
, int>::Element
&el
= *(elemArray
[adjNext
->theEdge()]);
511 priorQ
.decPriority(el
, new_dist
);
512 predAdj
[adjNext
->theEdge()] = adj_cur
;
513 dist
[adjNext
->theEdge()] = new_dist
;
514 toAdjEntry
[adjNext
->theEdge()] = adjNext
;
520 break; // leave while-loop if y_1 is found
525 path
.pushBack(adjLast
);
526 adjEntry run
= predAdj
[adjLast
];
533 OGDF_ASSERT(path
.size() >= 2);
538 bool FixedEmbeddingUpwardEdgeInserter::isConstraintFeasible(
540 const List
<edge
> &orig_edges
,
544 EdgeArray
<adjEntry
> &predAdj
)
546 //contruct path to adj->theEdge()
547 SList
<adjEntry
> path
;
548 path
.pushBack(adjNext
);
549 path
.pushFront(adjCurrent
);
550 adjEntry run
= predAdj
[adjCurrent
];
553 run
= predAdj
[run
->theEdge()];
558 cout << endl << endl << "current insertion path: " << endl;
559 forall_slistiterators(adjEntry, it, path) {
560 cout << (*it)->theEdge() << "; node: " << (*it)->theNode() << endl;
564 GraphCopy
M( (const Graph
&) UPR
); // merge graph
566 //convert adjEntry of path to adjEntry of M
567 SList
<adjEntry
> path_M
;
568 forall_slistiterators(adjEntry
, it
, path
) {
570 edge e_M
= M
.copy(a
->theEdge());
571 node v
= M
.copy(a
->theNode());
572 if (e_M
->source() == v
)
573 path_M
.pushBack(e_M
->adjSource());
575 path_M
.pushBack(e_M
->adjTarget());
578 // construct a partial path from src to adjNext
579 path_M
.popFrontRet();
580 node src
= M
.copy(UPR
.copy(e_orig
->source()));
581 node tgt
= M
.copy(UPR
.copy(e_orig
->target()));
582 while (!path_M
.empty()) {
583 edge eM
= path_M
.popFrontRet()->theEdge();
584 node d
= M
.split(eM
)->source();
590 //add the deleted edges
591 forall_listiterators(edge
, it
, orig_edges
) {
592 node a
= M
.copy(UPR
.copy((*it
)->source()));
593 node b
= M
.copy(UPR
.copy((*it
)->target()));
601 bool FixedEmbeddingUpwardEdgeInserter::isConstraintFeasible(
603 List
<edge
> &origEdges
,
605 SList
<adjEntry
> &path
)
607 GraphCopy
GC( (const Graph
&) UPR
);
608 GraphCopy
M((const Graph
&)GC
); // merge graph
610 //convert adjEntry of path to adjEntry of M
611 SList
<adjEntry
> path_M
;
612 forall_slistiterators(adjEntry
, it
, path
) {
614 edge e_M
= M
.copy( GC
.copy(a
->theEdge()) );
615 node v
= M
.copy(GC
.copy(a
->theNode()));
616 if (e_M
->source() == v
)
617 path_M
.pushBack(e_M
->adjSource());
619 path_M
.pushBack(e_M
->adjTarget());
624 cout << " insertion path for " << e_orig << endl;
625 forall_slistiterators(adjEntry, it, path_M) {
626 cout << (*it)->theEdge() << "; node: " << (*it)->theNode() << endl;
630 edge e
= GC
.newEdge(GC
.copy(UPR
.copy(e_orig
->source())), GC
.copy(UPR
.copy(e_orig
->target())));
632 CombinatorialEmbedding
Gamma(M
);
633 M
.insertEdgePathEmbedded(e
, Gamma
, path_M
);
635 OGDF_ASSERT(isAcyclic(M
));
637 //add the deleted edges
638 forall_listiterators(edge
, it
, origEdges
) {
639 node a
= M
.copy(GC
.copy(UPR
.copy((*it
)->source())));
640 node b
= M
.copy(GC
.copy(UPR
.copy((*it
)->target())));
648 void FixedEmbeddingUpwardEdgeInserter::feasibleEdges(
652 EdgeArray
<bool> &locked
,
653 List
<adjEntry
> &feasible
,
656 const CombinatorialEmbedding
&Gamma
= UPR
.getEmbedding();
658 OGDF_ASSERT(Gamma
.rightFace(adj
) == f
);
660 adjEntry start
= adj
, run
= adj
;
661 if (f
== Gamma
.externalFace()) {
664 if (adj
->theNode() == adj
->theEdge()->source()) {
666 *adj->theEdge() is on the right path of f, so walk ccw
667 *all edges between adj->theEdge() and the super sink t_hat on the right path are feasible.
670 if (run
->theEdge()->target() == UPR
.getSuperSink())
673 feasible
.pushBack(run
->twin());
674 run
= run
->faceCycleSucc();
677 //dynamic lock; all edges between super source and adj->theEdge() of the corredponding right path muss be locked
682 if (run
->theEdge()->source() == UPR
.getSuperSource())
684 locked
[run
->theEdge()] = true;
685 run
= run
->faceCyclePred();
692 *currentEdge is on the left path of f, so walk cw
693 *All edges between adj->theEdge() and the super sink t_hat on the left path are feasible.
696 if (run
->theEdge()->target()== UPR
.getSuperSink())
699 feasible
.pushBack(run
->twin());
700 run
= run
->faceCyclePred();
703 //dynamic lock; all edges between super source and adj->theEdge() of the corredponding left path muss be locked
708 if (run
->theEdge()->source() == UPR
.getSuperSource())
710 locked
[run
->theEdge()] = true;
711 run
= run
->faceCycleSucc();
721 if (adj
->theNode() == adj
->theEdge()->source()) {
723 *adj->theEdge() is on the left path of f; walk cw to the source-witch of f.
724 *All edges traversing by this walk are feasible.
727 if (run
->theEdge()->source() == run
->faceCycleSucc()->theEdge()->source()) //reach source-switch of f
730 feasible
.pushBack(run
->twin());
731 run
= run
->faceCycleSucc();
734 //dynamic lock; all edges between source-switch and adj->theEdge() of the corredponding left path muss be locked
739 locked
[run
->theEdge()] = true;
740 if (run
->theEdge()->source() == run
->faceCyclePred()->theEdge()->source()) //reach source-switch of f
742 run
= run
->faceCyclePred();
749 *adj->theEdge() is on the right path of f; walk ccw to the source-witch of f.
750 *All edges traversing by this walk are feasible.
753 if (run
->theEdge()->source() == run
->faceCyclePred()->theEdge()->source()) //reach source-switch of f
756 feasible
.pushBack(run
->twin());
757 run
= run
->faceCyclePred();
760 //dynamic lock; all edges between source-switch and adj->theEdge() of the corredponding right path muss be locked
765 locked
[run
->theEdge()] = true;
766 if (run
->theEdge()->source() == run
->faceCycleSucc()->theEdge()->source()) //reach source-switch of f
768 run
= run
->faceCycleSucc();
776 void FixedEmbeddingUpwardEdgeInserter::markUp(
779 //NodeArray<bool> &markedNodes,
780 EdgeArray
<bool> &markedEdges
)
782 // traversing G from v
783 Queue
<node
> nodesToDo
;
785 NodeArray
<bool> inQueue(G
, false);
786 while(!nodesToDo
.empty()) {
787 node w
= nodesToDo
.pop();
789 G
.outEdges(w
, outEdges
);
790 ListIterator
<edge
> it
;
791 for (it
= outEdges
.begin(); it
.valid(); ++it
) {
793 if (!inQueue
[e
->target()]) { // put the next node in queue if it is not already in queue
794 nodesToDo
.append( e
->target() );
795 inQueue
[e
->target()] = true;
797 markedEdges
[e
] = true; // mark edge
803 void FixedEmbeddingUpwardEdgeInserter::markDown(
806 //NodeArray<bool> &markedNodes,
807 EdgeArray
<bool> &markedEdges
)
809 // mark the subgraph, i.e all nodes and edges, which dominate node v
810 Queue
<node
> nodesToDo
;
812 NodeArray
<bool> inQueue(G
, false);
813 while(!nodesToDo
.empty()) {
814 node w
= nodesToDo
.pop();
816 G
.inEdges(w
, inEdges
);
817 ListIterator
<edge
> it
;
818 for (it
= inEdges
.begin(); it
.valid(); ++it
) {
820 if (!inQueue
[e
->source()]) {
821 nodesToDo
.append(e
->source() ); // put the next node in queue if it is not already in queue
822 inQueue
[e
->source()] = true;
824 markedEdges
[e
] = true; // mark the edge