6 * $Date: 2012-07-15 22:39:24 +0200 (So, 15. Jul 2012) $
7 ***************************************************************/
10 * \brief Implements class BiconnectedShellingOrder which computes
11 * a shelling order for a biconnected planar graph.
13 * \author Carsten Gutwenger
16 * This file is part of the Open Graph Drawing Framework (OGDF).
20 * See README.txt in the root directory of the OGDF installation for details.
23 * This program is free software; you can redistribute it and/or
24 * modify it under the terms of the GNU General Public License
25 * Version 2 or 3 as published by the Free Software Foundation;
26 * see the file LICENSE.txt included in the packaging of this file
30 * This program is distributed in the hope that it will be useful,
31 * but WITHOUT ANY WARRANTY; without even the implied warranty of
32 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
33 * GNU General Public License for more details.
36 * You should have received a copy of the GNU General Public
37 * License along with this program; if not, write to the Free
38 * Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
39 * Boston, MA 02110-1301, USA.
41 * \see http://www.gnu.org/copyleft/gpl.html
42 ***************************************************************/
45 #include <ogdf/planarlayout/BiconnectedShellingOrder.h>
46 #include <ogdf/basic/CombinatorialEmbedding.h>
47 #include <ogdf/basic/FaceArray.h>
48 #include <ogdf/basic/SList.h>
50 #include <ogdf/basic/extended_graph_alg.h>
51 #include <ogdf/basic/simple_graph_alg.h>
59 //---------------------------------------------------------
60 // pair of node v and list itrator it
61 //---------------------------------------------------------
69 PairNodeItem(node v
, ListIterator
<PairFaceItem
> it
= ListIterator
<PairFaceItem
>())
76 ListIterator
<PairFaceItem
> m_it
;
80 //---------------------------------------------------------
81 // pair of face f and list iterator it
82 //---------------------------------------------------------
99 PairFaceItem(face f
, ListIterator
<PairNodeItem
> it
)
106 ListIterator
<PairNodeItem
> m_it
;
110 // defines (as shortcuts)
111 // initialization of a variable
112 #define INIT_VAR(x,var,val) \
116 // decrement of a variable
117 #define DEC_VAR(x,var) \
121 // increment of a variable
122 #define INC_VAR(x,var) \
127 //---------------------------------------------------------
128 // class ComputeBicOrder
129 //---------------------------------------------------------
130 class ComputeBicOrder
133 // types of structures to be removed
134 enum CandidateType
{ typeFace
, typeNode
, typeEdge
};
139 const Graph
&G
, // biconnected planar graph
140 ConstCombinatorialEmbedding
&E
, // combinatorial embedding of G
141 face extFace
, // external face
142 double baseRatio
); // size of base (baseRatio * size(extFace)
144 // returns external face
145 face
externalFace() { return m_extFace
; }
147 // returns face left of adj
148 face
left(adjEntry adj
) { return m_pEmbedding
->leftFace(adj
); }
150 // returns face right of adj
151 face
right(adjEntry adj
) { return m_pEmbedding
->rightFace(adj
); }
153 // if v = c_i, returns face right of c_i -> c_i+1
154 face
right(node v
) { return left(m_nextSucc
[v
]); }
156 // if v = c_i, returns face left of c_i -> c_i-1
157 face
left(node v
) { return right(m_prevPred
[v
]); }
159 // returns number of virtual edges adjacent to v
162 // returns successor of v on contour (if v=c_i returns c_i+1)
163 node
next(node v
) { return m_next
[v
]; }
165 // returns predecessor of v on contour (if v=c_i returns c_ii1)
166 node
prev(node v
) { return m_prev
[v
]; }
168 // returns true <=> f contains a virtual edge
169 bool cutv(face f
) { return (m_virtSrc
[f
] != 0); }
171 // returns true <=> f is a possible next face, i.e
172 // outv(f) >= 3 and outv(f) = oute(f)+1
173 bool isPossFace(face f
) {
174 return (f
!= externalFace() && m_outv
[f
] >= 3 && m_outv
[f
] == m_oute
[f
]+1);
177 // returns true <=> v is a possible next node, i.e.
178 // cutf(v) <= 1, cutf(v) = virte(v), numsf(v) = 0 and deg(v) >= 3
179 bool isPossNode(node v
) { // precond.: v on C_k'
180 return (m_onBase
[v
] == false && m_cutf
[v
] <= 1 &&
181 m_cutf
[v
] == virte(v
) && m_numsf
[v
] == 0 && m_deg
[v
] >= 3);
184 // returns true <=> v=c_i and c_i -> c_i+1 is a possible next virtual edge, i.e.
185 // c_i -> c_i+1 is a virtual edge and (deg(c_i) = 2 and c_i != vLeft) or
186 // deg(c_i+1) = 2 and c_i+1 != vRight)
187 bool isPossVirt(node v
) { // precond.: v on C_k'
188 return m_virtEdge
[v
] && ((m_deg
[v
] == 2 && v
!= m_vLeft
) ||
189 (m_deg
[next(v
)] == 2 && next(v
) != m_vRight
));
192 // stores the next candidate in m_nextType and m_nextF, m_nextV or
193 // m_nextE (depending on type)
194 // returns true <=> there is a next candidate
197 // returns the type of the next candidate
198 CandidateType
nextPoss() { return m_nextType
; }
200 // puts nodes on base into shelling order set V
201 void setV1(ShellingOrderSet
&V
);
203 // initializes possible nodes and faces
204 void initPossibles();
206 // removes next possible face
207 void removeNextFace(ShellingOrderSet
&V
);
208 // removes next possible node
209 void removeNextNode(ShellingOrderSet
&V
);
210 // removes next possible virtual edge
211 void removeNextVirt(ShellingOrderSet
&V
);
213 // updates variables of face and nodes contained in m_updateFaces and
214 // m_updateNodes; also updates list of possible nodes, faces and virtual edges
217 // outputs contour and some node and face variables
218 // for debugging only
222 // if adj = w->v, puts edge (v,w) onto contour
223 void edgeToContour(adjEntry adj
);
224 // puts virtual edge (v,w) onto contour and sets m_nextSucc[v] and m_prevPred[w]
225 void virtToContour(node v
, node w
, adjEntry adjNextSucc
, adjEntry adjPrevPred
);
226 // puts virtual edge (v,w) onto contour
227 void virtToContour(node v
, node w
);
229 // returns vertex cl of a face to be removed
230 node
getFaceCl(face f
);
232 void setOutv(node v
);
233 void setSeqp(node cl
, node cr
);
234 void delOuterNode(node v
);
235 void decSeqp(node v
);
236 void putOnOuter(node v
, face f
);
237 void delOuterRef(face f
);
239 // returns faces adjacent with v in list L
240 void getAdjFaces(node v
, SListPure
<face
> &L
);
241 // returns nodes adjacent with v in list L; nodes are sorted from left
243 void getAdjNodes(node v
, SListPure
<node
> &L
);
245 // marks face f to be updated
246 void setUpdate(face f
);
247 // marks node v to be updated
248 void setUpdate(node v
);
250 void initVInFStruct(const ConstCombinatorialEmbedding
&E
);
251 bool vInF(node v
, face f
);
252 void delVInF(node v
, face f
);
254 int getBaseChain(ConstCombinatorialEmbedding
&E
,
260 adjEntry
findMaxBaseChain(ConstCombinatorialEmbedding
&E
,
264 const Graph
*m_pGraph
; // the graph
265 ConstCombinatorialEmbedding
*m_pEmbedding
; // the embedding of the graph
267 face m_extFace
; // the external face
269 adjEntry m_adjLeft
; // adjacency entry z_1 -> z_2 (if z_1,...,z_p is base)
270 adjEntry m_adjRight
; // adjacency entry z_p-1 -> z_p
272 node m_vLeft
, m_vRight
; // left and right node on base
273 int m_baseLength
; // length of base
275 // next candidate to be removed
276 CandidateType m_nextType
; // type of next candidate
277 face m_nextF
; // next face (if m_nextType = typeFace)
278 node m_nextV
; // next node (if m_nextType = typeNode)
279 node m_nextE
; // next virtual edge (if m_nextType = typeEdge)
281 // variables of nodes
282 NodeArray
<int> m_deg
; // current degree
283 NodeArray
<int> m_cutf
; // number of adjacent faces f with cutv(f) = true
284 NodeArray
<int> m_numsf
; // number of adjacent faces f with outv(f) > seqp(f)+1
285 NodeArray
<bool> m_onOuter
; // true <=> v on contour
286 NodeArray
<bool> m_onBase
; // true <=> v on base
288 // list iterator in m_possNodes containing node (or nil if not contained)
289 NodeArray
<ListIterator
<node
> > m_vLink
;
290 // list iterator in m_possVirt containing virtual edge at node (or nil if not contained)
291 NodeArray
<ListIterator
<node
> > m_virtLink
;
292 NodeArray
<bool> m_vUpdate
; // true <=> node marked to be updated
293 NodeArray
<ListPure
<PairFaceItem
> > m_inOutNodes
;
295 // variables of faces
296 FaceArray
<int> m_outv
, // number of nodes contained in face on contour
297 m_oute
, // number of edges contained in face on contour
298 m_seqp
; // number of sequential pairs c_i,c_i+1 of face
299 FaceArray
<node
> m_virtSrc
; // if face contains virtual edge e then source(e), otherwise nil
300 // list iterator in m_possFaces containing face (or nil if not contained)
301 FaceArray
<ListIterator
<face
> > m_fLink
;
302 FaceArray
<bool> m_fUpdate
; // true <=> face marked to be updated
303 FaceArray
<bool> m_isSf
; // true <=> outv(f) > seqp(f)+1
304 FaceArray
<ListPure
<PairNodeItem
> > m_outerNodes
; // list of all nodes of face on contour
306 // represantation of the contour
307 NodeArray
<node
> m_next
, m_prev
;
308 NodeArray
<adjEntry
> m_nextSucc
, m_prevPred
;
309 NodeArray
<bool> m_virtEdge
; // virt_edge[c_i] = true <=> (c_i,c_i+1) virtuelle Kante
311 // lists of possible faces, nodes and edges
312 ListPure
<face
> m_possFaces
; // faces with outv(f) >= 3 und outv(f) = oute(f)+1
313 ListPure
<node
> m_possNodes
; // nodes with cutf(v) <= 1, cutf(v) = virte(v), numsf(v) = 0 and deg(v) >= 3
314 ListPure
<node
> m_possVirt
; // node v denotes virtual edge e = (v,next[v]), that satisfies
315 // (deg(v) = 2 and v != vLeft) or (deg(next(v)) = 2 and next(v) != vRight)
317 ListPure
<node
> m_updateNodes
; // list of nodes to be updated
318 SListPure
<face
> m_updateFaces
; // list of faces to be updated
320 // deciding "v in F ?" in constant time
321 NodeArray
<List
<PairFaceItem
> > m_facesOf
;
322 FaceArray
<List
<PairNodeItem
> > m_nodesOf
;
326 void ComputeBicOrder::print()
328 cout
<< "contour:\n";
330 for(v
= m_vLeft
; v
!= 0; v
= m_next
[v
])
331 cout
<< " " << v
<< "[" << m_prev
[v
] << "," << m_prevPred
[v
] <<
332 " : " << m_next
[v
] << "," << m_nextSucc
[v
] <<
333 "; " << m_virtEdge
[v
] << "]\n";
335 cout
<< "node infos:\n";
336 forall_nodes(v
,*m_pGraph
)
337 cout
<< v
<< ": deg = " << m_deg
[v
] << ", cutf = " << m_cutf
[v
] <<
338 ", numsf = " << m_numsf
[v
] << endl
;
340 cout
<< "face infos:\n";
342 forall_faces(f
,*m_pEmbedding
) {
343 cout
<< f
->index() << ": outv = " << m_outv
[f
] << ", oute = " <<
344 m_oute
[f
] << ", seqp = " << m_seqp
[f
] << ", isSF = " <<
345 m_isSf
[f
] << ", virtSrc = " << m_virtSrc
[f
] << endl
;
351 ComputeBicOrder::ComputeBicOrder(const Graph
&G
, // the graph
352 ConstCombinatorialEmbedding
&E
, // embedding of the graph
353 face extFace
, // the external face
354 double baseRatio
) // length of the base = baseRatio*size(extface)
360 cout
<< "faces:" << endl
;
363 cout
<< fh
->index() << ":";
365 forall_face_adj(adj
,fh
)
370 cout
<< "adjacency lists:" << endl
;
381 m_vLink
.init(G
, ListIterator
<node
>());
382 m_virtLink
.init(G
, ListIterator
<node
>());
387 cout
<< "external face = " << extFace
->index() << endl
;
390 m_baseLength
= getBaseChain(E
, m_extFace
, baseRatio
, m_adjLeft
, m_adjRight
);
391 m_vLeft
= m_adjLeft
->theNode();
392 m_vRight
= m_adjRight
->twinNode();
395 cout
<< "vLeft = " << m_vLeft
<< ", " << "vRight = " << m_vRight
<< endl
;
398 // initialization of node and face variables
401 m_numsf
.init (G
, 0);
402 m_onOuter
.init (G
, false);
405 m_nextSucc
.init (G
);
406 m_prevPred
.init (G
);
407 m_virtEdge
.init (G
, false);
408 m_vUpdate
.init (G
, false);
409 m_inOutNodes
.init (G
);
413 m_virtSrc
.init (E
, 0);
414 m_fLink
.init (E
, ListIterator
<face
>());
415 m_fUpdate
.init (E
, false);
416 m_isSf
.init (E
, false);
417 m_outerNodes
.init (E
);
418 m_onBase
.init (G
, false);
422 // initialization of degree
425 m_deg
[v
] = v
->degree();
427 // initialization of m_onBase[v]
429 for(adj
= m_adjRight
; adj
!= m_adjLeft
; adj
= adj
->faceCyclePred())
430 m_onBase
[adj
->theNode()] = true;
431 m_onBase
[m_vLeft
] = m_onBase
[m_vRight
] = true;
439 face f
= E
.rightFace(adj2
);
440 if (f
!= m_extFace
) {
445 adj
= adj
->faceCyclePred();
446 } while(adj
!= m_adjRight
);
448 for(adj
= m_adjRight
->faceCycleSucc(); adj
!= m_adjLeft
; adj
= adj
->faceCycleSucc())
449 m_oute
[E
.leftFace(adj
)]++;
451 m_onOuter
[m_vLeft
] = true;
452 m_prevPred
[m_vLeft
] = m_nextSucc
[m_vRight
] = 0;
453 m_prev
[m_vLeft
] = m_next
[m_vRight
] = 0;
454 for (adj
= m_adjLeft
->faceCyclePred(); adj
!= m_adjRight
; adj
= adj
->faceCyclePred())
456 v
= adj
->twinNode(); w
= adj
->theNode();
469 for (v
= m_vLeft
; v
!= 0; v
= next(v
))
473 if ((m_isSf
[f
] = (m_outv
[f
] > m_seqp
[f
]+1)) == true)
480 void ComputeBicOrder::setV1(ShellingOrderSet
&V
)
482 V
= ShellingOrderSet(m_baseLength
, 0, 0);
486 for (i
= 1, adj
= m_adjLeft
; i
<= m_baseLength
;
487 i
++, adj
= adj
->faceCycleSucc())
489 V
[i
] = adj
->theNode();
494 void ComputeBicOrder::edgeToContour(adjEntry adj
)
496 node v
= adj
->twinNode(), w
= adj
->theNode();
500 m_nextSucc
[v
] = adj
->twin()->cyclicSucc();
501 m_prevPred
[w
] = adj
->cyclicPred();
502 m_virtEdge
[v
] = false;
506 void ComputeBicOrder::virtToContour(
509 adjEntry adjNextSucc
,
510 adjEntry adjPrevPred
)
514 m_nextSucc
[v
] = adjNextSucc
;
515 m_prevPred
[w
] = adjPrevPred
;
516 m_virtEdge
[v
] = true;
520 void ComputeBicOrder::virtToContour(node v
, node w
)
524 m_virtEdge
[v
] = true;
528 void ComputeBicOrder::putOnOuter(node v
, face f
)
530 ListIterator
<PairNodeItem
> it
;
532 it
= m_outerNodes
[f
].pushBack(PairNodeItem(v
));
533 (*it
).m_it
= m_inOutNodes
[v
].pushBack(PairFaceItem(f
,it
));
537 void ComputeBicOrder::delOuterRef(face f
)
539 ListPure
<PairNodeItem
> &L
= m_outerNodes
[f
];
544 m_inOutNodes
[x
.m_v
].del(x
.m_it
);
549 int ComputeBicOrder::virte(node v
)
553 if (m_onOuter
[v
] == true)
555 if (m_virtEdge
[v
] == true)
557 if (v
!= m_vLeft
&& m_virtEdge
[prev(v
)] == true)
564 void ComputeBicOrder::initVInFStruct(const ConstCombinatorialEmbedding
&E
)
575 forall_face_adj(adj
,f
) {
576 node v
= adj
->theNode();
578 ListIterator
<PairFaceItem
> it
= m_facesOf
[v
].pushBack(PairFaceItem(f
));
579 (*it
).m_it
= m_nodesOf
[f
].pushBack(PairNodeItem(v
,it
));
583 SListPure
<node
> smallV
;
586 if (m_facesOf
[v
].size() <= 5)
590 SListPure
<face
> smallF
;
592 if (m_nodesOf
[f
].size() <= 5)
598 if (!smallV
.empty()) {
599 v
= smallV
.popFrontRet();
601 ListIterator
<PairFaceItem
> it
;
602 for(it
= m_facesOf
[v
].begin(); it
.valid(); ++it
) {
603 PairFaceItem f_it
= *it
;
604 m_nodesOf
[f_it
.m_f
].del(f_it
.m_it
);
605 if (m_nodesOf
[f_it
.m_f
].size() == 5)
606 smallF
.pushBack(f_it
.m_f
);
608 } else if (!smallF
.empty()) {
609 f
= smallF
.popFrontRet();
610 ListIterator
<PairNodeItem
> it
;
611 for(it
= m_nodesOf
[f
].begin(); it
.valid(); ++it
) {
612 PairNodeItem v_it
= *it
;
613 m_facesOf
[v_it
.m_v
].del(v_it
.m_it
);
614 if (m_facesOf
[v_it
.m_v
].size() == 5)
615 smallV
.pushBack(v_it
.m_v
);
623 bool ComputeBicOrder::vInF(node v
, face f
)
625 ListIterator
<PairNodeItem
> itNI
;
626 for(itNI
= m_nodesOf
[f
].begin(); itNI
.valid(); ++itNI
)
627 if ((*itNI
).m_v
== v
) return true;
629 ListIterator
<PairFaceItem
> itFI
;
630 for(itFI
= m_facesOf
[v
].begin(); itFI
.valid(); ++itFI
)
631 if ((*itFI
).m_f
== f
) return true;
637 void ComputeBicOrder::delVInF(node v
, face f
)
639 List
<PairNodeItem
> &L_f
= m_nodesOf
[f
];
640 List
<PairFaceItem
> &L_v
= m_facesOf
[v
];
642 ListIterator
<PairNodeItem
> itNI
;
643 for(itNI
= L_f
.begin(); itNI
.valid(); ++itNI
) {
644 if ((*itNI
).m_v
== v
) {
650 ListIterator
<PairFaceItem
> itFI
;
651 for(itFI
= L_v
.begin(); itFI
.valid(); ++itFI
) {
652 if ((*itFI
).m_f
== f
) {
660 void ComputeBicOrder::initPossibles()
663 forall_faces (f
, (*m_pEmbedding
)) {
665 m_fLink
[f
] = m_possFaces
.pushBack(f
);
669 for (v
= next(m_vLeft
); v
!= m_vRight
; v
= next(v
))
671 m_vLink
[v
] = m_possNodes
.pushBack(v
);
675 bool ComputeBicOrder::getPossible()
677 if (!m_possFaces
.empty()) {
678 m_nextType
= typeFace
;
679 m_nextF
= m_possFaces
.popFrontRet();
682 } else if (!m_possNodes
.empty()) {
683 m_nextType
= typeNode
;
684 m_nextV
= m_possNodes
.popFrontRet();
687 } else if (!m_possVirt
.empty()) {
688 m_nextType
= typeEdge
;
689 m_nextE
= m_possVirt
.popFrontRet();
690 m_virtLink
[m_nextE
] = ListIterator
<node
>();
698 node
ComputeBicOrder::getFaceCl(face f
)
707 forall_face_adj(adj
, f
) {
708 if (m_onOuter
[v
= adj
->theNode()] == true && m_deg
[v
] == 2)
713 while (v
!= m_vLeft
&& m_deg
[v
] == 2)
720 void ComputeBicOrder::getAdjFaces(node v
, SListPure
<face
> &L
)
723 if (m_deg
[v
] <= 1) return;
725 adjEntry adjEnd
= (v
!= m_vLeft
) ? m_prevPred
[v
] : m_adjLeft
->cyclicPred();
726 adjEntry adjStart
= (v
!= m_vRight
) ? m_nextSucc
[v
] : m_adjRight
->twin()->cyclicSucc();
728 if (left(adjStart
) != m_extFace
)
729 L
.pushBack(left(adjStart
));
733 for (adj
= adjStart
; adj
!= adjEnd
; adj
= adj
->cyclicSucc())
734 L
.pushBack(right(adj
));
736 L
.pushBack(right(adjEnd
));
741 void ComputeBicOrder::getAdjNodes(node v
, SListPure
<node
> &L
)
743 adjEntry adjEnd
= (v
!= m_vLeft
) ? m_prevPred
[v
] : m_adjLeft
->cyclicPred();
744 adjEntry adjStart
= (v
!= m_vRight
) ? m_nextSucc
[v
] : m_adjRight
->twin()->cyclicSucc();
747 L
.pushBack((v
!= m_vLeft
) ? prev(v
) : m_adjLeft
->twinNode());
751 for (adj
= adjEnd
; adj
!= adjStart
; adj
= adj
->cyclicPred())
752 L
.pushBack(adj
->twinNode());
753 L
.pushBack(adjStart
->twinNode());
755 L
.pushBack((v
!= m_vRight
) ? next(v
) : m_adjRight
->theNode());
759 void ComputeBicOrder::decSeqp(node v
)
761 node vNext
= next(v
);
762 node vPrev
= prev(v
);
767 SListConstIterator
<face
> it
;
768 for(it
= L
.begin(); it
.valid(); ++it
) {
778 void ComputeBicOrder::delOuterNode(node v
)
780 ListIterator
<PairFaceItem
> it
;
781 for(it
= m_inOutNodes
[v
].begin(); it
.valid(); ++it
)
782 m_outerNodes
[(*it
).m_f
].del((*it
).m_it
);
786 void ComputeBicOrder::setOutv(node v
)
791 SListConstIterator
<face
> it
;
792 for(it
= L
.begin(); it
.valid(); ++it
) {
797 if (cutv(f
) == true) {
807 void ComputeBicOrder::setSeqp(node cl
, node cr
)
812 for (v
= cl
; v
!= cr
; v
= w
)
817 if (m_deg
[v
] < m_deg
[w
]) {
825 getAdjFaces(wSmall
, L
);
827 SListConstIterator
<face
> it
;
828 for(it
= L
.begin(); it
.valid(); ++it
) {
829 if (vInF(wBig
,*it
)) {
837 void ComputeBicOrder::removeNextFace(ShellingOrderSet
&V
)
840 cout
<< "remove next face: " << m_nextF
->index() << endl
;
843 node cl
= getFaceCl(m_nextF
), cr
, v
;
845 V
= ShellingOrderSet(m_outv
[m_nextF
]-2);
849 for (i
= 1, cr
= next(cl
); cr
!= m_vRight
&& m_deg
[cr
] == 2; i
++, cr
= next(cr
))
852 V
.leftAdj (m_virtEdge
[cl
] ? 0 : m_nextSucc
[cl
]->cyclicSucc()->twin());
853 V
.rightAdj(m_virtEdge
[prev(cr
)] ? 0 : m_prevPred
[cr
]->cyclicPred()->twin());
855 if (cutv(m_nextF
) && next(m_virtSrc
[m_nextF
]) == cr
)
861 v
= m_virtSrc
[m_nextF
];
863 m_possVirt
.del(m_virtLink
[v
]);
864 m_virtLink
[v
] = ListIterator
<node
>();
868 adjEntry adj
= m_nextSucc
[cl
]->twin();
872 if (adj
->theNode() == cr
)
875 INIT_VAR(adj
->theNode(),m_onOuter
,true)
878 adj
= adj
->faceCyclePred();
883 for (v
= cl
; v
!= cr
; v
= next(v
)) {
884 INC_VAR(right(v
),m_oute
)
891 // possibly remove virtual edge
893 if (m_virtSrc
[m_nextF
] == cl
) {
895 m_virtEdge
[cl
] = false;
897 m_virtSrc
[m_nextF
] = 0;
899 delOuterRef(m_nextF
);
903 void ComputeBicOrder::removeNextNode(ShellingOrderSet
&V
)
906 cout
<< "remove next node: " << m_nextV
<< endl
;
909 node cl
= prev(m_nextV
);
910 node cr
= next(m_nextV
);
912 V
= ShellingOrderSet(1);
915 if (m_virtEdge
[prev(m_nextV
)] == true) {
916 V
.left(m_prevPred
[m_nextV
]->twinNode());
917 V
.leftAdj(m_prevPred
[m_nextV
]);
919 V
.left(prev(m_nextV
));
920 V
.leftAdj(m_prevPred
[m_nextV
]->cyclicPred());
923 if (m_virtEdge
[m_nextV
] == true) {
924 V
.right(m_nextSucc
[m_nextV
]->twinNode());
925 V
.rightAdj(m_nextSucc
[m_nextV
]);
927 V
.right(next(m_nextV
));
928 V
.rightAdj(m_nextSucc
[m_nextV
]->cyclicSucc());
933 if (m_virtEdge
[prev(m_nextV
)]) {
934 INIT_VAR(prev(m_nextV
), m_virtEdge
, false)
936 fVirt
= left(m_nextV
);
937 m_virtSrc
[fVirt
] = 0;
940 if (m_virtEdge
[m_nextV
]) {
941 if (m_virtLink
[m_nextV
].valid()) {
942 m_possVirt
.del(m_virtLink
[m_nextV
]);
943 m_virtLink
[m_nextV
] = ListIterator
<node
>();
946 fVirt
= right(m_nextV
);
947 m_virtSrc
[fVirt
] = 0;
951 getAdjFaces(m_nextV
, L
);
952 SListConstIterator
<face
> itF
;
953 for(itF
= L
.begin(); itF
.valid(); ++itF
)
957 getAdjNodes(m_nextV
, L_v
);
959 delOuterNode(m_nextV
);
960 --m_oute
[left (m_nextV
)];
961 --m_oute
[right(m_nextV
)];
964 SListIterator
<node
> itV
;
965 for(itV
= L_v
.begin(); itV
.valid(); ++itV
) {
966 m_onOuter
[*itV
] = true;
967 DEC_VAR (*itV
, m_deg
)
971 node w1
= L_v
.popFrontRet();
972 bool firstTime
= true;
974 for(itV
= L_v
.begin(); itV
.valid(); ++itV
)
978 if (firstTime
== true) {
979 adj2
= m_nextSucc
[prev(m_nextV
)];
980 adj
= m_prevPred
[m_nextV
];
983 if (prev(m_nextV
) != m_vLeft
) {
985 if (vInF(prev(prev(m_nextV
)),f
))
990 adj2
= adj
->twin()->faceCyclePred()->twin();
991 adj
= adj
->cyclicPred();
996 node v
= adj2
->twinNode();
998 if (v
!= w
&& m_onOuter
[v
] == true)
1000 face f
= left(adj2
);
1002 // possibly remove "v in F" relation
1003 if (adj2
->theNode() != w1
)
1005 adjEntry adj1
= adj2
->twin()->faceCycleSucc();
1007 delVInF(adj1
->twinNode(),f
);
1008 adj1
= adj1
->faceCycleSucc();
1009 } while (adj1
->theNode() != w1
);
1011 if (f
== potF
&& adj2
->theNode() != prev(m_nextV
)) {
1015 // insert new virtual edge
1016 virtToContour(adj2
->theNode(), w
, adj2
, (w
== next(m_nextV
)) ?
1017 m_prevPred
[w
] : adj
->twin()->cyclicPred());
1021 INC_VAR(adj2
->theNode(),m_deg
)
1025 ListIterator
<PairNodeItem
> itU
;
1026 for(itU
= m_outerNodes
[f
].begin(); itU
.valid(); ++itU
) {
1027 INC_VAR((*itU
).m_v
, m_cutf
);
1030 m_virtSrc
[f
] = adj2
->theNode();
1035 edgeToContour(adj2
->twin());
1038 delOuterRef(left(adj2
));
1041 INIT_VAR(v
,m_onOuter
,true)
1042 if (adj2
->theNode() == cl
)
1044 ListIterator
<PairNodeItem
> it
, itSucc
;
1045 ListPure
<PairNodeItem
> &L
= m_outerNodes
[left(adj2
)];
1046 for(it
= L
.begin(); it
.valid(); it
= itSucc
) {
1048 if ((*it
).m_v
== cl
) {
1049 m_inOutNodes
[cl
].del((*it
).m_it
);
1054 m_outv
[left(adj2
)]--;
1056 adj2
= adj2
->twin()->faceCyclePred()->twin();
1061 for (node v
= cl
; v
!= cr
; v
= next(v
)) {
1062 INC_VAR(right(v
),m_oute
)
1069 if ((vVirt
!= 0 && m_virtSrc
[fVirt
] == 0) ||
1070 (vVirt
== cl
&& m_virtSrc
[fVirt
] != cl
)) {
1071 DEC_VAR(vVirt
,m_cutf
)
1076 void ComputeBicOrder::removeNextVirt(ShellingOrderSet
&V
)
1079 cout
<< "remove next virt: " << m_nextE
<< endl
;
1082 node v
, cl
= m_nextE
, cr
= next(m_nextE
);
1085 while (m_deg
[cl
] == 2 && cl
!= m_vLeft
)
1086 { cl
= prev(cl
); i
++; }
1087 while (m_deg
[cr
] == 2 && cr
!= m_vRight
)
1088 { cr
= next(cr
); i
++; }
1090 V
= ShellingOrderSet(i
,m_virtEdge
[cl
] ? 0 : m_prevPred
[next(cl
)],
1091 m_virtEdge
[prev(cr
)] ? 0 : m_nextSucc
[prev(cr
)]);
1092 for (i
= 1, v
= next(cl
); v
!= cr
; v
= next(v
)) {
1102 virtToContour(cl
, cr
);
1104 INIT_VAR(f
,m_outv
,(m_outv
[f
] - V
.len()))
1105 INIT_VAR(f
,m_oute
,(m_oute
[f
] - V
.len()))
1106 INIT_VAR(f
,m_seqp
,(m_seqp
[f
] - V
.len()-1))
1113 void ComputeBicOrder::setUpdate(node v
)
1115 if (m_vUpdate
[v
] == false) {
1116 m_updateNodes
.pushBack(v
);
1117 m_vUpdate
[v
] = true;
1122 void ComputeBicOrder::setUpdate(face f
)
1124 if (m_fUpdate
[f
] == false) {
1125 m_updateFaces
.pushBack(f
);
1126 m_fUpdate
[f
] = true;
1131 void ComputeBicOrder::doUpdate()
1133 while (!m_updateFaces
.empty())
1135 face f
= m_updateFaces
.popFrontRet();
1136 m_fUpdate
[f
] = false;
1137 bool isSeperatingFace
= (m_outv
[f
] > m_seqp
[f
]+1);
1138 if (isSeperatingFace
!= m_isSf
[f
])
1140 ListIterator
<PairNodeItem
> it
;
1141 for(it
= m_outerNodes
[f
].begin(); it
.valid(); ++it
)
1143 if (isSeperatingFace
) {
1144 INC_VAR((*it
).m_v
,m_numsf
)
1146 DEC_VAR((*it
).m_v
,m_numsf
)
1149 m_isSf
[f
] = isSeperatingFace
;
1151 bool possible
= isPossFace(f
);
1152 if (possible
&& !m_fLink
[f
].valid())
1153 m_fLink
[f
] = m_possFaces
.pushBack(f
);
1154 else if (!possible
&& m_fLink
[f
].valid()) {
1155 m_possFaces
.del(m_fLink
[f
]);
1156 m_fLink
[f
] = ListIterator
<face
>();
1160 ListIterator
<node
> it
, itPrev
;
1161 for (it
= m_updateNodes
.rbegin(); it
.valid(); it
= itPrev
)
1165 if (v
!= m_vLeft
&& m_virtEdge
[prev(v
)] == true)
1169 while (!m_updateNodes
.empty())
1171 node v
= m_updateNodes
.popFrontRet();
1172 m_vUpdate
[v
] = false;
1174 bool possible
= isPossNode(v
);
1175 if (possible
&& !m_vLink
[v
].valid())
1176 m_vLink
[v
] = m_possNodes
.pushBack(v
);
1177 else if (!possible
&& m_vLink
[v
].valid()) {
1178 m_possNodes
.del(m_vLink
[v
]);
1179 m_vLink
[v
] = ListIterator
<node
>();
1181 possible
= isPossVirt(v
);
1182 if (possible
&& !m_virtLink
[v
].valid())
1183 m_virtLink
[v
] = m_possVirt
.pushBack(v
);
1184 else if (!possible
&& m_virtLink
[v
].valid()) {
1185 m_possVirt
.del(m_virtLink
[v
]);
1186 m_virtLink
[v
] = ListIterator
<node
>();
1192 int ComputeBicOrder::getBaseChain(ConstCombinatorialEmbedding
&E
,
1199 adjLeft
= findMaxBaseChain(E
, f
, len
);
1200 len
= max(2, min(len
, (int)(baseRatio
*f
->size()+0.5)));
1203 for (int i
= 2; i
< len
; i
++)
1204 adjRight
= adjRight
->faceCycleSucc();
1212 QType (adjEntry adj
, int i
) {
1226 adjEntry
ComputeBicOrder::findMaxBaseChain(ConstCombinatorialEmbedding
&E
,
1230 const Graph
&G
= (const Graph
&) E
;
1233 NodeArray
<int> num(G
,-1);
1238 forall_face_adj(adj
,f
)
1239 num
[adj
->theNode()] = i
++;
1241 Array
<SListPure
<int> > diag(0,p
-1);
1242 forall_face_adj(adj
,f
)
1244 i
= num
[adj
->theNode()];
1246 for (adj2
= adj
->cyclicPred(); adj2
!= adj
->cyclicSucc();
1247 adj2
= adj2
->cyclicPred())
1249 j
= num
[adj2
->twinNode()];
1251 diag
[i
].pushBack(j
);
1256 Array
<SListIterator
<QType
> > posInQ (0,p
-1,SListIterator
<QType
>());
1259 bool firstRun
= true;
1260 adj
= f
->firstAdj();
1261 i
= num
[adj
->theNode()];
1263 adjEntry adjStart
= 0;
1265 if (posInQ
[i
].valid()) {
1266 adjEntry adj2
= Q
.front().m_start
;
1267 d
= (i
-num
[adj2
->theNode()]+p
) % p
+1;
1268 if (d
> length
|| (d
== length
&& adj2
->theNode()->index() < adjStart
->theNode()->index())) {
1272 SListIterator
<QType
> it
, itLimit
= posInQ
[i
];
1275 posInQ
[(*it
).m_limit
] = SListIterator
<QType
>();
1277 } while (it
!= itLimit
);
1280 if (diag
[i
].empty())
1284 SListConstIterator
<int> it
;
1285 for(it
= diag
[i
].begin(); it
.valid(); ++it
) {
1295 posInQ
[Q
.back().m_limit
] = 0;
1296 Q
.back().m_limit
= j
;
1297 posInQ
[j
] = Q
.rbegin();
1302 posInQ
[j
] = Q
.pushBack(QType(adj
,j
));
1304 adj
= adj
->faceCycleSucc();
1305 i
= num
[adj
->theNode()];
1306 if (i
== 0) firstRun
= false;
1307 } while (!Q
.empty());
1313 //---------------------------------------------------------
1314 // BiconnectedShellingOrder
1315 //---------------------------------------------------------
1317 void BiconnectedShellingOrder::doCall(const Graph
&G
,
1319 List
<ShellingOrderSet
> &partition
)
1321 OGDF_ASSERT(isBiconnected(G
) == true);
1322 OGDF_ASSERT(G
.representsCombEmbedding() == true);
1324 ConstCombinatorialEmbedding
E(G
);
1326 face extFace
= (adj
!= 0) ? E
.rightFace(adj
) : E
.maximalFace();
1327 ComputeBicOrder
cpo(G
,E
,extFace
,m_baseRatio
);
1329 cpo
.initPossibles();
1332 cout
<< "after initialization:\n";
1336 while(cpo
.getPossible())
1338 switch(cpo
.nextPoss())
1340 case ComputeBicOrder::typeFace
:
1341 partition
.pushFront(ShellingOrderSet());
1342 cpo
.removeNextFace(partition
.front());
1345 case ComputeBicOrder::typeNode
:
1346 partition
.pushFront(ShellingOrderSet());
1347 cpo
.removeNextNode(partition
.front());
1350 case ComputeBicOrder::typeEdge
:
1351 partition
.pushFront(ShellingOrderSet());
1352 cpo
.removeNextVirt(partition
.front());
1359 cout
<< "after update:\n";
1364 partition
.pushFront(ShellingOrderSet(2));
1365 cpo
.setV1(partition
.front());
1369 } // end namespace ogdf