Open
Graph Drawing
Framework

 v. 2023.09 (Elderberry)
 

EmbedderMaxFaceBiconnectedGraphsLayers.h
Go to the documentation of this file.
1 
33 #pragma once
34 
35 #include <ogdf/basic/ArrayBuffer.h>
37 #include <ogdf/basic/Graph.h>
38 #include <ogdf/basic/GraphList.h>
39 #include <ogdf/basic/List.h>
40 #include <ogdf/basic/basic.h>
46 
47 namespace ogdf {
48 
50 
62 template<class T>
64 public:
66  static void embed(Graph& G, adjEntry& adjExternal, const NodeArray<T>& nodeLength,
67  const EdgeArray<T>& edgeLength, const node& n = nullptr);
68 
71 
72 private:
75 
76  /* \brief Computes recursively the thickness of the skeleton graph of all
77  * nodes in the SPQR-tree.
78  *
79  * \param spqrTree The SPQR-tree of the treated graph.
80  * \param mu a node in the SPQR-tree.
81  * \param thickness saving the computed results - the thickness of each
82  * skeleton graph.
83  * \param nodeLength is saving for each node of the original graph \p G its
84  * length.
85  * \param edgeLength is saving the edge lengths of all edges in each skeleton
86  * graph of all tree nodes.
87  */
88  static void bottomUpThickness(const StaticSPQRTree& spqrTree, const node& mu,
89  NodeArray<T>& thickness, const NodeArray<T>& nodeLength,
90  const NodeArray<EdgeArray<T>>& edgeLength);
91 
92  /* \brief ExpandEdge embeds all edges in the skeleton graph \a S into an
93  * existing embedding and calls recursively itself for all virtual edges
94  * in S.
95  *
96  * \param spqrTree The SPQR-tree of the treated graph.
97  * \param treeNodeTreated is an array saving for each SPQR-tree node \p mu
98  * whether it was already treated by any call of ExpandEdge or not. Every
99  * \p mu should only be treated once.
100  * \param mu is a node in the SPQR-tree.
101  * \param leftNode is the node adjacent to referenceEdge, which should be "left"
102  * in the embedding
103  * \param nodeLength is an array saving the lengths of the nodes of \p G.
104  * \param edgeLength is saving the edge lengths of all edges in each skeleton
105  * graph of all tree nodes.
106  * \param thickness of each skeleton graph.
107  * \param newOrder is saving for each node \p n in \p G the new adjacency
108  * list. This is an output parameter.
109  * \param adjBeforeNodeArraySource is saving for the source of the reference edge
110  * of the skeleton of mu the adjacency entry, before which new entries have
111  * to be inserted.
112  * \param adjBeforeNodeArrayTarget is saving for the target of the reference edge
113  * of the skeleton of mu the adjacency entry, before which new entries have
114  * to be inserted.
115  * \param delta_u the distance from the second adjacent face of the reference edge
116  * except the external face to the external face of G.
117  * \param delta_d the distance from the external face to the external face of G.
118  * \param adjExternal is an adjacency entry in the external face.
119  * \param n is only set, if ExpandEdge is called for the first time, because
120  * then there is no virtual edge which has to be expanded, but the max face
121  * has to contain a certain node \p n.
122  */
123  static void expandEdge(const StaticSPQRTree& spqrTree, NodeArray<bool>& treeNodeTreated,
124  const node& mu, const node& leftNode, const NodeArray<T>& nodeLength,
125  const NodeArray<EdgeArray<T>>& edgeLength, const NodeArray<T>& thickness,
126  NodeArray<List<adjEntry>>& newOrder,
127  NodeArray<ListIterator<adjEntry>>& adjBeforeNodeArraySource,
128  NodeArray<ListIterator<adjEntry>>& adjBeforeNodeArrayTarget, const T& delta_u,
129  const T& delta_d, adjEntry& adjExternal, const node& n = nullptr);
130 
131  /* \brief Embeds all edges in the skeleton graph \a S of an S-node of the
132  * SPQR-tree into an existing embedding and calls recursively itself for
133  * all virtual edges in S.
134  *
135  * \param spqrTree The SPQR-tree of the treated graph.
136  * \param treeNodeTreated is an array saving for each SPQR-tree node \p mu
137  * whether it was already treated by any call of ExpandEdge or not. Every
138  * \p mu should only be treated once.
139  * \param mu is a node in the SPQR-tree.
140  * \param leftNode is the node adjacent to referenceEdge, which should be "left"
141  * in the embedding
142  * \param nodeLength is an array saving the lengths of the nodes of \p G.
143  * \param edgeLength is saving the edge lengths of all edges in each skeleton
144  * graph of all tree nodes.
145  * \param thickness of each skeleton graph.
146  * \param newOrder is saving for each node \p n in \p G the new adjacency
147  * list. This is an output parameter.
148  * \param adjBeforeNodeArraySource is saving for the source of the reference edge
149  * of the skeleton of mu the adjacency entry, before which new entries have
150  * to be inserted.
151  * \param adjBeforeNodeArrayTarget is saving for the target of the reference edge
152  * of the skeleton of mu the adjacency entry, before which new entries have
153  * to be inserted.
154  * \param delta_u the distance from the second adjacent face of the reference edge
155  * except the external face to the external face of G.
156  * \param delta_d the distance from the external face to the external face of G.
157  * \param adjExternal is an adjacency entry in the external face.
158  */
159  static void expandEdgeSNode(const StaticSPQRTree& spqrTree, NodeArray<bool>& treeNodeTreated,
160  const node& mu, const node& leftNode, const NodeArray<T>& nodeLength,
161  const NodeArray<EdgeArray<T>>& edgeLength, const NodeArray<T>& thickness,
162  NodeArray<List<adjEntry>>& newOrder,
163  NodeArray<ListIterator<adjEntry>>& adjBeforeNodeArraySource,
164  NodeArray<ListIterator<adjEntry>>& adjBeforeNodeArrayTarget, const T& delta_u,
165  const T& delta_d, adjEntry& adjExternal);
166 
167  /* \brief Embeds all edges in the skeleton graph \a S of an P-node of the
168  * SPQR-tree into an existing embedding and calls recursively itself for
169  * all virtual edges in S.
170  *
171  * \param spqrTree The SPQR-tree of the treated graph.
172  * \param treeNodeTreated is an array saving for each SPQR-tree node \p mu
173  * whether it was already treated by any call of ExpandEdge or not. Every
174  * \p mu should only be treated once.
175  * \param mu is a node in the SPQR-tree.
176  * \param leftNode is the node adjacent to referenceEdge, which should be "left"
177  * in the embedding
178  * \param nodeLength is an array saving the lengths of the nodes of \p G.
179  * \param edgeLength is saving the edge lengths of all edges in each skeleton
180  * graph of all tree nodes.
181  * \param thickness of each skeleton graph.
182  * \param newOrder is saving for each node \p n in \p G the new adjacency
183  * list. This is an output parameter.
184  * \param adjBeforeNodeArraySource is saving for the source of the reference edge
185  * of the skeleton of mu the adjacency entry, before which new entries have
186  * to be inserted.
187  * \param adjBeforeNodeArrayTarget is saving for the target of the reference edge
188  * of the skeleton of mu the adjacency entry, before which new entries have
189  * to be inserted.
190  * \param delta_u the distance from the second adjacent face of the reference edge
191  * except the external face to the external face of G.
192  * \param delta_d the distance from the external face to the external face of G.
193  * \param adjExternal is an adjacency entry in the external face.
194  */
195  static void expandEdgePNode(const StaticSPQRTree& spqrTree, NodeArray<bool>& treeNodeTreated,
196  const node& mu, const node& leftNode, const NodeArray<T>& nodeLength,
197  const NodeArray<EdgeArray<T>>& edgeLength, const NodeArray<T>& thickness,
198  NodeArray<List<adjEntry>>& newOrder,
199  NodeArray<ListIterator<adjEntry>>& adjBeforeNodeArraySource,
200  NodeArray<ListIterator<adjEntry>>& adjBeforeNodeArrayTarget, const T& delta_u,
201  const T& delta_d, adjEntry& adjExternal);
202 
203  /* \brief Embeds all edges in the skeleton graph \a S of an R-node of the
204  * SPQR-tree into an existing embedding and calls recursively itself for
205  * all virtual edges in S.
206  *
207  * \param spqrTree The SPQR-tree of the treated graph.
208  * \param treeNodeTreated is an array saving for each SPQR-tree node \p mu
209  * whether it was already treated by any call of ExpandEdge or not. Every
210  * \p mu should only be treated once.
211  * \param mu is a node in the SPQR-tree.
212  * \param leftNode is the node adjacent to referenceEdge, which should be "left"
213  * in the embedding
214  * \param nodeLength is an array saving the lengths of the nodes of \p G.
215  * \param edgeLength is saving the edge lengths of all edges in each skeleton
216  * graph of all tree nodes.
217  * \param thickness of each skeleton graph.
218  * \param newOrder is saving for each node \p n in \p G the new adjacency
219  * list. This is an output parameter.
220  * \param adjBeforeNodeArraySource is saving for the source of the reference edge
221  * of the skeleton of mu the adjacency entry, before which new entries have
222  * to be inserted.
223  * \param adjBeforeNodeArrayTarget is saving for the target of the reference edge
224  * of the skeleton of mu the adjacency entry, before which new entries have
225  * to be inserted.
226  * \param delta_u the distance from the second adjacent face of the reference edge
227  * except the external face to the external face of G.
228  * \param delta_d the distance from the external face to the external face of G.
229  * \param adjExternal is an adjacency entry in the external face.
230  * \param n is only set, if ExpandEdge is called for the first time, because
231  * then there is no virtual edge which has to be expanded, but the max face
232  * has to contain a certain node \p n.
233  */
234  static void expandEdgeRNode(const StaticSPQRTree& spqrTree, NodeArray<bool>& treeNodeTreated,
235  const node& mu, const node& leftNode, const NodeArray<T>& nodeLength,
236  const NodeArray<EdgeArray<T>>& edgeLength, const NodeArray<T>& thickness,
237  NodeArray<List<adjEntry>>& newOrder,
238  NodeArray<ListIterator<adjEntry>>& adjBeforeNodeArraySource,
239  NodeArray<ListIterator<adjEntry>>& adjBeforeNodeArrayTarget, const T& delta_u,
240  const T& delta_d, adjEntry& adjExternal, const node& n = nullptr);
241 
242  /* \brief Writes a given adjacency entry into the newOrder. If the edge
243  * belonging to ae is a virtual edge, it is expanded.
244  *
245  * \param ae is the adjacency entry which has to be expanded.
246  * \param before is the adjacency entry of the node in \p G, before
247  * which ae has to be inserted.
248  * \param spqrTree The SPQR-tree of the treated graph.
249  * \param treeNodeTreated is an array saving for each SPQR-tree node \p mu
250  * whether it was already treated by any call of ExpandEdge or not. Every
251  * \p mu should only be treated once.
252  * \param mu is a node in the SPQR-tree.
253  * \param leftNode is the node adjacent to referenceEdge, which should be "left"
254  * in the embedding
255  * \param nodeLength is an array saving the lengths of the nodes of \p G.
256  * \param edgeLength is saving the edge lengths of all edges in each skeleton
257  * graph of all tree nodes.
258  * \param thickness of each skeleton graph.
259  * \param newOrder is saving for each node \p n in \p G the new adjacency
260  * list. This is an output parameter.
261  * \param adjBeforeNodeArraySource is saving for the source of the reference edge
262  * of the skeleton of mu the adjacency entry, before which new entries have
263  * to be inserted.
264  * \param adjBeforeNodeArrayTarget is saving for the target of the reference edge
265  * of the skeleton of mu the adjacency entry, before which new entries have
266  * to be inserted.
267  * \param delta_u the distance from the second adjacent face of the reference edge
268  * except the external face to the external face of G.
269  * \param delta_d the distance from the external face to the external face of G.
270  * \param adjExternal is an adjacency entry in the external face.
271  */
273  const StaticSPQRTree& spqrTree, NodeArray<bool>& treeNodeTreated, const node& mu,
274  const node& leftNode, const NodeArray<T>& nodeLength,
275  const NodeArray<EdgeArray<T>>& edgeLength, const NodeArray<T>& thickness,
276  NodeArray<List<adjEntry>>& newOrder,
277  NodeArray<ListIterator<adjEntry>>& adjBeforeNodeArraySource,
278  NodeArray<ListIterator<adjEntry>>& adjBeforeNodeArrayTarget, const T& delta_u,
279  const T& delta_d, adjEntry& adjExternal);
280 
281  /* \brief Single source shortest path.
282  *
283  * \param G directed graph
284  * \param s source node
285  * \param length length of an edge
286  * \param d contains shortest path distances after call
287  */
288  static bool sssp(const Graph& G, const node& s, const EdgeArray<T>& length, NodeArray<T>& d);
289 };
290 
291 template<class T>
293  const NodeArray<T>& nodeLength, const EdgeArray<T>& edgeLength, const node& n /* = 0*/) {
294  //Base cases (SPQR-Tree-implementatioin would crash with these inputs):
295  OGDF_ASSERT(G.numberOfNodes() >= 2);
296  if (G.numberOfEdges() <= 2) {
297  edge e = G.firstEdge();
298  adjExternal = e->adjSource();
299  return;
300  }
301 
302  //First step: calculate maximum face and edge lengths for virtual edges
303  StaticSPQRTree spqrTree(G);
304  NodeArray<EdgeArray<T>> edgeLengthSkel;
305  compute(G, nodeLength, edgeLength, &spqrTree, edgeLengthSkel);
306 
307  //Second step: Embed G
308  T biggestFace = -1;
309  node bigFaceMu;
310  if (n == nullptr) {
311  for (node mu : spqrTree.tree().nodes) {
312  //Expand all faces in skeleton(mu) and get size of the largest of them:
313  T sizeMu = largestFaceInSkeleton(spqrTree, mu, nodeLength, edgeLengthSkel);
314  if (sizeMu > biggestFace) {
315  biggestFace = sizeMu;
316  bigFaceMu = mu;
317  }
318  }
319  } else {
320  node* mus = new node[n->degree()];
321  int i = 0;
322  for (adjEntry adj : n->adjEntries) {
323  mus[i] = spqrTree.skeletonOfReal(adj->theEdge()).treeNode();
324  bool alreadySeenMu = false;
325  for (int j = 0; j < i && !alreadySeenMu; j++) {
326  if (mus[i] == mus[j]) {
327  alreadySeenMu = true;
328  }
329  }
330  if (alreadySeenMu) {
331  i++;
332  continue;
333  } else {
334  //Expand all faces in skeleton(mu) containing n and get size of
335  //the largest of them:
336  T sizeInMu =
337  largestFaceContainingNode(spqrTree, mus[i], n, nodeLength, edgeLengthSkel);
338  if (sizeInMu > biggestFace) {
339  biggestFace = sizeInMu;
340  bigFaceMu = mus[i];
341  }
342 
343  i++;
344  }
345  }
346  delete[] mus;
347  }
348 
349  bigFaceMu = spqrTree.rootTreeAt(bigFaceMu);
350 
351  NodeArray<T> thickness(spqrTree.tree());
352  bottomUpThickness(spqrTree, bigFaceMu, thickness, nodeLength, edgeLengthSkel);
353 
354  NodeArray<List<adjEntry>> newOrder(G);
355  NodeArray<bool> treeNodeTreated(spqrTree.tree(), false);
357  adjExternal = nullptr;
358  NodeArray<ListIterator<adjEntry>> adjBeforeNodeArraySource(spqrTree.tree());
359  NodeArray<ListIterator<adjEntry>> adjBeforeNodeArrayTarget(spqrTree.tree());
360  expandEdge(spqrTree, treeNodeTreated, bigFaceMu, nullptr, nodeLength, edgeLengthSkel, thickness,
361  newOrder, adjBeforeNodeArraySource, adjBeforeNodeArrayTarget, 0, 0, adjExternal, n);
362 
363  for (node v : G.nodes) {
364  G.sort(v, newOrder[v]);
365  }
366 }
367 
368 template<class T>
370  ListIterator<adjEntry>& before, const StaticSPQRTree& spqrTree,
371  NodeArray<bool>& treeNodeTreated, const node& mu, const node& leftNode,
372  const NodeArray<T>& nodeLength, const NodeArray<EdgeArray<T>>& edgeLength,
373  const NodeArray<T>& thickness, NodeArray<List<adjEntry>>& newOrder,
374  NodeArray<ListIterator<adjEntry>>& adjBeforeNodeArraySource,
375  NodeArray<ListIterator<adjEntry>>& adjBeforeNodeArrayTarget, const T& delta_u,
376  const T& delta_d, adjEntry& adjExternal) {
377  Skeleton& S = spqrTree.skeleton(mu);
378  edge referenceEdge = S.referenceEdge();
379  if (S.isVirtual(ae->theEdge())) {
380  edge twinE = S.twinEdge(ae->theEdge());
381  node twinNT = S.twinTreeNode(ae->theEdge());
382 #if 0
383  Skeleton& twinS = spqrTree.skeleton(twinNT);
384 #endif
385 
386  if (!treeNodeTreated[twinNT]) {
387  node m_leftNode;
388  if (ae->theEdge()->source() == leftNode) {
389  m_leftNode = twinE->source();
390  } else {
391  m_leftNode = twinE->target();
392  }
393 
394  if (ae->theEdge()->source() == ae->theNode()) {
395  adjBeforeNodeArraySource[twinNT] = before;
396  } else {
397  adjBeforeNodeArrayTarget[twinNT] = before;
398  }
399 
400  //recursion call:
401  expandEdge(spqrTree, treeNodeTreated, twinNT, m_leftNode, nodeLength, edgeLength,
402  thickness, newOrder, adjBeforeNodeArraySource, adjBeforeNodeArrayTarget,
403  delta_u, delta_d, adjExternal);
404  }
405 
406  if (ae->theEdge() == referenceEdge) {
407  if (ae->theNode() == ae->theEdge()->source()) {
408  ListIterator<adjEntry> tmpBefore = adjBeforeNodeArraySource[mu];
409  adjBeforeNodeArraySource[mu] = before;
410  before = tmpBefore;
411  } else {
412  ListIterator<adjEntry> tmpBefore = adjBeforeNodeArrayTarget[mu];
413  adjBeforeNodeArrayTarget[mu] = before;
414  before = tmpBefore;
415  }
416  } else
417  {
418  if (ae->theNode() == ae->theEdge()->source()) {
419  before = adjBeforeNodeArraySource[twinNT];
420  } else {
421  before = adjBeforeNodeArrayTarget[twinNT];
422  }
423  }
424  } else
425  {
426  node origNode = S.original(ae->theNode());
427  edge origEdge = S.realEdge(ae->theEdge());
428 
429  if (origNode == origEdge->source()) {
430  if (!before.valid()) {
431  before = newOrder[origNode].pushBack(origEdge->adjSource());
432  } else {
433  before = newOrder[origNode].insertBefore(origEdge->adjSource(), before);
434  }
435  } else {
436  if (!before.valid()) {
437  before = newOrder[origNode].pushBack(origEdge->adjTarget());
438  } else {
439  before = newOrder[origNode].insertBefore(origEdge->adjTarget(), before);
440  }
441  }
442  }
443 }
444 
445 template<class T>
447  NodeArray<bool>& treeNodeTreated, const node& mu, const node& leftNode,
448  const NodeArray<T>& nodeLength, const NodeArray<EdgeArray<T>>& edgeLength,
449  const NodeArray<T>& thickness, NodeArray<List<adjEntry>>& newOrder,
450  NodeArray<ListIterator<adjEntry>>& adjBeforeNodeArraySource,
451  NodeArray<ListIterator<adjEntry>>& adjBeforeNodeArrayTarget, const T& delta_u,
452  const T& delta_d, adjEntry& adjExternal, const node& n /*= 0*/) {
453  treeNodeTreated[mu] = true;
454 
455  switch (spqrTree.typeOf(mu)) {
457  expandEdgeSNode(spqrTree, treeNodeTreated, mu, leftNode, nodeLength, edgeLength, thickness,
458  newOrder, adjBeforeNodeArraySource, adjBeforeNodeArrayTarget, delta_u, delta_d,
459  adjExternal);
460  break;
462  expandEdgePNode(spqrTree, treeNodeTreated, mu, leftNode, nodeLength, edgeLength, thickness,
463  newOrder, adjBeforeNodeArraySource, adjBeforeNodeArrayTarget, delta_u, delta_d,
464  adjExternal);
465  break;
467  expandEdgeRNode(spqrTree, treeNodeTreated, mu, leftNode, nodeLength, edgeLength, thickness,
468  newOrder, adjBeforeNodeArraySource, adjBeforeNodeArrayTarget, delta_u, delta_d,
469  adjExternal, n);
470  break;
471  default:
472  OGDF_ASSERT(false);
473  }
474 }
475 
476 template<class T>
478  NodeArray<bool>& treeNodeTreated, const node& mu, const node& leftNode,
479  const NodeArray<T>& nodeLength, const NodeArray<EdgeArray<T>>& edgeLength,
480  const NodeArray<T>& thickness, NodeArray<List<adjEntry>>& newOrder,
481  NodeArray<ListIterator<adjEntry>>& adjBeforeNodeArraySource,
482  NodeArray<ListIterator<adjEntry>>& adjBeforeNodeArrayTarget, const T& delta_u,
483  const T& delta_d, adjEntry& adjExternal) {
484  Skeleton& S = spqrTree.skeleton(mu);
485  edge referenceEdge = S.referenceEdge();
486  adjEntry startAdjEntry = nullptr;
487  if (leftNode == nullptr) {
488  for (edge e : S.getGraph().edges) {
489  if (!S.isVirtual(e)) {
490  startAdjEntry = e->adjSource();
491  break;
492  }
493  }
494  OGDF_ASSERT(startAdjEntry != nullptr);
495  } else if (leftNode->firstAdj()->theEdge() == referenceEdge) {
496  startAdjEntry = leftNode->lastAdj();
497  } else {
498  startAdjEntry = leftNode->firstAdj();
499  }
500 
501  adjEntry ae = startAdjEntry;
502  if (adjExternal == nullptr) {
503  edge orgEdge = S.realEdge(ae->theEdge());
504  if (orgEdge->source() == S.original(ae->theNode())) {
505  adjExternal = orgEdge->adjSource()->twin();
506  } else {
507  adjExternal = orgEdge->adjTarget()->twin();
508  }
509  }
510 
512  if (referenceEdge && leftNode == referenceEdge->source()) {
513  before = adjBeforeNodeArraySource[mu];
514  } else if (referenceEdge) {
515  before = adjBeforeNodeArrayTarget[mu];
516  }
517  ListIterator<adjEntry> beforeSource;
518 
519  bool firstStep = true;
520  while (firstStep || ae != startAdjEntry) {
521  //first treat ae with ae->theNode() is left node, then treat its twin:
522  node m_leftNode = ae->theNode();
523 
524  if (ae->theEdge() == referenceEdge) {
525  if (ae->theNode() == referenceEdge->source()) {
526  adjBeforeNodeArraySource[mu] = before;
527  } else {
528  adjBeforeNodeArrayTarget[mu] = before;
529  }
530  } else {
531  if (S.isVirtual(ae->theEdge()) && referenceEdge) {
532  node twinTN = S.twinTreeNode(ae->theEdge());
533  if (ae->theEdge()->source() == ae->theNode()) {
534  if (ae->theEdge()->target() == referenceEdge->source()) {
535  adjBeforeNodeArrayTarget[twinTN] = adjBeforeNodeArraySource[mu];
536  } else if (ae->theEdge()->target() == referenceEdge->target()) {
537  adjBeforeNodeArrayTarget[twinTN] = adjBeforeNodeArrayTarget[mu];
538  }
539  } else {
540  if (ae->theEdge()->source() == referenceEdge->source()) {
541  adjBeforeNodeArraySource[twinTN] = adjBeforeNodeArraySource[mu];
542  } else if (ae->theEdge()->source() == referenceEdge->target()) {
543  adjBeforeNodeArraySource[twinTN] = adjBeforeNodeArrayTarget[mu];
544  }
545  }
546  }
547 
548  adjEntryForNode(ae, before, spqrTree, treeNodeTreated, mu, m_leftNode, nodeLength,
549  edgeLength, thickness, newOrder, adjBeforeNodeArraySource,
550  adjBeforeNodeArrayTarget, delta_u, delta_d, adjExternal);
551  }
552 
553  if (firstStep) {
554  beforeSource = before;
555  firstStep = false;
556  }
557 
558  ae = ae->twin();
559  if (!referenceEdge) {
560  before = nullptr;
561  } else if (ae->theNode() == referenceEdge->source()) {
562  before = adjBeforeNodeArraySource[mu];
563  } else if (ae->theNode() == referenceEdge->target()) {
564  before = adjBeforeNodeArrayTarget[mu];
565  } else {
566  before = nullptr;
567  }
568  if (ae->theEdge() == referenceEdge) {
569  if (ae->theNode() == referenceEdge->source()) {
570  adjBeforeNodeArraySource[mu] = beforeSource;
571  } else {
572  adjBeforeNodeArrayTarget[mu] = beforeSource;
573  }
574  } else {
575  adjEntryForNode(ae, before, spqrTree, treeNodeTreated, mu, m_leftNode, nodeLength,
576  edgeLength, thickness, newOrder, adjBeforeNodeArraySource,
577  adjBeforeNodeArrayTarget, delta_u, delta_d, adjExternal);
578  }
579 
580  //set new adjacency entry pair (ae and its twin):
581  if (ae->theNode()->firstAdj() == ae) {
582  ae = ae->theNode()->lastAdj();
583  } else {
584  ae = ae->theNode()->firstAdj();
585  }
586  }
587 }
588 
589 template<class T>
591  NodeArray<bool>& treeNodeTreated, const node& mu, const node& leftNode,
592  const NodeArray<T>& nodeLength, const NodeArray<EdgeArray<T>>& edgeLength,
593  const NodeArray<T>& thickness, NodeArray<List<adjEntry>>& newOrder,
594  NodeArray<ListIterator<adjEntry>>& adjBeforeNodeArraySource,
595  NodeArray<ListIterator<adjEntry>>& adjBeforeNodeArrayTarget, const T& delta_u,
596  const T& delta_d, adjEntry& adjExternal) {
597  //Choose face defined by virtual edge and the longest edge different from it.
598  Skeleton& S = spqrTree.skeleton(mu);
599  edge referenceEdge = S.referenceEdge();
600  edge altReferenceEdge = nullptr;
601 
602  node m_leftNode = leftNode;
603  if (!m_leftNode) {
604  List<node> nodeList;
605  S.getGraph().allNodes(nodeList);
606  m_leftNode = *(nodeList.begin());
607  }
608  node m_rightNode = m_leftNode->firstAdj()->twinNode();
609 
610  if (referenceEdge == nullptr) {
611  for (edge e : S.getGraph().edges) {
612  if (!S.isVirtual(e)) {
613  altReferenceEdge = e;
614  edge orgEdge = S.realEdge(e);
615  if (orgEdge->source() == S.original(m_leftNode)) {
616  adjExternal = orgEdge->adjSource();
617  } else {
618  adjExternal = orgEdge->adjTarget();
619  }
620  break;
621  }
622  }
623  }
624 
625  //sort edges by length:
626  List<edge> graphEdges;
627  for (edge e : S.getGraph().edges) {
628  if (e == referenceEdge || e == altReferenceEdge) {
629  continue;
630  }
631 
632  if (!graphEdges.begin().valid()) {
633  graphEdges.pushBack(e);
634  } else {
635  for (ListIterator<edge> it = graphEdges.begin(); it.valid(); ++it) {
636  if (edgeLength[mu][e] > edgeLength[mu][*it]) {
637  graphEdges.insertBefore(e, it);
638  break;
639  }
640  ListIterator<edge> next = it;
641  ++next;
642  if (!next.valid()) {
643  graphEdges.pushBack(e);
644  break;
645  }
646  }
647  }
648  }
649 
650  List<edge> rightEdgeOrder;
651  ListIterator<adjEntry> beforeAltRefEdge;
652  ListIterator<adjEntry> beforeLeft;
653 
654  //begin with left node and longest edge:
655  for (int i = 0; i < 2; ++i) {
657  node n;
658  if (i == 0) {
659  n = m_leftNode;
660  } else {
661  n = m_rightNode;
662  before = beforeAltRefEdge;
663  }
664 
665  if (referenceEdge) {
666  if (n == referenceEdge->source()) {
667  before = adjBeforeNodeArraySource[mu];
668  } else {
669  before = adjBeforeNodeArrayTarget[mu];
670  }
671  }
672 
673  adjEntry ae;
674 
675  //all edges except reference edge:
676  if (i == 0) {
677  ListIterator<edge> lastPos;
678  ListIterator<adjEntry> beforeRight;
679  if (referenceEdge) {
680  if (referenceEdge->source() == m_rightNode) {
681  beforeRight = adjBeforeNodeArraySource[mu];
682  } else { //referenceEdge->target() == rightnode
683  beforeRight = adjBeforeNodeArrayTarget[mu];
684  }
685  }
686  bool insertBeforeLast = false;
687  bool oneEdgeInE_a = false;
688  T sum_E_a = 0;
689  T sum_E_b = 0;
690 
691  for (int looper = 0; looper < graphEdges.size(); looper++) {
692  edge e = *(graphEdges.get(looper));
693 
694  if (!lastPos.valid()) {
695  lastPos = rightEdgeOrder.pushBack(e);
696  } else if (insertBeforeLast) {
697  lastPos = rightEdgeOrder.insertBefore(e, lastPos);
698  } else {
699  lastPos = rightEdgeOrder.insertAfter(e, lastPos);
700  }
701 
702  //decide whether to choose face f_a or f_b as f_{mu, mu'}:
703  if (delta_u + sum_E_a < delta_d + sum_E_b) {
704  ListIterator<adjEntry> beforeU = before;
705 
706  if (e->source() == n) {
707  ae = e->adjSource();
708  } else {
709  ae = e->adjTarget();
710  }
711 
712  if (S.isVirtual(e)) {
713  node nu = S.twinTreeNode(e);
714 
715  T delta_u_nu = delta_u + sum_E_a;
716  T delta_d_nu = delta_d + sum_E_b;
717 
718  //buffer computed embedding:
719  NodeArray<List<adjEntry>> tmp_newOrder(spqrTree.originalGraph());
720  ListIterator<adjEntry> tmp_before;
721 
722  adjEntryForNode(ae, tmp_before, spqrTree, treeNodeTreated, mu, m_leftNode,
723  nodeLength, edgeLength, thickness, tmp_newOrder,
724  adjBeforeNodeArraySource, adjBeforeNodeArrayTarget, delta_d_nu,
725  delta_u_nu, adjExternal);
726 
727  //copy buffered embedding reversed into newOrder:
728  node leftOrg = S.original(m_leftNode);
729  node rightOrg = S.original(m_rightNode);
730  for (node nOG : spqrTree.originalGraph().nodes) {
731  List<adjEntry> nOG_tmp_adjList = tmp_newOrder[nOG];
732  if (nOG_tmp_adjList.size() == 0) {
733  continue;
734  }
735 
736  ListIterator<adjEntry>* m_before;
737  if (nOG == leftOrg) {
738  m_before = &beforeU;
739  } else if (nOG == rightOrg && referenceEdge) {
740  m_before = &beforeRight;
741  } else {
742  m_before = new ListIterator<adjEntry>();
743  }
744 
745  for (ListIterator<adjEntry> ae_it = nOG_tmp_adjList.begin();
746  ae_it.valid(); ++ae_it) {
747  adjEntry adjaEnt = *ae_it;
748  if (!m_before->valid()) {
749  *m_before = newOrder[nOG].pushBack(adjaEnt);
750  } else {
751  *m_before = newOrder[nOG].insertBefore(adjaEnt, *m_before);
752  }
753 
754  if (nOG == leftOrg || nOG == rightOrg) {
755  if (S.original(e->source()) == nOG) {
756  adjBeforeNodeArraySource[nu] = *m_before;
757  } else {
758  adjBeforeNodeArrayTarget[nu] = *m_before;
759  }
760  }
761  }
762 
763  if (nOG != leftOrg && (nOG != rightOrg || !referenceEdge)) {
764  delete m_before;
765  }
766  }
767 
768  sum_E_a += thickness[nu];
769  } else
770  {
771  adjEntryForNode(ae, beforeU, spqrTree, treeNodeTreated, mu, m_leftNode,
772  nodeLength, edgeLength, thickness, newOrder, adjBeforeNodeArraySource,
773  adjBeforeNodeArrayTarget, 0, 0, adjExternal);
774 
775  sum_E_a += 1;
776  }
777 
778  insertBeforeLast = false;
779  if (!oneEdgeInE_a) {
780  beforeLeft = beforeU;
781  oneEdgeInE_a = true;
782  }
783  } else
784  {
785  if (S.isVirtual(e)) {
786  node nu = S.twinTreeNode(e);
787  if (referenceEdge) {
788  if (e->source() == n) {
789  adjBeforeNodeArrayTarget[nu] = beforeRight;
790  } else {
791  adjBeforeNodeArraySource[nu] = beforeRight;
792  }
793  }
794  }
795 
796  T delta_u_nu = delta_u + sum_E_a;
797  T delta_d_nu = delta_d + sum_E_b;
798 
799  if (e->source() == n) {
800  ae = e->adjSource();
801  } else {
802  ae = e->adjTarget();
803  }
804 
805  adjEntryForNode(ae, before, spqrTree, treeNodeTreated, mu, m_leftNode,
806  nodeLength, edgeLength, thickness, newOrder, adjBeforeNodeArraySource,
807  adjBeforeNodeArrayTarget, delta_u_nu, delta_d_nu, adjExternal);
808 
809  if (S.isVirtual(e)) {
810  sum_E_b += thickness[S.twinTreeNode(e)];
811  } else {
812  sum_E_b += 1;
813  }
814 
815  insertBeforeLast = true;
816  if (!oneEdgeInE_a) {
817  beforeLeft = before;
818  }
819  }
820  }
821  } else {
822  for (ListIterator<edge> it = rightEdgeOrder.begin(); it.valid(); ++it) {
823  if ((*it)->source() == n) {
824  ae = (*it)->adjSource();
825  } else {
826  ae = (*it)->adjTarget();
827  }
828 
829  adjEntryForNode(ae, before, spqrTree, treeNodeTreated, mu, m_leftNode, nodeLength,
830  edgeLength, thickness, newOrder, adjBeforeNodeArraySource,
831  adjBeforeNodeArrayTarget, 0, 0, adjExternal);
832  }
833  }
834 
835  //(alternative) reference edge at last:
836  if (referenceEdge) {
837  if (i == 0) {
838  if (n == referenceEdge->source()) {
839  adjBeforeNodeArraySource[mu] = beforeLeft;
840  } else {
841  adjBeforeNodeArrayTarget[mu] = beforeLeft;
842  }
843  } else {
844  if (n == referenceEdge->source()) {
845  adjBeforeNodeArraySource[mu] = before;
846  } else {
847  adjBeforeNodeArrayTarget[mu] = before;
848  }
849  }
850  } else {
851  if (altReferenceEdge->source() == n) {
852  ae = altReferenceEdge->adjSource();
853  } else {
854  ae = altReferenceEdge->adjTarget();
855  }
856 
857  adjEntryForNode(ae, before, spqrTree, treeNodeTreated, mu, m_leftNode, nodeLength,
858  edgeLength, thickness, newOrder, adjBeforeNodeArraySource,
859  adjBeforeNodeArrayTarget, 0, 0, adjExternal);
860  }
861  }
862 }
863 
864 template<class T>
866  NodeArray<bool>& treeNodeTreated, const node& mu, const node& leftNode,
867  const NodeArray<T>& nodeLength, const NodeArray<EdgeArray<T>>& edgeLength,
868  const NodeArray<T>& thickness, NodeArray<List<adjEntry>>& newOrder,
869  NodeArray<ListIterator<adjEntry>>& adjBeforeNodeArraySource,
870  NodeArray<ListIterator<adjEntry>>& adjBeforeNodeArrayTarget, const T& delta_u,
871  const T& delta_d, adjEntry& adjExternal, const node& n /* = 0 */) {
872  Skeleton& S = spqrTree.skeleton(mu);
873  edge referenceEdge = S.referenceEdge();
874 
875  //compute biggest face containing the reference edge:
876  face maxFaceContEdge = nullptr;
877  List<node> maxFaceNodes;
878  planarEmbed(S.getGraph());
879  CombinatorialEmbedding combinatorialEmbedding(S.getGraph());
880  T bigFaceSize = -1;
881  adjEntry m_adjExternal = nullptr;
882  for (face f : combinatorialEmbedding.faces) {
883  bool containsVirtualEdgeOrN = false;
884  adjEntry this_m_adjExternal = nullptr;
885  T sizeOfFace = 0;
886  List<node> faceNodes;
887  for (adjEntry ae : f->entries) {
888  faceNodes.pushBack(ae->theNode());
889  if ((n == nullptr && (ae->theEdge() == referenceEdge || !referenceEdge))
890  || S.original(ae->theNode()) == n) {
891  containsVirtualEdgeOrN = true;
892  if (referenceEdge) {
893  this_m_adjExternal = ae;
894  }
895  }
896 
897  if (!referenceEdge && !S.isVirtual(ae->theEdge())) {
898  this_m_adjExternal = ae;
899  }
900 
901  sizeOfFace += edgeLength[mu][ae->theEdge()] + nodeLength[S.original(ae->theNode())];
902  }
903 
904  if (containsVirtualEdgeOrN && this_m_adjExternal && sizeOfFace > bigFaceSize) {
905  maxFaceNodes = faceNodes;
906  bigFaceSize = sizeOfFace;
907  maxFaceContEdge = f;
908  m_adjExternal = this_m_adjExternal;
909  }
910  }
911  OGDF_ASSERT(maxFaceContEdge);
912 
913  if (!adjExternal) {
914  edge orgEdge = S.realEdge(m_adjExternal->theEdge());
915  if (orgEdge->source() == S.original(m_adjExternal->theNode())) {
916  adjExternal = orgEdge->adjSource();
917  } else {
918  adjExternal = orgEdge->adjTarget();
919  }
920  }
921 
922  adjEntry adjMaxFace = m_adjExternal;
923 
924  //if embedding is mirror symmetrical embedding of desired embedding,
925  //invert adjacency list of all nodes:
926  if (referenceEdge) {
927  //successor of adjEntry of virtual edge in adjacency list of leftNode:
928  adjEntry succ_virtualEdge_leftNode;
929  if (leftNode == referenceEdge->source()) {
930  succ_virtualEdge_leftNode = referenceEdge->adjSource()->succ();
931  } else {
932  succ_virtualEdge_leftNode = referenceEdge->adjTarget()->succ();
933  }
934  if (!succ_virtualEdge_leftNode) {
935  succ_virtualEdge_leftNode = leftNode->firstAdj();
936  }
937 
938  bool succVELNAEInExtFace = false;
939  for (adjEntry aeExtFace : maxFaceContEdge->entries) {
940  if (aeExtFace->theEdge() == succ_virtualEdge_leftNode->theEdge()) {
941  succVELNAEInExtFace = true;
942  break;
943  }
944  }
945 
946  if (!succVELNAEInExtFace) {
947  for (node v : S.getGraph().nodes) {
948  List<adjEntry> newAdjOrder;
949  for (adjEntry ae = v->firstAdj(); ae; ae = ae->succ()) {
950  newAdjOrder.pushFront(ae);
951  }
952  S.getGraph().sort(v, newAdjOrder);
953  }
954  adjMaxFace = adjMaxFace->twin();
955  }
956  }
957 
958  NodeArray<bool> nodeTreated(S.getGraph(), false);
959  adjEntry start_ae;
960  if (referenceEdge) {
961  start_ae = adjMaxFace;
962  do {
963  if (start_ae->theEdge() == referenceEdge) {
964  start_ae = start_ae->faceCycleSucc();
965  break;
966  }
967  start_ae = start_ae->faceCycleSucc();
968  } while (start_ae != adjMaxFace);
969  } else {
970  start_ae = adjMaxFace;
971  }
972 
973  //For every edge a buffer saving adjacency entries written in embedding step
974  //for nodes on the maximum face, needed in step for other nodes.
975  EdgeArray<List<adjEntry>> buffer(S.getGraph());
976 
977  bool firstStep = true;
978  bool after_start_ae = true;
979  for (adjEntry ae = start_ae; firstStep || ae != start_ae;
980  after_start_ae = after_start_ae && ae->succ(),
981  ae = after_start_ae ? ae->faceCycleSucc()
982  : (!ae->faceCycleSucc() ? adjMaxFace : ae->faceCycleSucc())) {
983  firstStep = false;
984 #if 0
985  node nodeG = S.original(ae->theNode());
986 #endif
987  nodeTreated[ae->theNode()] = true;
988 
989  //copy adjacency list of nodes into newOrder:
991  edge vE = (ae->theEdge() == referenceEdge) ? referenceEdge : ae->theEdge();
992  node nu = (ae->theEdge() == referenceEdge) ? mu : S.twinTreeNode(ae->theEdge());
993  if (S.isVirtual(vE)) {
994  if (ae->theNode() == vE->source()) {
995  before = adjBeforeNodeArraySource[nu];
996  } else {
997  before = adjBeforeNodeArrayTarget[nu];
998  }
999  }
1000 
1001  bool after_ae = true;
1002  adjEntry m_start_ae;
1003  if (referenceEdge) {
1004  if (ae->theNode() == referenceEdge->source()) {
1005  m_start_ae = referenceEdge->adjSource();
1006  } else if (ae->theNode() == referenceEdge->target()) {
1007  m_start_ae = referenceEdge->adjTarget();
1008  } else {
1009  m_start_ae = ae;
1010  }
1011  } else {
1012  m_start_ae = ae;
1013  }
1014 
1015  adjEntry m_stop_ae;
1016  bool hit_stop_twice = false;
1017  int numOfHits = 0;
1018  if (referenceEdge
1019  && (ae->theNode() == referenceEdge->source()
1020  || ae->theNode() == referenceEdge->target())) {
1021  if (m_start_ae->succ()) {
1022  m_stop_ae = m_start_ae->succ();
1023  } else {
1024  m_stop_ae = m_start_ae->theNode()->firstAdj();
1025  hit_stop_twice = true;
1026  }
1027  } else {
1028  m_stop_ae = m_start_ae;
1029  }
1030 
1031  for (adjEntry aeN = m_start_ae;
1032  after_ae || (hit_stop_twice && numOfHits != 2) || aeN != m_stop_ae;
1033  after_ae = after_ae && aeN->succ(),
1034  aeN = after_ae ? aeN->succ()
1035  : (!aeN->succ() ? ae->theNode()->firstAdj() : aeN->succ()),
1036  numOfHits = (aeN == m_stop_ae) ? numOfHits + 1 : numOfHits) {
1037  node m_leftNode = nullptr;
1038  if (S.isVirtual(aeN->theEdge()) && aeN->theEdge() != referenceEdge) {
1039  //Compute left node of aeN->theNode(). First get adjacency entry in ext. face
1040  //(if edge is in ext. face) and compare face cycle successor with successor
1041  //in node adjacency list. If it is the same, it is the right node, otherwise
1042  //the left.
1043  adjEntry aeExtFace = nullptr;
1044  bool succInExtFace = false;
1045  bool aeNInExtFace = false;
1046  adjEntry aeNSucc = (aeN->succ()) ? aeN->succ() : ae->theNode()->firstAdj();
1047  aeExtFace = adjMaxFace;
1048  do {
1049  if (aeExtFace->theEdge() == aeNSucc->theEdge()) {
1050  succInExtFace = true;
1051  if (aeNInExtFace) {
1052  break;
1053  }
1054  }
1055  if (aeExtFace->theEdge() == aeN->theEdge()) {
1056  aeNInExtFace = true;
1057  if (succInExtFace) {
1058  break;
1059  }
1060  }
1061  aeExtFace = aeExtFace->faceCycleSucc();
1062  } while (aeExtFace != adjMaxFace);
1063  if (aeNInExtFace && succInExtFace) {
1064  m_leftNode = aeN->twinNode();
1065  } else {
1066  m_leftNode = aeN->theNode();
1067  }
1068 
1069  node twinTN = S.twinTreeNode(aeN->theEdge());
1070  if (referenceEdge) {
1071  if (aeN->theEdge()->source() == aeN->theNode()) {
1072  if (aeN->theEdge()->target() == referenceEdge->source()) {
1073  adjBeforeNodeArrayTarget[twinTN] = adjBeforeNodeArraySource[mu];
1074  } else if (aeN->theEdge()->target() == referenceEdge->target()) {
1075  adjBeforeNodeArrayTarget[twinTN] = adjBeforeNodeArrayTarget[mu];
1076  }
1077  } else {
1078  if (aeN->theEdge()->source() == referenceEdge->source()) {
1079  adjBeforeNodeArraySource[twinTN] = adjBeforeNodeArraySource[mu];
1080  } else if (aeN->theEdge()->source() == referenceEdge->target()) {
1081  adjBeforeNodeArraySource[twinTN] = adjBeforeNodeArrayTarget[mu];
1082  }
1083  }
1084  }
1085  }
1086 
1087  adjEntryForNode(aeN, before, spqrTree, treeNodeTreated, mu, m_leftNode, nodeLength,
1088  edgeLength, thickness, newOrder, adjBeforeNodeArraySource,
1089  adjBeforeNodeArrayTarget, 0, 0, adjExternal);
1090 
1091  //if the other node adjacent to the current treated edge is not in the
1092  //max face, put written edges into an buffer and clear the adjacency
1093  //list of that node.
1094  if (!maxFaceNodes.search(aeN->twinNode()).valid()) {
1095  node orig_aeN_twin_theNode = S.original(aeN->twinNode());
1096  buffer[aeN->theEdge()] = newOrder[orig_aeN_twin_theNode];
1097  newOrder[orig_aeN_twin_theNode].clear();
1098  }
1099  }
1100  }
1101 
1102  //Copy of not treated node's adjacency lists (internal nodes). Setting
1103  //of left node depending on minimal distance to external face of the
1104  //face defined by left node.
1105  bool DGcomputed = false;
1106  int f_ext_id = 0;
1107  int f_ref_id = 0;
1108  Graph DG;
1109  ArrayBuffer<node> fPG_to_nDG;
1110  NodeArray<List<adjEntry>> adjacencyList;
1111  List<List<adjEntry>> faces;
1112  NodeArray<T> dist_f_ref;
1113  NodeArray<T> dist_f_ext;
1114  AdjEntryArray<int> ae_to_face;
1115 
1116  for (node v : S.getGraph().nodes) {
1117  if (nodeTreated[v]) {
1118  continue;
1119  }
1120 
1121  node v_original = S.original(v);
1122  nodeTreated[v] = true;
1124  for (adjEntry ae = v->firstAdj(); ae; ae = ae->succ()) {
1125  if (buffer[ae->theEdge()].empty()) {
1126  T delta_u_nu = 0;
1127  T delta_d_nu = 0;
1128  bool frauenlinks = false;
1129  if (S.isVirtual(ae->theEdge())) {
1130  if (!DGcomputed) {
1131  ae_to_face.init(S.getGraph());
1132  EdgeArray<T> edgeLengthDG(DG);
1133  DGcomputed = true;
1134 
1135  //compute dual graph of skeleton graph:
1136  adjacencyList.init(S.getGraph());
1137  for (node nBG : S.getGraph().nodes) {
1138  for (adjEntry ae_nBG : nBG->adjEntries) {
1139  adjacencyList[nBG].pushBack(ae_nBG);
1140  }
1141  }
1142 
1143  NodeArray<List<adjEntry>> adjEntryTreated(S.getGraph());
1144  for (node nBG : S.getGraph().nodes) {
1145  for (adjEntry adj : nBG->adjEntries) {
1146  if (adjEntryTreated[nBG].search(adj).valid()) {
1147  continue;
1148  }
1149 
1150  List<adjEntry> newFace;
1151  adjEntry adj2 = adj;
1152  do {
1153  newFace.pushBack(adj2);
1154  ae_to_face[adj2] = faces.size();
1155  adjEntryTreated[adj2->theNode()].pushBack(adj2);
1156  List<adjEntry>& ladj = adjacencyList[adj2->twinNode()];
1157  adj2 = *ladj.cyclicPred(ladj.search(adj2->twin()));
1158  } while (adj2 != adj);
1159  faces.pushBack(newFace);
1160  }
1161  }
1162 
1163  for (ListIterator<List<adjEntry>> it = faces.begin(); it.valid(); ++it) {
1164  fPG_to_nDG.push(DG.newNode());
1165  }
1166 
1167  NodeArray<List<node>> adjFaces(DG);
1168  int i = 0;
1169  for (ListIterator<List<adjEntry>> it = faces.begin(); it.valid(); ++it) {
1170  int f1_id = i;
1171  for (ListIterator<adjEntry> it2 = (*it).begin(); it2.valid(); ++it2) {
1172  int f2_id = 0;
1173  int j = 0;
1174  for (ListIterator<List<adjEntry>> it3 = faces.begin(); it3.valid();
1175  ++it3) {
1176  bool do_break = false;
1177  for (ListIterator<adjEntry> it4 = (*it3).begin(); it4.valid();
1178  ++it4) {
1179  if ((*it4) == (*it2)->twin()) {
1180  f2_id = j;
1181  do_break = true;
1182  break;
1183  }
1184  }
1185  if (do_break) {
1186  break;
1187  }
1188  j++;
1189  }
1190 
1191  if (f1_id != f2_id
1192  && !adjFaces[fPG_to_nDG[f1_id]].search(fPG_to_nDG[f2_id]).valid()
1193  && !adjFaces[fPG_to_nDG[f2_id]].search(fPG_to_nDG[f1_id]).valid()) {
1194  adjFaces[fPG_to_nDG[f1_id]].pushBack(fPG_to_nDG[f2_id]);
1195  edge e1 = DG.newEdge(fPG_to_nDG[f1_id], fPG_to_nDG[f2_id]);
1196  edge e2 = DG.newEdge(fPG_to_nDG[f2_id], fPG_to_nDG[f1_id]);
1197 
1198  //set edge length:
1199  T e_length = -1;
1200  for (auto f1 : *it) {
1201  edge e = f1->theEdge();
1202  for (auto f2 : *faces.get(f2_id)) {
1203  if (f2->theEdge() == e
1204  && (e_length == -1
1205  || edgeLength[mu][e] < e_length)) {
1206  e_length = edgeLength[mu][e];
1207  }
1208  }
1209  }
1210  edgeLengthDG[e1] = e_length;
1211  edgeLengthDG[e2] = e_length;
1212  }
1213 
1214  if (*it2 == adjMaxFace) {
1215  f_ext_id = f1_id;
1216  }
1217  if (referenceEdge && *it2 == adjMaxFace->twin()) {
1218  f_ref_id = f1_id;
1219  }
1220  }
1221  i++;
1222  }
1223 
1224  //compute shortest path from every face to the external face:
1225  node f_ext_DG = fPG_to_nDG[f_ext_id];
1226  dist_f_ext.init(DG);
1227  sssp(DG, f_ext_DG, edgeLengthDG, dist_f_ext);
1228  if (referenceEdge) {
1229  node f_ref_DG = fPG_to_nDG[f_ref_id];
1230  dist_f_ref.init(DG);
1231  sssp(DG, f_ref_DG, edgeLengthDG, dist_f_ref);
1232  }
1233  }
1234 
1235  //choose face with minimal shortest path:
1236  T min1, min2;
1237  T pi_f_0_f_ext = dist_f_ext[fPG_to_nDG[ae_to_face[ae]]];
1238  T pi_f_1_f_ext = dist_f_ext[fPG_to_nDG[ae_to_face[ae->twin()]]];
1239  if (referenceEdge) {
1240  T pi_f_0_f_ref = dist_f_ref[fPG_to_nDG[ae_to_face[ae]]];
1241  T pi_f_1_f_ref = dist_f_ref[fPG_to_nDG[ae_to_face[ae->twin()]]];
1242 
1243  if (delta_u + pi_f_0_f_ref < delta_d + pi_f_0_f_ext) {
1244  min1 = delta_u + pi_f_0_f_ref;
1245  } else {
1246  min1 = delta_d + pi_f_0_f_ext;
1247  }
1248 
1249  if (delta_u + pi_f_1_f_ref < delta_d + pi_f_1_f_ext) {
1250  min2 = delta_u + pi_f_1_f_ref;
1251  } else {
1252  min2 = delta_d + pi_f_1_f_ext;
1253  }
1254 
1255  if (min1 > min2) {
1256  delta_u_nu = delta_u;
1257  if (pi_f_0_f_ref < pi_f_0_f_ext) {
1258  delta_u_nu += pi_f_0_f_ref;
1259  } else {
1260  delta_u_nu += pi_f_0_f_ext;
1261  }
1262  delta_d_nu = delta_d;
1263  if (pi_f_1_f_ref < pi_f_1_f_ext) {
1264  delta_d_nu += pi_f_1_f_ref;
1265  } else {
1266  delta_d_nu += pi_f_1_f_ext;
1267  }
1268  } else {
1269  frauenlinks = true;
1270  delta_u_nu = delta_u;
1271  if (pi_f_1_f_ref < pi_f_1_f_ext) {
1272  delta_u_nu += pi_f_1_f_ref;
1273  } else {
1274  delta_u_nu += pi_f_1_f_ext;
1275  }
1276  delta_d_nu = delta_d;
1277  if (pi_f_0_f_ref < pi_f_0_f_ext) {
1278  delta_d_nu += pi_f_0_f_ref;
1279  } else {
1280  delta_d_nu += pi_f_0_f_ext;
1281  }
1282  }
1283  } else {
1284  min1 = delta_d + pi_f_0_f_ext;
1285  min2 = delta_d + pi_f_1_f_ext;
1286 
1287  if (min1 > min2) {
1288  delta_u_nu = delta_u + pi_f_0_f_ext;
1289  delta_d_nu = delta_d + pi_f_1_f_ext;
1290  } else {
1291  frauenlinks = true;
1292  delta_u_nu = delta_u + pi_f_1_f_ext;
1293  delta_d_nu = delta_d + pi_f_0_f_ext;
1294  }
1295  }
1296  }
1297 
1298  if (frauenlinks) {
1299  node nu = S.twinTreeNode(ae->theEdge());
1300 
1301  //buffer computed embedding:
1302  NodeArray<List<adjEntry>> tmp_newOrder(spqrTree.originalGraph());
1303  ListIterator<adjEntry> tmp_before;
1304 
1305  adjEntryForNode(ae, tmp_before, spqrTree, treeNodeTreated, mu, v, nodeLength,
1306  edgeLength, thickness, tmp_newOrder, adjBeforeNodeArraySource,
1307  adjBeforeNodeArrayTarget, delta_u_nu, delta_d_nu, adjExternal);
1308 
1309  //copy buffered embedding reversed into newOrder:
1310 #if 0
1311  node m_leftNode = v;
1312 #endif
1313  node m_rightNode = ae->twinNode();
1314  node leftOrg = v_original;
1315  node rightOrg = S.original(m_rightNode);
1316  for (node nOG : spqrTree.originalGraph().nodes) {
1317  List<adjEntry> nOG_tmp_adjList = tmp_newOrder[nOG];
1318  if (nOG_tmp_adjList.size() == 0) {
1319  continue;
1320  }
1321 
1322  ListIterator<adjEntry>* m_before;
1323  if (nOG == leftOrg) {
1324  m_before = &before;
1325  } else {
1326  m_before = new ListIterator<adjEntry>();
1327  }
1328 
1329  for (ListIterator<adjEntry> ae_it = nOG_tmp_adjList.begin(); ae_it.valid();
1330  ++ae_it) {
1331  adjEntry adjaEnt = *ae_it;
1332  if (!m_before->valid()) {
1333  *m_before = newOrder[nOG].pushBack(adjaEnt);
1334  } else {
1335  *m_before = newOrder[nOG].insertBefore(adjaEnt, *m_before);
1336  }
1337 
1338  if (nOG == leftOrg || nOG == rightOrg) {
1339  if (S.original(ae->theEdge()->source()) == nOG) {
1340  adjBeforeNodeArraySource[nu] = *m_before;
1341  } else {
1342  adjBeforeNodeArrayTarget[nu] = *m_before;
1343  }
1344  }
1345  }
1346 
1347  if (nOG != leftOrg) {
1348  delete m_before;
1349  }
1350  }
1351  } else {
1352  adjEntryForNode(ae, before, spqrTree, treeNodeTreated, mu, v, nodeLength,
1353  edgeLength, thickness, newOrder, adjBeforeNodeArraySource,
1354  adjBeforeNodeArrayTarget, delta_u_nu, delta_d_nu, adjExternal);
1355  }
1356 
1357  if (!nodeTreated[ae->twinNode()]) {
1358  node orig_ae_twin_theNode = S.original(ae->twinNode());
1359  buffer[ae->theEdge()] = newOrder[orig_ae_twin_theNode];
1360  newOrder[orig_ae_twin_theNode].clear();
1361  }
1362  } else {
1363  buffer[ae->theEdge()].reverse();
1364  for (ListIterator<adjEntry> it = buffer[ae->theEdge()].begin(); it.valid(); ++it) {
1365  if (!before.valid()) {
1366  before = newOrder[v_original].pushFront(*it);
1367  } else {
1368  before = newOrder[v_original].insertBefore(*it, before);
1369  }
1370  }
1371  }
1372  }
1373  }
1374 }
1375 
1376 template<class T>
1378  const node& mu, NodeArray<T>& thickness, const NodeArray<T>& nodeLength,
1379  const NodeArray<EdgeArray<T>>& edgeLength) {
1380  //recursion:
1381  for (adjEntry adj : mu->adjEntries) {
1382  edge e_mu_to_nu = adj->theEdge();
1383  if (e_mu_to_nu->source() != mu) {
1384  continue;
1385  } else {
1386  node nu = e_mu_to_nu->target();
1387  bottomUpThickness(spqrTree, nu, thickness, nodeLength, edgeLength);
1388  }
1389  }
1390 
1391  Skeleton& S = spqrTree.skeleton(mu);
1392  edge referenceEdge = S.referenceEdge();
1393 
1394  if (!referenceEdge) { //root of SPQR-tree
1395  thickness[mu] = 0;
1396  return;
1397  }
1398 
1399  //set dLengths for all edges in skeleton graph:
1400  EdgeArray<T> dLength(S.getGraph());
1401  for (edge eSG : S.getGraph().edges) {
1402  if (eSG == referenceEdge) {
1403  continue;
1404  }
1405 
1406  if (S.isVirtual(eSG)) {
1407  node twinTN = S.twinTreeNode(eSG);
1408  dLength[eSG] = thickness[twinTN];
1409  } else {
1410  dLength[eSG] = edgeLength[mu][eSG];
1411  }
1412  }
1413 
1414  //compute thickness of skeleton(mu):
1415  switch (spqrTree.typeOf(mu)) {
1417  //thickness(mu) = min_{edges e != referenceEdge} dLength(e)
1418  T min_dLength = -1;
1419  for (edge eSG : S.getGraph().edges) {
1420  if (eSG == referenceEdge) {
1421  continue;
1422  }
1423  if (min_dLength == -1 || dLength[eSG] < min_dLength) {
1424  min_dLength = dLength[eSG];
1425  }
1426  }
1427  thickness[mu] = min_dLength;
1428  } break;
1430  //thickness(mu) = sum_{edges e != referenceEdge} dLength(e)
1431  T sumof_dLength = 0;
1432  for (edge eSG : S.getGraph().edges) {
1433  if (eSG == referenceEdge) {
1434  continue;
1435  }
1436  sumof_dLength += dLength[eSG];
1437  }
1438  thickness[mu] = sumof_dLength;
1439  } break;
1441  /* Let f^ref_0, ... , f^ref_k be the faces sharing at least one edge with
1442  * f_ref - the face adjacent to the reference edge not equal to the
1443  * external face f_ext. Compute the dual graph and set edge lengths for
1444  * two faces f_i, f_j, i != j, with at least one shared edge, to the
1445  * minimal dLength of the shared edges of f_i and f_j. Remove the node
1446  * related to face f_ref. thickness(mu) is then the length of the shortest
1447  * path from any of the faces f^ref_0, ... , f^ref_k to f_ext plus 1.
1448  */
1450  adjEntry ae_f_ext = referenceEdge->adjSource();
1451  adjEntry ae_f_ref = referenceEdge->adjTarget();
1452  T faceSize_f_ext = 0;
1453  adjEntry ae_f_ext_walker = ae_f_ext;
1454  do {
1455  faceSize_f_ext += nodeLength[S.original(ae_f_ext_walker->theNode())]
1456  + edgeLength[mu][ae_f_ext_walker->theEdge()];
1457  ae_f_ext_walker = ae_f_ext_walker->faceCycleSucc();
1458  } while (ae_f_ext_walker != ae_f_ext);
1459  T faceSize_f_ref = 0;
1460  adjEntry ae_f_ref_walker = ae_f_ref;
1461  do {
1462  faceSize_f_ref += nodeLength[S.original(ae_f_ref_walker->theNode())]
1463  + edgeLength[mu][ae_f_ref_walker->theEdge()];
1464  ae_f_ref_walker = ae_f_ref_walker->faceCycleSucc();
1465  } while (ae_f_ref_walker != ae_f_ref);
1466  if (faceSize_f_ext < faceSize_f_ref) {
1467  adjEntry ae_tmp = ae_f_ext;
1468  ae_f_ext = ae_f_ref;
1469  ae_f_ref = ae_tmp;
1470  }
1471 
1472  //compute dual graph:
1473  Graph DG;
1474  ArrayBuffer<node> fPG_to_nDG;
1475  NodeArray<List<adjEntry>> adjacencyList(S.getGraph());
1476  List<List<adjEntry>> faces;
1477  NodeArray<int> distances;
1478  EdgeArray<T> edgeLengthDG(DG);
1479  int f_ref_id = -1;
1480  int f_ext_id = -1;
1481 
1482  for (node nBG : S.getGraph().nodes) {
1483  for (adjEntry ae_nBG : nBG->adjEntries) {
1484  adjacencyList[nBG].pushBack(ae_nBG);
1485  }
1486  }
1487 
1488  NodeArray<List<adjEntry>> adjEntryTreated(S.getGraph());
1489  for (node nBG : S.getGraph().nodes) {
1490  for (adjEntry adj : nBG->adjEntries) {
1491  if (adjEntryTreated[nBG].search(adj).valid()) {
1492  continue;
1493  }
1494 
1495  List<adjEntry> newFace;
1496  adjEntry adj2 = adj;
1497  do {
1498  newFace.pushBack(adj2);
1499  adjEntryTreated[adj2->theNode()].pushBack(adj2);
1500  List<adjEntry>& ladj = adjacencyList[adj2->twinNode()];
1501  adj2 = *ladj.cyclicPred(ladj.search(adj2->twin()));
1502  } while (adj2 != adj);
1503  faces.pushBack(newFace);
1504  }
1505  }
1506 
1507  for (ListIterator<List<adjEntry>> it = faces.begin(); it.valid(); ++it) {
1508  fPG_to_nDG.push(DG.newNode());
1509  }
1510 
1511  NodeArray<List<node>> adjFaces(DG);
1512  int i = 0;
1513  for (ListIterator<List<adjEntry>> it = faces.begin(); it.valid(); ++it) {
1514  int f1_id = i;
1515  for (ListIterator<adjEntry> it2 = (*it).begin(); it2.valid(); ++it2) {
1516  int f2_id = 0;
1517  int j = 0;
1518  for (ListIterator<List<adjEntry>> it3 = faces.begin(); it3.valid(); ++it3) {
1519  bool do_break = false;
1520  for (ListIterator<adjEntry> it4 = (*it3).begin(); it4.valid(); ++it4) {
1521  if ((*it4) == (*it2)->twin()) {
1522  f2_id = j;
1523  do_break = true;
1524  break;
1525  }
1526  }
1527  if (do_break) {
1528  break;
1529  }
1530  j++;
1531  }
1532 
1533  if (f1_id != f2_id && !adjFaces[fPG_to_nDG[f1_id]].search(fPG_to_nDG[f2_id]).valid()
1534  && !adjFaces[fPG_to_nDG[f2_id]].search(fPG_to_nDG[f1_id]).valid()) {
1535  adjFaces[fPG_to_nDG[f1_id]].pushBack(fPG_to_nDG[f2_id]);
1536  adjFaces[fPG_to_nDG[f2_id]].pushBack(fPG_to_nDG[f1_id]);
1537  edge e1 = DG.newEdge(fPG_to_nDG[f1_id], fPG_to_nDG[f2_id]);
1538  edge e2 = DG.newEdge(fPG_to_nDG[f2_id], fPG_to_nDG[f1_id]);
1539 
1540  //set edge length:
1541  T e_length = -1;
1542  for (ListIterator<adjEntry> it_f1 = (*it).begin(); it_f1.valid(); ++it_f1) {
1543  edge e = (*it_f1)->theEdge();
1544  for (ListIterator<adjEntry> it_f2 = (*(faces.get(f2_id))).begin();
1545  it_f2.valid(); ++it_f2) {
1546  if ((*it_f2)->theEdge() == e
1547  && (e_length == -1 || edgeLength[mu][e] < e_length)) {
1548  e_length = edgeLength[mu][e];
1549  }
1550  }
1551  }
1552  edgeLengthDG[e1] = e_length;
1553  edgeLengthDG[e2] = e_length;
1554  }
1555 
1556  if (*it2 == ae_f_ext) {
1557  f_ext_id = f1_id;
1558  }
1559  if (*it2 == ae_f_ref) {
1560  f_ref_id = f1_id;
1561  }
1562  }
1563  i++;
1564  }
1565 
1566  //the faces sharing at least one edge with f_ref:
1567  node nDG_f_ref = fPG_to_nDG[f_ref_id];
1568  List<node>& f_ref_adj_faces = adjFaces[nDG_f_ref];
1569 
1570  //remove node related to f_ref from dual graph:
1571  DG.delNode(fPG_to_nDG[f_ref_id]);
1572 
1573  //compute shortest path and set thickness:
1574  NodeArray<T> dist(DG);
1575  node nDG_f_ext = fPG_to_nDG[f_ext_id];
1576  sssp(DG, nDG_f_ext, edgeLengthDG, dist);
1577  T minDist = -1;
1578  for (ListIterator<node> it_adj_faces = f_ref_adj_faces.begin(); it_adj_faces.valid();
1579  ++it_adj_faces) {
1580  node fDG = *it_adj_faces;
1581  if (fDG != nDG_f_ext) {
1582  T d = dist[fDG];
1583  if (minDist == -1 || d < minDist) {
1584  minDist = d;
1585  }
1586  }
1587  }
1588  thickness[mu] = minDist + 1;
1589  } break;
1590  default:
1591  OGDF_ASSERT(false);
1592  }
1593 }
1594 
1595 template<class T>
1597  const EdgeArray<T>& length, NodeArray<T>& d) {
1598  const T infinity = 20000000; // big number. danger. think about it.
1599 
1600  //Initialize-Single-Source(G, s):
1601  d.init(G);
1602  for (node v : G.nodes) {
1603  d[v] = infinity;
1604  }
1605 
1606  d[s] = 0;
1607  for (int i = 1; i < G.numberOfNodes(); ++i) {
1608  for (edge e : G.edges) {
1609  //relax(u, v, w): // e == (u, v), length == w
1610  if (d[e->target()] > d[e->source()] + length[e]) {
1611  d[e->target()] = d[e->source()] + length[e];
1612  }
1613  }
1614  }
1615 
1616  //check for negative cycle:
1617  for (edge e : G.edges) {
1618  if (d[e->target()] > d[e->source()] + length[e]) {
1619  return false;
1620  }
1621  }
1622 
1623  return true;
1624 }
1625 
1626 }
ogdf::ArrayBuffer
An array that keeps track of the number of inserted elements; also usable as an efficient stack.
Definition: Array.h:53
ogdf
The namespace for all OGDF objects.
Definition: multilevelmixer.cpp:39
ogdf::Skeleton::isVirtual
virtual bool isVirtual(edge e) const =0
Returns true iff e is a virtual edge.
ArrayBuffer.h
Declaration and implementation of ArrayBuffer class.
Graph.h
Includes declaration of graph class.
ogdf::Graph::sort
void sort(node v, const ADJ_ENTRY_LIST &newOrder)
Sorts the adjacency list of node v according to newOrder.
Definition: Graph_d.h:1482
ogdf::StaticSPQRTree
Linear-time implementation of static SPQR-trees.
Definition: StaticSPQRTree.h:79
OGDF_ASSERT
#define OGDF_ASSERT(expr)
Assert condition expr. See doc/build.md for more information.
Definition: basic.h:66
ogdf::Graph::delNode
virtual void delNode(node v)
Removes node v and all incident edges from the graph.
ogdf::AdjElement::theNode
node theNode() const
Returns the node whose adjacency list contains this element.
Definition: Graph_d.h:166
ogdf::matching_blossom::infinity
TWeight infinity()
Helper function to get the maximum value for a given weight type.
Definition: utils.h:46
SPQRTree.h
Declaration of class SPQRTree.
ogdf::Skeleton::realEdge
virtual edge realEdge(edge e) const =0
Returns the real edge that corresponds to skeleton edge e.
ogdf::NodeElement::lastAdj
adjEntry lastAdj() const
Returns the last entry in the adjacency list.
Definition: Graph_d.h:289
extended_graph_alg.h
Declaration of extended graph algorithms.
StaticSPQRTree.h
Declaration of class StaticSPQRTree.
ogdf::EmbedderMaxFaceBiconnectedGraphs
Embedder that maximizing the external face.
Definition: EmbedderMaxFaceBiconnectedGraphs.h:54
ogdf::Graph::allNodes
void allNodes(CONTAINER &nodeContainer) const
Returns a container with all nodes of the graph.
Definition: Graph_d.h:1036
ogdf::FaceElement::entries
internal::FaceAdjContainer entries
Container maintaining the adjacency entries in the face.
Definition: CombinatorialEmbedding.h:142
ogdf::EmbedderMaxFaceBiconnectedGraphsLayers::bottomUpThickness
static void bottomUpThickness(const StaticSPQRTree &spqrTree, const node &mu, NodeArray< T > &thickness, const NodeArray< T > &nodeLength, const NodeArray< EdgeArray< T >> &edgeLength)
Definition: EmbedderMaxFaceBiconnectedGraphsLayers.h:1377
ogdf::EmbedderMaxFaceBiconnectedGraphsLayers::expandEdgeRNode
static void expandEdgeRNode(const StaticSPQRTree &spqrTree, NodeArray< bool > &treeNodeTreated, const node &mu, const node &leftNode, const NodeArray< T > &nodeLength, const NodeArray< EdgeArray< T >> &edgeLength, const NodeArray< T > &thickness, NodeArray< List< adjEntry >> &newOrder, NodeArray< ListIterator< adjEntry >> &adjBeforeNodeArraySource, NodeArray< ListIterator< adjEntry >> &adjBeforeNodeArrayTarget, const T &delta_u, const T &delta_d, adjEntry &adjExternal, const node &n=nullptr)
Definition: EmbedderMaxFaceBiconnectedGraphsLayers.h:865
ogdf::ListIteratorBase::valid
bool valid() const
Returns true iff the iterator points to an element.
Definition: List.h:153
ogdf::EmbedderMaxFaceBiconnectedGraphsLayers::sssp
static bool sssp(const Graph &G, const node &s, const EdgeArray< T > &length, NodeArray< T > &d)
Definition: EmbedderMaxFaceBiconnectedGraphsLayers.h:1596
ogdf::EmbedderMaxFaceBiconnectedGraphsLayers::adjEntryForNode
static void adjEntryForNode(adjEntry &ae, ListIterator< adjEntry > &before, const StaticSPQRTree &spqrTree, NodeArray< bool > &treeNodeTreated, const node &mu, const node &leftNode, const NodeArray< T > &nodeLength, const NodeArray< EdgeArray< T >> &edgeLength, const NodeArray< T > &thickness, NodeArray< List< adjEntry >> &newOrder, NodeArray< ListIterator< adjEntry >> &adjBeforeNodeArraySource, NodeArray< ListIterator< adjEntry >> &adjBeforeNodeArrayTarget, const T &delta_u, const T &delta_d, adjEntry &adjExternal)
Definition: EmbedderMaxFaceBiconnectedGraphsLayers.h:369
ogdf::Direction::before
@ before
ogdf::Skeleton::treeNode
node treeNode() const
Returns the corresponding node in the owner tree T to which S belongs.
Definition: Skeleton.h:80
ogdf::StaticSPQRTree::skeletonOfReal
const Skeleton & skeletonOfReal(edge e) const override
Returns the skeleton that contains the real edge e.
Definition: StaticSPQRTree.h:174
ogdf::EmbedderMaxFaceBiconnectedGraphsLayers
Embedder that maximizes the external face (plus layers approach).
Definition: EmbedderMaxFaceBiconnectedGraphsLayers.h:63
ogdf::AdjElement::twin
adjEntry twin() const
Returns the corresponding adjacency element associated with the same edge.
Definition: Graph_d.h:172
ogdf::List::insertAfter
iterator insertAfter(const E &x, iterator it)
Inserts element x after it.
Definition: List.h:1572
ogdf::AdjElement
Class for adjacency list elements.
Definition: Graph_d.h:142
ogdf::StaticSPQRTree::skeleton
Skeleton & skeleton(node v) const override
Returns the skeleton of node v.
Definition: StaticSPQRTree.h:156
ogdf::AdjElement::theEdge
edge theEdge() const
Returns the edge associated with this adjacency entry.
Definition: Graph_d.h:160
Skeleton.h
Declaration of class Skeleton.
ogdf::Graph::nodes
internal::GraphObjectContainer< NodeElement > nodes
The container containing all node objects.
Definition: Graph_d.h:932
ogdf::ConstCombinatorialEmbedding::faces
internal::GraphObjectContainer< FaceElement > faces
The container containing all face objects.
Definition: CombinatorialEmbedding.h:230
ogdf::Skeleton::referenceEdge
edge referenceEdge() const
Returns the reference edge of S in M.
Definition: Skeleton.h:87
ogdf::NodeElement::degree
int degree() const
Returns the degree of the node (indegree + outdegree).
Definition: Graph_d.h:283
ogdf::List::pushFront
iterator pushFront(const E &x)
Adds element x at the beginning of the list.
Definition: List.h:1534
ogdf::Skeleton::twinEdge
virtual edge twinEdge(edge e) const =0
Returns the twin edge of skeleton edge e.
GraphList.h
Decralation of GraphElement and GraphList classes.
ogdf::SPQRTree::NodeType::PNode
@ PNode
ogdf::AdjElement::succ
adjEntry succ() const
Returns the successor in the adjacency list.
Definition: Graph_d.h:218
ogdf::NodeElement::adjEntries
internal::GraphObjectContainer< AdjElement > adjEntries
The container containing all entries in the adjacency list of this node.
Definition: Graph_d.h:271
ogdf::EmbedderMaxFaceBiconnectedGraphsLayers::embed
static void embed(Graph &G, adjEntry &adjExternal, const NodeArray< T > &nodeLength, const EdgeArray< T > &edgeLength, const node &n=nullptr)
Embeds G by computing and extending a maximum face in G containing n.
Definition: EmbedderMaxFaceBiconnectedGraphsLayers.h:292
ogdf::ArrayBuffer::push
void push(E e)
Puts a new element in the buffer.
Definition: ArrayBuffer.h:217
ogdf::planarEmbed
bool planarEmbed(Graph &G)
Returns true, if G is planar, false otherwise. If true is returned, G will be planarly embedded.
Definition: extended_graph_alg.h:318
ogdf::EdgeElement::source
node source() const
Returns the source node of the edge.
Definition: Graph_d.h:398
ogdf::StaticSPQRTree::rootTreeAt
node rootTreeAt(edge e) override
Roots T at edge e and returns the new root node of T.
ogdf::List
Doubly linked lists (maintaining the length of the list).
Definition: DfsMakeBiconnected.h:40
ogdf::internal::GraphRegisteredArray
RegisteredArray for nodes, edges and adjEntries of a graph.
Definition: Graph_d.h:658
ogdf::StaticSPQRTree::originalGraph
const Graph & originalGraph() const override
Returns a reference to the original graph G.
Definition: StaticSPQRTree.h:123
ogdf::EdgeElement::adjSource
adjEntry adjSource() const
Returns the corresponding adjacancy entry at source node.
Definition: Graph_d.h:407
ogdf::Graph
Data type for general directed graphs (adjacency list representation).
Definition: Graph_d.h:869
ogdf::EmbedderMaxFaceBiconnectedGraphsLayers::expandEdgePNode
static void expandEdgePNode(const StaticSPQRTree &spqrTree, NodeArray< bool > &treeNodeTreated, const node &mu, const node &leftNode, const NodeArray< T > &nodeLength, const NodeArray< EdgeArray< T >> &edgeLength, const NodeArray< T > &thickness, NodeArray< List< adjEntry >> &newOrder, NodeArray< ListIterator< adjEntry >> &adjBeforeNodeArraySource, NodeArray< ListIterator< adjEntry >> &adjBeforeNodeArrayTarget, const T &delta_u, const T &delta_d, adjEntry &adjExternal)
Definition: EmbedderMaxFaceBiconnectedGraphsLayers.h:590
ogdf::EmbedderMaxFaceBiconnectedGraphsLayers::expandEdge
static void expandEdge(const StaticSPQRTree &spqrTree, NodeArray< bool > &treeNodeTreated, const node &mu, const node &leftNode, const NodeArray< T > &nodeLength, const NodeArray< EdgeArray< T >> &edgeLength, const NodeArray< T > &thickness, NodeArray< List< adjEntry >> &newOrder, NodeArray< ListIterator< adjEntry >> &adjBeforeNodeArraySource, NodeArray< ListIterator< adjEntry >> &adjBeforeNodeArrayTarget, const T &delta_u, const T &delta_d, adjEntry &adjExternal, const node &n=nullptr)
Definition: EmbedderMaxFaceBiconnectedGraphsLayers.h:446
ogdf::Skeleton::twinTreeNode
virtual node twinTreeNode(edge e) const =0
Returns the tree node in T containing the twin edge of skeleton edge e.
ogdf::Skeleton::getGraph
const Graph & getGraph() const
Returns a reference to the skeleton graph M.
Definition: Skeleton.h:90
ogdf::AdjElement::twinNode
node twinNode() const
Returns the associated node of the corresponding adjacency entry (shorthand for twin()->theNode()).
Definition: Graph_d.h:175
ogdf::EdgeElement::adjTarget
adjEntry adjTarget() const
Returns the corresponding adjacancy entry at target node.
Definition: Graph_d.h:410
ogdf::StaticSPQRTree::typeOf
NodeType typeOf(node v) const override
Returns the type of node v.
Definition: StaticSPQRTree.h:147
ogdf::StaticSPQRTree::tree
const Graph & tree() const override
Returns a reference to the tree T.
Definition: StaticSPQRTree.h:126
ogdf::Graph::edges
internal::GraphObjectContainer< EdgeElement > edges
The container containing all edge objects.
Definition: Graph_d.h:935
basic.h
Basic declarations, included by all source files.
EmbedderMaxFaceBiconnectedGraphs.h
Declares ogdf::EmbedderMaxFaceBiconnectedGraphs.
CombinatorialEmbedding.h
Declaration of CombinatorialEmbedding and face.
ogdf::Graph::newNode
node newNode(int index=-1)
Creates a new node and returns it.
Definition: Graph_d.h:1064
ogdf::CombinatorialEmbedding
Combinatorial embeddings of planar graphs with modification functionality.
Definition: CombinatorialEmbedding.h:406
ogdf::NodeElement::firstAdj
adjEntry firstAdj() const
Returns the first entry in the adjaceny list.
Definition: Graph_d.h:286
ogdf::AdjElement::faceCycleSucc
adjEntry faceCycleSucc() const
Returns the cyclic successor in face.
Definition: Graph_d.h:212
ogdf::EdgeElement
Class for the representation of edges.
Definition: Graph_d.h:363
List.h
Declaration of doubly linked lists and iterators.
ogdf::Skeleton
Skeleton graphs of nodes in an SPQR-tree.
Definition: Skeleton.h:60
ogdf::RegisteredArray< GraphRegistry< Key >, Value, WithDefault, Graph >::init
void init(const Graph *base=nullptr)
Reinitializes the array. Associates the array with the matching registry of base.
Definition: RegisteredArray.h:858
ogdf::EmbedderMaxFaceBiconnectedGraphsLayers::expandEdgeSNode
static void expandEdgeSNode(const StaticSPQRTree &spqrTree, NodeArray< bool > &treeNodeTreated, const node &mu, const node &leftNode, const NodeArray< T > &nodeLength, const NodeArray< EdgeArray< T >> &edgeLength, const NodeArray< T > &thickness, NodeArray< List< adjEntry >> &newOrder, NodeArray< ListIterator< adjEntry >> &adjBeforeNodeArraySource, NodeArray< ListIterator< adjEntry >> &adjBeforeNodeArrayTarget, const T &delta_u, const T &delta_d, adjEntry &adjExternal)
Definition: EmbedderMaxFaceBiconnectedGraphsLayers.h:477
ogdf::Skeleton::original
virtual node original(node v) const =0
Returns the vertex in the original graph G that corresponds to v.
ogdf::SPQRTree::NodeType::RNode
@ RNode
ogdf::List::size
int size() const
Returns the number of elements in the list.
Definition: List.h:1488
ogdf::ListIteratorBase
Encapsulates a pointer to a list element.
Definition: List.h:51
ogdf::EdgeElement::target
node target() const
Returns the target node of the edge.
Definition: Graph_d.h:401
ogdf::Graph::newEdge
edge newEdge(node v, node w, int index=-1)
Creates a new edge (v,w) and returns it.
Definition: Graph_d.h:1083
ogdf::NodeElement
Class for the representation of nodes.
Definition: Graph_d.h:240
ogdf::List::pushBack
iterator pushBack(const E &x)
Adds element x at the end of the list.
Definition: List.h:1547
ogdf::SPQRTree::NodeType::SNode
@ SNode
ogdf::internal::EdgeArrayBase2
RegisteredArray for edges of a graph, specialized for EdgeArray<edge>.
Definition: Graph_d.h:716
ogdf::List::insertBefore
iterator insertBefore(const E &x, iterator it)
Inserts element x before it.
Definition: List.h:1566
ogdf::FaceElement
Faces in a combinatorial embedding.
Definition: CombinatorialEmbedding.h:118