Open
Graph Drawing
Framework

 v. 2023.09 (Elderberry)
 

EmbedderMaxFaceBiconnectedGraphs.h
Go to the documentation of this file.
1 
32 #pragma once
33 
35 #include <ogdf/basic/Graph.h>
36 #include <ogdf/basic/GraphList.h>
37 #include <ogdf/basic/List.h>
38 #include <ogdf/basic/basic.h>
43 
44 namespace ogdf {
45 
47 
53 template<class T>
55 public:
66  static void embed(Graph& G, adjEntry& adjExternal, const NodeArray<T>& nodeLength,
67  const EdgeArray<T>& edgeLength, const node& n = nullptr);
68 
78  static void compute(const Graph& G, const NodeArray<T>& nodeLength,
79  const EdgeArray<T>& edgeLength, StaticSPQRTree* spqrTree,
80  NodeArray<EdgeArray<T>>& edgeLengthSkel);
81 
90  static T computeSize(const Graph& G, const node& n, const NodeArray<T>& nodeLength,
91  const EdgeArray<T>& edgeLength);
92 
104  static T computeSize(const Graph& G, const node& n, const NodeArray<T>& nodeLength,
105  const EdgeArray<T>& edgeLength, StaticSPQRTree* spqrTree);
106 
120  static T computeSize(const Graph& G, const node& n, const NodeArray<T>& nodeLength,
121  const EdgeArray<T>& edgeLength, StaticSPQRTree* spqrTree,
122  const NodeArray<EdgeArray<T>>& edgeLengthSkel);
123 
131  static T computeSize(const Graph& G, const NodeArray<T>& nodeLength,
132  const EdgeArray<T>& edgeLength);
133 
147  static T computeSize(const Graph& G, const NodeArray<T>& nodeLength,
148  const EdgeArray<T>& edgeLength, StaticSPQRTree* spqrTree,
149  NodeArray<EdgeArray<T>>& edgeLengthSkel);
150 
151 protected:
162  static void bottomUpTraversal(StaticSPQRTree& spqrTree, const node& mu,
163  const NodeArray<T>& nodeLength, NodeArray<EdgeArray<T>>& edgeLength);
164 
175  static void topDownTraversal(StaticSPQRTree& spqrTree, const node& mu,
176  const NodeArray<T>& nodeLength, NodeArray<EdgeArray<T>>& edgeLength);
177 
189  static T largestFaceContainingNode(const StaticSPQRTree& spqrTree, const node& mu, const node& n,
190  const NodeArray<T>& nodeLength, const NodeArray<EdgeArray<T>>& edgeLength);
191 
201  static T largestFaceInSkeleton(const StaticSPQRTree& spqrTree, const node& mu,
202  const NodeArray<T>& nodeLength, const NodeArray<EdgeArray<T>>& edgeLength);
203 
204  /* \brief ExpandEdge embeds all edges in the skeleton graph \a S into an
205  * existing embedding and calls recursively itself for all virtual edges
206  * in S.
207  *
208  * \param spqrTree The SPQR-tree of the treated graph.
209  * \param treeNodeTreated is an array saving for each SPQR-tree node \p mu
210  * whether it was already treated by any call of ExpandEdge or not. Every
211  * \p mu should only be treated once.
212  * \param mu is a node in the SPQR-tree.
213  * \param leftNode is the node adjacent to referenceEdge, which should be "left"
214  * in the embedding
215  * \param nodeLength is an array saving the lengths of the nodes of \p G.
216  * \param edgeLength is saving the edge lengths of all edges in each skeleton
217  * graph of all tree nodes.
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 adjExternal is an adjacency entry in the external face.
227  * \param n is only set, if ExpandEdge is called for the first time, because
228  * then there is no virtual edge which has to be expanded, but the max face
229  * has to contain a certain node \p n.
230  */
231  static void expandEdge(const StaticSPQRTree& spqrTree, NodeArray<bool>& treeNodeTreated,
232  const node& mu, const node& leftNode, const NodeArray<T>& nodeLength,
233  const NodeArray<EdgeArray<T>>& edgeLength, NodeArray<List<adjEntry>>& newOrder,
234  NodeArray<ListIterator<adjEntry>>& adjBeforeNodeArraySource,
235  NodeArray<ListIterator<adjEntry>>& adjBeforeNodeArrayTarget, adjEntry& adjExternal,
236  const node& n = nullptr);
237 
238  /* \brief Embeds all edges in the skeleton graph \a S of an S-node of the
239  * SPQR-tree into an existing embedding and calls recursively itself for
240  * all virtual edges in S.
241  *
242  * \param spqrTree The SPQR-tree of the treated graph.
243  * \param treeNodeTreated is an array saving for each SPQR-tree node \p mu
244  * whether it was already treated by any call of ExpandEdge or not. Every
245  * \p mu should only be treated once.
246  * \param mu is a node in the SPQR-tree.
247  * \param leftNode is the node adjacent to referenceEdge, which should be "left"
248  * in the embedding
249  * \param nodeLength is an array saving the lengths of the nodes of \p G.
250  * \param edgeLength is saving the edge lengths of all edges in each skeleton
251  * graph of all tree nodes.
252  * \param newOrder is saving for each node \p n in \p G the new adjacency
253  * list. This is an output parameter.
254  * \param adjBeforeNodeArraySource is saving for the source of the reference edge
255  * of the skeleton of mu the adjacency entry, before which new entries have
256  * to be inserted.
257  * \param adjBeforeNodeArrayTarget is saving for the target of the reference edge
258  * of the skeleton of mu the adjacency entry, before which new entries have
259  * to be inserted.
260  * \param adjExternal is an adjacency entry in the external face.
261  */
262  static void expandEdgeSNode(const StaticSPQRTree& spqrTree, NodeArray<bool>& treeNodeTreated,
263  const node& mu, const node& leftNode, const NodeArray<T>& nodeLength,
264  const NodeArray<EdgeArray<T>>& edgeLength, NodeArray<List<adjEntry>>& newOrder,
265  NodeArray<ListIterator<adjEntry>>& adjBeforeNodeArraySource,
266  NodeArray<ListIterator<adjEntry>>& adjBeforeNodeArrayTarget, adjEntry& adjExternal);
267 
268  /* \brief Embeds all edges in the skeleton graph \a S of an P-node of the
269  * SPQR-tree into an existing embedding and calls recursively itself for
270  * all virtual edges in S.
271  *
272  * \param spqrTree The SPQR-tree of the treated graph.
273  * \param treeNodeTreated is an array saving for each SPQR-tree node \p mu
274  * whether it was already treated by any call of ExpandEdge or not. Every
275  * \p mu should only be treated once.
276  * \param mu is a node in the SPQR-tree.
277  * \param leftNode is the node adjacent to referenceEdge, which should be "left"
278  * in the embedding
279  * \param nodeLength is an array saving the lengths of the nodes of \p G.
280  * \param edgeLength is saving the edge lengths of all edges in each skeleton
281  * graph of all tree nodes.
282  * \param newOrder is saving for each node \p n in \p G the new adjacency
283  * list. This is an output parameter.
284  * \param adjBeforeNodeArraySource is saving for the source of the reference edge
285  * of the skeleton of mu the adjacency entry, before which new entries have
286  * to be inserted.
287  * \param adjBeforeNodeArrayTarget is saving for the target of the reference edge
288  * of the skeleton of mu the adjacency entry, before which new entries have
289  * to be inserted.
290  * \param adjExternal is an adjacency entry in the external face.
291  */
292  static void expandEdgePNode(const StaticSPQRTree& spqrTree, NodeArray<bool>& treeNodeTreated,
293  const node& mu, const node& leftNode, const NodeArray<T>& nodeLength,
294  const NodeArray<EdgeArray<T>>& edgeLength, NodeArray<List<adjEntry>>& newOrder,
295  NodeArray<ListIterator<adjEntry>>& adjBeforeNodeArraySource,
296  NodeArray<ListIterator<adjEntry>>& adjBeforeNodeArrayTarget, adjEntry& adjExternal);
297 
298  /* \brief Embeds all edges in the skeleton graph \a S of an R-node of the
299  * SPQR-tree into an existing embedding and calls recursively itself for
300  * all virtual edges in S.
301  *
302  * \param spqrTree The SPQR-tree of the treated graph.
303  * \param treeNodeTreated is an array saving for each SPQR-tree node \p mu
304  * whether it was already treated by any call of ExpandEdge or not. Every
305  * \p mu should only be treated once.
306  * \param mu is a node in the SPQR-tree.
307  * \param leftNode is the node adjacent to referenceEdge, which should be "left"
308  * in the embedding
309  * \param nodeLength is an array saving the lengths of the nodes of \p G.
310  * \param edgeLength is saving the edge lengths of all edges in each skeleton
311  * graph of all tree nodes.
312  * \param newOrder is saving for each node \p n in \p G the new adjacency
313  * list. This is an output parameter.
314  * \param adjBeforeNodeArraySource is saving for the source of the reference edge
315  * of the skeleton of mu the adjacency entry, before which new entries have
316  * to be inserted.
317  * \param adjBeforeNodeArrayTarget is saving for the target of the reference edge
318  * of the skeleton of mu the adjacency entry, before which new entries have
319  * to be inserted.
320  * \param adjExternal is an adjacency entry in the external face.
321  * \param n is only set, if ExpandEdge is called for the first time, because
322  * then there is no virtual edge which has to be expanded, but the max face
323  * has to contain a certain node \p n.
324  */
325  static void expandEdgeRNode(const StaticSPQRTree& spqrTree, NodeArray<bool>& treeNodeTreated,
326  const node& mu, const node& leftNode, const NodeArray<T>& nodeLength,
327  const NodeArray<EdgeArray<T>>& edgeLength, NodeArray<List<adjEntry>>& newOrder,
328  NodeArray<ListIterator<adjEntry>>& adjBeforeNodeArraySource,
329  NodeArray<ListIterator<adjEntry>>& adjBeforeNodeArrayTarget, adjEntry& adjExternal,
330  const node& n);
331 
332  /* \brief Writes a given adjacency entry into the newOrder. If the edge
333  * belonging to ae is a virtual edge, it is expanded.
334  *
335  * \param ae is the adjacency entry which has to be expanded.
336  * \param before is the adjacency entry of the node in \p G, before
337  * which ae has to be inserted.
338  * \param spqrTree The SPQR-tree of the treated graph.
339  * \param treeNodeTreated is an array saving for each SPQR-tree node \p mu
340  * whether it was already treated by any call of ExpandEdge or not. Every
341  * \p mu should only be treated once.
342  * \param mu is a node in the SPQR-tree.
343  * \param leftNode is the node adjacent to referenceEdge, which should be "left"
344  * in the embedding
345  * \param nodeLength is an array saving the lengths of the nodes of \p G.
346  * \param edgeLength is saving the edge lengths of all edges in each skeleton
347  * graph of all tree nodes.
348  * \param newOrder is saving for each node \p n in \p G the new adjacency
349  * list. This is an output parameter.
350  * \param adjBeforeNodeArraySource is saving for the source of the reference edge
351  * of the skeleton of mu the adjacency entry, before which new entries have
352  * to be inserted.
353  * \param adjBeforeNodeArrayTarget is saving for the target of the reference edge
354  * of the skeleton of mu the adjacency entry, before which new entries have
355  * to be inserted.
356  * \param adjExternal is an adjacency entry in the external face.
357  */
359  const StaticSPQRTree& spqrTree, NodeArray<bool>& treeNodeTreated, const node& mu,
360  const node& leftNode, const NodeArray<T>& nodeLength,
361  const NodeArray<EdgeArray<T>>& edgeLength, NodeArray<List<adjEntry>>& newOrder,
362  NodeArray<ListIterator<adjEntry>>& adjBeforeNodeArraySource,
363  NodeArray<ListIterator<adjEntry>>& adjBeforeNodeArrayTarget, adjEntry& adjExternal);
364 };
365 
366 template<class T>
368  const NodeArray<T>& nodeLength, const EdgeArray<T>& edgeLength, const node& n /* = 0*/) {
369  //Base cases (SPQR-Tree implementation would crash with these inputs):
370  OGDF_ASSERT(G.numberOfNodes() >= 2);
371  if (G.numberOfEdges() <= 2) {
372  edge e = G.firstEdge();
373  adjExternal = e->adjSource();
374  return;
375  }
376 
377  //First step: calculate maximum face and edge lengths for virtual edges
378  StaticSPQRTree spqrTree(G);
379  NodeArray<EdgeArray<T>> edgeLengthSkel;
380  compute(G, nodeLength, edgeLength, &spqrTree, edgeLengthSkel);
381 
382  //Second step: Embed G
383  T biggestFace = -1;
384  node bigFaceMu = nullptr;
385  if (n == nullptr) {
386  for (node mu : spqrTree.tree().nodes) {
387  //Expand all faces in skeleton(mu) and get size of the largest of them:
388  T sizeMu = largestFaceInSkeleton(spqrTree, mu, nodeLength, edgeLengthSkel);
389  if (sizeMu > biggestFace) {
390  biggestFace = sizeMu;
391  bigFaceMu = mu;
392  }
393  }
394  } else {
395  node* mus = new node[n->degree()];
396  int i = 0;
397  for (adjEntry adj : n->adjEntries) {
398  edge nAdjEdge = adj->theEdge();
399  mus[i] = spqrTree.skeletonOfReal(nAdjEdge).treeNode();
400  bool alreadySeenMu = false;
401  for (int j = 0; j < i && !alreadySeenMu; j++) {
402  if (mus[i] == mus[j]) {
403  alreadySeenMu = true;
404  }
405  }
406  if (alreadySeenMu) {
407  i++;
408  continue;
409  } else {
410  //Expand all faces in skeleton(mu) containing n and get size of
411  //the largest of them:
412  T sizeInMu =
413  largestFaceContainingNode(spqrTree, mus[i], n, nodeLength, edgeLengthSkel);
414  if (sizeInMu > biggestFace) {
415  biggestFace = sizeInMu;
416  bigFaceMu = mus[i];
417  }
418 
419  i++;
420  }
421  }
422  delete[] mus;
423  }
424  OGDF_ASSERT(bigFaceMu != nullptr);
425 
426  bigFaceMu = spqrTree.rootTreeAt(bigFaceMu);
427 
428  NodeArray<List<adjEntry>> newOrder(G);
429  NodeArray<bool> treeNodeTreated(spqrTree.tree(), false);
431  adjExternal = nullptr;
432  NodeArray<ListIterator<adjEntry>> adjBeforeNodeArraySource(spqrTree.tree());
433  NodeArray<ListIterator<adjEntry>> adjBeforeNodeArrayTarget(spqrTree.tree());
434  expandEdge(spqrTree, treeNodeTreated, bigFaceMu, nullptr, nodeLength, edgeLengthSkel, newOrder,
435  adjBeforeNodeArraySource, adjBeforeNodeArrayTarget, adjExternal, n);
436 
437  for (node v : G.nodes) {
438  G.sort(v, newOrder[v]);
439  }
440 }
441 
442 template<class T>
444  ListIterator<adjEntry>& before, const StaticSPQRTree& spqrTree,
445  NodeArray<bool>& treeNodeTreated, const node& mu, const node& leftNode,
446  const NodeArray<T>& nodeLength, const NodeArray<EdgeArray<T>>& edgeLength,
447  NodeArray<List<adjEntry>>& newOrder,
448  NodeArray<ListIterator<adjEntry>>& adjBeforeNodeArraySource,
449  NodeArray<ListIterator<adjEntry>>& adjBeforeNodeArrayTarget, adjEntry& adjExternal) {
450  Skeleton& S = spqrTree.skeleton(mu);
451  edge referenceEdge = S.referenceEdge();
452  if (S.isVirtual(ae->theEdge())) {
453  edge twinE = S.twinEdge(ae->theEdge());
454  node twinNT = S.twinTreeNode(ae->theEdge());
455 #if 0
456  Skeleton& twinS = spqrTree.skeleton(twinNT);
457 #endif
458 
459  if (!treeNodeTreated[twinNT]) {
460  node m_leftNode;
461  if (ae->theEdge()->source() == leftNode) {
462  m_leftNode = twinE->source();
463  } else {
464  m_leftNode = twinE->target();
465  }
466 
467  if (ae->theEdge()->source() == ae->theNode()) {
468  adjBeforeNodeArraySource[twinNT] = before;
469  } else {
470  adjBeforeNodeArrayTarget[twinNT] = before;
471  }
472 
473  //recursion call:
474  expandEdge(spqrTree, treeNodeTreated, twinNT, m_leftNode, nodeLength, edgeLength,
475  newOrder, adjBeforeNodeArraySource, adjBeforeNodeArrayTarget, adjExternal);
476  }
477 
478  if (ae->theEdge() == referenceEdge) {
479  if (ae->theNode() == ae->theEdge()->source()) {
480  ListIterator<adjEntry> tmpBefore = adjBeforeNodeArraySource[mu];
481  adjBeforeNodeArraySource[mu] = before;
482  before = tmpBefore;
483  } else {
484  ListIterator<adjEntry> tmpBefore = adjBeforeNodeArrayTarget[mu];
485  adjBeforeNodeArrayTarget[mu] = before;
486  before = tmpBefore;
487  }
488  } else
489  {
490  if (ae->theNode() == ae->theEdge()->source()) {
491  before = adjBeforeNodeArraySource[twinNT];
492  } else {
493  before = adjBeforeNodeArrayTarget[twinNT];
494  }
495  }
496  } else
497  {
498  node origNode = S.original(ae->theNode());
499  edge origEdge = S.realEdge(ae->theEdge());
500  if (origNode == origEdge->source()) {
501  if (!before.valid()) {
502  before = newOrder[origNode].pushBack(origEdge->adjSource());
503  } else {
504  before = newOrder[origNode].insertBefore(origEdge->adjSource(), before);
505  }
506  } else {
507  if (!before.valid()) {
508  before = newOrder[origNode].pushBack(origEdge->adjTarget());
509  } else {
510  before = newOrder[origNode].insertBefore(origEdge->adjTarget(), before);
511  }
512  }
513  }
514 }
515 
516 template<class T>
518  NodeArray<bool>& treeNodeTreated, const node& mu, const node& leftNode,
519  const NodeArray<T>& nodeLength, const NodeArray<EdgeArray<T>>& edgeLength,
520  NodeArray<List<adjEntry>>& newOrder,
521  NodeArray<ListIterator<adjEntry>>& adjBeforeNodeArraySource,
522  NodeArray<ListIterator<adjEntry>>& adjBeforeNodeArrayTarget, adjEntry& adjExternal,
523  const node& n /*= 0*/) {
524  treeNodeTreated[mu] = true;
525 
526  switch (spqrTree.typeOf(mu)) {
528  expandEdgeSNode(spqrTree, treeNodeTreated, mu, leftNode, nodeLength, edgeLength, newOrder,
529  adjBeforeNodeArraySource, adjBeforeNodeArrayTarget, adjExternal);
530  break;
532  expandEdgePNode(spqrTree, treeNodeTreated, mu, leftNode, nodeLength, edgeLength, newOrder,
533  adjBeforeNodeArraySource, adjBeforeNodeArrayTarget, adjExternal);
534  break;
536  expandEdgeRNode(spqrTree, treeNodeTreated, mu, leftNode, nodeLength, edgeLength, newOrder,
537  adjBeforeNodeArraySource, adjBeforeNodeArrayTarget, adjExternal, n);
538  break;
539  default:
540  OGDF_ASSERT(false);
541  }
542 }
543 
544 template<class T>
546  NodeArray<bool>& treeNodeTreated, const node& mu, const node& leftNode,
547  const NodeArray<T>& nodeLength, const NodeArray<EdgeArray<T>>& edgeLength,
548  NodeArray<List<adjEntry>>& newOrder,
549  NodeArray<ListIterator<adjEntry>>& adjBeforeNodeArraySource,
550  NodeArray<ListIterator<adjEntry>>& adjBeforeNodeArrayTarget, adjEntry& adjExternal) {
551  Skeleton& S = spqrTree.skeleton(mu);
552  edge referenceEdge = S.referenceEdge();
553  adjEntry startAdjEntry = nullptr;
554  if (!leftNode) {
555  for (edge e : S.getGraph().edges) {
556  if (!S.isVirtual(e)) {
557  startAdjEntry = e->adjSource();
558  break;
559  }
560  }
561  OGDF_ASSERT(startAdjEntry);
562  } else if (leftNode->firstAdj()->theEdge() == referenceEdge) {
563  startAdjEntry = leftNode->lastAdj();
564  } else {
565  startAdjEntry = leftNode->firstAdj();
566  }
567 
568  adjEntry ae = startAdjEntry;
569  if (!adjExternal) {
570  edge orgEdge = S.realEdge(ae->theEdge());
571  if (orgEdge->source() == S.original(ae->theNode())) {
572  adjExternal = orgEdge->adjSource()->twin();
573  } else {
574  adjExternal = orgEdge->adjTarget()->twin();
575  }
576  }
577 
579  if (referenceEdge && leftNode == referenceEdge->source()) {
580  before = adjBeforeNodeArraySource[mu];
581  } else if (referenceEdge) {
582  before = adjBeforeNodeArrayTarget[mu];
583  }
584  ListIterator<adjEntry> beforeSource;
585 
586  bool firstStep = true;
587  while (firstStep || ae != startAdjEntry) {
588  //first treat ae with ae->theNode() is left node, then treat its twin:
589  node m_leftNode = ae->theNode();
590 
591  if (ae->theEdge() == referenceEdge) {
592  // NOLINTNEXTLINE(clang-analyzer-core.CallAndMessage): referenceEdge cannot be null
593  if (ae->theNode() == referenceEdge->source()) {
594  adjBeforeNodeArraySource[mu] = before;
595  } else {
596  adjBeforeNodeArrayTarget[mu] = before;
597  }
598  } else {
599  adjEntryForNode(ae, before, spqrTree, treeNodeTreated, mu, m_leftNode, nodeLength,
600  edgeLength, newOrder, adjBeforeNodeArraySource, adjBeforeNodeArrayTarget,
601  adjExternal);
602  }
603 
604  if (firstStep) {
605  beforeSource = before;
606  firstStep = false;
607  }
608 
609  ae = ae->twin();
610  before = nullptr;
611  if (ae->theEdge() == referenceEdge) {
612  // NOLINTNEXTLINE(clang-analyzer-core.CallAndMessage): referenceEdge cannot be null
613  if (ae->theNode() == referenceEdge->source()) {
614  adjBeforeNodeArraySource[mu] = beforeSource;
615  } else {
616  adjBeforeNodeArrayTarget[mu] = beforeSource;
617  }
618  } else {
619  adjEntryForNode(ae, before, spqrTree, treeNodeTreated, mu, m_leftNode, nodeLength,
620  edgeLength, newOrder, adjBeforeNodeArraySource, adjBeforeNodeArrayTarget,
621  adjExternal);
622  }
623 
624  //set new adjacency entry pair (ae and its twin):
625  if (ae->theNode()->firstAdj() == ae) {
626  ae = ae->theNode()->lastAdj();
627  } else {
628  ae = ae->theNode()->firstAdj();
629  }
630  }
631 }
632 
633 template<class T>
635  NodeArray<bool>& treeNodeTreated, const node& mu, const node& leftNode,
636  const NodeArray<T>& nodeLength, const NodeArray<EdgeArray<T>>& edgeLength,
637  NodeArray<List<adjEntry>>& newOrder,
638  NodeArray<ListIterator<adjEntry>>& adjBeforeNodeArraySource,
639  NodeArray<ListIterator<adjEntry>>& adjBeforeNodeArrayTarget, adjEntry& adjExternal) {
640  //Choose face defined by virtual edge and the longest edge different from it.
641  Skeleton& S = spqrTree.skeleton(mu);
642  edge referenceEdge = S.referenceEdge();
643  edge altReferenceEdge = nullptr;
644 
645  node m_leftNode = leftNode;
646  if (!m_leftNode) {
647  List<node> nodeList;
648  S.getGraph().allNodes(nodeList);
649  m_leftNode = *(nodeList.begin());
650  }
651  node m_rightNode = m_leftNode->firstAdj()->twinNode();
652 
653  if (!referenceEdge) {
654  for (edge e : S.getGraph().edges) {
655  if (!S.isVirtual(e)) {
656  altReferenceEdge = e;
657  edge orgEdge = S.realEdge(e);
658  if (orgEdge->source() == S.original(m_leftNode)) {
659  adjExternal = orgEdge->adjSource();
660  } else {
661  adjExternal = orgEdge->adjTarget();
662  }
663 
664  break;
665  }
666  }
667  }
668 
669  edge longestEdge = nullptr;
670  for (edge e : S.getGraph().edges) {
671  if (e == referenceEdge || e == altReferenceEdge) {
672  continue;
673  }
674  if (!longestEdge || edgeLength[mu][e] > edgeLength[mu][longestEdge]) {
675  longestEdge = e;
676  }
677  }
678 
679  List<edge> rightEdgeOrder;
680  ListIterator<adjEntry> beforeAltRefEdge;
681 
682  //begin with left node and longest edge:
683  for (int i = 0; i < 2; ++i) {
685  node n;
686  if (i == 0) {
687  n = m_leftNode;
688  } else {
689  n = m_rightNode;
690  before = beforeAltRefEdge;
691  }
692 
693  if (referenceEdge) {
694  if (n == referenceEdge->source()) {
695  before = adjBeforeNodeArraySource[mu];
696  } else {
697  before = adjBeforeNodeArrayTarget[mu];
698  }
699  }
700 
701  List<edge> edgeList;
702  S.getGraph().allEdges(edgeList);
703  adjEntry ae;
704 
705  //if left node, longest edge at first:
706  if (i == 0) {
707  if (longestEdge->source() == n) {
708  ae = longestEdge->adjSource();
709  } else {
710  ae = longestEdge->adjTarget();
711  }
712 
713  if (referenceEdge && S.isVirtual(longestEdge)) {
714  node nu = S.twinTreeNode(longestEdge);
715  if (longestEdge->source() == n) {
716  if (referenceEdge->source() == n) {
717  adjBeforeNodeArrayTarget[nu] = adjBeforeNodeArrayTarget[mu];
718  } else {
719  adjBeforeNodeArrayTarget[nu] = adjBeforeNodeArraySource[mu];
720  }
721  } else {
722  if (referenceEdge->source() == n) {
723  adjBeforeNodeArraySource[nu] = adjBeforeNodeArrayTarget[mu];
724  } else {
725  adjBeforeNodeArraySource[nu] = adjBeforeNodeArraySource[mu];
726  }
727  }
728  }
729 
730  adjEntryForNode(ae, before, spqrTree, treeNodeTreated, mu, m_leftNode, nodeLength,
731  edgeLength, newOrder, adjBeforeNodeArraySource, adjBeforeNodeArrayTarget,
732  adjExternal);
733  }
734 
735  //all edges except reference edge and longest edge:
736  if (i == 0) {
737  //all virtual edges
738  for (edge e : edgeList) {
739  if (e == referenceEdge || e == longestEdge || e == altReferenceEdge
740  || !S.isVirtual(e)) {
741  continue;
742  }
743 
744  node nu = S.twinTreeNode(e);
745  if (referenceEdge != nullptr && e->source() == n) {
746  if (referenceEdge->source() == n) {
747  adjBeforeNodeArrayTarget[nu] = adjBeforeNodeArrayTarget[mu];
748  } else {
749  adjBeforeNodeArrayTarget[nu] = adjBeforeNodeArraySource[mu];
750  }
751  } else if (referenceEdge) {
752  if (referenceEdge->source() == n) {
753  adjBeforeNodeArraySource[nu] = adjBeforeNodeArrayTarget[mu];
754  } else {
755  adjBeforeNodeArraySource[nu] = adjBeforeNodeArraySource[mu];
756  }
757  }
758 
759  rightEdgeOrder.pushFront(e);
760 
761  if (e->source() == n) {
762  ae = e->adjSource();
763  } else {
764  ae = e->adjTarget();
765  }
766 
767  adjEntryForNode(ae, before, spqrTree, treeNodeTreated, mu, m_leftNode, nodeLength,
768  edgeLength, newOrder, adjBeforeNodeArraySource, adjBeforeNodeArrayTarget,
769  adjExternal);
770  }
771 
772  //all real edges
773  for (edge e : edgeList) {
774  if (e == referenceEdge || e == longestEdge || e == altReferenceEdge
775  || S.isVirtual(e)) {
776  continue;
777  }
778 
779  rightEdgeOrder.pushFront(e);
780 
781  if (e->source() == n) {
782  ae = e->adjSource();
783  } else {
784  ae = e->adjTarget();
785  }
786 
787  adjEntryForNode(ae, before, spqrTree, treeNodeTreated, mu, m_leftNode, nodeLength,
788  edgeLength, newOrder, adjBeforeNodeArraySource, adjBeforeNodeArrayTarget,
789  adjExternal);
790  }
791  } else {
792  for (edge e : rightEdgeOrder) {
793  if (e->source() == n) {
794  ae = e->adjSource();
795  } else {
796  ae = e->adjTarget();
797  }
798 
799  adjEntryForNode(ae, before, spqrTree, treeNodeTreated, mu, m_leftNode, nodeLength,
800  edgeLength, newOrder, adjBeforeNodeArraySource, adjBeforeNodeArrayTarget,
801  adjExternal);
802  }
803  }
804 
805  //if not left node, longest edge:
806  if (i == 1) {
807  if (longestEdge->source() == n) {
808  ae = longestEdge->adjSource();
809  } else {
810  ae = longestEdge->adjTarget();
811  }
812 
813  adjEntryForNode(ae, before, spqrTree, treeNodeTreated, mu, m_leftNode, nodeLength,
814  edgeLength, newOrder, adjBeforeNodeArraySource, adjBeforeNodeArrayTarget,
815  adjExternal);
816  }
817 
818  //(alternative) reference edge at last:
819  if (referenceEdge) {
820  if (n == referenceEdge->source()) {
821  adjBeforeNodeArraySource[mu] = before;
822  } else {
823  adjBeforeNodeArrayTarget[mu] = before;
824  }
825  } else {
826  node newLeftNode;
827  if (i == 0) {
828  newLeftNode = m_leftNode->firstAdj()->twinNode();
829  } else {
830  newLeftNode = m_leftNode;
831  }
832 
833  if (altReferenceEdge->source() == n) {
834  ae = altReferenceEdge->adjSource();
835  } else {
836  ae = altReferenceEdge->adjTarget();
837  }
838 
839  adjEntryForNode(ae, before, spqrTree, treeNodeTreated, mu, newLeftNode, nodeLength,
840  edgeLength, newOrder, adjBeforeNodeArraySource, adjBeforeNodeArrayTarget,
841  adjExternal);
842 
843  if (i == 0 && S.isVirtual(altReferenceEdge)) {
844  node nu = S.twinTreeNode(altReferenceEdge);
845  if (altReferenceEdge->source() == n) {
846  beforeAltRefEdge = adjBeforeNodeArrayTarget[nu];
847  } else {
848  beforeAltRefEdge = adjBeforeNodeArraySource[nu];
849  }
850  }
851  }
852  }
853 }
854 
855 template<class T>
857  NodeArray<bool>& treeNodeTreated, const node& mu, const node& leftNode,
858  const NodeArray<T>& nodeLength, const NodeArray<EdgeArray<T>>& edgeLength,
859  NodeArray<List<adjEntry>>& newOrder,
860  NodeArray<ListIterator<adjEntry>>& adjBeforeNodeArraySource,
861  NodeArray<ListIterator<adjEntry>>& adjBeforeNodeArrayTarget, adjEntry& adjExternal,
862  const node& n /* = 0 */) {
863  Skeleton& S = spqrTree.skeleton(mu);
864  edge referenceEdge = S.referenceEdge();
865 
866  //compute biggest face containing the reference edge:
867  face maxFaceContEdge = nullptr;
868  List<node> maxFaceNodes;
869  planarEmbed(S.getGraph());
870  CombinatorialEmbedding combinatorialEmbedding(S.getGraph());
871  T bigFaceSize = -1;
872  adjEntry m_adjExternal = nullptr;
873  for (face f : combinatorialEmbedding.faces) {
874  bool containsVirtualEdgeOrN = false;
875  adjEntry this_m_adjExternal = nullptr;
876  T sizeOfFace = 0;
877  List<node> faceNodes;
878  for (adjEntry ae : f->entries) {
879  faceNodes.pushBack(ae->theNode());
880  if ((n == nullptr && (ae->theEdge() == referenceEdge || !referenceEdge))
881  || S.original(ae->theNode()) == n) {
882  containsVirtualEdgeOrN = true;
883  if (referenceEdge) {
884  this_m_adjExternal = ae;
885  }
886  }
887 
888  if (!referenceEdge && !S.isVirtual(ae->theEdge())) {
889  this_m_adjExternal = ae;
890  }
891 
892  sizeOfFace += edgeLength[mu][ae->theEdge()] + nodeLength[S.original(ae->theNode())];
893  }
894 
895  if (containsVirtualEdgeOrN && this_m_adjExternal && sizeOfFace > bigFaceSize) {
896  maxFaceNodes = faceNodes;
897  bigFaceSize = sizeOfFace;
898  maxFaceContEdge = f;
899  m_adjExternal = this_m_adjExternal;
900  }
901  }
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  OGDF_ASSERT(maxFaceContEdge);
913  adjEntry adjMaxFace = maxFaceContEdge->firstAdj();
914 
915  //if embedding is mirror symmetrical embedding of desired embedding,
916  //invert adjacency list of all nodes:
917  if (referenceEdge) {
918  //successor of adjEntry of virtual edge in adjacency list of leftNode:
919  adjEntry succ_virtualEdge_leftNode;
920  if (leftNode == referenceEdge->source()) {
921  succ_virtualEdge_leftNode = referenceEdge->adjSource()->succ();
922  } else {
923  succ_virtualEdge_leftNode = referenceEdge->adjTarget()->succ();
924  }
925  if (!succ_virtualEdge_leftNode) {
926  succ_virtualEdge_leftNode = leftNode->firstAdj();
927  }
928 
929  bool succVELNAEInExtFace = false;
930  for (adjEntry aeExtFace : maxFaceContEdge->entries) {
931  if (aeExtFace->theEdge() == succ_virtualEdge_leftNode->theEdge()) {
932  succVELNAEInExtFace = true;
933  break;
934  }
935  }
936 
937  if (!succVELNAEInExtFace) {
938  for (node v : S.getGraph().nodes) {
939  List<adjEntry> newAdjOrder;
940  for (adjEntry ae = v->firstAdj(); ae; ae = ae->succ()) {
941  newAdjOrder.pushFront(ae);
942  }
943  S.getGraph().sort(v, newAdjOrder);
944  }
945  adjMaxFace = adjMaxFace->twin();
946  }
947  }
948 
949  NodeArray<bool> nodeTreated(S.getGraph(), false);
950  adjEntry start_ae;
951  if (referenceEdge) {
952  start_ae = adjMaxFace;
953  do {
954  if (start_ae->theEdge() == referenceEdge) {
955  start_ae = start_ae->faceCycleSucc();
956  break;
957  }
958  start_ae = start_ae->faceCycleSucc();
959  } while (start_ae != adjMaxFace);
960  } else {
961  start_ae = adjMaxFace;
962  }
963 
964  //For every edge a buffer saving adjacency entries written in embedding step
965  //for nodes on the maximum face, needed in step for other nodes.
966  EdgeArray<List<adjEntry>> buffer(S.getGraph());
967 
968  bool firstStep = true;
969  bool after_start_ae = true;
970  for (adjEntry ae = start_ae; firstStep || ae != start_ae;
971  after_start_ae = after_start_ae && ae->succ(),
972  ae = after_start_ae ? ae->faceCycleSucc()
973  : (!ae->faceCycleSucc() ? adjMaxFace : ae->faceCycleSucc())) {
974  firstStep = false;
975 #if 0
976  node nodeG = S.original(ae->theNode());
977 #endif
978  nodeTreated[ae->theNode()] = true;
979 
980  //copy adjacency list of nodes into newOrder:
982  edge vE = (ae->theEdge() == referenceEdge) ? referenceEdge : ae->theEdge();
983  node nu = (ae->theEdge() == referenceEdge) ? mu : S.twinTreeNode(ae->theEdge());
984  if (S.isVirtual(vE)) {
985  if (ae->theNode() == vE->source()) {
986  before = adjBeforeNodeArraySource[nu];
987  } else {
988  before = adjBeforeNodeArrayTarget[nu];
989  }
990  }
991 
992  bool after_ae = true;
993  adjEntry m_start_ae;
994  if (ae->theEdge() == referenceEdge) {
995  if (ae->succ()) {
996  m_start_ae = ae->succ();
997  } else {
998  m_start_ae = ae->theNode()->firstAdj();
999  }
1000  } else {
1001  m_start_ae = ae;
1002  }
1003 
1004  for (adjEntry aeN = m_start_ae; after_ae || aeN != m_start_ae;
1005  after_ae = after_ae && aeN->succ(),
1006  aeN = after_ae ? aeN->succ()
1007  : (!aeN->succ() ? ae->theNode()->firstAdj() : aeN->succ())) {
1008  node m_leftNode = nullptr;
1009  if (S.isVirtual(aeN->theEdge()) && aeN->theEdge() != referenceEdge) {
1010  //Compute left node of aeN->theNode(). First get adjacency entry in ext. face
1011  //(if edge is in ext. face) and compare face cycle successor with successor
1012  //in node adjacency list. If it is the same, it is the right node, otherwise
1013  //the left.
1014  adjEntry aeExtFace = nullptr;
1015  bool succInExtFace = false;
1016  bool aeNInExtFace = false;
1017  adjEntry aeNSucc = (aeN->succ()) ? aeN->succ() : ae->theNode()->firstAdj();
1018  aeExtFace = adjMaxFace;
1019  do {
1020  if (aeExtFace->theEdge() == aeNSucc->theEdge()) {
1021  succInExtFace = true;
1022  if (aeNInExtFace) {
1023  break;
1024  }
1025  }
1026  if (aeExtFace->theEdge() == aeN->theEdge()) {
1027  aeNInExtFace = true;
1028  if (succInExtFace) {
1029  break;
1030  }
1031  }
1032  aeExtFace = aeExtFace->faceCycleSucc();
1033  } while (aeExtFace != adjMaxFace);
1034  if (aeNInExtFace && succInExtFace) {
1035  m_leftNode = aeN->twinNode();
1036  } else {
1037  m_leftNode = aeN->theNode();
1038  }
1039 
1040  node twinTN = S.twinTreeNode(aeN->theEdge());
1041  if (referenceEdge) {
1042  if (aeN->theEdge()->source() == aeN->theNode()) {
1043  if (aeN->theEdge()->target() == referenceEdge->source()) {
1044  adjBeforeNodeArrayTarget[twinTN] = adjBeforeNodeArraySource[mu];
1045  } else if (aeN->theEdge()->target() == referenceEdge->target()) {
1046  adjBeforeNodeArrayTarget[twinTN] = adjBeforeNodeArrayTarget[mu];
1047  }
1048  } else {
1049  if (aeN->theEdge()->source() == referenceEdge->source()) {
1050  adjBeforeNodeArraySource[twinTN] = adjBeforeNodeArraySource[mu];
1051  } else if (aeN->theEdge()->source() == referenceEdge->target()) {
1052  adjBeforeNodeArraySource[twinTN] = adjBeforeNodeArrayTarget[mu];
1053  }
1054  }
1055  }
1056  }
1057 
1058  adjEntryForNode(aeN, before, spqrTree, treeNodeTreated, mu, m_leftNode, nodeLength,
1059  edgeLength, newOrder, adjBeforeNodeArraySource, adjBeforeNodeArrayTarget,
1060  adjExternal);
1061 
1062  //if the other node adjacent to the current treated edge is not in the
1063  //max face, put written edges into an buffer and clear the adjacency
1064  //list of that node.
1065  if (!maxFaceNodes.search(aeN->twinNode()).valid()) {
1066  node orig_aeN_twin_theNode = S.original(aeN->twinNode());
1067  buffer[aeN->theEdge()] = newOrder[orig_aeN_twin_theNode];
1068  newOrder[orig_aeN_twin_theNode].clear();
1069  }
1070  }
1071  }
1072 
1073  //Simple copy of not treated node's adjacency lists (internal nodes). Setting
1074  //of left node not necessary, because all nodes are not in external face.
1075  for (node v : S.getGraph().nodes) {
1076  if (nodeTreated[v]) {
1077  continue;
1078  }
1079 
1080  node v_original = S.original(v);
1081  nodeTreated[v] = true;
1083  for (adjEntry ae = v->firstAdj(); ae; ae = ae->succ()) {
1084  if (buffer[ae->theEdge()].empty()) {
1085  adjEntryForNode(ae, before, spqrTree, treeNodeTreated, mu, ae->theNode(),
1086  nodeLength, edgeLength, newOrder, adjBeforeNodeArraySource,
1087  adjBeforeNodeArrayTarget, adjExternal);
1088 
1089  if (!nodeTreated[ae->twinNode()]) {
1090  node orig_ae_twin_theNode = S.original(ae->twinNode());
1091  buffer[ae->theEdge()] = newOrder[orig_ae_twin_theNode];
1092  newOrder[orig_ae_twin_theNode].clear();
1093  }
1094  } else {
1095  buffer[ae->theEdge()].reverse();
1096  for (ListIterator<adjEntry> it = buffer[ae->theEdge()].begin(); it.valid(); ++it) {
1097  if (!before.valid()) {
1098  before = newOrder[v_original].pushFront(*it);
1099  } else {
1100  before = newOrder[v_original].insertBefore(*it, before);
1101  }
1102  }
1103  }
1104  }
1105  }
1106 }
1107 
1108 template<class T>
1110  const EdgeArray<T>& edgeLength, StaticSPQRTree* spqrTree,
1111  NodeArray<EdgeArray<T>>& edgeLengthSkel) {
1112  //base cases (SPQR-tree implementation would crash for such graphs):
1113  if (G.numberOfNodes() <= 1 || G.numberOfEdges() <= 2) {
1114  return;
1115  }
1116 
1117  //set length for all real edges in skeletons to length of the original edge
1118  //and initialize edge lengths for virtual edges with 0:
1119  edgeLengthSkel.init(spqrTree->tree());
1120  for (node v : spqrTree->tree().nodes) {
1121  edgeLengthSkel[v].init(spqrTree->skeleton(v).getGraph());
1122  for (edge e : spqrTree->skeleton(v).getGraph().edges) {
1123  if (spqrTree->skeleton(v).isVirtual(e)) {
1124  edgeLengthSkel[v][e] = 0;
1125  } else {
1126  edgeLengthSkel[v][e] = edgeLength[spqrTree->skeleton(v).realEdge(e)];
1127  }
1128  }
1129  }
1130 
1131  //set component-length for all non-reference edges:
1132  bottomUpTraversal(*spqrTree, spqrTree->rootNode(), nodeLength, edgeLengthSkel);
1133  //set component length for all reference edges:
1134  topDownTraversal(*spqrTree, spqrTree->rootNode(), nodeLength, edgeLengthSkel);
1135 }
1136 
1137 template<class T>
1139  const EdgeArray<T>& edgeLength) {
1140  //base cases (SPQR-tree implementation would crash for such graphs):
1141  OGDF_ASSERT(G.numberOfNodes() >= 2);
1142  if (G.numberOfEdges() == 1) {
1143  edge e = G.firstEdge();
1144  return edgeLength[e] + nodeLength[e->source()] + nodeLength[e->target()];
1145  }
1146  if (G.numberOfEdges() == 2) {
1147  edge e1 = G.firstEdge();
1148  edge e2 = e1->succ();
1149  return edgeLength[e1] + edgeLength[e2] + nodeLength[e1->source()] + nodeLength[e1->target()];
1150  }
1151  StaticSPQRTree spqrTree(G);
1152  NodeArray<EdgeArray<T>> edgeLengthSkel;
1153  return computeSize(G, nodeLength, edgeLength, spqrTree, edgeLengthSkel);
1154 }
1155 
1156 template<class T>
1158  const EdgeArray<T>& edgeLength, StaticSPQRTree* spqrTree,
1159  NodeArray<EdgeArray<T>>& edgeLengthSkel) {
1160  //base cases (SPQR-tree implementation would crash for such graphs):
1161  OGDF_ASSERT(G.numberOfNodes() >= 2);
1162  if (G.numberOfEdges() == 1) {
1163  edge e = G.firstEdge();
1164  return edgeLength[e] + nodeLength[e->source()] + nodeLength[e->target()];
1165  }
1166  if (G.numberOfEdges() == 2) {
1167  edge e1 = G.firstEdge();
1168  edge e2 = e1->succ();
1169  return edgeLength[e1] + edgeLength[e2] + nodeLength[e1->source()] + nodeLength[e1->target()];
1170  }
1171 
1172  //set length for all real edges in skeletons to length of the original edge
1173  //and initialize edge lengths for virtual edges with 0:
1174  OGDF_ASSERT(spqrTree != nullptr);
1175  edgeLengthSkel.init(spqrTree->tree());
1176  for (node v : spqrTree->tree().nodes) {
1177  edgeLengthSkel[v].init(spqrTree->skeleton(v).getGraph());
1178  for (edge e : spqrTree->skeleton(v).getGraph().edges) {
1179  if (spqrTree->skeleton(v).isVirtual(e)) {
1180  edgeLengthSkel[v][e] = 0;
1181  } else {
1182  edgeLengthSkel[v][e] = edgeLength[spqrTree->skeleton(v).realEdge(e)];
1183  }
1184  }
1185  }
1186 
1187  //set component-length for all non-reference edges:
1188  bottomUpTraversal(*spqrTree, spqrTree->rootNode(), nodeLength, edgeLengthSkel);
1189  //set component length for all reference edges:
1190  topDownTraversal(*spqrTree, spqrTree->rootNode(), nodeLength, edgeLengthSkel);
1191 
1192  T biggestFace = -1;
1193  for (node mu : spqrTree->tree().nodes) {
1194  //Expand all faces in skeleton(mu) and get size of the largest of them:
1195  T sizeMu = largestFaceInSkeleton(*spqrTree, mu, nodeLength, edgeLengthSkel);
1196  if (sizeMu > biggestFace) {
1197  biggestFace = sizeMu;
1198  }
1199  }
1200 
1201  return biggestFace;
1202 }
1203 
1204 template<class T>
1206  const NodeArray<T>& nodeLength, const EdgeArray<T>& edgeLength) {
1207  //base cases (SPQR-tree implementation would crash for such graphs):
1208  OGDF_ASSERT(G.numberOfNodes() >= 2);
1209  if (G.numberOfEdges() == 1) {
1210  edge e = G.firstEdge();
1211  return edgeLength[e] + nodeLength[e->source()] + nodeLength[e->target()];
1212  }
1213  if (G.numberOfEdges() == 2) {
1214  edge e1 = G.firstEdge();
1215  edge e2 = e1->succ();
1216  return edgeLength[e1] + edgeLength[e2] + nodeLength[e1->source()] + nodeLength[e1->target()];
1217  }
1218  StaticSPQRTree spqrTree(G);
1219  NodeArray<EdgeArray<T>> edgeLengthSkel;
1220  compute(G, nodeLength, edgeLength, &spqrTree, edgeLengthSkel);
1221  return computeSize(G, n, nodeLength, edgeLength, &spqrTree, edgeLengthSkel);
1222 }
1223 
1224 template<class T>
1226  const NodeArray<T>& nodeLength, const EdgeArray<T>& edgeLength, StaticSPQRTree* spqrTree) {
1227  NodeArray<EdgeArray<T>> edgeLengthSkel;
1228  compute(G, nodeLength, edgeLength, spqrTree, edgeLengthSkel);
1229  return computeSize(G, n, nodeLength, edgeLength, spqrTree, edgeLengthSkel);
1230 }
1231 
1232 template<class T>
1234  const NodeArray<T>& nodeLength, const EdgeArray<T>& edgeLength, StaticSPQRTree* spqrTree,
1235  const NodeArray<EdgeArray<T>>& edgeLengthSkel) {
1236  //base cases (SPQR-tree implementation would crash for such graphs):
1237  OGDF_ASSERT(G.numberOfNodes() >= 2);
1238  if (G.numberOfEdges() == 1) {
1239  edge e = G.firstEdge();
1240  return edgeLength[e] + nodeLength[e->source()] + nodeLength[e->target()];
1241  } else if (G.numberOfEdges() == 2) {
1242  edge e1 = G.firstEdge();
1243  edge e2 = e1->succ();
1244  return edgeLength[e1] + edgeLength[e2] + nodeLength[e1->source()] + nodeLength[e1->target()];
1245  }
1246 
1247  node* mus = new node[n->degree()];
1248  int i = 0;
1249  T biggestFace = -1;
1250  for (adjEntry adj : n->adjEntries) {
1251  mus[i] = spqrTree->skeletonOfReal(adj->theEdge()).treeNode();
1252  bool alreadySeenMu = false;
1253  for (int j = 0; j < i && !alreadySeenMu; j++) {
1254  if (mus[i] == mus[j]) {
1255  alreadySeenMu = true;
1256  }
1257  }
1258  if (alreadySeenMu) {
1259  i++;
1260  continue;
1261  } else {
1262  //Expand all faces in skeleton(mu) containing n and get size of the largest of them:
1263  T sizeInMu = largestFaceContainingNode(*spqrTree, mus[i], n, nodeLength, edgeLengthSkel);
1264  if (sizeInMu > biggestFace) {
1265  biggestFace = sizeInMu;
1266  }
1267 
1268  i++;
1269  }
1270  }
1271  delete[] mus;
1272 
1273  return biggestFace;
1274 }
1275 
1276 template<class T>
1278  const node& mu, const NodeArray<T>& nodeLength, NodeArray<EdgeArray<T>>& edgeLength) {
1279  //Recursion:
1280  for (adjEntry adj : mu->adjEntries) {
1281  edge ed = adj->theEdge();
1282  if (ed->source() == mu) {
1283  bottomUpTraversal(spqrTree, ed->target(), nodeLength, edgeLength);
1284  }
1285  }
1286 
1287  for (edge e : spqrTree.skeleton(mu).getGraph().edges) {
1288  //do not treat real edges here and do not treat reference edges:
1289  if (!spqrTree.skeleton(mu).isVirtual(e) || e == spqrTree.skeleton(mu).referenceEdge()) {
1290  continue;
1291  }
1292 
1293  //pertinent node of e in the SPQR-tree:
1294  node nu = spqrTree.skeleton(mu).twinTreeNode(e);
1295  //reference edge of nu (virtual edge in nu associated with mu):
1296  edge er = spqrTree.skeleton(nu).referenceEdge();
1297  //sum of the lengths of the two poles of mu:
1298  node refEdgeSource = spqrTree.skeleton(nu).referenceEdge()->source();
1299  node origRefEdgeSource = spqrTree.skeleton(nu).original(refEdgeSource);
1300  node refEdgeTarget = spqrTree.skeleton(nu).referenceEdge()->target();
1301  node origRefEdgeTarget = spqrTree.skeleton(nu).original(refEdgeTarget);
1302  T ell = nodeLength[origRefEdgeSource] + nodeLength[origRefEdgeTarget];
1303 
1304  if (spqrTree.typeOf(nu) == SPQRTree::NodeType::SNode) {
1305  //size of a face in skeleton(nu) minus ell
1306  T sizeOfFace = 0;
1307  for (node nS : spqrTree.skeleton(nu).getGraph().nodes) {
1308  sizeOfFace += nodeLength[spqrTree.skeleton(nu).original(nS)];
1309  }
1310 
1311  for (edge eS : spqrTree.skeleton(nu).getGraph().edges) {
1312  sizeOfFace += edgeLength[nu][eS];
1313  }
1314 
1315  edgeLength[mu][e] = sizeOfFace - ell;
1316  } else if (spqrTree.typeOf(nu) == SPQRTree::NodeType::PNode) {
1317  //length of the longest edge different from er in skeleton(nu)
1318  edge longestEdge = nullptr;
1319  for (edge ed : spqrTree.skeleton(nu).getGraph().edges) {
1320  if (ed != er && (!longestEdge || edgeLength[nu][ed] > edgeLength[nu][longestEdge])) {
1321  longestEdge = ed;
1322  }
1323  }
1324  edgeLength[mu][e] = edgeLength[nu][longestEdge];
1325  } else if (spqrTree.typeOf(nu) == SPQRTree::NodeType::RNode) {
1326  //size of the largest face containing er in skeleton(nu) minus ell
1327  //Calculate an embedding of the graph (it exists only two which are
1328  //mirror-symmetrical):
1329  planarEmbed(spqrTree.skeleton(nu).getGraph());
1330  CombinatorialEmbedding combinatorialEmbedding(spqrTree.skeleton(nu).getGraph());
1331  T biggestFaceSize = -1;
1332  for (face f : combinatorialEmbedding.faces) {
1333  T sizeOfFace = 0;
1334  bool containsEr = false;
1335  for (adjEntry ae : f->entries) {
1336  if (ae->theEdge() == er) {
1337  containsEr = true;
1338  }
1339  sizeOfFace += edgeLength[nu][ae->theEdge()]
1340  + nodeLength[spqrTree.skeleton(nu).original(ae->theNode())];
1341  }
1342 
1343  if (containsEr && sizeOfFace > biggestFaceSize) {
1344  biggestFaceSize = sizeOfFace;
1345  }
1346  }
1347 
1348  edgeLength[mu][e] = biggestFaceSize - ell;
1349  } else { //should never happen
1350  edgeLength[mu][e] = 1;
1351  }
1352  }
1353 }
1354 
1355 template<class T>
1357  const NodeArray<T>& nodeLength, NodeArray<EdgeArray<T>>& edgeLength) {
1358  //S: skeleton of mu
1359  Skeleton& S = spqrTree.skeleton(mu);
1360 
1361  //Get all reference edges of the children nu of mu and set their component length:
1362  for (adjEntry adj : mu->adjEntries) {
1363  edge ed = adj->theEdge();
1364  if (ed->source() != mu) {
1365  continue;
1366  }
1367 
1368  node nu = ed->target();
1369  edge referenceEdgeOfNu = spqrTree.skeleton(nu).referenceEdge();
1370  edge eSnu = spqrTree.skeleton(nu).twinEdge(referenceEdgeOfNu);
1371  if (spqrTree.typeOf(mu) == SPQRTree::NodeType::SNode) {
1372  //Let L be the sum of the length of all vertices and edges in S. The component
1373  //length of the reference edge of nu is L minus the length of e_{S, nu} minus
1374  //the lengths of the two vertices incident to e_{S, nu}.
1375  T L = 0;
1376  for (edge ed2 : S.getGraph().edges) {
1377  L += edgeLength[mu][ed2];
1378  }
1379  for (node no : S.getGraph().nodes) {
1380  L += nodeLength[S.original(no)];
1381  }
1382 
1383  edgeLength[nu][referenceEdgeOfNu] = L - edgeLength[mu][eSnu]
1384  - nodeLength[S.original(eSnu->source())] - nodeLength[S.original(eSnu->target())];
1385  } else if (spqrTree.typeOf(mu) == SPQRTree::NodeType::PNode) {
1386  //The component length of the reference edge of nu is the length of the longest
1387  //edge in S different from e_{S, nu}.
1388  edge longestEdge = nullptr;
1389  for (edge ed2 : S.getGraph().edges) {
1390  if (ed2 != eSnu
1391  && (!longestEdge || edgeLength[mu][ed2] > edgeLength[mu][longestEdge])) {
1392  longestEdge = ed2;
1393  }
1394  }
1395  edgeLength[nu][referenceEdgeOfNu] = edgeLength[mu][longestEdge];
1396  } else if (spqrTree.typeOf(mu) == SPQRTree::NodeType::RNode) {
1397  //Let f be the largest face in S containing e_{S, nu}. The component length of
1398  //the reference edge of nu is the size of f minus the length of e_{S, nu} minus
1399  //the lengths of the two vertices incident to e_{S, nu}.
1400 
1401  //Calculate an embedding of the graph (it exists only two which are
1402  //mirror-symmetrical):
1403  planarEmbed(S.getGraph());
1404  CombinatorialEmbedding combinatorialEmbedding(S.getGraph());
1405  T biggestFaceSize = -1;
1406  for (face f : combinatorialEmbedding.faces) {
1407  T sizeOfFace = 0;
1408  bool containsESnu = false;
1409  for (adjEntry ae : f->entries) {
1410  if (ae->theEdge() == eSnu) {
1411  containsESnu = true;
1412  }
1413  sizeOfFace +=
1414  edgeLength[mu][ae->theEdge()] + nodeLength[S.original(ae->theNode())];
1415  }
1416  if (containsESnu && sizeOfFace > biggestFaceSize) {
1417  biggestFaceSize = sizeOfFace;
1418  }
1419  }
1420  edgeLength[nu][referenceEdgeOfNu] = biggestFaceSize - edgeLength[mu][eSnu]
1421  - nodeLength[S.original(eSnu->source())] - nodeLength[S.original(eSnu->target())];
1422  } else { //should never happen
1423  edgeLength[nu][referenceEdgeOfNu] = 0;
1424  }
1425 
1426  //Recursion:
1427  topDownTraversal(spqrTree, ed->target(), nodeLength, edgeLength);
1428  }
1429 }
1430 
1431 template<class T>
1433  const node& mu, const node& n, const NodeArray<T>& nodeLength,
1434  const NodeArray<EdgeArray<T>>& edgeLength) {
1435  bool containsARealEdge = false;
1436  if (spqrTree.typeOf(mu) == SPQRTree::NodeType::RNode) {
1437  //The largest face containing n is the largest face containg n in any embedding of S.
1438  planarEmbed(spqrTree.skeleton(mu).getGraph());
1439  CombinatorialEmbedding combinatorialEmbedding(spqrTree.skeleton(mu).getGraph());
1440  T biggestFaceSize = -1;
1441  for (face f : combinatorialEmbedding.faces) {
1442  T sizeOfFace = 0;
1443  bool containingN = false;
1444  bool m_containsARealEdge = false;
1445  for (adjEntry ae : f->entries) {
1446  if (spqrTree.skeleton(mu).original(ae->theNode()) == n) {
1447  containingN = true;
1448  }
1449  if (!spqrTree.skeleton(mu).isVirtual(ae->theEdge())) {
1450  m_containsARealEdge = true;
1451  }
1452  sizeOfFace += edgeLength[mu][ae->theEdge()];
1453  sizeOfFace += nodeLength[spqrTree.skeleton(mu).original(ae->theNode())];
1454  }
1455  if (containingN && sizeOfFace > biggestFaceSize) {
1456  biggestFaceSize = sizeOfFace;
1457  containsARealEdge = m_containsARealEdge;
1458  }
1459  }
1460 
1461  if (!containsARealEdge) {
1462  return -1;
1463  }
1464  return biggestFaceSize;
1465  } else if (spqrTree.typeOf(mu) == SPQRTree::NodeType::PNode) {
1466  //Find the two longest edges, they define the largest face containg n.
1467  edge longestEdges[2] = {nullptr, nullptr};
1468  for (edge edgeWalker : spqrTree.skeleton(mu).getGraph().edges) {
1469  if (!longestEdges[1] || edgeLength[mu][edgeWalker] > edgeLength[mu][longestEdges[1]]) {
1470  if (!longestEdges[0] || edgeLength[mu][edgeWalker] > edgeLength[mu][longestEdges[0]]) {
1471  longestEdges[1] = longestEdges[0];
1472  longestEdges[0] = edgeWalker;
1473  } else {
1474  longestEdges[1] = edgeWalker;
1475  }
1476  }
1477  }
1478 
1479  if (!spqrTree.skeleton(mu).isVirtual(longestEdges[0])
1480  || !spqrTree.skeleton(mu).isVirtual(longestEdges[1])) {
1481  containsARealEdge = true;
1482  }
1483 
1484  if (!containsARealEdge) {
1485  return -1;
1486  }
1487 
1488  return edgeLength[mu][longestEdges[0]] + edgeLength[mu][longestEdges[1]];
1489  } else if (spqrTree.typeOf(mu) == SPQRTree::NodeType::SNode) {
1490  //The largest face containing n is any face in the single existing embedding of S.
1491  T sizeOfFace = 0;
1492  for (node nS : spqrTree.skeleton(mu).getGraph().nodes) {
1493  sizeOfFace += nodeLength[spqrTree.skeleton(mu).original(nS)];
1494  }
1495 
1496  for (edge eS : spqrTree.skeleton(mu).getGraph().edges) {
1497  if (!spqrTree.skeleton(mu).isVirtual(eS)) {
1498  containsARealEdge = true;
1499  }
1500  sizeOfFace += edgeLength[mu][eS];
1501  }
1502 
1503  if (!containsARealEdge) {
1504  return -1;
1505  }
1506 
1507  return sizeOfFace;
1508  }
1509 
1510  //should never end here...
1511  return 42;
1512 }
1513 
1514 template<class T>
1516  const node& mu, const NodeArray<T>& nodeLength, const NodeArray<EdgeArray<T>>& edgeLength) {
1517  bool containsARealEdge = false;
1518  if (spqrTree.typeOf(mu) == SPQRTree::NodeType::RNode) {
1519  //The largest face is a largest face in any embedding of S.
1520  planarEmbed(spqrTree.skeleton(mu).getGraph());
1521  CombinatorialEmbedding combinatorialEmbedding(spqrTree.skeleton(mu).getGraph());
1522  T biggestFaceSize = -1;
1523  for (face f : combinatorialEmbedding.faces) {
1524  bool m_containsARealEdge = false;
1525  T sizeOfFace = 0;
1526  for (adjEntry ae : f->entries) {
1527 #if 0
1528  node originalNode = spqrTree.skeleton(mu).original(ae->theNode());
1529 #endif
1530  if (!spqrTree.skeleton(mu).isVirtual(ae->theEdge())) {
1531  m_containsARealEdge = true;
1532  }
1533  sizeOfFace += edgeLength[mu][ae->theEdge()]
1534  + nodeLength[spqrTree.skeleton(mu).original(ae->theNode())];
1535  }
1536 
1537  if (sizeOfFace > biggestFaceSize) {
1538  biggestFaceSize = sizeOfFace;
1539  containsARealEdge = m_containsARealEdge;
1540  }
1541  }
1542 
1543  if (!containsARealEdge) {
1544  return -1;
1545  }
1546 
1547  return biggestFaceSize;
1548  } else if (spqrTree.typeOf(mu) == SPQRTree::NodeType::PNode) {
1549  //Find the two longest edges, they define the largest face.
1550  edge longestEdges[2] = {nullptr, nullptr};
1551  for (edge edgeWalker : spqrTree.skeleton(mu).getGraph().edges) {
1552  if (!longestEdges[1] || edgeLength[mu][edgeWalker] > edgeLength[mu][longestEdges[1]]) {
1553  if (!longestEdges[0] || edgeLength[mu][edgeWalker] > edgeLength[mu][longestEdges[0]]) {
1554  longestEdges[1] = longestEdges[0];
1555  longestEdges[0] = edgeWalker;
1556  } else {
1557  longestEdges[1] = edgeWalker;
1558  }
1559  }
1560  }
1561 
1562  if (!spqrTree.skeleton(mu).isVirtual(longestEdges[0])
1563  || !spqrTree.skeleton(mu).isVirtual(longestEdges[1])) {
1564  containsARealEdge = true;
1565  }
1566 
1567  if (!containsARealEdge) {
1568  return -1;
1569  }
1570 
1571  return edgeLength[mu][longestEdges[0]] + edgeLength[mu][longestEdges[1]];
1572  } else if (spqrTree.typeOf(mu) == SPQRTree::NodeType::SNode) {
1573  //The largest face is any face in the single existing embedding of S.
1574  T sizeOfFace = 0;
1575  for (node nS : spqrTree.skeleton(mu).getGraph().nodes) {
1576  sizeOfFace += nodeLength[spqrTree.skeleton(mu).original(nS)];
1577  }
1578 
1579  for (edge eS : spqrTree.skeleton(mu).getGraph().edges) {
1580  if (!spqrTree.skeleton(mu).isVirtual(eS)) {
1581  containsARealEdge = true;
1582  }
1583  sizeOfFace += edgeLength[mu][eS];
1584  }
1585 
1586  if (!containsARealEdge) {
1587  return -1;
1588  }
1589 
1590  return sizeOfFace;
1591  }
1592 
1593  //should never end here...
1594  return 42;
1595 }
1596 
1597 }
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.
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::AdjElement::theNode
node theNode() const
Returns the node whose adjacency list contains this element.
Definition: Graph_d.h:166
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::EmbedderMaxFaceBiconnectedGraphs::compute
static void compute(const Graph &G, const NodeArray< T > &nodeLength, const EdgeArray< T > &edgeLength, StaticSPQRTree *spqrTree, NodeArray< EdgeArray< T >> &edgeLengthSkel)
Computes the component lengths of all virtual edges in spqrTree.
Definition: EmbedderMaxFaceBiconnectedGraphs.h:1109
ogdf::EmbedderMaxFaceBiconnectedGraphs::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, NodeArray< List< adjEntry >> &newOrder, NodeArray< ListIterator< adjEntry >> &adjBeforeNodeArraySource, NodeArray< ListIterator< adjEntry >> &adjBeforeNodeArrayTarget, adjEntry &adjExternal)
Definition: EmbedderMaxFaceBiconnectedGraphs.h:545
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::EmbedderMaxFaceBiconnectedGraphs::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, NodeArray< List< adjEntry >> &newOrder, NodeArray< ListIterator< adjEntry >> &adjBeforeNodeArraySource, NodeArray< ListIterator< adjEntry >> &adjBeforeNodeArrayTarget, adjEntry &adjExternal)
Definition: EmbedderMaxFaceBiconnectedGraphs.h:443
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::Graph::allEdges
void allEdges(CONTAINER &edgeContainer) const
Returns a container with all edges of the graph.
Definition: Graph_d.h:1046
ogdf::AdjElement::twin
adjEntry twin() const
Returns the corresponding adjacency element associated with the same edge.
Definition: Graph_d.h:172
ogdf::AdjElement
Class for adjacency list elements.
Definition: Graph_d.h:142
ogdf::FaceElement::firstAdj
adjEntry firstAdj() const
Returns the first adjacency element in the face.
Definition: CombinatorialEmbedding.h:148
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::EmbedderMaxFaceBiconnectedGraphs::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, NodeArray< List< adjEntry >> &newOrder, NodeArray< ListIterator< adjEntry >> &adjBeforeNodeArraySource, NodeArray< ListIterator< adjEntry >> &adjBeforeNodeArrayTarget, adjEntry &adjExternal)
Definition: EmbedderMaxFaceBiconnectedGraphs.h:634
ogdf::EmbedderMaxFaceBiconnectedGraphs::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: EmbedderMaxFaceBiconnectedGraphs.h:367
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::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::EmbedderMaxFaceBiconnectedGraphs::topDownTraversal
static void topDownTraversal(StaticSPQRTree &spqrTree, const node &mu, const NodeArray< T > &nodeLength, NodeArray< EdgeArray< T >> &edgeLength)
Top down traversal of SPQR-tree computing the component length of all reference edges.
Definition: EmbedderMaxFaceBiconnectedGraphs.h:1356
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.
CombinatorialEmbedding.h
Declaration of CombinatorialEmbedding and face.
ogdf::EmbedderMaxFaceBiconnectedGraphs::computeSize
static T computeSize(const Graph &G, const node &n, const NodeArray< T > &nodeLength, const EdgeArray< T > &edgeLength)
Returns the size of a maximum external face in G containing the node n.
Definition: EmbedderMaxFaceBiconnectedGraphs.h:1205
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::StaticSPQRTree::rootNode
node rootNode() const override
Returns the root node of T.
Definition: StaticSPQRTree.h:132
ogdf::AdjElement::faceCycleSucc
adjEntry faceCycleSucc() const
Returns the cyclic successor in face.
Definition: Graph_d.h:212
ogdf::EmbedderMaxFaceBiconnectedGraphs::bottomUpTraversal
static void bottomUpTraversal(StaticSPQRTree &spqrTree, const node &mu, const NodeArray< T > &nodeLength, NodeArray< EdgeArray< T >> &edgeLength)
Bottom up traversal of SPQR-tree computing the component length of all non-reference edges.
Definition: EmbedderMaxFaceBiconnectedGraphs.h:1277
ogdf::EdgeElement
Class for the representation of edges.
Definition: Graph_d.h:363
List.h
Declaration of doubly linked lists and iterators.
ogdf::EdgeElement::succ
edge succ() const
Returns the successor in the list of all edges.
Definition: Graph_d.h:433
ogdf::Skeleton
Skeleton graphs of nodes in an SPQR-tree.
Definition: Skeleton.h:60
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::EmbedderMaxFaceBiconnectedGraphs::largestFaceContainingNode
static T largestFaceContainingNode(const StaticSPQRTree &spqrTree, const node &mu, const node &n, const NodeArray< T > &nodeLength, const NodeArray< EdgeArray< T >> &edgeLength)
Computes the size of a maximum face in the skeleton graph of mu containing n.
Definition: EmbedderMaxFaceBiconnectedGraphs.h:1432
ogdf::EmbedderMaxFaceBiconnectedGraphs::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, NodeArray< List< adjEntry >> &newOrder, NodeArray< ListIterator< adjEntry >> &adjBeforeNodeArraySource, NodeArray< ListIterator< adjEntry >> &adjBeforeNodeArrayTarget, adjEntry &adjExternal, const node &n)
Definition: EmbedderMaxFaceBiconnectedGraphs.h:856
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::NodeElement
Class for the representation of nodes.
Definition: Graph_d.h:240
ogdf::EmbedderMaxFaceBiconnectedGraphs::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, NodeArray< List< adjEntry >> &newOrder, NodeArray< ListIterator< adjEntry >> &adjBeforeNodeArraySource, NodeArray< ListIterator< adjEntry >> &adjBeforeNodeArrayTarget, adjEntry &adjExternal, const node &n=nullptr)
Definition: EmbedderMaxFaceBiconnectedGraphs.h:517
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::EmbedderMaxFaceBiconnectedGraphs::largestFaceInSkeleton
static T largestFaceInSkeleton(const StaticSPQRTree &spqrTree, const node &mu, const NodeArray< T > &nodeLength, const NodeArray< EdgeArray< T >> &edgeLength)
Computes the size of a maximum face in the skeleton graph of mu.
Definition: EmbedderMaxFaceBiconnectedGraphs.h:1515
ogdf::FaceElement
Faces in a combinatorial embedding.
Definition: CombinatorialEmbedding.h:118