Open
Graph Drawing
Framework

 v. 2023.09 (Elderberry)
 

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