Open
Graph Drawing
Framework

 v. 2023.09 (Elderberry)
 

Loading...
Searching...
No Matches
DualGraph.h
Go to the documentation of this file.
1
32#pragma once
33
38
39namespace ogdf {
40
41template<bool isConst>
42class DualGraphBase;
43
45
47
55template<bool isConst>
57public:
58 using Embedding = typename std::conditional<isConst, const ConstCombinatorialEmbedding,
60
62 explicit DualGraphBase(Embedding& CE) : m_primalEmbedding(CE) {
63 const Graph& primalGraph = CE.getGraph();
64 init(*(new Graph));
65 Graph& dualGraph = getGraph();
66
67 m_dualNode.init(CE);
68 m_dualEdge.init(primalGraph);
69 m_dualFace.init(primalGraph);
70#ifdef OGDF_DEBUG
71 m_primalNode.init(*this, nullptr);
72#else
73 m_primalNode.init(*this);
74#endif
75 m_primalFace.init(dualGraph);
76 m_primalEdge.init(dualGraph);
77
78 // create dual nodes
79 for (face f : CE.faces) {
80 node vDual = dualGraph.newNode();
81 m_dualNode[f] = vDual;
82 m_primalFace[vDual] = f;
83 }
84
85 // create dual edges
86 for (edge e : primalGraph.edges) {
87 adjEntry aE = e->adjSource();
88 node vDualSource = m_dualNode[CE.rightFace(aE)];
89 node vDualTarget = m_dualNode[CE.leftFace(aE)];
91 m_primalEdge[eDual] = e;
92 m_dualEdge[e] = eDual;
93 }
94
95 // sort adjElements of every dual node corresponding to dual embedding
96 for (face f : CE.faces) {
97 node vDual = m_dualNode[f];
98 List<adjEntry> newOrder;
99
100 for (adjEntry adj : f->entries) {
101 edge e = adj->theEdge();
102 edge eDual = m_dualEdge[e];
103 bool isSource = adj == e->adjSource();
104 adjEntry adjDual = isSource ? eDual->adjSource() : eDual->adjTarget();
105 newOrder.pushBack(adjDual);
106 }
107
108 dualGraph.sort(vDual, newOrder);
109 }
110
111 // calculate dual faces and links to corresponding primal nodes
112 computeFaces();
113
114 for (node v : primalGraph.nodes) {
115 edge ePrimal = v->firstAdj()->theEdge();
116 edge eDual = m_dualEdge[ePrimal];
117 face fDual = rightFace(eDual->adjSource());
118 if (ePrimal->source() == v) {
119 fDual = leftFace(eDual->adjSource());
120 }
121
122 OGDF_ASSERT(m_primalNode[fDual] == nullptr);
123
124 m_dualFace[v] = fDual;
125 m_primalNode[fDual] = v;
126 }
127 }
128
131 clear();
132 delete m_cpGraph;
133 }
134
136 Embedding& getPrimalEmbedding() const { return m_primalEmbedding; }
137
139 const Graph& getPrimalGraph() const { return m_primalEmbedding.getGraph(); }
140
143
145
149 const node& primalNode(face f) const { return m_primalNode[f]; }
150
152
156 const edge& primalEdge(edge e) const { return m_primalEdge[e]; }
157
159
163 const face& primalFace(node v) const { return m_primalFace[v]; }
164
166
170 const node& dualNode(face f) const { return m_dualNode[f]; }
171
173
177 const edge& dualEdge(edge e) const { return m_dualEdge[e]; }
178
180
184 const face& dualFace(node v) const { return m_dualFace[v]; }
185
189
193 edge oldDualEdge {m_dualEdge[e]};
194
195#ifdef OGDF_DEBUG
197 face oldDualFace {rightFace(oldDualEdge->adjSource())};
198#endif
199
200 // Create new edge in the primal graph.
201 edge newPrimalEdge {m_primalEmbedding.split(e)};
202 node newPrimalNode {newPrimalEdge->source()};
203
204 // Create new edge in the dual graph.
205 edge newDualEdge {CombinatorialEmbedding::splitFace(oldDualEdge->adjSource(),
206 oldDualEdge->adjSource()->faceCycleSucc())};
207 face newDualFace {leftFace(newDualEdge->adjSource())};
208
209 // Update node and edge mappings.
210 m_dualEdge[newPrimalEdge] = newDualEdge;
211 m_primalEdge[newDualEdge] = newPrimalEdge;
212
213 m_dualFace[newPrimalNode] = newDualFace;
214 m_primalNode[newDualFace] = newPrimalNode;
215
216 OGDF_ASSERT(m_dualFace[oldPrimalNode] == oldDualFace);
217 OGDF_ASSERT(m_primalNode[oldDualFace] == oldPrimalNode);
218
219#ifdef OGDF_HEAVY_DEBUG
221#endif
222
223 return newPrimalEdge;
224 }
225
229 // Join faces in the dual graph, unsplit edge in the primal graph.
230 face oldDualFace {CombinatorialEmbedding::joinFaces(m_dualEdge[eOut])};
231 m_primalEmbedding.unsplit(eIn, eOut);
232 node oldPrimalNode {eIn->target()};
233
234 // Update node and edge mappings.
235 m_dualFace[oldPrimalNode] = oldDualFace;
236 m_primalNode[oldDualFace] = oldPrimalNode;
237 OGDF_ASSERT(m_primalEdge[m_dualEdge[eIn]] == eIn);
238
239#ifdef OGDF_HEAVY_DEBUG
241#endif
242 }
243
247 node oldPrimalNode {adjStartLeft->theNode()};
248 face oldDualFace {m_dualFace[oldPrimalNode]};
249
250 // Split node in the primal graph.
251 node newPrimalNode {m_primalEmbedding.splitNode(adjStartLeft, adjStartRight)};
252 edge newPrimalEdge {adjStartLeft->cyclicPred()->theEdge()};
253
254 // Split face in the dual graph.
255 adjEntry dualAdjLeft {dualAdj(adjStartLeft, true)};
256 adjEntry dualAdjRight {dualAdj(adjStartRight, true)};
257 OGDF_ASSERT(dualAdjLeft->theNode() == m_dualNode[m_primalEmbedding.leftFace(adjStartLeft)]);
258 OGDF_ASSERT(dualAdjRight->theNode() == m_dualNode[m_primalEmbedding.leftFace(adjStartRight)]);
259 edge newDualEdge {CombinatorialEmbedding::splitFace(dualAdjLeft, dualAdjRight)};
260 face newDualFace {leftFace(newDualEdge->adjSource())};
261
262 // Update node and edge mappings.
263 m_dualEdge[newPrimalEdge] = newDualEdge;
264 m_primalEdge[newDualEdge] = newPrimalEdge;
265
266 m_dualFace[newPrimalNode] = oldDualFace;
267 m_primalNode[oldDualFace] = newPrimalNode;
268
269 m_dualFace[oldPrimalNode] = newDualFace;
270 m_primalNode[newDualFace] = oldPrimalNode;
271
272#ifdef OGDF_HEAVY_DEBUG
274#endif
275
276 return newPrimalNode;
277 }
278
282 edge dualEdge {m_dualEdge[e]};
283
284 // Contract e in in the primal graph, join faces in the dual graph.
285 // TODO Joining faces in the dual graph currently always acts as if
286 // keepSelfLoops is true.
287 node newPrimalNode {m_primalEmbedding.contract(e, keepSelfLoops)};
288 face newDualFace {CombinatorialEmbedding::joinFaces(dualEdge)};
289
290 // Update node and edge mappings.
291 m_dualFace[newPrimalNode] = newDualFace;
292 m_primalNode[newDualFace] = newPrimalNode;
293
294#ifdef OGDF_HEAVY_DEBUG
296#endif
297
298 return newPrimalNode;
299 }
300
304#ifdef OGDF_DEBUG
305 face oldPrimalFace {m_primalEmbedding.rightFace(adjSrc)};
306 node oldDualNode {m_dualNode[oldPrimalFace]};
307#endif
308
309 // Create new edge in the primal graph.
310 edge newPrimalEdge {m_primalEmbedding.splitFace(adjSrc, adjTgt, sourceAfter)};
311 face newPrimalFace {m_primalEmbedding.leftFace(newPrimalEdge->adjSource())};
312
313 // Create new edge in the dual graph.
314 adjEntry leftAdj {dualAdj(adjTgt)};
315 adjEntry rightAdj {dualAdj(adjSrc)};
316 OGDF_ASSERT(leftAdj->theNode() == oldDualNode);
317 OGDF_ASSERT(rightAdj->theNode() == oldDualNode);
318
319 node newDualNode {CombinatorialEmbedding::splitNode(leftAdj, rightAdj)};
320 edge newDualEdge {leftAdj->cyclicPred()->theEdge()};
321
322 // Update node and edge mappings.
323 m_dualEdge[newPrimalEdge] = newDualEdge;
324 m_primalEdge[newDualEdge] = newPrimalEdge;
325
326 m_dualNode[newPrimalFace] = newDualNode;
327 m_primalFace[newDualNode] = newPrimalFace;
328
329 OGDF_ASSERT(m_dualNode[oldPrimalFace] == oldDualNode);
330 OGDF_ASSERT(m_primalFace[oldDualNode] == oldPrimalFace);
331
332#ifdef OGDF_HEAVY_DEBUG
334#endif
335
336 return newPrimalEdge;
337 }
338
342 return addEdgeToIsolatedNodePrimal(adjTgt, v, false);
343 }
344
348 return addEdgeToIsolatedNodePrimal(adjSrc, v, true);
349 }
350
354 edge eDual {m_dualEdge[e]};
355
356 // Join faces in the primal graph, contract edges in the dual graph.
357 face oldPrimalFace {m_primalEmbedding.joinFaces(e)};
358 node oldDualNode {CombinatorialEmbedding::contract(eDual, true)};
359
360 m_primalFace[oldDualNode] = oldPrimalFace;
361 m_dualNode[oldPrimalFace] = oldDualNode;
362
363#ifdef OGDF_HEAVY_DEBUG
365#endif
366
367 return oldPrimalFace;
368 }
369
373 OGDF_ASSERT(v->degree() == 1);
374
375 edge primalEdge {v->firstAdj()->theEdge()};
376 edge dualEdge {m_dualEdge[primalEdge]};
377#ifdef OGDF_DEBUG
378 node otherPrimalNode {primalEdge->opposite(v)};
379#endif
380
381 m_primalEmbedding.removeDeg1(v);
382#ifdef OGDF_DEBUG
384#endif
385 CombinatorialEmbedding::joinFaces(dualEdge);
386
388 OGDF_ASSERT(m_primalNode[newDualFace] == otherPrimalNode);
389
390#ifdef OGDF_HEAVY_DEBUG
392#endif
393 }
394
398 m_primalEmbedding.reverseEdge(e);
399 CombinatorialEmbedding::reverseEdge(m_dualEdge[e]);
400
401#ifdef OGDF_HEAVY_DEBUG
403#endif
404 }
405
406#ifdef OGDF_DEBUG
408 void consistencyCheck() const {
409 Embedding::consistencyCheck();
410
411 const Graph& primalGraph {m_primalEmbedding.getGraph()};
412 const Graph& dualGraph {getGraph()};
413 OGDF_ASSERT(primalGraph.numberOfNodes() == numberOfFaces());
414 OGDF_ASSERT(primalGraph.numberOfEdges() == dualGraph.numberOfEdges());
415 OGDF_ASSERT(m_primalEmbedding.numberOfFaces() == dualGraph.numberOfNodes());
416
417 for (node vDual : dualGraph.nodes) {
418 OGDF_ASSERT(m_dualNode[m_primalFace[vDual]] == vDual);
419 }
420 for (edge eDual : dualGraph.edges) {
421 OGDF_ASSERT(m_dualEdge[m_primalEdge[eDual]] == eDual);
422
423 // A dual edge leads from the right to the left face of its primal edge.
424 OGDF_ASSERT(leftFace(eDual->adjSource()) == m_dualFace[m_primalEdge[eDual]->source()]);
425 OGDF_ASSERT(rightFace(eDual->adjSource()) == m_dualFace[m_primalEdge[eDual]->target()]);
426 }
427 for (face fDual : Embedding::faces) {
428 OGDF_ASSERT(m_dualFace[m_primalNode[fDual]] == fDual);
429 }
430 }
431#endif
432
433protected:
441
442private:
446#ifdef OGDF_DEBUG
447 face oldPrimalFace {m_primalEmbedding.rightFace(adj)};
448 node oldDualNode {m_dualNode[oldPrimalFace]};
449#endif
450 node oldPrimalNode {adj->theNode()};
451 face oldDualFace {m_dualFace[oldPrimalNode]};
452
454 edge newPrimalEdge {adjSrc ? m_primalEmbedding.addEdgeToIsolatedNode(adj, v)
455 : m_primalEmbedding.addEdgeToIsolatedNode(v, adj)};
456 // If the new primal edge goes from v to adj, the new dual self-loop has to
457 // go from its right to its left side. Hence, we pass !adjSrc to splitFace().
459 OGDF_ASSERT(dualAdjEntry->theNode() == oldDualNode);
460 edge newDualEdge {CombinatorialEmbedding::splitFace(dualAdjEntry, dualAdjEntry, !adjSrc)};
461 face newDualFace {leftFace(newDualEdge->adjSource())};
462
463 // Update node and edge mappings.
464 m_dualEdge[newPrimalEdge] = newDualEdge;
465 m_primalEdge[newDualEdge] = newPrimalEdge;
466
467 if (adjSrc) {
468 m_primalNode[oldDualFace] = v;
469 m_dualFace[v] = oldDualFace;
470
471 m_primalNode[newDualFace] = oldPrimalNode;
472 m_dualFace[oldPrimalNode] = newDualFace;
473 } else {
474 m_primalNode[newDualFace] = v;
475 m_dualFace[v] = newDualFace;
476
477 OGDF_ASSERT(m_primalNode[oldDualFace] == oldPrimalNode);
478 OGDF_ASSERT(m_dualFace[oldPrimalNode] == oldDualFace);
479 }
480
481#ifdef OGDF_HEAVY_DEBUG
483#endif
484
485 return newPrimalEdge;
486 }
487
490 inline adjEntry dualAdj(adjEntry primalAdj, bool reverse = false) {
491 return primalAdj->isSource() != reverse ? m_dualEdge[primalAdj->theEdge()]->adjSource()
492 : m_dualEdge[primalAdj->theEdge()]->adjTarget();
493 }
494};
495
496}
Declaration of CombinatorialEmbedding and face.
Declaration and implementation of EdgeArray class.
declaration and implementation of FaceArray class
Declaration and implementation of NodeArray class.
Class for adjacency list elements.
Definition Graph_d.h:79
adjEntry faceCyclePred() const
Returns the cyclic predecessor in face.
Definition Graph_d.h:152
edge theEdge() const
Returns the edge associated with this adjacency entry.
Definition Graph_d.h:97
bool isSource() const
Returns true iff this is the source adjacency entry of the corresponding edge.
Definition Graph_d.h:416
node theNode() const
Returns the node whose adjacency list contains this element.
Definition Graph_d.h:103
Combinatorial embeddings of planar graphs with modification functionality.
Combinatorial embeddings of planar graphs.
A dual graph including its combinatorial embedding of an embedded graph.
Definition DualGraph.h:56
const face & primalFace(node v) const
Returns the face in the embedding of the primal graph corresponding to v.
Definition DualGraph.h:163
void removeDeg1Primal(node v)
Removes degree-1 node v.
Definition DualGraph.h:372
~DualGraphBase()
Destructor.
Definition DualGraph.h:130
node splitNodePrimal(adjEntry adjStartLeft, adjEntry adjStartRight)
Splits a node while preserving the order of adjacency entries.
Definition DualGraph.h:246
typename std::conditional< isConst, const ConstCombinatorialEmbedding, CombinatorialEmbedding >::type Embedding
Definition DualGraph.h:59
FaceArray< node > m_dualNode
The corresponding node in the dual graph.
Definition DualGraph.h:438
const face & dualFace(node v) const
Returns the face in the embedding of the dual graph corresponding to v.
Definition DualGraph.h:184
FaceArray< node > m_primalNode
The corresponding node in the primal graph.
Definition DualGraph.h:435
edge addEdgeToIsolatedNodePrimal(adjEntry adjSrc, node v)
Inserts a new edge similarly to splitFace without having to call computeFaces again.
Definition DualGraph.h:347
Embedding & m_primalEmbedding
The embedding of the primal graph.
Definition DualGraph.h:434
EdgeArray< edge > m_primalEdge
The corresponding edge in the primal graph.
Definition DualGraph.h:437
face joinFacesPrimal(edge e)
Removes edge e and joins the two faces adjacent to e.
Definition DualGraph.h:353
void reverseEdgePrimal(edge e)
Reverses edges e and updates embedding.
Definition DualGraph.h:397
edge splitPrimal(edge e)
Splits edge e=(v,w) into e=(v,u) and e'=(u,w) creating a new node u.
Definition DualGraph.h:192
edge splitFacePrimal(adjEntry adjSrc, adjEntry adjTgt, bool sourceAfter=false)
Splits a face by inserting a new edge.
Definition DualGraph.h:303
void unsplitPrimal(edge eIn, edge eOut)
Undoes a split operation.
Definition DualGraph.h:228
const edge & primalEdge(edge e) const
Returns the edge in the primal graph corresponding to e.
Definition DualGraph.h:156
node contractPrimal(edge e, bool keepSelfLoops=false)
Contracts edge e while preserving the order of adjacency entries.
Definition DualGraph.h:281
NodeArray< face > m_dualFace
The corresponding face in embedding of the dual graph.
Definition DualGraph.h:439
const Graph & getPrimalGraph() const
Returns a reference to the primal graph.
Definition DualGraph.h:139
DualGraphBase(Embedding &CE)
Constructor; creates dual graph and its combinatorial embedding.
Definition DualGraph.h:62
const node & dualNode(face f) const
Returns the node in the dual graph corresponding to f.
Definition DualGraph.h:170
Embedding & getPrimalEmbedding() const
Returns a reference to the combinatorial embedding of the primal graph.
Definition DualGraph.h:136
edge addEdgeToIsolatedNodePrimal(adjEntry adj, node v, bool adjSrc)
Inserts a new edge similarly to splitFace without having to call computeFaces again.
Definition DualGraph.h:445
const node & primalNode(face f) const
Returns the node in the primal graph corresponding to f.
Definition DualGraph.h:149
adjEntry dualAdj(adjEntry primalAdj, bool reverse=false)
Returns the corresponding adjEntry of the dual edge of primalAdj (or the opposite adjEntry of the dua...
Definition DualGraph.h:490
EdgeArray< edge > m_dualEdge
The corresponding edge in the dual graph.
Definition DualGraph.h:440
const edge & dualEdge(edge e) const
Returns the edge in the dual graph corresponding to e.
Definition DualGraph.h:177
NodeArray< face > m_primalFace
The corresponding facee in the embedding of the primal graph.
Definition DualGraph.h:436
edge addEdgeToIsolatedNodePrimal(node v, adjEntry adjTgt)
Inserts a new edge similarly to splitFace without having to call computeFaces again.
Definition DualGraph.h:341
Dynamic arrays indexed with edges.
Definition EdgeArray.h:125
Class for the representation of edges.
Definition Graph_d.h:300
adjEntry adjSource() const
Returns the corresponding adjacancy entry at source node.
Definition Graph_d.h:344
node target() const
Returns the target node of the edge.
Definition Graph_d.h:338
Dynamic arrays indexed with faces of a combinatorial embedding.
Definition FaceArray.h:126
Faces in a combinatorial embedding.
Data type for general directed graphs (adjacency list representation).
Definition Graph_d.h:521
Doubly linked lists (maintaining the length of the list).
Definition List.h:1435
iterator pushBack(const E &x)
Adds element x at the end of the list.
Definition List.h:1531
Dynamic arrays indexed with nodes.
Definition NodeArray.h:125
Class for the representation of nodes.
Definition Graph_d.h:177
int degree() const
Returns the degree of the node (indegree + outdegree).
Definition Graph_d.h:220
adjEntry firstAdj() const
Returns the first entry in the adjaceny list.
Definition Graph_d.h:223
#define OGDF_EXPORT
Specifies that a function or class is exported by the OGDF DLL.
Definition config.h:101
Reverse< T > reverse(T &container)
Provides iterators for container to make it easily iterable in reverse.
Definition Reverse.h:74
#define OGDF_ASSERT(expr)
Assert condition expr. See doc/build.md for more information.
Definition basic.h:41
static MultilevelBuilder * getDoubleFactoredZeroAdjustedMerger()
The namespace for all OGDF objects.