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