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