Open
Graph Drawing
Framework

 v. 2023.09 (Elderberry)
 

Loading...
Searching...
No Matches
EmbedderMaxFaceBiconnectedGraphs.h
Go to the documentation of this file.
1
32#pragma once
33
37
38namespace ogdf {
39
41
47template<class T>
49public:
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,
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,
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,
144
145protected:
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,
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,
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,
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,
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,
358};
359
360template<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
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) {
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) {
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;
428 expandEdge(spqrTree, treeNodeTreated, bigFaceMu, nullptr, nodeLength, edgeLengthSkel, newOrder,
430
431 for (node v : G.nodes) {
432 G.sort(v, newOrder[v]);
433 }
434}
435
436template<class T>
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,
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]) {
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()) {
463 } else {
465 }
466
467 //recursion call:
468 expandEdge(spqrTree, treeNodeTreated, twinNT, m_leftNode, nodeLength, edgeLength,
470 }
471
472 if (ae->theEdge() == referenceEdge) {
473 if (ae->theNode() == ae->theEdge()->source()) {
477 } else {
481 }
482 } else
483 {
484 if (ae->theNode() == ae->theEdge()->source()) {
486 } else {
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
510template<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,
517 const node& n /*= 0*/) {
518 treeNodeTreated[mu] = true;
519
520 switch (spqrTree.typeOf(mu)) {
522 expandEdgeSNode(spqrTree, treeNodeTreated, mu, leftNode, nodeLength, edgeLength, newOrder,
524 break;
526 expandEdgePNode(spqrTree, treeNodeTreated, mu, leftNode, nodeLength, edgeLength, newOrder,
528 break;
530 expandEdgeRNode(spqrTree, treeNodeTreated, mu, leftNode, nodeLength, edgeLength, newOrder,
532 break;
533 default:
534 OGDF_ASSERT(false);
535 }
536}
537
538template<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,
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 }
556 } else if (leftNode->firstAdj()->theEdge() == referenceEdge) {
557 startAdjEntry = leftNode->lastAdj();
558 } else {
559 startAdjEntry = leftNode->firstAdj();
560 }
561
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()) {
575 } else if (referenceEdge) {
577 }
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()) {
589 } else {
591 }
592 } else {
593 adjEntryForNode(ae, before, spqrTree, treeNodeTreated, mu, m_leftNode, nodeLength,
596 }
597
598 if (firstStep) {
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()) {
609 } else {
611 }
612 } else {
613 adjEntryForNode(ae, before, spqrTree, treeNodeTreated, mu, m_leftNode, nodeLength,
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
627template<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,
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
640 if (!m_leftNode) {
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)) {
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
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;
685 }
686
687 if (referenceEdge) {
688 if (n == referenceEdge->source()) {
690 } else {
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) {
712 } else {
714 }
715 } else {
716 if (referenceEdge->source() == n) {
718 } else {
720 }
721 }
722 }
723
724 adjEntryForNode(ae, before, spqrTree, treeNodeTreated, mu, m_leftNode, nodeLength,
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) {
742 } else {
744 }
745 } else if (referenceEdge) {
746 if (referenceEdge->source() == n) {
748 } else {
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,
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,
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,
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,
810 }
811
812 //(alternative) reference edge at last:
813 if (referenceEdge) {
814 if (n == referenceEdge->source()) {
816 } else {
818 }
819 } else {
821 if (i == 0) {
822 newLeftNode = m_leftNode->firstAdj()->twinNode();
823 } else {
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,
836
837 if (i == 0 && S.isVirtual(altReferenceEdge)) {
838 node nu = S.twinTreeNode(altReferenceEdge);
839 if (altReferenceEdge->source() == n) {
841 } else {
843 }
844 }
845 }
846 }
847}
848
849template<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,
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;
863 planarEmbed(S.getGraph());
865 T bigFaceSize = -1;
866 adjEntry m_adjExternal = nullptr;
867 for (face f : combinatorialEmbedding.faces) {
868 bool containsVirtualEdgeOrN = false;
870 T sizeOfFace = 0;
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) {
877 if (referenceEdge) {
879 }
880 }
881
882 if (!referenceEdge && !S.isVirtual(ae->theEdge())) {
884 }
885
886 sizeOfFace += edgeLength[mu][ae->theEdge()] + nodeLength[S.original(ae->theNode())];
887 }
888
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
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:
914 if (leftNode == referenceEdge->source()) {
915 succ_virtualEdge_leftNode = referenceEdge->adjSource()->succ();
916 } else {
917 succ_virtualEdge_leftNode = referenceEdge->adjTarget()->succ();
918 }
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) {
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);
945 if (referenceEdge) {
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 {
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()) {
981 } else {
983 }
984 }
985
986 bool after_ae = true;
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
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();
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()) {
1039 } else if (aeN->theEdge()->target() == referenceEdge->target()) {
1041 }
1042 } else {
1043 if (aeN->theEdge()->source() == referenceEdge->source()) {
1045 } else if (aeN->theEdge()->source() == referenceEdge->target()) {
1047 }
1048 }
1049 }
1050 }
1051
1052 adjEntryForNode(aeN, before, spqrTree, treeNodeTreated, mu, m_leftNode, nodeLength,
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,
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
1102template<class T>
1104 const EdgeArray<T>& edgeLength, StaticSPQRTree* spqrTree,
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
1131template<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 }
1147 return computeSize(G, nodeLength, edgeLength, spqrTree, edgeLengthSkel);
1148}
1149
1150template<class T>
1152 const EdgeArray<T>& edgeLength, StaticSPQRTree* spqrTree,
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) {
1192 }
1193 }
1194
1195 return biggestFace;
1196}
1197
1198template<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 }
1214 compute(G, nodeLength, edgeLength, &spqrTree, edgeLengthSkel);
1215 return computeSize(G, n, nodeLength, edgeLength, &spqrTree, edgeLengthSkel);
1216}
1217
1218template<class T>
1220 const NodeArray<T>& nodeLength, const EdgeArray<T>& edgeLength, StaticSPQRTree* spqrTree) {
1222 compute(G, nodeLength, edgeLength, spqrTree, edgeLengthSkel);
1223 return computeSize(G, n, nodeLength, edgeLength, spqrTree, edgeLengthSkel);
1224}
1225
1226template<class T>
1228 const NodeArray<T>& nodeLength, const EdgeArray<T>& edgeLength, StaticSPQRTree* spqrTree,
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) {
1260 }
1261
1262 i++;
1263 }
1264 }
1265 delete[] mus;
1266
1267 return biggestFace;
1268}
1269
1270template<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());
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
1339 }
1340 }
1341
1342 edgeLength[mu][e] = biggestFaceSize - ell;
1343 } else { //should never happen
1344 edgeLength[mu][e] = 1;
1345 }
1346 }
1347}
1348
1349template<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());
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 }
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
1425template<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());
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 }
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];
1467 } else {
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
1508template<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());
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
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];
1550 } else {
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}
Declaration of CombinatorialEmbedding and face.
Declaration of class StaticSPQRTree.
Class for adjacency list elements.
Definition Graph_d.h:79
adjEntry succ() const
Returns the successor in the adjacency list.
Definition Graph_d.h:155
edge theEdge() const
Returns the edge associated with this adjacency entry.
Definition Graph_d.h:97
node theNode() const
Returns the node whose adjacency list contains this element.
Definition Graph_d.h:103
Combinatorial embeddings of planar graphs with modification functionality.
Dynamic arrays indexed with edges.
Definition EdgeArray.h:125
Class for the representation of edges.
Definition Graph_d.h:300
adjEntry adjSource() const
Returns the corresponding adjacancy entry at source node.
Definition Graph_d.h:344
adjEntry adjTarget() const
Returns the corresponding adjacancy entry at target node.
Definition Graph_d.h:347
node target() const
Returns the target node of the edge.
Definition Graph_d.h:338
node source() const
Returns the source node of the edge.
Definition Graph_d.h:335
Embedder that maximizing the external face.
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)
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.
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)
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.
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.
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.
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.
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.
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.
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)
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)
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)
Faces in a combinatorial embedding.
Data type for general directed graphs (adjacency list representation).
Definition Graph_d.h:521
Doubly linked lists (maintaining the length of the list).
Definition List.h:1435
Encapsulates a pointer to a list element.
Definition List.h:103
Dynamic arrays indexed with nodes.
Definition NodeArray.h:125
Class for the representation of nodes.
Definition Graph_d.h:177
int degree() const
Returns the degree of the node (indegree + outdegree).
Definition Graph_d.h:220
internal::GraphObjectContainer< AdjElement > adjEntries
The container containing all entries in the adjacency list of this node.
Definition Graph_d.h:208
Skeleton graphs of nodes in an SPQR-tree.
Definition Skeleton.h:59
Linear-time implementation of static SPQR-trees.
Declaration of extended graph algorithms.
bool planarEmbed(Graph &G)
Returns true, if G is planar, false otherwise. If true is returned, G will be planarly embedded.
#define OGDF_ASSERT(expr)
Assert condition expr. See doc/build.md for more information.
Definition basic.h:41
static MultilevelBuilder * getDoubleFactoredZeroAdjustedMerger()
The namespace for all OGDF objects.