Open
Graph Drawing
Framework

 v. 2023.09 (Elderberry)
 

Loading...
Searching...
No Matches
EmbedderMaxFaceBiconnectedGraphsLayers.h
Go to the documentation of this file.
1
33#pragma once
34
36
37namespace ogdf {
38
40
52template<class T>
54public:
56 static void embed(Graph& G, adjEntry& adjExternal, const NodeArray<T>& nodeLength,
57 const EdgeArray<T>& edgeLength, const node& n = nullptr);
58
61
62private:
65
66 /* \brief Computes recursively the thickness of the skeleton graph of all
67 * nodes in the SPQR-tree.
68 *
69 * \param spqrTree The SPQR-tree of the treated graph.
70 * \param mu a node in the SPQR-tree.
71 * \param thickness saving the computed results - the thickness of each
72 * skeleton graph.
73 * \param nodeLength is saving for each node of the original graph \p G its
74 * length.
75 * \param edgeLength is saving the edge lengths of all edges in each skeleton
76 * graph of all tree nodes.
77 */
78 static void bottomUpThickness(const StaticSPQRTree& spqrTree, const node& mu,
79 NodeArray<T>& thickness, const NodeArray<T>& nodeLength,
80 const NodeArray<EdgeArray<T>>& edgeLength);
81
82 /* \brief ExpandEdge embeds all edges in the skeleton graph \a S into an
83 * existing embedding and calls recursively itself for all virtual edges
84 * in S.
85 *
86 * \param spqrTree The SPQR-tree of the treated graph.
87 * \param treeNodeTreated is an array saving for each SPQR-tree node \p mu
88 * whether it was already treated by any call of ExpandEdge or not. Every
89 * \p mu should only be treated once.
90 * \param mu is a node in the SPQR-tree.
91 * \param leftNode is the node adjacent to referenceEdge, which should be "left"
92 * in the embedding
93 * \param nodeLength is an array saving the lengths of the nodes of \p G.
94 * \param edgeLength is saving the edge lengths of all edges in each skeleton
95 * graph of all tree nodes.
96 * \param thickness of each skeleton graph.
97 * \param newOrder is saving for each node \p n in \p G the new adjacency
98 * list. This is an output parameter.
99 * \param adjBeforeNodeArraySource is saving for the source of the reference edge
100 * of the skeleton of mu the adjacency entry, before which new entries have
101 * to be inserted.
102 * \param adjBeforeNodeArrayTarget is saving for the target of the reference edge
103 * of the skeleton of mu the adjacency entry, before which new entries have
104 * to be inserted.
105 * \param delta_u the distance from the second adjacent face of the reference edge
106 * except the external face to the external face of G.
107 * \param delta_d the distance from the external face to the external face of G.
108 * \param adjExternal is an adjacency entry in the external face.
109 * \param n is only set, if ExpandEdge is called for the first time, because
110 * then there is no virtual edge which has to be expanded, but the max face
111 * has to contain a certain node \p n.
112 */
113 static void expandEdge(const StaticSPQRTree& spqrTree, NodeArray<bool>& treeNodeTreated,
114 const node& mu, const node& leftNode, const NodeArray<T>& nodeLength,
115 const NodeArray<EdgeArray<T>>& edgeLength, const NodeArray<T>& thickness,
116 NodeArray<List<adjEntry>>& newOrder,
119 const T& delta_d, adjEntry& adjExternal, const node& n = nullptr);
120
121 /* \brief Embeds all edges in the skeleton graph \a S of an S-node of the
122 * SPQR-tree into an existing embedding and calls recursively itself for
123 * all virtual edges in S.
124 *
125 * \param spqrTree The SPQR-tree of the treated graph.
126 * \param treeNodeTreated is an array saving for each SPQR-tree node \p mu
127 * whether it was already treated by any call of ExpandEdge or not. Every
128 * \p mu should only be treated once.
129 * \param mu is a node in the SPQR-tree.
130 * \param leftNode is the node adjacent to referenceEdge, which should be "left"
131 * in the embedding
132 * \param nodeLength is an array saving the lengths of the nodes of \p G.
133 * \param edgeLength is saving the edge lengths of all edges in each skeleton
134 * graph of all tree nodes.
135 * \param thickness of each skeleton graph.
136 * \param newOrder is saving for each node \p n in \p G the new adjacency
137 * list. This is an output parameter.
138 * \param adjBeforeNodeArraySource is saving for the source of the reference edge
139 * of the skeleton of mu the adjacency entry, before which new entries have
140 * to be inserted.
141 * \param adjBeforeNodeArrayTarget is saving for the target of the reference edge
142 * of the skeleton of mu the adjacency entry, before which new entries have
143 * to be inserted.
144 * \param delta_u the distance from the second adjacent face of the reference edge
145 * except the external face to the external face of G.
146 * \param delta_d the distance from the external face to the external face of G.
147 * \param adjExternal is an adjacency entry in the external face.
148 */
149 static void expandEdgeSNode(const StaticSPQRTree& spqrTree, NodeArray<bool>& treeNodeTreated,
150 const node& mu, const node& leftNode, const NodeArray<T>& nodeLength,
151 const NodeArray<EdgeArray<T>>& edgeLength, const NodeArray<T>& thickness,
152 NodeArray<List<adjEntry>>& newOrder,
155 const T& delta_d, adjEntry& adjExternal);
156
157 /* \brief Embeds all edges in the skeleton graph \a S of an P-node of the
158 * SPQR-tree into an existing embedding and calls recursively itself for
159 * all virtual edges in S.
160 *
161 * \param spqrTree The SPQR-tree of the treated graph.
162 * \param treeNodeTreated is an array saving for each SPQR-tree node \p mu
163 * whether it was already treated by any call of ExpandEdge or not. Every
164 * \p mu should only be treated once.
165 * \param mu is a node in the SPQR-tree.
166 * \param leftNode is the node adjacent to referenceEdge, which should be "left"
167 * in the embedding
168 * \param nodeLength is an array saving the lengths of the nodes of \p G.
169 * \param edgeLength is saving the edge lengths of all edges in each skeleton
170 * graph of all tree nodes.
171 * \param thickness of each skeleton graph.
172 * \param newOrder is saving for each node \p n in \p G the new adjacency
173 * list. This is an output parameter.
174 * \param adjBeforeNodeArraySource is saving for the source of the reference edge
175 * of the skeleton of mu the adjacency entry, before which new entries have
176 * to be inserted.
177 * \param adjBeforeNodeArrayTarget is saving for the target of the reference edge
178 * of the skeleton of mu the adjacency entry, before which new entries have
179 * to be inserted.
180 * \param delta_u the distance from the second adjacent face of the reference edge
181 * except the external face to the external face of G.
182 * \param delta_d the distance from the external face to the external face of G.
183 * \param adjExternal is an adjacency entry in the external face.
184 */
185 static void expandEdgePNode(const StaticSPQRTree& spqrTree, NodeArray<bool>& treeNodeTreated,
186 const node& mu, const node& leftNode, const NodeArray<T>& nodeLength,
187 const NodeArray<EdgeArray<T>>& edgeLength, const NodeArray<T>& thickness,
188 NodeArray<List<adjEntry>>& newOrder,
191 const T& delta_d, adjEntry& adjExternal);
192
193 /* \brief Embeds all edges in the skeleton graph \a S of an R-node of the
194 * SPQR-tree into an existing embedding and calls recursively itself for
195 * all virtual edges in S.
196 *
197 * \param spqrTree The SPQR-tree of the treated graph.
198 * \param treeNodeTreated is an array saving for each SPQR-tree node \p mu
199 * whether it was already treated by any call of ExpandEdge or not. Every
200 * \p mu should only be treated once.
201 * \param mu is a node in the SPQR-tree.
202 * \param leftNode is the node adjacent to referenceEdge, which should be "left"
203 * in the embedding
204 * \param nodeLength is an array saving the lengths of the nodes of \p G.
205 * \param edgeLength is saving the edge lengths of all edges in each skeleton
206 * graph of all tree nodes.
207 * \param thickness of each skeleton graph.
208 * \param newOrder is saving for each node \p n in \p G the new adjacency
209 * list. This is an output parameter.
210 * \param adjBeforeNodeArraySource is saving for the source of the reference edge
211 * of the skeleton of mu the adjacency entry, before which new entries have
212 * to be inserted.
213 * \param adjBeforeNodeArrayTarget is saving for the target of the reference edge
214 * of the skeleton of mu the adjacency entry, before which new entries have
215 * to be inserted.
216 * \param delta_u the distance from the second adjacent face of the reference edge
217 * except the external face to the external face of G.
218 * \param delta_d the distance from the external face to the external face of G.
219 * \param adjExternal is an adjacency entry in the external face.
220 * \param n is only set, if ExpandEdge is called for the first time, because
221 * then there is no virtual edge which has to be expanded, but the max face
222 * has to contain a certain node \p n.
223 */
224 static void expandEdgeRNode(const StaticSPQRTree& spqrTree, NodeArray<bool>& treeNodeTreated,
225 const node& mu, const node& leftNode, const NodeArray<T>& nodeLength,
226 const NodeArray<EdgeArray<T>>& edgeLength, const NodeArray<T>& thickness,
227 NodeArray<List<adjEntry>>& newOrder,
230 const T& delta_d, adjEntry& adjExternal, const node& n = nullptr);
231
232 /* \brief Writes a given adjacency entry into the newOrder. If the edge
233 * belonging to ae is a virtual edge, it is expanded.
234 *
235 * \param ae is the adjacency entry which has to be expanded.
236 * \param before is the adjacency entry of the node in \p G, before
237 * which ae has to be inserted.
238 * \param spqrTree The SPQR-tree of the treated graph.
239 * \param treeNodeTreated is an array saving for each SPQR-tree node \p mu
240 * whether it was already treated by any call of ExpandEdge or not. Every
241 * \p mu should only be treated once.
242 * \param mu is a node in the SPQR-tree.
243 * \param leftNode is the node adjacent to referenceEdge, which should be "left"
244 * in the embedding
245 * \param nodeLength is an array saving the lengths of the nodes of \p G.
246 * \param edgeLength is saving the edge lengths of all edges in each skeleton
247 * graph of all tree nodes.
248 * \param thickness of each skeleton graph.
249 * \param newOrder is saving for each node \p n in \p G the new adjacency
250 * list. This is an output parameter.
251 * \param adjBeforeNodeArraySource is saving for the source of the reference edge
252 * of the skeleton of mu the adjacency entry, before which new entries have
253 * to be inserted.
254 * \param adjBeforeNodeArrayTarget is saving for the target of the reference edge
255 * of the skeleton of mu the adjacency entry, before which new entries have
256 * to be inserted.
257 * \param delta_u the distance from the second adjacent face of the reference edge
258 * except the external face to the external face of G.
259 * \param delta_d the distance from the external face to the external face of G.
260 * \param adjExternal is an adjacency entry in the external face.
261 */
263 const StaticSPQRTree& spqrTree, NodeArray<bool>& treeNodeTreated, const node& mu,
264 const node& leftNode, const NodeArray<T>& nodeLength,
265 const NodeArray<EdgeArray<T>>& edgeLength, const NodeArray<T>& thickness,
266 NodeArray<List<adjEntry>>& newOrder,
269 const T& delta_d, adjEntry& adjExternal);
270
271 /* \brief Single source shortest path.
272 *
273 * \param G directed graph
274 * \param s source node
275 * \param length length of an edge
276 * \param d contains shortest path distances after call
277 */
278 static bool sssp(const Graph& G, const node& s, const EdgeArray<T>& length, NodeArray<T>& d);
279};
280
281template<class T>
283 const NodeArray<T>& nodeLength, const EdgeArray<T>& edgeLength, const node& n /* = 0*/) {
284 //Base cases (SPQR-Tree-implementatioin would crash with these inputs):
285 OGDF_ASSERT(G.numberOfNodes() >= 2);
286 if (G.numberOfEdges() <= 2) {
287 edge e = G.firstEdge();
288 adjExternal = e->adjSource();
289 return;
290 }
291
292 //First step: calculate maximum face and edge lengths for virtual edges
295 compute(G, nodeLength, edgeLength, &spqrTree, edgeLengthSkel);
296
297 //Second step: Embed G
298 T biggestFace = -1;
300 if (n == nullptr) {
301 for (node mu : spqrTree.tree().nodes) {
302 //Expand all faces in skeleton(mu) and get size of the largest of them:
303 T sizeMu = largestFaceInSkeleton(spqrTree, mu, nodeLength, edgeLengthSkel);
304 if (sizeMu > biggestFace) {
306 bigFaceMu = mu;
307 }
308 }
309 } else {
310 node* mus = new node[n->degree()];
311 int i = 0;
312 for (adjEntry adj : n->adjEntries) {
313 mus[i] = spqrTree.skeletonOfReal(adj->theEdge()).treeNode();
314 bool alreadySeenMu = false;
315 for (int j = 0; j < i && !alreadySeenMu; j++) {
316 if (mus[i] == mus[j]) {
317 alreadySeenMu = true;
318 }
319 }
320 if (alreadySeenMu) {
321 i++;
322 continue;
323 } else {
324 //Expand all faces in skeleton(mu) containing n and get size of
325 //the largest of them:
326 T sizeInMu =
327 largestFaceContainingNode(spqrTree, mus[i], n, nodeLength, edgeLengthSkel);
328 if (sizeInMu > biggestFace) {
330 bigFaceMu = mus[i];
331 }
332
333 i++;
334 }
335 }
336 delete[] mus;
337 }
338
339 bigFaceMu = spqrTree.rootTreeAt(bigFaceMu);
340
342 bottomUpThickness(spqrTree, bigFaceMu, thickness, nodeLength, edgeLengthSkel);
343
344 NodeArray<List<adjEntry>> newOrder(G);
345 NodeArray<bool> treeNodeTreated(spqrTree.tree(), false);
347 adjExternal = nullptr;
350 expandEdge(spqrTree, treeNodeTreated, bigFaceMu, nullptr, nodeLength, edgeLengthSkel, thickness,
352
353 for (node v : G.nodes) {
354 G.sort(v, newOrder[v]);
355 }
356}
357
358template<class T>
361 NodeArray<bool>& treeNodeTreated, const node& mu, const node& leftNode,
362 const NodeArray<T>& nodeLength, const NodeArray<EdgeArray<T>>& edgeLength,
366 const T& delta_d, adjEntry& adjExternal) {
367 Skeleton& S = spqrTree.skeleton(mu);
368 edge referenceEdge = S.referenceEdge();
369 if (S.isVirtual(ae->theEdge())) {
370 edge twinE = S.twinEdge(ae->theEdge());
371 node twinNT = S.twinTreeNode(ae->theEdge());
372#if 0
373 Skeleton& twinS = spqrTree.skeleton(twinNT);
374#endif
375
376 if (!treeNodeTreated[twinNT]) {
378 if (ae->theEdge()->source() == leftNode) {
379 m_leftNode = twinE->source();
380 } else {
381 m_leftNode = twinE->target();
382 }
383
384 if (ae->theEdge()->source() == ae->theNode()) {
386 } else {
388 }
389
390 //recursion call:
391 expandEdge(spqrTree, treeNodeTreated, twinNT, m_leftNode, nodeLength, edgeLength,
394 }
395
396 if (ae->theEdge() == referenceEdge) {
397 if (ae->theNode() == ae->theEdge()->source()) {
401 } else {
405 }
406 } else
407 {
408 if (ae->theNode() == ae->theEdge()->source()) {
410 } else {
412 }
413 }
414 } else
415 {
416 node origNode = S.original(ae->theNode());
417 edge origEdge = S.realEdge(ae->theEdge());
418
419 if (origNode == origEdge->source()) {
420 if (!before.valid()) {
421 before = newOrder[origNode].pushBack(origEdge->adjSource());
422 } else {
423 before = newOrder[origNode].insertBefore(origEdge->adjSource(), before);
424 }
425 } else {
426 if (!before.valid()) {
427 before = newOrder[origNode].pushBack(origEdge->adjTarget());
428 } else {
429 before = newOrder[origNode].insertBefore(origEdge->adjTarget(), before);
430 }
431 }
432 }
433}
434
435template<class T>
437 NodeArray<bool>& treeNodeTreated, const node& mu, const node& leftNode,
438 const NodeArray<T>& nodeLength, const NodeArray<EdgeArray<T>>& edgeLength,
442 const T& delta_d, adjEntry& adjExternal, const node& n /*= 0*/) {
443 treeNodeTreated[mu] = true;
444
445 switch (spqrTree.typeOf(mu)) {
447 expandEdgeSNode(spqrTree, treeNodeTreated, mu, leftNode, nodeLength, edgeLength, thickness,
450 break;
452 expandEdgePNode(spqrTree, treeNodeTreated, mu, leftNode, nodeLength, edgeLength, thickness,
455 break;
457 expandEdgeRNode(spqrTree, treeNodeTreated, mu, leftNode, nodeLength, edgeLength, thickness,
459 adjExternal, n);
460 break;
461 default:
462 OGDF_ASSERT(false);
463 }
464}
465
466template<class T>
468 NodeArray<bool>& treeNodeTreated, const node& mu, const node& leftNode,
469 const NodeArray<T>& nodeLength, const NodeArray<EdgeArray<T>>& edgeLength,
473 const T& delta_d, adjEntry& adjExternal) {
474 Skeleton& S = spqrTree.skeleton(mu);
475 edge referenceEdge = S.referenceEdge();
476 adjEntry startAdjEntry = nullptr;
477 if (leftNode == nullptr) {
478 for (edge e : S.getGraph().edges) {
479 if (!S.isVirtual(e)) {
480 startAdjEntry = e->adjSource();
481 break;
482 }
483 }
484 OGDF_ASSERT(startAdjEntry != nullptr);
485 } else if (leftNode->firstAdj()->theEdge() == referenceEdge) {
486 startAdjEntry = leftNode->lastAdj();
487 } else {
488 startAdjEntry = leftNode->firstAdj();
489 }
490
492 if (adjExternal == nullptr) {
493 edge orgEdge = S.realEdge(ae->theEdge());
494 if (orgEdge->source() == S.original(ae->theNode())) {
495 adjExternal = orgEdge->adjSource()->twin();
496 } else {
497 adjExternal = orgEdge->adjTarget()->twin();
498 }
499 }
500
502 if (referenceEdge && leftNode == referenceEdge->source()) {
504 } else if (referenceEdge) {
506 }
508
509 bool firstStep = true;
510 while (firstStep || ae != startAdjEntry) {
511 //first treat ae with ae->theNode() is left node, then treat its twin:
512 node m_leftNode = ae->theNode();
513
514 if (ae->theEdge() == referenceEdge) {
515 if (ae->theNode() == referenceEdge->source()) {
517 } else {
519 }
520 } else {
521 if (S.isVirtual(ae->theEdge()) && referenceEdge) {
522 node twinTN = S.twinTreeNode(ae->theEdge());
523 if (ae->theEdge()->source() == ae->theNode()) {
524 if (ae->theEdge()->target() == referenceEdge->source()) {
526 } else if (ae->theEdge()->target() == referenceEdge->target()) {
528 }
529 } else {
530 if (ae->theEdge()->source() == referenceEdge->source()) {
532 } else if (ae->theEdge()->source() == referenceEdge->target()) {
534 }
535 }
536 }
537
538 adjEntryForNode(ae, before, spqrTree, treeNodeTreated, mu, m_leftNode, nodeLength,
539 edgeLength, thickness, newOrder, adjBeforeNodeArraySource,
541 }
542
543 if (firstStep) {
545 firstStep = false;
546 }
547
548 ae = ae->twin();
549 if (!referenceEdge) {
550 before = nullptr;
551 } else if (ae->theNode() == referenceEdge->source()) {
553 } else if (ae->theNode() == referenceEdge->target()) {
555 } else {
556 before = nullptr;
557 }
558 if (ae->theEdge() == referenceEdge) {
559 if (ae->theNode() == referenceEdge->source()) {
561 } else {
563 }
564 } else {
565 adjEntryForNode(ae, before, spqrTree, treeNodeTreated, mu, m_leftNode, nodeLength,
566 edgeLength, thickness, newOrder, adjBeforeNodeArraySource,
568 }
569
570 //set new adjacency entry pair (ae and its twin):
571 if (ae->theNode()->firstAdj() == ae) {
572 ae = ae->theNode()->lastAdj();
573 } else {
574 ae = ae->theNode()->firstAdj();
575 }
576 }
577}
578
579template<class T>
581 NodeArray<bool>& treeNodeTreated, const node& mu, const node& leftNode,
582 const NodeArray<T>& nodeLength, const NodeArray<EdgeArray<T>>& edgeLength,
586 const T& delta_d, adjEntry& adjExternal) {
587 //Choose face defined by virtual edge and the longest edge different from it.
588 Skeleton& S = spqrTree.skeleton(mu);
589 edge referenceEdge = S.referenceEdge();
590 edge altReferenceEdge = nullptr;
591
593 if (!m_leftNode) {
595 S.getGraph().allNodes(nodeList);
596 m_leftNode = *(nodeList.begin());
597 }
598 node m_rightNode = m_leftNode->firstAdj()->twinNode();
599
600 if (referenceEdge == nullptr) {
601 for (edge e : S.getGraph().edges) {
602 if (!S.isVirtual(e)) {
604 edge orgEdge = S.realEdge(e);
605 if (orgEdge->source() == S.original(m_leftNode)) {
606 adjExternal = orgEdge->adjSource();
607 } else {
608 adjExternal = orgEdge->adjTarget();
609 }
610 break;
611 }
612 }
613 }
614
615 //sort edges by length:
617 for (edge e : S.getGraph().edges) {
618 if (e == referenceEdge || e == altReferenceEdge) {
619 continue;
620 }
621
622 if (!graphEdges.begin().valid()) {
623 graphEdges.pushBack(e);
624 } else {
625 for (ListIterator<edge> it = graphEdges.begin(); it.valid(); ++it) {
626 if (edgeLength[mu][e] > edgeLength[mu][*it]) {
627 graphEdges.insertBefore(e, it);
628 break;
629 }
630 ListIterator<edge> next = it;
631 ++next;
632 if (!next.valid()) {
633 graphEdges.pushBack(e);
634 break;
635 }
636 }
637 }
638 }
639
643
644 //begin with left node and longest edge:
645 for (int i = 0; i < 2; ++i) {
647 node n;
648 if (i == 0) {
649 n = m_leftNode;
650 } else {
651 n = m_rightNode;
653 }
654
655 if (referenceEdge) {
656 if (n == referenceEdge->source()) {
658 } else {
660 }
661 }
662
663 adjEntry ae;
664
665 //all edges except reference edge:
666 if (i == 0) {
669 if (referenceEdge) {
670 if (referenceEdge->source() == m_rightNode) {
672 } else { //referenceEdge->target() == rightnode
674 }
675 }
676 bool insertBeforeLast = false;
677 bool oneEdgeInE_a = false;
678 T sum_E_a = 0;
679 T sum_E_b = 0;
680
681 for (int looper = 0; looper < graphEdges.size(); looper++) {
682 edge e = *(graphEdges.get(looper));
683
684 if (!lastPos.valid()) {
685 lastPos = rightEdgeOrder.pushBack(e);
686 } else if (insertBeforeLast) {
687 lastPos = rightEdgeOrder.insertBefore(e, lastPos);
688 } else {
689 lastPos = rightEdgeOrder.insertAfter(e, lastPos);
690 }
691
692 //decide whether to choose face f_a or f_b as f_{mu, mu'}:
693 if (delta_u + sum_E_a < delta_d + sum_E_b) {
695
696 if (e->source() == n) {
697 ae = e->adjSource();
698 } else {
699 ae = e->adjTarget();
700 }
701
702 if (S.isVirtual(e)) {
703 node nu = S.twinTreeNode(e);
704
707
708 //buffer computed embedding:
711
712 adjEntryForNode(ae, tmp_before, spqrTree, treeNodeTreated, mu, m_leftNode,
713 nodeLength, edgeLength, thickness, tmp_newOrder,
716
717 //copy buffered embedding reversed into newOrder:
718 node leftOrg = S.original(m_leftNode);
719 node rightOrg = S.original(m_rightNode);
720 for (node nOG : spqrTree.originalGraph().nodes) {
722 if (nOG_tmp_adjList.size() == 0) {
723 continue;
724 }
725
727 if (nOG == leftOrg) {
728 m_before = &beforeU;
729 } else if (nOG == rightOrg && referenceEdge) {
731 } else {
733 }
734
736 ae_it.valid(); ++ae_it) {
738 if (!m_before->valid()) {
739 *m_before = newOrder[nOG].pushBack(adjaEnt);
740 } else {
741 *m_before = newOrder[nOG].insertBefore(adjaEnt, *m_before);
742 }
743
744 if (nOG == leftOrg || nOG == rightOrg) {
745 if (S.original(e->source()) == nOG) {
747 } else {
749 }
750 }
751 }
752
753 if (nOG != leftOrg && (nOG != rightOrg || !referenceEdge)) {
754 delete m_before;
755 }
756 }
757
758 sum_E_a += thickness[nu];
759 } else
760 {
761 adjEntryForNode(ae, beforeU, spqrTree, treeNodeTreated, mu, m_leftNode,
762 nodeLength, edgeLength, thickness, newOrder, adjBeforeNodeArraySource,
764
765 sum_E_a += 1;
766 }
767
768 insertBeforeLast = false;
769 if (!oneEdgeInE_a) {
771 oneEdgeInE_a = true;
772 }
773 } else
774 {
775 if (S.isVirtual(e)) {
776 node nu = S.twinTreeNode(e);
777 if (referenceEdge) {
778 if (e->source() == n) {
780 } else {
782 }
783 }
784 }
785
788
789 if (e->source() == n) {
790 ae = e->adjSource();
791 } else {
792 ae = e->adjTarget();
793 }
794
795 adjEntryForNode(ae, before, spqrTree, treeNodeTreated, mu, m_leftNode,
796 nodeLength, edgeLength, thickness, newOrder, adjBeforeNodeArraySource,
798
799 if (S.isVirtual(e)) {
800 sum_E_b += thickness[S.twinTreeNode(e)];
801 } else {
802 sum_E_b += 1;
803 }
804
805 insertBeforeLast = true;
806 if (!oneEdgeInE_a) {
808 }
809 }
810 }
811 } else {
812 for (ListIterator<edge> it = rightEdgeOrder.begin(); it.valid(); ++it) {
813 if ((*it)->source() == n) {
814 ae = (*it)->adjSource();
815 } else {
816 ae = (*it)->adjTarget();
817 }
818
819 adjEntryForNode(ae, before, spqrTree, treeNodeTreated, mu, m_leftNode, nodeLength,
820 edgeLength, thickness, newOrder, adjBeforeNodeArraySource,
822 }
823 }
824
825 //(alternative) reference edge at last:
826 if (referenceEdge) {
827 if (i == 0) {
828 if (n == referenceEdge->source()) {
830 } else {
832 }
833 } else {
834 if (n == referenceEdge->source()) {
836 } else {
838 }
839 }
840 } else {
841 if (altReferenceEdge->source() == n) {
842 ae = altReferenceEdge->adjSource();
843 } else {
844 ae = altReferenceEdge->adjTarget();
845 }
846
847 adjEntryForNode(ae, before, spqrTree, treeNodeTreated, mu, m_leftNode, nodeLength,
848 edgeLength, thickness, newOrder, adjBeforeNodeArraySource,
850 }
851 }
852}
853
854template<class T>
856 NodeArray<bool>& treeNodeTreated, const node& mu, const node& leftNode,
857 const NodeArray<T>& nodeLength, const NodeArray<EdgeArray<T>>& edgeLength,
861 const T& delta_d, adjEntry& adjExternal, const node& n /* = 0 */) {
862 Skeleton& S = spqrTree.skeleton(mu);
863 edge referenceEdge = S.referenceEdge();
864
865 //compute biggest face containing the reference edge:
866 face maxFaceContEdge = nullptr;
868 planarEmbed(S.getGraph());
870 T bigFaceSize = -1;
871 adjEntry m_adjExternal = nullptr;
872 for (face f : combinatorialEmbedding.faces) {
873 bool containsVirtualEdgeOrN = false;
875 T sizeOfFace = 0;
877 for (adjEntry ae : f->entries) {
878 faceNodes.pushBack(ae->theNode());
879 if ((n == nullptr && (ae->theEdge() == referenceEdge || !referenceEdge))
880 || S.original(ae->theNode()) == n) {
882 if (referenceEdge) {
884 }
885 }
886
887 if (!referenceEdge && !S.isVirtual(ae->theEdge())) {
889 }
890
891 sizeOfFace += edgeLength[mu][ae->theEdge()] + nodeLength[S.original(ae->theNode())];
892 }
893
898 m_adjExternal = this_m_adjExternal;
899 }
900 }
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 adjEntry adjMaxFace = m_adjExternal;
913
914 //if embedding is mirror symmetrical embedding of desired embedding,
915 //invert adjacency list of all nodes:
916 if (referenceEdge) {
917 //successor of adjEntry of virtual edge in adjacency list of leftNode:
919 if (leftNode == referenceEdge->source()) {
920 succ_virtualEdge_leftNode = referenceEdge->adjSource()->succ();
921 } else {
922 succ_virtualEdge_leftNode = referenceEdge->adjTarget()->succ();
923 }
926 }
927
928 bool succVELNAEInExtFace = false;
929 for (adjEntry aeExtFace : maxFaceContEdge->entries) {
930 if (aeExtFace->theEdge() == succ_virtualEdge_leftNode->theEdge()) {
931 succVELNAEInExtFace = true;
932 break;
933 }
934 }
935
936 if (!succVELNAEInExtFace) {
937 for (node v : S.getGraph().nodes) {
939 for (adjEntry ae = v->firstAdj(); ae; ae = ae->succ()) {
940 newAdjOrder.pushFront(ae);
941 }
942 S.getGraph().sort(v, newAdjOrder);
943 }
944 adjMaxFace = adjMaxFace->twin();
945 }
946 }
947
948 NodeArray<bool> nodeTreated(S.getGraph(), false);
950 if (referenceEdge) {
952 do {
953 if (start_ae->theEdge() == referenceEdge) {
954 start_ae = start_ae->faceCycleSucc();
955 break;
956 }
957 start_ae = start_ae->faceCycleSucc();
958 } while (start_ae != adjMaxFace);
959 } else {
961 }
962
963 //For every edge a buffer saving adjacency entries written in embedding step
964 //for nodes on the maximum face, needed in step for other nodes.
965 EdgeArray<List<adjEntry>> buffer(S.getGraph());
966
967 bool firstStep = true;
968 bool after_start_ae = true;
969 for (adjEntry ae = start_ae; firstStep || ae != start_ae;
970 after_start_ae = after_start_ae && ae->succ(),
971 ae = after_start_ae ? ae->faceCycleSucc()
972 : (!ae->faceCycleSucc() ? adjMaxFace : ae->faceCycleSucc())) {
973 firstStep = false;
974#if 0
975 node nodeG = S.original(ae->theNode());
976#endif
977 nodeTreated[ae->theNode()] = true;
978
979 //copy adjacency list of nodes into newOrder:
981 edge vE = (ae->theEdge() == referenceEdge) ? referenceEdge : ae->theEdge();
982 node nu = (ae->theEdge() == referenceEdge) ? mu : S.twinTreeNode(ae->theEdge());
983 if (S.isVirtual(vE)) {
984 if (ae->theNode() == vE->source()) {
986 } else {
988 }
989 }
990
991 bool after_ae = true;
993 if (referenceEdge) {
994 if (ae->theNode() == referenceEdge->source()) {
995 m_start_ae = referenceEdge->adjSource();
996 } else if (ae->theNode() == referenceEdge->target()) {
997 m_start_ae = referenceEdge->adjTarget();
998 } else {
999 m_start_ae = ae;
1000 }
1001 } else {
1002 m_start_ae = ae;
1003 }
1004
1006 bool hit_stop_twice = false;
1007 int numOfHits = 0;
1008 if (referenceEdge
1009 && (ae->theNode() == referenceEdge->source()
1010 || ae->theNode() == referenceEdge->target())) {
1011 if (m_start_ae->succ()) {
1012 m_stop_ae = m_start_ae->succ();
1013 } else {
1014 m_stop_ae = m_start_ae->theNode()->firstAdj();
1015 hit_stop_twice = true;
1016 }
1017 } else {
1019 }
1020
1021 for (adjEntry aeN = m_start_ae;
1022 after_ae || (hit_stop_twice && numOfHits != 2) || aeN != m_stop_ae;
1023 after_ae = after_ae && aeN->succ(),
1024 aeN = after_ae ? aeN->succ()
1025 : (!aeN->succ() ? ae->theNode()->firstAdj() : aeN->succ()),
1026 numOfHits = (aeN == m_stop_ae) ? numOfHits + 1 : numOfHits) {
1027 node m_leftNode = nullptr;
1028 if (S.isVirtual(aeN->theEdge()) && aeN->theEdge() != referenceEdge) {
1029 //Compute left node of aeN->theNode(). First get adjacency entry in ext. face
1030 //(if edge is in ext. face) and compare face cycle successor with successor
1031 //in node adjacency list. If it is the same, it is the right node, otherwise
1032 //the left.
1033 adjEntry aeExtFace = nullptr;
1034 bool succInExtFace = false;
1035 bool aeNInExtFace = false;
1036 adjEntry aeNSucc = (aeN->succ()) ? aeN->succ() : ae->theNode()->firstAdj();
1038 do {
1039 if (aeExtFace->theEdge() == aeNSucc->theEdge()) {
1040 succInExtFace = true;
1041 if (aeNInExtFace) {
1042 break;
1043 }
1044 }
1045 if (aeExtFace->theEdge() == aeN->theEdge()) {
1046 aeNInExtFace = true;
1047 if (succInExtFace) {
1048 break;
1049 }
1050 }
1051 aeExtFace = aeExtFace->faceCycleSucc();
1052 } while (aeExtFace != adjMaxFace);
1053 if (aeNInExtFace && succInExtFace) {
1054 m_leftNode = aeN->twinNode();
1055 } else {
1056 m_leftNode = aeN->theNode();
1057 }
1058
1059 node twinTN = S.twinTreeNode(aeN->theEdge());
1060 if (referenceEdge) {
1061 if (aeN->theEdge()->source() == aeN->theNode()) {
1062 if (aeN->theEdge()->target() == referenceEdge->source()) {
1064 } else if (aeN->theEdge()->target() == referenceEdge->target()) {
1066 }
1067 } else {
1068 if (aeN->theEdge()->source() == referenceEdge->source()) {
1070 } else if (aeN->theEdge()->source() == referenceEdge->target()) {
1072 }
1073 }
1074 }
1075 }
1076
1077 adjEntryForNode(aeN, before, spqrTree, treeNodeTreated, mu, m_leftNode, nodeLength,
1078 edgeLength, thickness, newOrder, adjBeforeNodeArraySource,
1080
1081 //if the other node adjacent to the current treated edge is not in the
1082 //max face, put written edges into an buffer and clear the adjacency
1083 //list of that node.
1084 if (!maxFaceNodes.search(aeN->twinNode()).valid()) {
1085 node orig_aeN_twin_theNode = S.original(aeN->twinNode());
1086 buffer[aeN->theEdge()] = newOrder[orig_aeN_twin_theNode];
1087 newOrder[orig_aeN_twin_theNode].clear();
1088 }
1089 }
1090 }
1091
1092 //Copy of not treated node's adjacency lists (internal nodes). Setting
1093 //of left node depending on minimal distance to external face of the
1094 //face defined by left node.
1095 bool DGcomputed = false;
1096 int f_ext_id = 0;
1097 int f_ref_id = 0;
1098 Graph DG;
1099 ArrayBuffer<node> fPG_to_nDG;
1101 List<List<adjEntry>> faces;
1105
1106 for (node v : S.getGraph().nodes) {
1107 if (nodeTreated[v]) {
1108 continue;
1109 }
1110
1111 node v_original = S.original(v);
1112 nodeTreated[v] = true;
1114 for (adjEntry ae = v->firstAdj(); ae; ae = ae->succ()) {
1115 if (buffer[ae->theEdge()].empty()) {
1116 T delta_u_nu = 0;
1117 T delta_d_nu = 0;
1118 bool frauenlinks = false;
1119 if (S.isVirtual(ae->theEdge())) {
1120 if (!DGcomputed) {
1121 ae_to_face.init(S.getGraph());
1123 DGcomputed = true;
1124
1125 //compute dual graph of skeleton graph:
1126 adjacencyList.init(S.getGraph());
1127 for (node nBG : S.getGraph().nodes) {
1128 for (adjEntry ae_nBG : nBG->adjEntries) {
1129 adjacencyList[nBG].pushBack(ae_nBG);
1130 }
1131 }
1132
1134 for (node nBG : S.getGraph().nodes) {
1135 for (adjEntry adj : nBG->adjEntries) {
1136 if (adjEntryTreated[nBG].search(adj).valid()) {
1137 continue;
1138 }
1139
1141 adjEntry adj2 = adj;
1142 do {
1143 newFace.pushBack(adj2);
1144 ae_to_face[adj2] = faces.size();
1145 adjEntryTreated[adj2->theNode()].pushBack(adj2);
1146 List<adjEntry>& ladj = adjacencyList[adj2->twinNode()];
1147 adj2 = *ladj.cyclicPred(ladj.search(adj2->twin()));
1148 } while (adj2 != adj);
1149 faces.pushBack(newFace);
1150 }
1151 }
1152
1153 for (ListIterator<List<adjEntry>> it = faces.begin(); it.valid(); ++it) {
1154 fPG_to_nDG.push(DG.newNode());
1155 }
1156
1158 int i = 0;
1159 for (ListIterator<List<adjEntry>> it = faces.begin(); it.valid(); ++it) {
1160 int f1_id = i;
1161 for (ListIterator<adjEntry> it2 = (*it).begin(); it2.valid(); ++it2) {
1162 int f2_id = 0;
1163 int j = 0;
1164 for (ListIterator<List<adjEntry>> it3 = faces.begin(); it3.valid();
1165 ++it3) {
1166 bool do_break = false;
1167 for (ListIterator<adjEntry> it4 = (*it3).begin(); it4.valid();
1168 ++it4) {
1169 if ((*it4) == (*it2)->twin()) {
1170 f2_id = j;
1171 do_break = true;
1172 break;
1173 }
1174 }
1175 if (do_break) {
1176 break;
1177 }
1178 j++;
1179 }
1180
1181 if (f1_id != f2_id
1182 && !adjFaces[fPG_to_nDG[f1_id]].search(fPG_to_nDG[f2_id]).valid()
1183 && !adjFaces[fPG_to_nDG[f2_id]].search(fPG_to_nDG[f1_id]).valid()) {
1184 adjFaces[fPG_to_nDG[f1_id]].pushBack(fPG_to_nDG[f2_id]);
1185 edge e1 = DG.newEdge(fPG_to_nDG[f1_id], fPG_to_nDG[f2_id]);
1186 edge e2 = DG.newEdge(fPG_to_nDG[f2_id], fPG_to_nDG[f1_id]);
1187
1188 //set edge length:
1189 T e_length = -1;
1190 for (auto f1 : *it) {
1191 edge e = f1->theEdge();
1192 for (auto f2 : *faces.get(f2_id)) {
1193 if (f2->theEdge() == e
1194 && (e_length == -1
1195 || edgeLength[mu][e] < e_length)) {
1196 e_length = edgeLength[mu][e];
1197 }
1198 }
1199 }
1202 }
1203
1204 if (*it2 == adjMaxFace) {
1205 f_ext_id = f1_id;
1206 }
1207 if (referenceEdge && *it2 == adjMaxFace->twin()) {
1208 f_ref_id = f1_id;
1209 }
1210 }
1211 i++;
1212 }
1213
1214 //compute shortest path from every face to the external face:
1215 node f_ext_DG = fPG_to_nDG[f_ext_id];
1216 dist_f_ext.init(DG);
1218 if (referenceEdge) {
1219 node f_ref_DG = fPG_to_nDG[f_ref_id];
1220 dist_f_ref.init(DG);
1222 }
1223 }
1224
1225 //choose face with minimal shortest path:
1226 T min1, min2;
1227 T pi_f_0_f_ext = dist_f_ext[fPG_to_nDG[ae_to_face[ae]]];
1228 T pi_f_1_f_ext = dist_f_ext[fPG_to_nDG[ae_to_face[ae->twin()]]];
1229 if (referenceEdge) {
1230 T pi_f_0_f_ref = dist_f_ref[fPG_to_nDG[ae_to_face[ae]]];
1231 T pi_f_1_f_ref = dist_f_ref[fPG_to_nDG[ae_to_face[ae->twin()]]];
1232
1235 } else {
1237 }
1238
1241 } else {
1243 }
1244
1245 if (min1 > min2) {
1247 if (pi_f_0_f_ref < pi_f_0_f_ext) {
1249 } else {
1251 }
1253 if (pi_f_1_f_ref < pi_f_1_f_ext) {
1255 } else {
1257 }
1258 } else {
1259 frauenlinks = true;
1261 if (pi_f_1_f_ref < pi_f_1_f_ext) {
1263 } else {
1265 }
1267 if (pi_f_0_f_ref < pi_f_0_f_ext) {
1269 } else {
1271 }
1272 }
1273 } else {
1276
1277 if (min1 > min2) {
1280 } else {
1281 frauenlinks = true;
1284 }
1285 }
1286 }
1287
1288 if (frauenlinks) {
1289 node nu = S.twinTreeNode(ae->theEdge());
1290
1291 //buffer computed embedding:
1294
1295 adjEntryForNode(ae, tmp_before, spqrTree, treeNodeTreated, mu, v, nodeLength,
1298
1299 //copy buffered embedding reversed into newOrder:
1300#if 0
1301 node m_leftNode = v;
1302#endif
1303 node m_rightNode = ae->twinNode();
1305 node rightOrg = S.original(m_rightNode);
1306 for (node nOG : spqrTree.originalGraph().nodes) {
1308 if (nOG_tmp_adjList.size() == 0) {
1309 continue;
1310 }
1311
1313 if (nOG == leftOrg) {
1314 m_before = &before;
1315 } else {
1317 }
1318
1319 for (ListIterator<adjEntry> ae_it = nOG_tmp_adjList.begin(); ae_it.valid();
1320 ++ae_it) {
1322 if (!m_before->valid()) {
1323 *m_before = newOrder[nOG].pushBack(adjaEnt);
1324 } else {
1325 *m_before = newOrder[nOG].insertBefore(adjaEnt, *m_before);
1326 }
1327
1328 if (nOG == leftOrg || nOG == rightOrg) {
1329 if (S.original(ae->theEdge()->source()) == nOG) {
1331 } else {
1333 }
1334 }
1335 }
1336
1337 if (nOG != leftOrg) {
1338 delete m_before;
1339 }
1340 }
1341 } else {
1342 adjEntryForNode(ae, before, spqrTree, treeNodeTreated, mu, v, nodeLength,
1343 edgeLength, thickness, newOrder, adjBeforeNodeArraySource,
1345 }
1346
1347 if (!nodeTreated[ae->twinNode()]) {
1348 node orig_ae_twin_theNode = S.original(ae->twinNode());
1349 buffer[ae->theEdge()] = newOrder[orig_ae_twin_theNode];
1350 newOrder[orig_ae_twin_theNode].clear();
1351 }
1352 } else {
1353 buffer[ae->theEdge()].reverse();
1354 for (ListIterator<adjEntry> it = buffer[ae->theEdge()].begin(); it.valid(); ++it) {
1355 if (!before.valid()) {
1356 before = newOrder[v_original].pushFront(*it);
1357 } else {
1358 before = newOrder[v_original].insertBefore(*it, before);
1359 }
1360 }
1361 }
1362 }
1363 }
1364}
1365
1366template<class T>
1368 const node& mu, NodeArray<T>& thickness, const NodeArray<T>& nodeLength,
1369 const NodeArray<EdgeArray<T>>& edgeLength) {
1370 //recursion:
1371 for (adjEntry adj : mu->adjEntries) {
1372 edge e_mu_to_nu = adj->theEdge();
1373 if (e_mu_to_nu->source() != mu) {
1374 continue;
1375 } else {
1376 node nu = e_mu_to_nu->target();
1377 bottomUpThickness(spqrTree, nu, thickness, nodeLength, edgeLength);
1378 }
1379 }
1380
1381 Skeleton& S = spqrTree.skeleton(mu);
1382 edge referenceEdge = S.referenceEdge();
1383
1384 if (!referenceEdge) { //root of SPQR-tree
1385 thickness[mu] = 0;
1386 return;
1387 }
1388
1389 //set dLengths for all edges in skeleton graph:
1390 EdgeArray<T> dLength(S.getGraph());
1391 for (edge eSG : S.getGraph().edges) {
1392 if (eSG == referenceEdge) {
1393 continue;
1394 }
1395
1396 if (S.isVirtual(eSG)) {
1397 node twinTN = S.twinTreeNode(eSG);
1399 } else {
1400 dLength[eSG] = edgeLength[mu][eSG];
1401 }
1402 }
1403
1404 //compute thickness of skeleton(mu):
1405 switch (spqrTree.typeOf(mu)) {
1407 //thickness(mu) = min_{edges e != referenceEdge} dLength(e)
1408 T min_dLength = -1;
1409 for (edge eSG : S.getGraph().edges) {
1410 if (eSG == referenceEdge) {
1411 continue;
1412 }
1413 if (min_dLength == -1 || dLength[eSG] < min_dLength) {
1415 }
1416 }
1417 thickness[mu] = min_dLength;
1418 } break;
1420 //thickness(mu) = sum_{edges e != referenceEdge} dLength(e)
1421 T sumof_dLength = 0;
1422 for (edge eSG : S.getGraph().edges) {
1423 if (eSG == referenceEdge) {
1424 continue;
1425 }
1427 }
1429 } break;
1431 /* Let f^ref_0, ... , f^ref_k be the faces sharing at least one edge with
1432 * f_ref - the face adjacent to the reference edge not equal to the
1433 * external face f_ext. Compute the dual graph and set edge lengths for
1434 * two faces f_i, f_j, i != j, with at least one shared edge, to the
1435 * minimal dLength of the shared edges of f_i and f_j. Remove the node
1436 * related to face f_ref. thickness(mu) is then the length of the shortest
1437 * path from any of the faces f^ref_0, ... , f^ref_k to f_ext plus 1.
1438 */
1439 CombinatorialEmbedding CE(S.getGraph());
1440 adjEntry ae_f_ext = referenceEdge->adjSource();
1441 adjEntry ae_f_ref = referenceEdge->adjTarget();
1442 T faceSize_f_ext = 0;
1444 do {
1445 faceSize_f_ext += nodeLength[S.original(ae_f_ext_walker->theNode())]
1446 + edgeLength[mu][ae_f_ext_walker->theEdge()];
1447 ae_f_ext_walker = ae_f_ext_walker->faceCycleSucc();
1448 } while (ae_f_ext_walker != ae_f_ext);
1449 T faceSize_f_ref = 0;
1451 do {
1452 faceSize_f_ref += nodeLength[S.original(ae_f_ref_walker->theNode())]
1453 + edgeLength[mu][ae_f_ref_walker->theEdge()];
1454 ae_f_ref_walker = ae_f_ref_walker->faceCycleSucc();
1455 } while (ae_f_ref_walker != ae_f_ref);
1459 ae_f_ref = ae_tmp;
1460 }
1461
1462 //compute dual graph:
1463 Graph DG;
1464 ArrayBuffer<node> fPG_to_nDG;
1466 List<List<adjEntry>> faces;
1467 NodeArray<int> distances;
1469 int f_ref_id = -1;
1470 int f_ext_id = -1;
1471
1472 for (node nBG : S.getGraph().nodes) {
1473 for (adjEntry ae_nBG : nBG->adjEntries) {
1474 adjacencyList[nBG].pushBack(ae_nBG);
1475 }
1476 }
1477
1479 for (node nBG : S.getGraph().nodes) {
1480 for (adjEntry adj : nBG->adjEntries) {
1481 if (adjEntryTreated[nBG].search(adj).valid()) {
1482 continue;
1483 }
1484
1486 adjEntry adj2 = adj;
1487 do {
1488 newFace.pushBack(adj2);
1489 adjEntryTreated[adj2->theNode()].pushBack(adj2);
1490 List<adjEntry>& ladj = adjacencyList[adj2->twinNode()];
1491 adj2 = *ladj.cyclicPred(ladj.search(adj2->twin()));
1492 } while (adj2 != adj);
1493 faces.pushBack(newFace);
1494 }
1495 }
1496
1497 for (ListIterator<List<adjEntry>> it = faces.begin(); it.valid(); ++it) {
1498 fPG_to_nDG.push(DG.newNode());
1499 }
1500
1502 int i = 0;
1503 for (ListIterator<List<adjEntry>> it = faces.begin(); it.valid(); ++it) {
1504 int f1_id = i;
1505 for (ListIterator<adjEntry> it2 = (*it).begin(); it2.valid(); ++it2) {
1506 int f2_id = 0;
1507 int j = 0;
1508 for (ListIterator<List<adjEntry>> it3 = faces.begin(); it3.valid(); ++it3) {
1509 bool do_break = false;
1510 for (ListIterator<adjEntry> it4 = (*it3).begin(); it4.valid(); ++it4) {
1511 if ((*it4) == (*it2)->twin()) {
1512 f2_id = j;
1513 do_break = true;
1514 break;
1515 }
1516 }
1517 if (do_break) {
1518 break;
1519 }
1520 j++;
1521 }
1522
1523 if (f1_id != f2_id && !adjFaces[fPG_to_nDG[f1_id]].search(fPG_to_nDG[f2_id]).valid()
1524 && !adjFaces[fPG_to_nDG[f2_id]].search(fPG_to_nDG[f1_id]).valid()) {
1525 adjFaces[fPG_to_nDG[f1_id]].pushBack(fPG_to_nDG[f2_id]);
1526 adjFaces[fPG_to_nDG[f2_id]].pushBack(fPG_to_nDG[f1_id]);
1527 edge e1 = DG.newEdge(fPG_to_nDG[f1_id], fPG_to_nDG[f2_id]);
1528 edge e2 = DG.newEdge(fPG_to_nDG[f2_id], fPG_to_nDG[f1_id]);
1529
1530 //set edge length:
1531 T e_length = -1;
1532 for (ListIterator<adjEntry> it_f1 = (*it).begin(); it_f1.valid(); ++it_f1) {
1533 edge e = (*it_f1)->theEdge();
1534 for (ListIterator<adjEntry> it_f2 = (*(faces.get(f2_id))).begin();
1535 it_f2.valid(); ++it_f2) {
1536 if ((*it_f2)->theEdge() == e
1537 && (e_length == -1 || edgeLength[mu][e] < e_length)) {
1538 e_length = edgeLength[mu][e];
1539 }
1540 }
1541 }
1544 }
1545
1546 if (*it2 == ae_f_ext) {
1547 f_ext_id = f1_id;
1548 }
1549 if (*it2 == ae_f_ref) {
1550 f_ref_id = f1_id;
1551 }
1552 }
1553 i++;
1554 }
1555
1556 //the faces sharing at least one edge with f_ref:
1557 node nDG_f_ref = fPG_to_nDG[f_ref_id];
1559
1560 //remove node related to f_ref from dual graph:
1561 DG.delNode(fPG_to_nDG[f_ref_id]);
1562
1563 //compute shortest path and set thickness:
1565 node nDG_f_ext = fPG_to_nDG[f_ext_id];
1566 sssp(DG, nDG_f_ext, edgeLengthDG, dist);
1567 T minDist = -1;
1569 ++it_adj_faces) {
1571 if (fDG != nDG_f_ext) {
1572 T d = dist[fDG];
1573 if (minDist == -1 || d < minDist) {
1574 minDist = d;
1575 }
1576 }
1577 }
1578 thickness[mu] = minDist + 1;
1579 } break;
1580 default:
1581 OGDF_ASSERT(false);
1582 }
1583}
1584
1585template<class T>
1587 const EdgeArray<T>& length, NodeArray<T>& d) {
1588 const T infinity = 20000000; // big number. danger. think about it.
1589
1590 //Initialize-Single-Source(G, s):
1591 d.init(G);
1592 for (node v : G.nodes) {
1593 d[v] = infinity;
1594 }
1595
1596 d[s] = 0;
1597 for (int i = 1; i < G.numberOfNodes(); ++i) {
1598 for (edge e : G.edges) {
1599 //relax(u, v, w): // e == (u, v), length == w
1600 if (d[e->target()] > d[e->source()] + length[e]) {
1601 d[e->target()] = d[e->source()] + length[e];
1602 }
1603 }
1604 }
1605
1606 //check for negative cycle:
1607 for (edge e : G.edges) {
1608 if (d[e->target()] > d[e->source()] + length[e]) {
1609 return false;
1610 }
1611 }
1612
1613 return true;
1614}
1615
1616}
Declares ogdf::EmbedderMaxFaceBiconnectedGraphs.
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
Dynamic arrays indexed with adjacency entries.
An array that keeps track of the number of inserted elements; also usable as an efficient stack.
Definition ArrayBuffer.h:56
void push(E e)
Puts a new element in the buffer.
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 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.
Embedder that maximizes the external face (plus layers approach).
static void expandEdge(const StaticSPQRTree &spqrTree, NodeArray< bool > &treeNodeTreated, const node &mu, const node &leftNode, const NodeArray< T > &nodeLength, const NodeArray< EdgeArray< T > > &edgeLength, const NodeArray< T > &thickness, NodeArray< List< adjEntry > > &newOrder, NodeArray< ListIterator< adjEntry > > &adjBeforeNodeArraySource, NodeArray< ListIterator< adjEntry > > &adjBeforeNodeArrayTarget, const T &delta_u, const T &delta_d, adjEntry &adjExternal, const node &n=nullptr)
static void expandEdgePNode(const StaticSPQRTree &spqrTree, NodeArray< bool > &treeNodeTreated, const node &mu, const node &leftNode, const NodeArray< T > &nodeLength, const NodeArray< EdgeArray< T > > &edgeLength, const NodeArray< T > &thickness, NodeArray< List< adjEntry > > &newOrder, NodeArray< ListIterator< adjEntry > > &adjBeforeNodeArraySource, NodeArray< ListIterator< adjEntry > > &adjBeforeNodeArrayTarget, const T &delta_u, const T &delta_d, adjEntry &adjExternal)
static bool sssp(const Graph &G, const node &s, const EdgeArray< T > &length, NodeArray< T > &d)
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, const NodeArray< T > &thickness, NodeArray< List< adjEntry > > &newOrder, NodeArray< ListIterator< adjEntry > > &adjBeforeNodeArraySource, NodeArray< ListIterator< adjEntry > > &adjBeforeNodeArrayTarget, const T &delta_u, const T &delta_d, adjEntry &adjExternal)
static void expandEdgeSNode(const StaticSPQRTree &spqrTree, NodeArray< bool > &treeNodeTreated, const node &mu, const node &leftNode, const NodeArray< T > &nodeLength, const NodeArray< EdgeArray< T > > &edgeLength, const NodeArray< T > &thickness, NodeArray< List< adjEntry > > &newOrder, NodeArray< ListIterator< adjEntry > > &adjBeforeNodeArraySource, NodeArray< ListIterator< adjEntry > > &adjBeforeNodeArrayTarget, const T &delta_u, const T &delta_d, adjEntry &adjExternal)
static void bottomUpThickness(const StaticSPQRTree &spqrTree, const node &mu, NodeArray< T > &thickness, const NodeArray< T > &nodeLength, const NodeArray< EdgeArray< T > > &edgeLength)
static void expandEdgeRNode(const StaticSPQRTree &spqrTree, NodeArray< bool > &treeNodeTreated, const node &mu, const node &leftNode, const NodeArray< T > &nodeLength, const NodeArray< EdgeArray< T > > &edgeLength, const NodeArray< T > &thickness, NodeArray< List< adjEntry > > &newOrder, NodeArray< ListIterator< adjEntry > > &adjBeforeNodeArraySource, NodeArray< ListIterator< adjEntry > > &adjBeforeNodeArrayTarget, const T &delta_u, const T &delta_d, adjEntry &adjExternal, const node &n=nullptr)
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.
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
int size() const
Returns the number of elements in the list.
Definition List.h:1472
iterator pushBack(const E &x)
Adds element x at the end of the list.
Definition List.h:1531
Encapsulates a pointer to a list element.
Definition List.h:103
bool valid() const
Returns true iff the iterator points to an element.
Definition List.h:137
iterator begin()
Returns an iterator to the first element of the list.
Definition List.h:375
const_iterator get(int pos) const
Returns a const iterator pointing to the element at position pos.
Definition List.h:325
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.
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.