Don't import ogdf namespace
[TortoiseGit.git] / ext / OGDF / src / decomposition / PlanarSPQRTree.cpp
blobfef63ac622161b88154d0d417057facc1470adad
1 /*
2 * $Revision: 2599 $
4 * last checkin:
5 * $Author: chimani $
6 * $Date: 2012-07-15 22:39:24 +0200 (So, 15. Jul 2012) $
7 ***************************************************************/
9 /** \file
10 * \brief Implementation of class PlanarSPQRTree
12 * \author Carsten Gutwenger
14 * \par License:
15 * This file is part of the Open Graph Drawing Framework (OGDF).
17 * \par
18 * Copyright (C)<br>
19 * See README.txt in the root directory of the OGDF installation for details.
21 * \par
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
26 * for details.
28 * \par
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.
34 * \par
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 ***************************************************************/
44 #include <ogdf/decomposition/PlanarSPQRTree.h>
45 #include <ogdf/basic/extended_graph_alg.h>
48 namespace ogdf {
50 //-------------------------------------------------------------------
51 // PlanarSPQRTree
52 //-------------------------------------------------------------------
55 // initialization: additionally embeds skeleton graphs or adpots embedding
56 // given by original graph
57 void PlanarSPQRTree::init(bool isEmbedded)
59 if (isEmbedded) {
60 adoptEmbedding();
62 } else {
64 node v;
65 forall_nodes(v,tree())
66 planarEmbed(skeleton(v).getGraph());
71 void PlanarSPQRTree::adoptEmbedding()
73 OGDF_ASSERT_IF(dlExtendedChecking, originalGraph().representsCombEmbedding());
75 // ordered list of adjacency entries (for one original node) in all
76 // skeletons (where this node occurs)
77 NodeArray<SListPure<adjEntry> > adjEdges(tree());
78 // copy in skeleton of current original node
79 NodeArray<node> currentCopy(tree(),0);
80 NodeArray<adjEntry> lastAdj(tree(),0);
81 SListPure<node> current; // currently processed nodes
83 node vOrig;
84 forall_nodes(vOrig,originalGraph())
86 adjEntry adjOrig;
87 forall_adj(adjOrig,vOrig)
89 edge eOrig = adjOrig->theEdge();
90 const Skeleton &S = skeletonOfReal(eOrig);
91 edge eCopy = copyOfReal(eOrig);
93 adjEntry adjCopy = (S.original(eCopy->source()) == vOrig) ?
94 eCopy->adjSource() : eCopy->adjTarget();
96 setPosInEmbedding(adjEdges,currentCopy,lastAdj,current,S,adjCopy);
99 SListConstIterator<node> it;
100 for(it = current.begin(); it.valid(); ++it) {
101 node vT = *it;
103 skeleton(vT).getGraph().sort(currentCopy[vT],adjEdges[vT]);
105 adjEdges[vT].clear();
106 currentCopy[vT] = 0;
109 current.clear();
114 void PlanarSPQRTree::setPosInEmbedding(
115 NodeArray<SListPure<adjEntry> > &adjEdges,
116 NodeArray<node> &currentCopy,
117 NodeArray<adjEntry> &lastAdj,
118 SListPure<node> &current,
119 const Skeleton &S,
120 adjEntry adj)
122 node vT = S.treeNode();
124 adjEdges[vT].pushBack(adj);
126 node vCopy = adj->theNode();
127 node vOrig = S.original(vCopy);
129 if(currentCopy[vT] == 0) {
130 currentCopy[vT] = vCopy;
131 current.pushBack(vT);
133 adjEntry adjVirt;
134 forall_adj(adjVirt,vCopy) {
135 edge eCopy = S.twinEdge(adjVirt->theEdge());
136 if (eCopy == 0) continue;
137 if (adjVirt == adj) {
138 lastAdj[vT] = adj;
139 continue;
142 const Skeleton &STwin = skeleton(S.twinTreeNode(adjVirt->theEdge()));
144 adjEntry adjCopy = (STwin.original(eCopy->source()) == vOrig) ?
145 eCopy->adjSource() : eCopy->adjTarget();
147 setPosInEmbedding(adjEdges,currentCopy,lastAdj,current,
148 STwin, adjCopy);
151 } else if (lastAdj[vT] != 0 && lastAdj[vT] != adj) {
152 adjEntry adjVirt = lastAdj[vT];
153 edge eCopy = S.twinEdge(adjVirt->theEdge());
155 const Skeleton &STwin = skeleton(S.twinTreeNode(adjVirt->theEdge()));
157 adjEntry adjCopy = (STwin.original(eCopy->source()) == vOrig) ?
158 eCopy->adjSource() : eCopy->adjTarget();
160 setPosInEmbedding(adjEdges,currentCopy,lastAdj,current,
161 STwin, adjCopy);
163 lastAdj[vT] = 0;
170 // embed original graph according to embedding of skeletons
172 // The procedure also handles the case when some (real or virtual)
173 // edges are reversed (used in upward-planarity algorithms)
174 void PlanarSPQRTree::embed(Graph &G)
176 OGDF_ASSERT(&G == &originalGraph());
178 const Skeleton &S = skeleton(rootNode());
179 const Graph &M = S.getGraph();
181 node v;
182 forall_nodes(v,M)
184 node vOrig = S.original(v);
185 SListPure<adjEntry> adjEdges;
187 adjEntry adj;
188 forall_adj(adj,v) {
189 edge e = adj->theEdge();
190 edge eOrig = S.realEdge(e);
192 if (eOrig != 0) {
193 adjEntry adjOrig = (vOrig == eOrig->source()) ?
194 eOrig->adjSource() : eOrig->adjTarget();
195 OGDF_ASSERT(adjOrig->theNode() == S.original(v));
196 adjEdges.pushBack(adjOrig);
198 } else {
199 node wT = S.twinTreeNode(e);
200 edge eTwin = S.twinEdge(e);
201 expandVirtualEmbed(wT,
202 (vOrig == skeleton(wT).original(eTwin->source())) ?
203 eTwin->adjSource() : eTwin->adjTarget(),
204 adjEdges);
208 G.sort(vOrig,adjEdges);
211 edge e;
212 forall_adj_edges(e,rootNode()) {
213 node wT = e->target();
214 if (wT != rootNode())
215 createInnerVerticesEmbed(G, wT);
220 void PlanarSPQRTree::expandVirtualEmbed(node vT,
221 adjEntry adjVirt,
222 SListPure<adjEntry> &adjEdges)
224 const Skeleton &S = skeleton(vT);
226 node v = adjVirt->theNode();
227 node vOrig = S.original(v);
229 adjEntry adj;
230 for (adj = adjVirt->cyclicSucc(); adj != adjVirt; adj = adj->cyclicSucc())
232 edge e = adj->theEdge();
233 edge eOrig = S.realEdge(e);
235 if (eOrig != 0) {
236 adjEntry adjOrig = (vOrig == eOrig->source()) ?
237 eOrig->adjSource() : eOrig->adjTarget();
238 OGDF_ASSERT(adjOrig->theNode() == S.original(v));
239 adjEdges.pushBack(adjOrig);
241 } else {
242 node wT = S.twinTreeNode(e);
243 edge eTwin = S.twinEdge(e);
244 expandVirtualEmbed(wT,
245 (vOrig == skeleton(wT).original(eTwin->source())) ?
246 eTwin->adjSource() : eTwin->adjTarget(),
247 adjEdges);
253 void PlanarSPQRTree::createInnerVerticesEmbed(Graph &G, node vT)
255 const Skeleton &S = skeleton(vT);
256 const Graph& M = S.getGraph();
258 node src = S.referenceEdge()->source();
259 node tgt = S.referenceEdge()->target();
261 node v;
262 forall_nodes(v,M)
264 if (v == src || v == tgt) continue;
266 node vOrig = S.original(v);
267 SListPure<adjEntry> adjEdges;
269 adjEntry adj;
270 forall_adj(adj,v) {
271 edge e = adj->theEdge();
272 edge eOrig = S.realEdge(e);
274 if (eOrig != 0) {
275 adjEntry adjOrig = (vOrig == eOrig->source()) ?
276 eOrig->adjSource() : eOrig->adjTarget();
277 OGDF_ASSERT(adjOrig->theNode() == S.original(v));
278 adjEdges.pushBack(adjOrig);
279 } else {
280 node wT = S.twinTreeNode(e);
281 edge eTwin = S.twinEdge(e);
282 expandVirtualEmbed(wT,
283 (vOrig == skeleton(wT).original(eTwin->source())) ?
284 eTwin->adjSource() : eTwin->adjTarget(),
285 adjEdges);
289 G.sort(vOrig,adjEdges);
292 edge e;
293 forall_adj_edges(e,vT) {
294 node wT = e->target();
295 if (wT != vT)
296 createInnerVerticesEmbed(G, wT);
303 // basic update functions for manipulating embeddings
305 // reversing the skeleton of an R- or P-node
306 void PlanarSPQRTree::reverse(node vT)
308 skeleton(vT).getGraph().reverseAdjEdges();
312 // swapping two adjacency entries in the skeleton of a P-node
313 void PlanarSPQRTree::swap(node vT, adjEntry adj1, adjEntry adj2)
315 OGDF_ASSERT(typeOf(vT) == PNode);
317 Graph &M = skeleton(vT).getGraph();
319 M.swapAdjEdges(adj1,adj2);
320 M.swapAdjEdges(adj1->twin(),adj2->twin());
324 // swapping two edges in the skeleton of a P-node
325 void PlanarSPQRTree::swap(node vT, edge e1, edge e2)
327 OGDF_ASSERT(typeOf(vT) == PNode);
329 if (e1->source() == e2->source())
330 swap(vT,e1->adjSource(),e2->adjSource());
331 else
332 swap(vT,e1->adjSource(),e2->adjTarget());
337 // number of possible embeddings of original graph
339 double PlanarSPQRTree::numberOfEmbeddings(node vT) const
341 double num = 1.0;
343 switch(typeOf(vT)) {
344 case RNode:
345 num = 2; break;
346 case PNode:
347 //node vFirst = skeleton(vT).getGraph().firstNode();
348 for (int i = skeleton(vT).getGraph().firstNode()->degree()-1; i >= 2; --i)
349 num *= i;
350 break;
351 case SNode:
352 break;
355 edge e;
356 forall_adj_edges(e,vT) {
357 node wT = e->target();
358 if(wT != vT)
359 num *= numberOfEmbeddings(wT);
362 return num;
368 // randomly embed skeleton graphs
370 void PlanarSPQRTree::randomEmbed()
372 node vT;
373 forall_nodes(vT,tree()) {
374 if (typeOf(vT) == RNode) {
375 int doReverse = randomNumber(0,1);
377 if (doReverse == 1)
378 reverse(vT);
380 } else if (typeOf(vT) == PNode) {
381 const Skeleton &S = skeleton(vT);
382 adjEntry adjRef = S.referenceEdge()->adjSource();
384 SList<adjEntry> adjEdges;
385 adjEntry adj;
386 for (adj = adjRef->cyclicSucc(); adj != adjRef; adj = adj->cyclicSucc())
387 adjEdges.pushBack(adj);
389 adjEdges.permute();
391 adj = adjRef->cyclicSucc();
392 SListConstIterator<adjEntry> it;
393 for (it = adjEdges.begin(); it.valid(); ++it)
395 adjEntry adjNext = *it;
396 if (adjNext != adj) {
397 swap(vT,adj,adjNext);
398 adj = adjNext;
400 adj = adj->cyclicSucc();
407 } // end namespace ogdf