Loading [MathJax]/extensions/tex2jax.js

Open
Graph Drawing
Framework

 v. 2023.09 (Elderberry)
 

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