Open
Graph Drawing
Framework

 v. 2023.09 (Elderberry)
 

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