Loading [MathJax]/extensions/tex2jax.js

Open
Graph Drawing
Framework

 v. 2023.09 (Elderberry)
 

All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
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.