Don't import ogdf namespace
[TortoiseGit.git] / ext / OGDF / ogdf / internal / planarity / BoyerMyrvoldPlanar.h
blob6ae1c407115856e3c99901400fe34ae2b3b52d45
1 /*
2 * $Revision: 2584 $
4 * last checkin:
5 * $Author: gutwenger $
6 * $Date: 2012-07-12 02:38:07 +0200 (Do, 12. Jul 2012) $
7 ***************************************************************/
9 /** \file
10 * \brief Declaration of the class BoyerMyrvoldPlanar
12 * \author Jens Schmidt
15 * \par License:
16 * This file is part of the Open Graph Drawing Framework (OGDF).
18 * \par
19 * Copyright (C)<br>
20 * See README.txt in the root directory of the OGDF installation for details.
22 * \par
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
27 * for details.
29 * \par
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.
35 * \par
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 #ifdef _MSC_VER
46 #pragma once
47 #endif
49 #ifndef OGDF_BOYER_MYRVOLD_PLANAR_H
50 #define OGDF_BOYER_MYRVOLD_PLANAR_H
52 #include <ogdf/basic/Graph_d.h>
53 #include <ogdf/basic/NodeArray.h>
54 #include <ogdf/basic/Stack.h>
55 #include <ogdf/basic/List.h>
56 #include <ogdf/basic/SList.h>
59 namespace ogdf {
61 //! Directions for clockwise and counterclockwise traversal
62 enum enumDirection {
63 CCW=0,
64 CW=1
67 //! Type of edge
68 /** @param 0 undefined
69 * @param 1 selfloop
70 * @param 2 backedge
71 * @param 3 DFS-edge
72 * @param 4 parallel DFS-edge
73 * @param 5 deleted backedge
75 enum enumEdgeType {
76 EDGE_UNDEFINED=0,
77 EDGE_SELFLOOP=1,
78 EDGE_BACK=2,
79 EDGE_DFS=3,
80 EDGE_DFS_PARALLEL=4,
81 EDGE_BACK_DELETED=5
84 class KuratowskiStructure;
85 class FindKuratowskis;
87 //! This class implements the extended BoyerMyrvold planarity embedding algorithm
88 class BoyerMyrvoldPlanar
90 friend class BoyerMyrvold;
91 friend class BoyerMyrvoldInit;
92 friend class FindKuratowskis;
93 friend class ExtractKuratowskis;
95 public:
96 //! Constructor, for parameters see BoyerMyrvold
97 BoyerMyrvoldPlanar(
98 Graph& g,
99 bool bundles,
100 int m_embeddingGrade,
101 bool limitStructures,
102 SListPure<KuratowskiStructure>& output,
103 bool randomDFSTree,
104 bool avoidE2Minors);
106 //! Destructor
107 ~BoyerMyrvoldPlanar() { }
109 //! Starts the embedding algorithm
110 bool start();
112 //! Denotes the different embedding options
113 enum enumEmbeddingGrade {
114 doNotEmbed=-3, // and not find any kuratowski subdivisions
115 doNotFind=-2, // but embed
116 doFindUnlimited=-1, // and embed
117 doFindZero=0 // and embed
120 //! Flips all nodes of the bicomp with unique, real, rootchild c as necessary
121 /** @param c is the unique rootchild of the bicomp
122 * @param marker is the value which marks nodes as visited
123 * @param visited is the array containing visiting information
124 * @param wholeGraph Iff true, all bicomps of all connected components will be traversed
125 * @param deleteFlipFlags Iff true, the flipping flags will be deleted after flipping
127 void flipBicomp(
128 int c,
129 int marker,
130 NodeArray<int>& visited,
131 bool wholeGraph,
132 bool deleteFlipFlags);
134 // avoid automatic creation of assignment operator
135 //! Assignment operator is undefined!
136 BoyerMyrvoldPlanar &operator=(const BoyerMyrvoldPlanar &);
138 protected:
139 /***** Methods for Walkup and Walkdown ******/
141 //! Checks whether node \a w is pertinent. \a w has to be non-virtual.
142 inline bool pertinent(node w) {
143 OGDF_ASSERT(w!=NULL);
144 if (m_dfi[w] <= 0) return false;
145 return (!m_backedgeFlags[w].empty() || !m_pertinentRoots[w].empty());
148 //! Checks whether real node \a w is internally active while embedding node with DFI \a v
149 inline bool internallyActive(node w, int v) {
150 OGDF_ASSERT(w!=NULL);
151 if (m_dfi[w] <= 0) return false;
152 return (pertinent(w) && !externallyActive(w,v));
155 //! Checks whether real node \a w is externally active while embedding node with DFI \a v
156 inline bool externallyActive(node w, int v) {
157 OGDF_ASSERT(w!=NULL);
158 if (m_dfi[w] <= 0) return false;
159 if (m_leastAncestor[w] < v) return true;
160 if (m_separatedDFSChildList[w].empty()) return false;
161 return (m_lowPoint[m_separatedDFSChildList[w].front()] < v);
164 //! Checks whether real node \a w is inactive while embedding node with DFI \a v
165 inline bool inactive(node w, int v) {
166 OGDF_ASSERT(w!=NULL);
167 if (m_dfi[w] <= 0) return true;
168 if (!m_backedgeFlags[w].empty() || !m_pertinentRoots[w].empty()
169 || m_leastAncestor[w] < v) return false;
170 if (m_separatedDFSChildList[w].empty()) return true;
171 return (m_lowPoint[m_separatedDFSChildList[w].front()] >= v);
174 //! Checks all dynamic information about a node \a w while embedding node with DFI \a v
176 * @return This method returns the following values:
177 * - 0 = inactive
178 * - 1 = internallyActive
179 * - 2 = pertinent and externallyActive
180 * - 3 = externallyActive and not pertinent
182 inline int infoAboutNode(node w, int v) {
183 OGDF_ASSERT(w!=NULL);
184 if (m_dfi[w] <= 0) return 0;
185 if (!m_pertinentRoots[w].empty() || !m_backedgeFlags[w].empty()) {
186 // pertinent
187 if (m_leastAncestor[w] < v) return 2;
188 if (m_separatedDFSChildList[w].empty()) return 1;
189 return (m_lowPoint[m_separatedDFSChildList[w].front()] < v
190 ? 2 : 1);
191 } else {
192 // not pertinent
193 if (m_leastAncestor[w] < v) return 3;
194 if (m_separatedDFSChildList[w].empty()) return 0;
195 return (m_lowPoint[m_separatedDFSChildList[w].front()] < v
196 ? 3 : 0);
200 //! Walks upon external face in the given \a direction starting at \a w
201 /** If none of the bicomps has been flipped then CW = clockwise and
202 * CCW = counterclockwise holds. In general, the traversaldirection could have
203 * been changed due to flipped components. If this occurs, the
204 * traversaldirection is flipped.
206 inline node successorOnExternalFace(node w, int& direction) {
207 OGDF_ASSERT(w!=NULL);
208 OGDF_ASSERT(w->degree()>0);
209 OGDF_ASSERT(m_link[CW][w]!=NULL && m_link[CCW][w]!=NULL);
210 adjEntry adj = m_link[direction][w];
211 OGDF_ASSERT(adj->theNode()!=NULL);
213 if (w->degree() > 1) direction =
214 adj==beforeShortCircuitEdge(adj->theNode(),CCW)->twin();
215 OGDF_ASSERT(direction || adj==beforeShortCircuitEdge(adj->theNode(),CW)->twin());
216 return adj->theNode();
219 //! Walks upon external face in given \a direction avoiding short circuit edges
220 inline node successorWithoutShortCircuit(node w, int& direction) {
221 OGDF_ASSERT(w!=NULL);
222 OGDF_ASSERT(w->degree()>0);
223 OGDF_ASSERT(m_link[CW][w]!=NULL && m_link[CCW][w]!=NULL);
224 adjEntry adj = beforeShortCircuitEdge(w,direction);
225 OGDF_ASSERT(adj->theNode()!=NULL);
227 if (w->degree() > 1) direction =
228 adj==beforeShortCircuitEdge(adj->theNode(),CCW)->twin();
229 OGDF_ASSERT(direction || adj==beforeShortCircuitEdge(adj->theNode(),CW)->twin());
230 return adj->theNode();
233 //! Returns the successornode on the external face in given \a direction
234 /** \a direction is not changed.
236 inline node constSuccessorOnExternalFace(node v, int direction) {
237 OGDF_ASSERT(v!=NULL);
238 OGDF_ASSERT(v->degree()>0);
239 return m_link[direction][v]->theNode();
242 //! Walks upon external face in \a direction avoiding short circuit edges
243 /** \a direction is not changed.
245 inline node constSuccessorWithoutShortCircuit(node v, int direction) {
246 OGDF_ASSERT(v!=NULL);
247 OGDF_ASSERT(v->degree()>0);
248 return beforeShortCircuitEdge(v,direction)->theNode();
251 //! Returns underlying former adjEntry, if a short circuit edge in \a direction of \a v exists
252 /** Otherwise the common edge is returned. In every case the returned adjEntry
253 * points to the targetnode.
255 inline adjEntry beforeShortCircuitEdge(node v, int direction) {
256 OGDF_ASSERT(v!=NULL);
257 return (m_beforeSCE[direction][v]==NULL) ? m_link[direction][v] : m_beforeSCE[direction][v];
260 //! Walks upon external face in the given \a direction starting at \a w until an active vertex is reached
261 /** Returns dynamical typeinformation \a info of that endvertex.
263 node activeSuccessor(node w, int& direction, int v, int& info);
265 //! Walks upon external face in the given \a direction (without changing it) until an active vertex is reached
266 /** Returns dynamical typeinformation \a info of that endvertex. But does not change the \a direction.
268 inline node constActiveSuccessor(node w, int direction, int v, int& info) {
269 return activeSuccessor(w,direction,v,info);
272 //! Checks, if one ore more wNodes exist between the two stopping vertices \a stopx and \a stopy
273 /** The node \a root is root of the bicomp containing the stopping vertices
275 inline bool wNodesExist(node root, node stopx, node stopy) {
276 OGDF_ASSERT(root != stopx && root != stopy && stopx != stopy);
277 int dir = CCW;
278 bool between = false;
279 while (root != NULL) {
280 root = successorOnExternalFace(root,dir);
281 if (between && pertinent(root)) {
282 return true;
284 if (root == stopx || root == stopy) {
285 if (between) {
286 return false;
288 between = true;
291 return false;
294 //! Prints informations about node \a v
295 inline void printNodeInfo(node v) {
296 cout << "\nprintNodeInfo(" << m_dfi[v] << "): ";
297 cout << "CCW=" << m_dfi[constSuccessorOnExternalFace(v,CCW)];
298 cout << ",CW=" << m_dfi[constSuccessorOnExternalFace(v,CW)];
299 cout << "\tCCWBefore=" << m_dfi[constSuccessorWithoutShortCircuit(v,CCW)];
300 cout << ",CWBefore=" << m_dfi[constSuccessorWithoutShortCircuit(v,CW)];
301 cout << "\tadjList: ";
302 adjEntry adj;
303 for (adj = v->firstAdj(); adj; adj = adj->succ()) {
304 cout << adj->twinNode() << " ";
308 //! Merges the last two biconnected components saved in \a stack while embedding them
309 /** \a j is the outgoing traversal direction of the current node to embed
311 void mergeBiconnectedComponent(StackPure<int>& stack, const int j);
313 //! Merges the last two biconnected components saved in \a stack without embedding them
314 /** \a j is the outgoing traversal direction of the current node to embed
316 void mergeBiconnectedComponentOnlyPlanar(StackPure<int>& stack, const int j);
318 //! Embeds backedges from node \a v with direction \a v_dir to node \a w with direction \a w_dir
319 /** \a i is the DFI of current embedded node.
321 void embedBackedges(const node v, const int v_dir,
322 const node w, const int w_dir, const int i);
324 //! Links (not embed) backedges from node \a v with direction \a v_dir to node \a w with direction \a w_dir
325 /** \a i is the DFI of current embedded node.
327 void embedBackedgesOnlyPlanar(const node v, const int v_dir,
328 const node w, const int w_dir, const int i);
330 //! Creates a short circuit edge from node \a v with direction \a v_dir to node \a w with direction \a w_dir
331 void createShortCircuitEdge(const node v, const int v_dir,
332 const node w, const int w_dir);
334 //! Walkup: Builds the pertinent subgraph for the backedge \a back.
335 /** \a back is the backedge between nodes \a v and \a w. \a v is the current node to embed.
336 * All visited nodes are marked with value \a marker. The Function returns the last traversed node.
338 node walkup(const node v, const node w, const int marker, const edge back);
340 //! Walkdown: Embeds all backedges with DFI \a i as targetnode to node \a v
342 * @param i is the DFI of the current vertex to embed
343 * @param v is the virtual node being the root of the bicomp attached to \a i
344 * @param findKuratowskis collects information in order to extract Kuratowski Subdivisions later
345 * @return 1, iff the embedding process found a stopping configuration
347 int walkdown(const int i, const node v, FindKuratowskis* findKuratowskis);
349 //! Merges unprocessed virtual nodes such as the dfs-roots with their real counterpart
350 void mergeUnprocessedNodes();
352 //! Postprocessing of the graph, so that all virtual vertices are embedded and all bicomps are flipped
353 /** In addition, embedding steps for parallel edges and self-loops are implemented.
355 void postProcessEmbedding();
357 //! Starts the embedding phase, which embeds \a m_g node by node in descending DFI-order.
358 /** Returns true, if graph is planar, false otherwise.
360 bool embed();
363 /***** Members ******/
364 //! Input graph, which can be altered
365 Graph& m_g;
367 //! Some parameters... see BoyerMyrvold for further options
368 const bool m_bundles;
369 const int m_embeddingGrade;
370 const bool m_limitStructures;
371 const bool m_randomDFSTree;
372 const bool m_avoidE2Minors;
374 //! The whole number of bicomps, which have to be flipped
375 int m_flippedNodes;
377 /***** Members from Boyer Myrvold-Init ******/
378 //! Link to non-virtual vertex of a virtual Vertex.
379 /** A virtual vertex has negative DFI of the DFS-Child of related non-virtual Vertex
381 NodeArray<node> m_realVertex;
383 //! The one and only DFI-NodeArray
384 NodeArray<int> m_dfi;
386 //! Returns appropriate node from given DFI
387 Array<node> m_nodeFromDFI;
389 //! Links to opposite adjacency entries on external face in clockwise resp. ccw order
390 /** m_link[0]=CCW, m_link[1]=CW
392 NodeArray<adjEntry> m_link[2];
394 //! Links for short circuit edges.
395 /** If short circuit edges are introduced, the former adjEntries to the neighbors
396 * have to be saved here for embedding and merging purposes. If there is no
397 * short circuit edge, this adjEntry is NULL.
399 NodeArray<adjEntry> m_beforeSCE[2];
401 //! The adjEntry which goes from DFS-parent to current vertex
402 NodeArray<adjEntry> m_adjParent;
404 //! The DFI of the least ancestor node over all backedges
405 /** If no backedge exists, the least ancestor is the DFI of that node itself
407 NodeArray<int> m_leastAncestor;
409 //! Contains the type of each \a edge
410 /** @param 0 = EDGE_UNDEFINED
411 * @param 1 = EDGE_SELFLOOP
412 * @param 2 = EDGE_BACK
413 * @param 3 = EDGE_DFS
414 * @param 4 = EDGE_DFS_PARALLEL
415 * @param 5 = EDGE_BACK_DELETED
417 EdgeArray<int> m_edgeType;
419 //! The lowpoint of each \a node
420 NodeArray<int> m_lowPoint;
422 //! The highest DFI in a subtree with \a node as root
423 NodeArray<int> m_highestSubtreeDFI;
425 //! A list to all separated DFS-children of \a node
426 /** The list is sorted by lowpoint values (in linear time)
428 NodeArray<ListPure<node> > m_separatedDFSChildList;
430 //! Pointer to \a node contained in the DFSChildList of his parent, if exists.
431 /** If node isn't in list or list doesn't exist, the pointer is set to NULL.
433 NodeArray<ListIterator<node> > m_pNodeInParent;
435 /***** Members for Walkup and Walkdown ******/
436 //! This Array keeps track of all vertices that are visited by current walkup
437 NodeArray<int> m_visited;
439 //! Identifies the rootnode of the child bicomp the given backedge points to
440 EdgeArray<node> m_pointsToRoot;
442 //! Keeps track of all vertices that are visited by the walkup through a specific backedge
443 /** This is done in order to refer to the unique child-bicomp of v.
445 NodeArray<int> m_visitedWithBackedge;
447 //! Iff true, the node is the root of a bicomp which has to be flipped.
448 /** The DFS-child of every bicomp root vertex is unique. if a bicomp
449 * is flipped, this DFS-child is marked to check whether the bicomp
450 * has to be flipped or not.
452 NodeArray<bool> m_flipped;
454 //! Holds information, if node is the source of a backedge.
455 /** This information refers to the adjEntries on the targetnode
456 * and is used during the walkdown
458 NodeArray<SListPure<adjEntry> > m_backedgeFlags;
460 //! List of virtual bicomp roots, that are pertinent to the current embedded node
461 NodeArray<SListPure<node> > m_pertinentRoots;
463 //! Data structure for the kuratowski subdivisions, which will be returned
464 SListPure<KuratowskiStructure>& m_output;
470 #endif