Open
Graph Drawing
Framework

 v.2012.05
 

EmbedderMaxFaceBiconnectedGraphsLayers.h
Go to the documentation of this file.
00001 /*
00002  * $Revision: 2299 $
00003  * 
00004  * last checkin:
00005  *   $Author: gutwenger $ 
00006  *   $Date: 2012-05-07 15:57:08 +0200 (Mon, 07 May 2012) $ 
00007  ***************************************************************/
00008  
00050 #ifdef _MSC_VER
00051 #pragma once
00052 #endif
00053 
00054 #ifndef OGDF_EMBEDDER_MAX_FACE_BICONNECTED_GRAPHS_Layers_H
00055 #define OGDF_EMBEDDER_MAX_FACE_BICONNECTED_GRAPHS_Layers_H
00056 
00057 #include <ogdf/decomposition/StaticSPQRTree.h>
00058 #include <ogdf/basic/CombinatorialEmbedding.h>
00059 #include <ogdf/planarity/PlanarModule.h>
00060 #include <ogdf/graphalg/ShortestPathWithBFM.h>
00061 
00062 
00063 namespace ogdf {
00064 
00065 template<class T>
00066 class EmbedderMaxFaceBiconnectedGraphsLayers
00067 {
00068 public:
00070     EmbedderMaxFaceBiconnectedGraphsLayers() { }
00071 
00082     static void embed(
00083         Graph& G,
00084         adjEntry& adjExternal,
00085         const NodeArray<T>& nodeLength,
00086         const EdgeArray<T>& edgeLength,
00087         const node& n = 0);
00088 
00098     static void compute(
00099         const Graph& G,
00100         const NodeArray<T>& nodeLength,
00101         const EdgeArray<T>& edgeLength,
00102         StaticSPQRTree& spqrTree,
00103         NodeArray< EdgeArray<T> >& edgeLengthSkel);
00104     
00113     static T computeSize(
00114         const Graph& G,
00115         const node& n,
00116         const NodeArray<T>& nodeLength,
00117         const EdgeArray<T>& edgeLength);
00118 
00130     static T computeSize(
00131         const Graph& G,
00132         const node& n,
00133         const NodeArray<T>& nodeLength,
00134         const EdgeArray<T>& edgeLength,
00135         StaticSPQRTree& spqrTree);
00136 
00150     static T computeSize(
00151         const Graph& G,
00152         const node& n,
00153         const NodeArray<T>& nodeLength,
00154         const EdgeArray<T>& edgeLength,
00155         StaticSPQRTree& spqrTree,
00156         const NodeArray< EdgeArray<T> >& edgeLengthSkel);
00157 
00165     static T computeSize(
00166         const Graph& G,
00167         const NodeArray<T>& nodeLength,
00168         const EdgeArray<T>& edgeLength);
00169 
00183     static T computeSize(
00184         const Graph& G,
00185         const NodeArray<T>& nodeLength,
00186         const EdgeArray<T>& edgeLength,
00187         StaticSPQRTree& spqrTree,
00188         NodeArray< EdgeArray<T> >& edgeLengthSkel);
00189 
00190 private:
00201     static void bottomUpTraversal(
00202         StaticSPQRTree& spqrTree,
00203         const node& mu,
00204         const NodeArray<T>& nodeLength,
00205         NodeArray< EdgeArray<T> >& edgeLength);
00206 
00217     static void topDownTraversal(
00218         StaticSPQRTree& spqrTree,
00219         const node& mu,
00220         const NodeArray<T>& nodeLength,
00221         NodeArray< EdgeArray<T> >& edgeLength);
00222 
00234     static T largestFaceContainingNode(
00235         const StaticSPQRTree& spqrTree,
00236         const node& mu,
00237         const node& n,
00238         const NodeArray<T>& nodeLength,
00239         const NodeArray< EdgeArray<T> >& edgeLength);
00240 
00250     static T largestFaceInSkeleton(
00251         const StaticSPQRTree& spqrTree,
00252         const node& mu,
00253         const NodeArray<T>& nodeLength,
00254         const NodeArray< EdgeArray<T> >& edgeLength);
00255 
00256     /* \brief Computes recursively the thickness of the skeleton graph of all
00257      *   nodes in the SPQR-tree.
00258      *
00259      * \param spqrTree The SPQR-tree of the treated graph.
00260      * \param mu a node in the SPQR-tree.
00261      * \param thickness saving the computed results - the thickness of each
00262      *   skeleton graph.
00263      * \param nodeLength is saving for each node of the original graph \a G its
00264      *   length.
00265      * \param edgeLength is saving the edge lengths of all edges in each skeleton
00266      *   graph of all tree nodes.
00267      */
00268     static void bottomUpThickness(
00269         const StaticSPQRTree& spqrTree,
00270         const node& mu,
00271         NodeArray<T>& thickness,
00272         const NodeArray<T>& nodeLength,
00273         const NodeArray< EdgeArray<T> >& edgeLength);
00274 
00275     /* \brief ExpandEdge embeds all edges in the skeleton graph \a S into an
00276      *   existing embedding and calls recursively itself for all virtual edges
00277      *   in S.
00278      *
00279      * \param spqrTree The SPQR-tree of the treated graph.
00280      * \param treeNodeTreated is an array saving for each SPQR-tree node \a mu
00281      *   whether it was already treated by any call of ExpandEdge or not. Every
00282      *   \a mu should only be treated once.
00283      * \param mu is a node in the SPQR-tree.
00284      * \param leftNode is the node adjacent to referenceEdge, which should be "left"
00285      *   in the embedding
00286      * \param nodeLength is an array saving the lengths of the nodes of \a G.
00287      * \param edgeLength is saving the edge lengths of all edges in each skeleton
00288      *   graph of all tree nodes.
00289      * \param thickness of each skeleton graph.
00290      * \param newOrder is saving for each node \a n in \a G the new adjacency
00291      *   list. This is an output parameter.
00292      * \param adjBeforeNodeArraySource is saving for the source of the reference edge
00293      *   of the skeleton of mu the adjacency entry, before which new entries have
00294      *   to be inserted.
00295      * \param adjBeforeNodeArrayTarget is saving for the target of the reference edge
00296      *   of the skeleton of mu the adjacency entry, before which new entries have
00297      *   to be inserted.
00298      * \param delta_u the distance from the second adjacent face of the reference edge
00299      *   except the external face to the external face of G.
00300      * \param delta_d the distance from the external face to the external face of G.
00301      * \param adjExternal is an adjacency entry in the external face.
00302      * \param n is only set, if ExpandEdge is called for the first time, because
00303      *   then there is no virtual edge which has to be expanded, but the max face
00304      *   has to contain a certain node \a n.
00305      */
00306     static void expandEdge(
00307         const StaticSPQRTree& spqrTree,
00308         NodeArray<bool>& treeNodeTreated,
00309         const node& mu,
00310         const node& leftNode,
00311         const NodeArray<T>& nodeLength,
00312         const NodeArray< EdgeArray<T> >& edgeLength,
00313         const NodeArray<T>& thickness,
00314         NodeArray< List<adjEntry> >& newOrder,
00315         NodeArray< ListIterator<adjEntry> >& adjBeforeNodeArraySource,
00316         NodeArray< ListIterator<adjEntry> >& adjBeforeNodeArrayTarget,
00317         const T& delta_u,
00318         const T& delta_d,
00319         adjEntry& adjExternal,
00320         const node& n = 0);
00321 
00322     /* \brief Embeds all edges in the skeleton graph \a S of an S-node of the
00323      *   SPQR-tree into an existing embedding and calls recursively itself for
00324      *   all virtual edges in S.
00325      *
00326      * \param spqrTree The SPQR-tree of the treated graph.
00327      * \param treeNodeTreated is an array saving for each SPQR-tree node \a mu
00328      *   whether it was already treated by any call of ExpandEdge or not. Every
00329      *   \a mu should only be treated once.
00330      * \param mu is a node in the SPQR-tree.
00331      * \param leftNode is the node adjacent to referenceEdge, which should be "left"
00332      *   in the embedding
00333      * \param nodeLength is an array saving the lengths of the nodes of \a G.
00334      * \param edgeLength is saving the edge lengths of all edges in each skeleton
00335      *   graph of all tree nodes.
00336      * \param thickness of each skeleton graph.
00337      * \param newOrder is saving for each node \a n in \a G the new adjacency
00338      *   list. This is an output parameter.
00339      * \param adjBeforeNodeArraySource is saving for the source of the reference edge
00340      *   of the skeleton of mu the adjacency entry, before which new entries have
00341      *   to be inserted.
00342      * \param adjBeforeNodeArrayTarget is saving for the target of the reference edge
00343      *   of the skeleton of mu the adjacency entry, before which new entries have
00344      *   to be inserted.
00345      * \param delta_u the distance from the second adjacent face of the reference edge
00346      *   except the external face to the external face of G.
00347      * \param delta_d the distance from the external face to the external face of G.
00348      * \param adjExternal is an adjacency entry in the external face.
00349      */
00350     static void expandEdgeSNode(
00351         const StaticSPQRTree& spqrTree,
00352         NodeArray<bool>& treeNodeTreated,
00353         const node& mu,
00354         const node& leftNode,
00355         const NodeArray<T>& nodeLength,
00356         const NodeArray< EdgeArray<T> >& edgeLength,
00357         const NodeArray<T>& thickness,
00358         NodeArray< List<adjEntry> >& newOrder,
00359         NodeArray< ListIterator<adjEntry> >& adjBeforeNodeArraySource,
00360         NodeArray< ListIterator<adjEntry> >& adjBeforeNodeArrayTarget,
00361         const T& delta_u,
00362         const T& delta_d,
00363         adjEntry& adjExternal);
00364 
00365     /* \brief Embeds all edges in the skeleton graph \a S of an P-node of the
00366      *   SPQR-tree into an existing embedding and calls recursively itself for
00367      *   all virtual edges in S.
00368      *
00369      * \param spqrTree The SPQR-tree of the treated graph.
00370      * \param treeNodeTreated is an array saving for each SPQR-tree node \a mu
00371      *   whether it was already treated by any call of ExpandEdge or not. Every
00372      *   \a mu should only be treated once.
00373      * \param mu is a node in the SPQR-tree.
00374      * \param leftNode is the node adjacent to referenceEdge, which should be "left"
00375      *   in the embedding
00376      * \param nodeLength is an array saving the lengths of the nodes of \a G.
00377      * \param edgeLength is saving the edge lengths of all edges in each skeleton
00378      *   graph of all tree nodes.
00379      * \param thickness of each skeleton graph.
00380      * \param newOrder is saving for each node \a n in \a G the new adjacency
00381      *   list. This is an output parameter.
00382      * \param adjBeforeNodeArraySource is saving for the source of the reference edge
00383      *   of the skeleton of mu the adjacency entry, before which new entries have
00384      *   to be inserted.
00385      * \param adjBeforeNodeArrayTarget is saving for the target of the reference edge
00386      *   of the skeleton of mu the adjacency entry, before which new entries have
00387      *   to be inserted.
00388      * \param delta_u the distance from the second adjacent face of the reference edge
00389      *   except the external face to the external face of G.
00390      * \param delta_d the distance from the external face to the external face of G.
00391      * \param adjExternal is an adjacency entry in the external face.
00392      */
00393     static void expandEdgePNode(
00394         const StaticSPQRTree& spqrTree,
00395         NodeArray<bool>& treeNodeTreated,
00396         const node& mu,
00397         const node& leftNode,
00398         const NodeArray<T>& nodeLength,
00399         const NodeArray< EdgeArray<T> >& edgeLength,
00400         const NodeArray<T>& thickness,
00401         NodeArray< List<adjEntry> >& newOrder,
00402         NodeArray< ListIterator<adjEntry> >& adjBeforeNodeArraySource,
00403         NodeArray< ListIterator<adjEntry> >& adjBeforeNodeArrayTarget,
00404         const T& delta_u,
00405         const T& delta_d,
00406         adjEntry& adjExternal);
00407 
00408     /* \brief Embeds all edges in the skeleton graph \a S of an R-node of the
00409      *   SPQR-tree into an existing embedding and calls recursively itself for
00410      *   all virtual edges in S.
00411      *
00412      * \param spqrTree The SPQR-tree of the treated graph.
00413      * \param treeNodeTreated is an array saving for each SPQR-tree node \a mu
00414      *   whether it was already treated by any call of ExpandEdge or not. Every
00415      *   \a mu should only be treated once.
00416      * \param mu is a node in the SPQR-tree.
00417      * \param leftNode is the node adjacent to referenceEdge, which should be "left"
00418      *   in the embedding
00419      * \param nodeLength is an array saving the lengths of the nodes of \a G.
00420      * \param edgeLength is saving the edge lengths of all edges in each skeleton
00421      *   graph of all tree nodes.
00422      * \param thickness of each skeleton graph.
00423      * \param newOrder is saving for each node \a n in \a G the new adjacency
00424      *   list. This is an output parameter.
00425      * \param adjBeforeNodeArraySource is saving for the source of the reference edge
00426      *   of the skeleton of mu the adjacency entry, before which new entries have
00427      *   to be inserted.
00428      * \param adjBeforeNodeArrayTarget is saving for the target of the reference edge
00429      *   of the skeleton of mu the adjacency entry, before which new entries have
00430      *   to be inserted.
00431      * \param delta_u the distance from the second adjacent face of the reference edge
00432      *   except the external face to the external face of G.
00433      * \param delta_d the distance from the external face to the external face of G.
00434      * \param adjExternal is an adjacency entry in the external face.
00435      * \param n is only set, if ExpandEdge is called for the first time, because
00436      *   then there is no virtual edge which has to be expanded, but the max face
00437      *   has to contain a certain node \a n.
00438      */
00439     static void expandEdgeRNode(
00440         const StaticSPQRTree& spqrTree,
00441         NodeArray<bool>& treeNodeTreated,
00442         const node& mu,
00443         const node& leftNode,
00444         const NodeArray<T>& nodeLength,
00445         const NodeArray< EdgeArray<T> >& edgeLength,
00446         const NodeArray<T>& thickness,
00447         NodeArray< List<adjEntry> >& newOrder,
00448         NodeArray< ListIterator<adjEntry> >& adjBeforeNodeArraySource,
00449         NodeArray< ListIterator<adjEntry> >& adjBeforeNodeArrayTarget,
00450         const T& delta_u,
00451         const T& delta_d,
00452         adjEntry& adjExternal,
00453         const node& n = 0);
00454 
00455     /* \brief Writes a given adjacency entry into the newOrder. If the edge
00456      *   belonging to ae is a virtual edge, it is expanded.
00457      *
00458      * \param ae is the adjacency entry which has to be expanded.
00459      * \param before is the adjacency entry of the node in \a G, before
00460      *   which ae has to be inserted.
00461      * \param spqrTree The SPQR-tree of the treated graph.
00462      * \param treeNodeTreated is an array saving for each SPQR-tree node \a mu
00463      *   whether it was already treated by any call of ExpandEdge or not. Every
00464      *   \a mu should only be treated once.
00465      * \param mu is a node in the SPQR-tree.
00466      * \param leftNode is the node adjacent to referenceEdge, which should be "left"
00467      *   in the embedding
00468      * \param nodeLength is an array saving the lengths of the nodes of \a G.
00469      * \param edgeLength is saving the edge lengths of all edges in each skeleton
00470      *   graph of all tree nodes.
00471      * \param thickness of each skeleton graph.
00472      * \param newOrder is saving for each node \a n in \a G the new adjacency
00473      *   list. This is an output parameter.
00474      * \param adjBeforeNodeArraySource is saving for the source of the reference edge
00475      *   of the skeleton of mu the adjacency entry, before which new entries have
00476      *   to be inserted.
00477      * \param adjBeforeNodeArrayTarget is saving for the target of the reference edge
00478      *   of the skeleton of mu the adjacency entry, before which new entries have
00479      *   to be inserted.
00480      * \param delta_u the distance from the second adjacent face of the reference edge
00481      *   except the external face to the external face of G.
00482      * \param delta_d the distance from the external face to the external face of G.
00483      * \param adjExternal is an adjacency entry in the external face.
00484      */
00485     static void adjEntryForNode(
00486         adjEntry& ae,
00487         ListIterator<adjEntry>& before,
00488         const StaticSPQRTree& spqrTree,
00489         NodeArray<bool>& treeNodeTreated,
00490         const node& mu,
00491         const node& leftNode,
00492         const NodeArray<T>& nodeLength,
00493         const NodeArray< EdgeArray<T> >& edgeLength,
00494         const NodeArray<T>& thickness,
00495         NodeArray< List<adjEntry> >& newOrder,
00496         NodeArray< ListIterator<adjEntry> >& adjBeforeNodeArraySource,
00497         NodeArray< ListIterator<adjEntry> >& adjBeforeNodeArrayTarget,
00498         const T& delta_u,
00499         const T& delta_d,
00500         adjEntry& adjExternal);
00501 
00502     /* \brief Single source shortest path.
00503      *
00504      * \param G directed graph
00505      * \param s source node
00506      * \param length length of an edge
00507      * \param d contains shortest path distances after call
00508      */
00509     static bool sssp(
00510         const Graph& G,
00511         const node& s,
00512         const EdgeArray<T>& length,
00513         NodeArray<T>& d);
00514 };
00515 
00516 
00517 template<class T>
00518 void EmbedderMaxFaceBiconnectedGraphsLayers<T>::embed(
00519     Graph& G,
00520     adjEntry& adjExternal,
00521     const NodeArray<T>& nodeLength,
00522     const EdgeArray<T>& edgeLength,
00523     const node& n /* = 0*/)
00524 {
00525     //Base cases (SPQR-Tree-implementatioin would crash with these inputs):
00526     if (G.empty())
00527         return;
00528     if (G.numberOfNodes() == 1)
00529         return;
00530     if (G.numberOfEdges() == 1)
00531     {
00532         edge e = G.chooseEdge();
00533         node n1 = e->source();
00534         node n2 = e->target();
00535         NodeArray< List<adjEntry> > newOrder(G);
00536         newOrder[n1].pushBack(e->adjSource());
00537         newOrder[n2].pushBack(e->adjTarget());
00538         G.sort(n1, newOrder[n1]);
00539         G.sort(n2, newOrder[n2]);
00540         adjExternal = e->adjSource();
00541         return;
00542     }
00543 
00544     //****************************************************************************
00545     //First step: calculate maximum face and edge lengths for virtual edges
00546     //****************************************************************************
00547     StaticSPQRTree spqrTree(G);
00548     NodeArray< EdgeArray<T> > edgeLengthSkel;
00549     compute(G, nodeLength, edgeLength, spqrTree, edgeLengthSkel);
00550 
00551     //****************************************************************************
00552     //Second step: Embed G
00553     //****************************************************************************
00554     T biggestFace = -1;
00555     node bigFaceMu;
00556     if (n == 0)
00557     {
00558         node mu;
00559         forall_nodes(mu, spqrTree.tree())
00560         {
00561             //Expand all faces in skeleton(mu) and get size of the largest of them:
00562             T sizeMu = largestFaceInSkeleton(spqrTree, mu, nodeLength, edgeLengthSkel);
00563             if (sizeMu > biggestFace)
00564             {
00565                 biggestFace = sizeMu;
00566                 bigFaceMu = mu;
00567             }
00568         }
00569     }
00570     else
00571     {
00572         edge nAdjEdge;
00573         node* mus = new node[n->degree()];
00574         int i = 0;
00575         forall_adj_edges(nAdjEdge, n)
00576         {
00577             mus[i] = spqrTree.skeletonOfReal(nAdjEdge).treeNode();
00578             bool alreadySeenMu = false;
00579             for (int j = 0; j < i && !alreadySeenMu; j++)
00580             {
00581                 if (mus[i] == mus[j])
00582                     alreadySeenMu = true;
00583             }
00584             if (alreadySeenMu)
00585             {
00586                 i++;
00587                 continue;
00588             }
00589             else
00590             {
00591                 //Expand all faces in skeleton(mu) containing n and get size of
00592                 //the largest of them:
00593                 T sizeInMu = largestFaceContainingNode(spqrTree, mus[i], n,
00594                                                        nodeLength, edgeLengthSkel);
00595                 if (sizeInMu > biggestFace)
00596                 {
00597                     biggestFace = sizeInMu;
00598                     bigFaceMu = mus[i];
00599                 }
00600 
00601                 i++;
00602             }
00603         }
00604         delete mus;
00605     }
00606 
00607     bigFaceMu = spqrTree.rootTreeAt(bigFaceMu);
00608 
00609     NodeArray<T> thickness(spqrTree.tree());
00610     bottomUpThickness(spqrTree, bigFaceMu, thickness, nodeLength, edgeLengthSkel);
00611 
00612     NodeArray< List<adjEntry> > newOrder(G);
00613     NodeArray<bool> treeNodeTreated(spqrTree.tree(), false);
00614     ListIterator<adjEntry> it;
00615     adjExternal = 0;
00616     NodeArray< ListIterator<adjEntry> > adjBeforeNodeArraySource(spqrTree.tree());
00617     NodeArray< ListIterator<adjEntry> > adjBeforeNodeArrayTarget(spqrTree.tree());
00618     expandEdge(spqrTree, treeNodeTreated, bigFaceMu, 0, nodeLength,
00619                edgeLengthSkel, thickness, newOrder, adjBeforeNodeArraySource,
00620                adjBeforeNodeArrayTarget, 0, 0, adjExternal, n);
00621 
00622     node v;
00623     forall_nodes(v, G)
00624         G.sort(v, newOrder[v]);
00625 }
00626 
00627 template<class T>
00628 void EmbedderMaxFaceBiconnectedGraphsLayers<T>::adjEntryForNode(
00629     adjEntry& ae,
00630     ListIterator<adjEntry>& before,
00631     const StaticSPQRTree& spqrTree,
00632     NodeArray<bool>& treeNodeTreated,
00633     const node& mu,
00634     const node& leftNode,
00635     const NodeArray<T>& nodeLength,
00636     const NodeArray< EdgeArray<T> >& edgeLength,
00637     const NodeArray<T>& thickness,
00638     NodeArray< List<adjEntry> >& newOrder,
00639     NodeArray< ListIterator<adjEntry> >& adjBeforeNodeArraySource,
00640     NodeArray< ListIterator<adjEntry> >& adjBeforeNodeArrayTarget,
00641     const T& delta_u,
00642     const T& delta_d,
00643     adjEntry& adjExternal)
00644 {
00645     Skeleton& S = spqrTree.skeleton(mu);
00646     edge referenceEdge = S.referenceEdge();
00647     if (S.isVirtual(ae->theEdge()))
00648     {
00649         edge twinE = S.twinEdge(ae->theEdge());
00650         node twinNT = S.twinTreeNode(ae->theEdge());
00651         //Skeleton& twinS = spqrTree.skeleton(twinNT);
00652         
00653         if (!treeNodeTreated[twinNT])
00654         {
00655             node m_leftNode;
00656             if (ae->theEdge()->source() == leftNode)
00657                 m_leftNode = twinE->source();
00658             else
00659                 m_leftNode = twinE->target();
00660 
00661             if (ae->theEdge()->source() == ae->theNode())
00662                 adjBeforeNodeArraySource[twinNT] = before;
00663             else
00664                 adjBeforeNodeArrayTarget[twinNT] = before;
00665 
00666             //recursion call:
00667             expandEdge(spqrTree, treeNodeTreated, twinNT, m_leftNode,
00668                        nodeLength, edgeLength, thickness, newOrder,
00669                        adjBeforeNodeArraySource, adjBeforeNodeArrayTarget,
00670                        delta_u, delta_d, adjExternal);
00671         } //if (!treeNodeTreated[twinNT])
00672 
00673         if (ae->theEdge() == referenceEdge)
00674         {
00675             if (ae->theNode() == ae->theEdge()->source())
00676             {
00677                 ListIterator<adjEntry> tmpBefore = adjBeforeNodeArraySource[mu];
00678                 adjBeforeNodeArraySource[mu] = before;
00679                 before = tmpBefore;
00680             }
00681             else
00682             {
00683                 ListIterator<adjEntry> tmpBefore = adjBeforeNodeArrayTarget[mu];
00684                 adjBeforeNodeArrayTarget[mu] = before;
00685                 before = tmpBefore;
00686             }
00687         }
00688         else 
00689         {
00690             if (ae->theNode() == ae->theEdge()->source())
00691                 before = adjBeforeNodeArraySource[twinNT];
00692             else
00693                 before = adjBeforeNodeArrayTarget[twinNT];
00694         }
00695     }
00696     else 
00697     {
00698         node origNode = S.original(ae->theNode());
00699         edge origEdge = S.realEdge(ae->theEdge());
00700 
00701         if (origNode == origEdge->source())
00702         {
00703             if (!before.valid())
00704                 before = newOrder[origNode].pushBack(origEdge->adjSource());
00705             else
00706                 before = newOrder[origNode].insertBefore(origEdge->adjSource(), before);
00707         }
00708         else
00709         {
00710             if (!before.valid())
00711                 before = newOrder[origNode].pushBack(origEdge->adjTarget());
00712             else
00713                 before = newOrder[origNode].insertBefore(origEdge->adjTarget(), before);
00714         }
00715     } //else //!(S.isVirtual(ae->theEdge()))
00716 }
00717 
00718 template<class T>
00719 void EmbedderMaxFaceBiconnectedGraphsLayers<T>::expandEdge(
00720     const StaticSPQRTree& spqrTree,
00721     NodeArray<bool>& treeNodeTreated,
00722     const node& mu,
00723     const node& leftNode,
00724     const NodeArray<T>& nodeLength,
00725     const NodeArray< EdgeArray<T> >& edgeLength,
00726     const NodeArray<T>& thickness,
00727     NodeArray< List<adjEntry> >& newOrder,
00728     NodeArray< ListIterator<adjEntry> >& adjBeforeNodeArraySource,
00729     NodeArray< ListIterator<adjEntry> >& adjBeforeNodeArrayTarget,
00730     const T& delta_u,
00731     const T& delta_d,
00732     adjEntry& adjExternal,
00733     const node& n /*= 0*/)
00734 {
00735     treeNodeTreated[mu] = true;
00736 
00737     switch(spqrTree.typeOf(mu))
00738     {
00739     case SPQRTree::SNode:
00740         expandEdgeSNode(spqrTree, treeNodeTreated, mu, leftNode,
00741             nodeLength, edgeLength, thickness, newOrder, adjBeforeNodeArraySource,
00742             adjBeforeNodeArrayTarget, delta_u, delta_d, adjExternal);
00743         break;
00744     case SPQRTree::PNode:
00745         expandEdgePNode(spqrTree, treeNodeTreated, mu, leftNode,
00746             nodeLength, edgeLength, thickness, newOrder, adjBeforeNodeArraySource,
00747             adjBeforeNodeArrayTarget, delta_u, delta_d, adjExternal);
00748         break;
00749     case SPQRTree::RNode:
00750         expandEdgeRNode(spqrTree, treeNodeTreated, mu, leftNode,
00751             nodeLength, edgeLength, thickness, newOrder, adjBeforeNodeArraySource,
00752             adjBeforeNodeArrayTarget, delta_u, delta_d, adjExternal, n);
00753         break;
00754     OGDF_NODEFAULT
00755     }
00756 }
00757 
00758 template<class T>
00759 void EmbedderMaxFaceBiconnectedGraphsLayers<T>::expandEdgeSNode(
00760     const StaticSPQRTree& spqrTree,
00761     NodeArray<bool>& treeNodeTreated,
00762     const node& mu,
00763     const node& leftNode,
00764     const NodeArray<T>& nodeLength,
00765     const NodeArray< EdgeArray<T> >& edgeLength,
00766     const NodeArray<T>& thickness,
00767     NodeArray< List<adjEntry> >& newOrder,
00768     NodeArray< ListIterator<adjEntry> >& adjBeforeNodeArraySource,
00769     NodeArray< ListIterator<adjEntry> >& adjBeforeNodeArrayTarget,
00770     const T& delta_u,
00771     const T& delta_d,
00772     adjEntry& adjExternal)
00773 {
00774     Skeleton& S = spqrTree.skeleton(mu);
00775     edge referenceEdge = S.referenceEdge();
00776     adjEntry startAdjEntry;
00777     if (leftNode == 0)
00778     {
00779         edge e;
00780         forall_edges(e, S.getGraph())
00781         {
00782             if (!S.isVirtual(e))
00783             {
00784                 startAdjEntry = e->adjSource();
00785                 break;
00786             }
00787         }
00788     }
00789     else if (leftNode->firstAdj()->theEdge() == referenceEdge)
00790         startAdjEntry = leftNode->lastAdj();
00791     else
00792         startAdjEntry = leftNode->firstAdj();
00793 
00794     adjEntry ae = startAdjEntry;
00795     if (adjExternal == 0)
00796     {
00797         edge orgEdge = S.realEdge(ae->theEdge());
00798         if (orgEdge->source() == S.original(ae->theNode()))
00799             adjExternal = orgEdge->adjSource()->twin();
00800         else
00801             adjExternal = orgEdge->adjTarget()->twin();
00802     }
00803 
00804     ListIterator<adjEntry> before;
00805     if (!(referenceEdge == 0) && leftNode == referenceEdge->source())
00806         before = adjBeforeNodeArraySource[mu];
00807     else if (!(referenceEdge == 0))
00808         before = adjBeforeNodeArrayTarget[mu];
00809     ListIterator<adjEntry> beforeSource;
00810 
00811     bool firstStep = true;
00812     while (firstStep || ae != startAdjEntry)
00813     {
00814         //first treat ae with ae->theNode() is left node, then treat its twin:
00815         node m_leftNode = ae->theNode();
00816 
00817         if (ae->theEdge() == referenceEdge)
00818         {
00819             if (ae->theNode() == referenceEdge->source())
00820                 adjBeforeNodeArraySource[mu] = before;
00821             else
00822                 adjBeforeNodeArrayTarget[mu] = before;
00823         }
00824         else
00825         {
00826             if (S.isVirtual(ae->theEdge()) && !(referenceEdge == 0))
00827             {
00828                 node twinTN = S.twinTreeNode(ae->theEdge());
00829                 if (ae->theEdge()->source() == ae->theNode())
00830                 {
00831                     if (ae->theEdge()->target() == referenceEdge->source())
00832                         adjBeforeNodeArrayTarget[twinTN] = adjBeforeNodeArraySource[mu];
00833                     else if (ae->theEdge()->target() == referenceEdge->target())
00834                         adjBeforeNodeArrayTarget[twinTN] = adjBeforeNodeArrayTarget[mu];
00835                 }
00836                 else
00837                 {
00838                     if (ae->theEdge()->source() == referenceEdge->source())
00839                         adjBeforeNodeArraySource[twinTN] = adjBeforeNodeArraySource[mu];
00840                     else if (ae->theEdge()->source() == referenceEdge->target())
00841                         adjBeforeNodeArraySource[twinTN] = adjBeforeNodeArrayTarget[mu];
00842                 }
00843             }
00844 
00845             adjEntryForNode(ae, before, spqrTree, treeNodeTreated, mu,
00846                 m_leftNode, nodeLength, edgeLength, thickness, newOrder, 
00847                 adjBeforeNodeArraySource, adjBeforeNodeArrayTarget,
00848                 delta_u, delta_d, adjExternal);
00849         }
00850 
00851         if (firstStep)
00852         {
00853             beforeSource = before;
00854             firstStep = false;
00855         }
00856 
00857         ae = ae->twin();
00858         if (referenceEdge == 0)
00859             before = 0;
00860         else if (ae->theNode() == referenceEdge->source())
00861             before = adjBeforeNodeArraySource[mu];
00862         else if (ae->theNode() == referenceEdge->target())
00863             before = adjBeforeNodeArrayTarget[mu];
00864         else
00865             before = 0;
00866         if (ae->theEdge() == referenceEdge)
00867         {
00868             if (ae->theNode() == referenceEdge->source())
00869                 adjBeforeNodeArraySource[mu] = beforeSource;
00870             else
00871                 adjBeforeNodeArrayTarget[mu] = beforeSource;
00872         }
00873         else
00874             adjEntryForNode(ae, before, spqrTree, treeNodeTreated, mu,
00875                 m_leftNode, nodeLength, edgeLength, thickness, newOrder,
00876                 adjBeforeNodeArraySource, adjBeforeNodeArrayTarget,
00877                 delta_u, delta_d, adjExternal);
00878 
00879         //set new adjacency entry pair (ae and its twin):
00880         if (ae->theNode()->firstAdj() == ae)
00881             ae = ae->theNode()->lastAdj();
00882         else
00883             ae = ae->theNode()->firstAdj();
00884     }
00885 }
00886 
00887 template<class T>
00888 void EmbedderMaxFaceBiconnectedGraphsLayers<T>::expandEdgePNode(
00889     const StaticSPQRTree& spqrTree,
00890     NodeArray<bool>& treeNodeTreated,
00891     const node& mu,
00892     const node& leftNode,
00893     const NodeArray<T>& nodeLength,
00894     const NodeArray< EdgeArray<T> >& edgeLength,
00895     const NodeArray<T>& thickness,
00896     NodeArray< List<adjEntry> >& newOrder,
00897     NodeArray< ListIterator<adjEntry> >& adjBeforeNodeArraySource,
00898     NodeArray< ListIterator<adjEntry> >& adjBeforeNodeArrayTarget,
00899     const T& delta_u,
00900     const T& delta_d,
00901     adjEntry& adjExternal)
00902 {
00903     //Choose face defined by virtual edge and the longest edge different from it.
00904     Skeleton& S = spqrTree.skeleton(mu);
00905     edge referenceEdge = S.referenceEdge();
00906     edge altReferenceEdge = 0;
00907 
00908     node m_leftNode = leftNode;
00909     if (m_leftNode == 0)
00910     {
00911         List<node> nodeList;
00912         S.getGraph().allNodes(nodeList);
00913         m_leftNode = *(nodeList.begin());
00914     }
00915     node m_rightNode = m_leftNode->firstAdj()->twinNode();
00916 
00917     edge e;
00918     if (referenceEdge == 0)
00919     {
00920         forall_edges(e, S.getGraph())
00921         {
00922             if (!S.isVirtual(e))
00923             {
00924                 altReferenceEdge = e;
00925                 edge orgEdge = S.realEdge(e);
00926                 if (orgEdge->source() == S.original(m_leftNode))
00927                     adjExternal = orgEdge->adjSource();
00928                 else
00929                     adjExternal = orgEdge->adjTarget();
00930                 break;
00931             }
00932         }
00933     }
00934 
00935     //sort edges by length:
00936     List<edge> graphEdges;
00937     forall_edges(e, S.getGraph())
00938     {
00939         if (e == referenceEdge || e == altReferenceEdge)
00940             continue;
00941 
00942         if (!graphEdges.begin().valid())
00943             graphEdges.pushBack(e);
00944         else
00945         {
00946             for (ListIterator<edge> it = graphEdges.begin(); it.valid(); it++)
00947             {
00948                 if (edgeLength[mu][e] > edgeLength[mu][*it])
00949                 {
00950                     graphEdges.insertBefore(e, it);
00951                     break;
00952                 }
00953                 ListIterator<edge> next = it;
00954                 next++;
00955                 if (!next.valid())
00956                 {
00957                     graphEdges.pushBack(e);
00958                     break;
00959                 }
00960             }
00961         }
00962     }
00963 
00964     List<edge> rightEdgeOrder;
00965     ListIterator<adjEntry> beforeAltRefEdge;
00966     ListIterator<adjEntry> beforeLeft;
00967 
00968     //begin with left node and longest edge:
00969     for (int i = 0; i < 2; i++)
00970     {
00971         ListIterator<adjEntry> before;
00972         node n;
00973         if (i == 0)
00974             n = m_leftNode;
00975         else
00976         {
00977             n = m_rightNode;
00978             before = beforeAltRefEdge;
00979         }
00980 
00981         if (!(referenceEdge == 0))
00982         {
00983             if (n == referenceEdge->source())
00984                 before = adjBeforeNodeArraySource[mu];
00985             else
00986                 before = adjBeforeNodeArrayTarget[mu];
00987         }
00988 
00989         adjEntry ae;
00990 
00991         //all edges except reference edge:
00992         if (i == 0)
00993         {
00994             ListIterator<edge> lastPos;
00995             ListIterator<adjEntry> beforeRight;
00996             if (!(referenceEdge == 0))
00997             {
00998                 if (referenceEdge->source() == m_rightNode)
00999                     beforeRight = adjBeforeNodeArraySource[mu];
01000                 else //referenceEdge->target() == rightnode
01001                     beforeRight = adjBeforeNodeArrayTarget[mu];
01002             }
01003             bool insertBeforeLast = false;
01004             bool oneEdgeInE_a = false;
01005             T sum_E_a = 0;
01006             T sum_E_b = 0;
01007 
01008             for (int looper = 0; looper < graphEdges.size(); looper++)
01009             {
01010                 edge e = *(graphEdges.get(looper));
01011 
01012                 if (!lastPos.valid())
01013                     lastPos = rightEdgeOrder.pushBack(e);
01014                 else if (insertBeforeLast)
01015                     lastPos = rightEdgeOrder.insertBefore(e, lastPos);
01016                 else
01017                     lastPos = rightEdgeOrder.insertAfter(e, lastPos);
01018 
01019                 //decide whether to choose face f_a or f_b as f_{mu, mu'}:
01020                 if (delta_u + sum_E_a < delta_d + sum_E_b)
01021                 {
01022                     ListIterator<adjEntry> beforeU = before;
01023 
01024                     if (e->source() == n)
01025                         ae = e->adjSource();
01026                     else
01027                         ae = e->adjTarget();
01028 
01029                     if (S.isVirtual(e))
01030                     {
01031                         node nu = S.twinTreeNode(e);
01032                         
01033                         T delta_u_nu = delta_u + sum_E_a;
01034                         T delta_d_nu = delta_d + sum_E_b;
01035                         
01036                         //buffer computed embedding:
01037                         NodeArray< List<adjEntry> > tmp_newOrder(spqrTree.originalGraph());
01038                         ListIterator<adjEntry> tmp_before;
01039                         
01040                         adjEntryForNode(ae, tmp_before, spqrTree, treeNodeTreated, mu, 
01041                             m_leftNode, nodeLength, edgeLength, thickness,
01042                             tmp_newOrder, adjBeforeNodeArraySource,
01043                             adjBeforeNodeArrayTarget, delta_d_nu, delta_u_nu, adjExternal);
01044 
01045                         //copy buffered embedding reversed into newOrder:
01046                         node leftOrg = S.original(m_leftNode);
01047                         node rightOrg = S.original(m_rightNode);
01048                         node nOG;
01049                         forall_nodes(nOG, spqrTree.originalGraph())
01050                         {
01051                             List<adjEntry> nOG_tmp_adjList = tmp_newOrder[nOG];
01052                             if (nOG_tmp_adjList.size() == 0)
01053                                 continue;
01054 
01055                             ListIterator<adjEntry>* m_before;
01056                             if (nOG == leftOrg)
01057                                 m_before = &beforeU;
01058                             else if (nOG == rightOrg && !(referenceEdge == 0))
01059                                 m_before = &beforeRight;
01060                             else
01061                                 m_before = OGDF_NEW ListIterator<adjEntry>();
01062 
01063                             for (ListIterator<adjEntry> ae_it = nOG_tmp_adjList.begin(); ae_it.valid(); ae_it++)
01064                             {
01065                                 adjEntry adjaEnt = *ae_it;
01066                                 if (!m_before->valid())
01067                                     *m_before = newOrder[nOG].pushBack(adjaEnt);
01068                                 else
01069                                     *m_before = newOrder[nOG].insertBefore(adjaEnt, *m_before);
01070 
01071                                 if (nOG == leftOrg || nOG == rightOrg)
01072                                 {
01073                                     if (S.original(e->source()) == nOG)
01074                                         adjBeforeNodeArraySource[nu] = *m_before;
01075                                     else
01076                                         adjBeforeNodeArrayTarget[nu] = *m_before;
01077                                 }
01078                             }
01079 
01080                             if (nOG != leftOrg && (nOG != rightOrg || referenceEdge == 0))
01081                                 delete m_before;
01082                         } //forall_nodes(nOG, spqrTree.originalGraph())
01083                         
01084                         sum_E_a += thickness[nu];
01085                     }
01086                     else 
01087                     {
01088                         adjEntryForNode(ae, beforeU, spqrTree, treeNodeTreated, mu,
01089                             m_leftNode, nodeLength, edgeLength, thickness,
01090                             newOrder, adjBeforeNodeArraySource,
01091                             adjBeforeNodeArrayTarget, 0, 0, adjExternal);
01092 
01093                         sum_E_a += 1;
01094                     }
01095 
01096                     insertBeforeLast = false;
01097                     if (!oneEdgeInE_a)
01098                     {
01099                         beforeLeft = beforeU;
01100                         oneEdgeInE_a = true;
01101                     }
01102                 }
01103                 else 
01104                 {
01105                     if (S.isVirtual(e))
01106                     {
01107                         node nu = S.twinTreeNode(e);
01108                         if (!(referenceEdge == 0))
01109                         {
01110                             if (e->source() == n)
01111                                 adjBeforeNodeArrayTarget[nu] = beforeRight;
01112                             else
01113                                 adjBeforeNodeArraySource[nu] = beforeRight;
01114                         }
01115                     }
01116 
01117                     T delta_u_nu = delta_u + sum_E_a;
01118                     T delta_d_nu = delta_d + sum_E_b;
01119 
01120                     if (e->source() == n)
01121                         ae = e->adjSource();
01122                     else
01123                         ae = e->adjTarget();
01124                     
01125                     adjEntryForNode(ae, before, spqrTree, treeNodeTreated, mu,
01126                         m_leftNode, nodeLength, edgeLength, thickness, newOrder,
01127                         adjBeforeNodeArraySource, adjBeforeNodeArrayTarget,
01128                         delta_u_nu, delta_d_nu, adjExternal);
01129 
01130                     if (S.isVirtual(e))
01131                         sum_E_b += thickness[S.twinTreeNode(e)];
01132                     else
01133                         sum_E_b += 1;
01134 
01135                     insertBeforeLast = true;
01136                     if (!oneEdgeInE_a)
01137                         beforeLeft = before;
01138                 }
01139             }
01140         }
01141         else
01142         {
01143             for (ListIterator<edge> it = rightEdgeOrder.begin(); it.valid(); it++)
01144             {
01145                 if ((*it)->source() == n)
01146                     ae = (*it)->adjSource();
01147                 else
01148                     ae = (*it)->adjTarget();
01149 
01150                 adjEntryForNode(ae, before, spqrTree, treeNodeTreated, mu,
01151                     m_leftNode, nodeLength, edgeLength, thickness, newOrder,
01152                     adjBeforeNodeArraySource, adjBeforeNodeArrayTarget,
01153                     0, 0, adjExternal);
01154             }
01155         }
01156 
01157         //(alternative) reference edge at last:
01158         if (!(referenceEdge == 0))
01159         {
01160             if (i == 0)
01161             {
01162                 if (n == referenceEdge->source())
01163                     adjBeforeNodeArraySource[mu] = beforeLeft;
01164                 else
01165                     adjBeforeNodeArrayTarget[mu] = beforeLeft;
01166             }
01167             else
01168             {
01169                 if (n == referenceEdge->source())
01170                     adjBeforeNodeArraySource[mu] = before;
01171                 else
01172                     adjBeforeNodeArrayTarget[mu] = before;
01173             }
01174         }
01175         else
01176         {
01177             if (altReferenceEdge->source() == n)
01178                 ae = altReferenceEdge->adjSource();
01179             else
01180                 ae = altReferenceEdge->adjTarget();
01181 
01182             adjEntryForNode(ae, before, spqrTree, treeNodeTreated, mu,
01183                 m_leftNode, nodeLength, edgeLength, thickness, newOrder,
01184                 adjBeforeNodeArraySource, adjBeforeNodeArrayTarget,
01185                 0, 0, adjExternal);
01186         }
01187     }
01188 }
01189 
01190 template<class T>
01191 void EmbedderMaxFaceBiconnectedGraphsLayers<T>::expandEdgeRNode(
01192     const StaticSPQRTree& spqrTree,
01193     NodeArray<bool>& treeNodeTreated,
01194     const node& mu,
01195     const node& leftNode,
01196     const NodeArray<T>& nodeLength,
01197     const NodeArray< EdgeArray<T> >& edgeLength,
01198     const NodeArray<T>& thickness,
01199     NodeArray< List<adjEntry> >& newOrder,
01200     NodeArray< ListIterator<adjEntry> >& adjBeforeNodeArraySource,
01201     NodeArray< ListIterator<adjEntry> >& adjBeforeNodeArrayTarget,
01202     const T& delta_u,
01203     const T& delta_d,
01204     adjEntry& adjExternal,
01205     const node& n /* = 0 */)
01206 {
01207     Skeleton& S = spqrTree.skeleton(mu);
01208     edge referenceEdge = S.referenceEdge();
01209 
01210     //compute biggest face containing the reference edge:
01211     face maxFaceContEdge;
01212     List<node> maxFaceNodes;
01213     PlanarModule pm;
01214     pm.planarEmbed(S.getGraph());
01215     CombinatorialEmbedding combinatorialEmbedding(S.getGraph());
01216     T bigFaceSize = -1;
01217     adjEntry m_adjExternal = 0;
01218     face f;
01219     forall_faces(f, combinatorialEmbedding)
01220     {
01221         bool containsVirtualEdgeOrN = false;
01222         adjEntry this_m_adjExternal = 0;
01223         T sizeOfFace = 0;
01224         List<node> faceNodes;
01225         adjEntry ae;
01226         forall_face_adj(ae, f)
01227         {
01228             faceNodes.pushBack(ae->theNode());
01229             if (  (n == 0 && (ae->theEdge() == referenceEdge || referenceEdge == 0))
01230                     || S.original(ae->theNode()) == n)
01231             {
01232                 containsVirtualEdgeOrN = true;
01233                 if (!(referenceEdge == 0))
01234                     this_m_adjExternal = ae;
01235             }
01236 
01237             if (referenceEdge == 0 && !S.isVirtual(ae->theEdge()))
01238                 this_m_adjExternal = ae;
01239 
01240             sizeOfFace += edgeLength[mu][ae->theEdge()]
01241                                  +  nodeLength[S.original(ae->theNode())];          
01242         }
01243 
01244         if (containsVirtualEdgeOrN && !(this_m_adjExternal == 0) && sizeOfFace > bigFaceSize)
01245         {
01246             maxFaceNodes = faceNodes;
01247             bigFaceSize = sizeOfFace;
01248             maxFaceContEdge = f;
01249             m_adjExternal = this_m_adjExternal;
01250         }
01251     }
01252 
01253     if (adjExternal == 0)
01254     {
01255         edge orgEdge = S.realEdge(m_adjExternal->theEdge());
01256         if (orgEdge->source() == S.original(m_adjExternal->theNode()))
01257             adjExternal = orgEdge->adjSource();
01258         else
01259             adjExternal = orgEdge->adjTarget();
01260     }
01261 
01262     adjEntry adjMaxFace = m_adjExternal;
01263     
01264     //if embedding is mirror symmetrical embedding of desired embedding,
01265     //invert adjacency list of all nodes:
01266     if (!(referenceEdge == 0))
01267     {
01268         //successor of adjEntry of virtual edge in adjacency list of leftNode:
01269         adjEntry succ_virtualEdge_leftNode;
01270         if (leftNode == referenceEdge->source())
01271             succ_virtualEdge_leftNode = referenceEdge->adjSource()->succ();
01272         else
01273             succ_virtualEdge_leftNode = referenceEdge->adjTarget()->succ();
01274         if (!succ_virtualEdge_leftNode)
01275             succ_virtualEdge_leftNode = leftNode->firstAdj();
01276 
01277         bool succVELNAEInExtFace = false;
01278         adjEntry aeExtFace;
01279         forall_face_adj(aeExtFace, maxFaceContEdge)
01280         {
01281             if (aeExtFace->theEdge() == succ_virtualEdge_leftNode->theEdge())
01282             {
01283                 succVELNAEInExtFace = true;
01284                 break;
01285             }
01286         }
01287         
01288         if (!succVELNAEInExtFace)
01289         {
01290             node v;
01291             forall_nodes(v, S.getGraph())
01292             {
01293                 List<adjEntry> newAdjOrder;
01294                 for (adjEntry ae = v->firstAdj(); ae; ae = ae->succ())
01295                     newAdjOrder.pushFront(ae);
01296                 S.getGraph().sort(v, newAdjOrder);
01297             }
01298             adjMaxFace = adjMaxFace->twin();
01299         }
01300     }
01301 
01302     NodeArray<bool> nodeTreated(S.getGraph(), false);
01303     adjEntry start_ae;
01304     if (!(referenceEdge == 0))
01305     {
01306         start_ae = adjMaxFace;
01307         do
01308         {
01309             if (start_ae->theEdge() == referenceEdge)
01310             {
01311                 start_ae = start_ae->faceCycleSucc();
01312                 break;
01313             }
01314             start_ae = start_ae->faceCycleSucc();
01315         } while(start_ae != adjMaxFace);
01316     }
01317     else
01318         start_ae = adjMaxFace;
01319 
01320     //For every edge a buffer saving adjacency entries written in embedding step
01321     //for nodes on the maximum face, needed in step for other nodes.
01322     EdgeArray< List<adjEntry> > buffer(S.getGraph());
01323 
01324     bool firstStep = true;
01325     bool after_start_ae = true;
01326     for (adjEntry ae = start_ae;
01327          firstStep || ae != start_ae;
01328          after_start_ae = (!after_start_ae || !ae->succ()) ? false : true,
01329            ae = after_start_ae ? ae->faceCycleSucc()
01330                                : (!ae->faceCycleSucc() ? adjMaxFace
01331                                                        : ae->faceCycleSucc()))
01332     {
01333         firstStep = false;
01334         //node nodeG = S.original(ae->theNode());
01335         nodeTreated[ae->theNode()] = true;
01336 
01337         //copy adjacency list of nodes into newOrder:
01338         ListIterator<adjEntry> before;
01339         edge vE = (ae->theEdge() == referenceEdge) ? referenceEdge : ae->theEdge();
01340         node nu = (ae->theEdge() == referenceEdge) ? mu : S.twinTreeNode(ae->theEdge());
01341         if (S.isVirtual(vE))
01342         {
01343             if (ae->theNode() == vE->source())
01344                 before = adjBeforeNodeArraySource[nu];
01345             else
01346                 before = adjBeforeNodeArrayTarget[nu];
01347         }
01348 
01349         bool after_ae = true;
01350         adjEntry m_start_ae;
01351         if (!(referenceEdge == 0))
01352         {
01353             if (ae->theNode() == referenceEdge->source())
01354                 m_start_ae = referenceEdge->adjSource();
01355             else if (ae->theNode() == referenceEdge->target())
01356                 m_start_ae = referenceEdge->adjTarget();
01357             else
01358                 m_start_ae = ae;
01359         }
01360         else
01361             m_start_ae = ae;
01362 
01363         adjEntry m_stop_ae;
01364         bool hit_stop_twice = false;
01365         int numOfHits = 0;
01366         if (   !(referenceEdge == 0)
01367             && (   ae->theNode() == referenceEdge->source()
01368                 || ae->theNode() == referenceEdge->target()))
01369         {
01370             if (m_start_ae->succ())
01371                 m_stop_ae = m_start_ae->succ();
01372             else
01373             {
01374                 m_stop_ae = m_start_ae->theNode()->firstAdj();
01375                 hit_stop_twice = true;
01376             }
01377         }
01378         else
01379             m_stop_ae = m_start_ae;
01380 
01381         for (adjEntry aeN = m_start_ae;
01382              after_ae || (hit_stop_twice && numOfHits != 2) || aeN != m_stop_ae;
01383              after_ae = (!after_ae || !aeN->succ()) ? false : true,
01384              aeN = after_ae ? aeN->succ()
01385                : (!aeN->succ() ? ae->theNode()->firstAdj() : aeN->succ()),
01386                numOfHits = (aeN == m_stop_ae) ? numOfHits + 1 : numOfHits)
01387         {
01388             node m_leftNode = 0;
01389             if (S.isVirtual(aeN->theEdge()) && aeN->theEdge() != referenceEdge)
01390             {
01391                 //Compute left node of aeN->theNode(). First get adjacency entry in ext. face
01392                 //(if edge is in ext. face) and compare face cycle successor with successor
01393                 //in node adjacency list. If it is the same, it is the right node, otherwise
01394                 //the left.
01395                 adjEntry aeExtFace = 0;
01396                 bool succInExtFace = false;
01397                 bool aeNInExtFace = false;
01398                 adjEntry aeNSucc = (aeN->succ()) ? aeN->succ() : ae->theNode()->firstAdj();
01399                 aeExtFace = adjMaxFace;
01400                 do
01401                 {
01402                     if (aeExtFace->theEdge() == aeNSucc->theEdge())
01403                     {
01404                         succInExtFace = true;
01405                         if (aeNInExtFace)
01406                             break;
01407                     }
01408                     if (aeExtFace->theEdge() == aeN->theEdge())
01409                     {
01410                         aeNInExtFace = true;
01411                         if (succInExtFace)
01412                             break;
01413                     }
01414                     aeExtFace = aeExtFace->faceCycleSucc();
01415                 } while(aeExtFace != adjMaxFace);
01416                 if (aeNInExtFace && succInExtFace)
01417                     m_leftNode = aeN->twinNode();
01418                 else
01419                     m_leftNode = aeN->theNode();
01420 
01421                 node twinTN = S.twinTreeNode(aeN->theEdge());
01422                 if (!(referenceEdge == 0))
01423                 {
01424                     if (aeN->theEdge()->source() == aeN->theNode())
01425                     {
01426                         if (aeN->theEdge()->target() == referenceEdge->source())
01427                             adjBeforeNodeArrayTarget[twinTN] = adjBeforeNodeArraySource[mu];
01428                         else if (aeN->theEdge()->target() == referenceEdge->target())
01429                             adjBeforeNodeArrayTarget[twinTN] = adjBeforeNodeArrayTarget[mu];
01430                     }
01431                     else
01432                     {
01433                         if (aeN->theEdge()->source() == referenceEdge->source())
01434                             adjBeforeNodeArraySource[twinTN] = adjBeforeNodeArraySource[mu];
01435                         else if (aeN->theEdge()->source() == referenceEdge->target())
01436                             adjBeforeNodeArraySource[twinTN] = adjBeforeNodeArrayTarget[mu];
01437                     }
01438                 }
01439             }
01440 
01441             adjEntryForNode(aeN, before, spqrTree, treeNodeTreated, mu,
01442                 m_leftNode, nodeLength, edgeLength, thickness, newOrder,
01443                 adjBeforeNodeArraySource, adjBeforeNodeArrayTarget,
01444                 0, 0, adjExternal);
01445 
01446             //if the other node adjacent to the current treated edge is not in the
01447             //max face, put written edges into an buffer and clear the adjacency
01448             //list of that node.
01449             if (maxFaceNodes.search(aeN->twinNode()) == -1)
01450             {
01451                 node orig_aeN_twin_theNode = S.original(aeN->twinNode());
01452                 buffer[aeN->theEdge()] = newOrder[orig_aeN_twin_theNode];
01453                 newOrder[orig_aeN_twin_theNode].clear();
01454             }
01455         } //for (adjEntry aeN = m_start_ae; [...]
01456     } //for (adjEntry ae = start_ae; [...]
01457 
01458     //Copy of not treated node's adjacency lists (internal nodes). Setting
01459     //of left node depending on minimal distance to external face of the
01460     //face defined by left node.
01461     bool DGcomputed = false;
01462     int f_ext_id = 0;
01463     int f_ref_id = 0;
01464     Graph* p_DG;
01465     List<node>* p_fPG_to_nDG;
01466     NodeArray<int>* p_nDG_to_fPG;
01467     NodeArray< List<adjEntry> >* p_adjacencyList;
01468     List< List<adjEntry> >* p_faces;
01469     NodeArray<T>* p_dist_f_ref;
01470     NodeArray<T>* p_dist_f_ext;
01471     AdjEntryArray<int>* p_ae_to_face;
01472 
01473     node v;
01474     forall_nodes(v, S.getGraph())
01475     {
01476         if (nodeTreated[v])
01477             continue;
01478 
01479         node v_original = S.original(v);
01480         nodeTreated[v] = true;
01481         ListIterator<adjEntry> before;
01482         for (adjEntry ae = v->firstAdj(); ae; ae = ae->succ())
01483         {
01484             if (buffer[ae->theEdge()].empty())
01485             {
01486                 T delta_u_nu = 0;
01487                 T delta_d_nu = 0;
01488                 bool frauenlinks = false;
01489                 if (S.isVirtual(ae->theEdge()))
01490                 {
01491                     if (!DGcomputed)
01492                     {
01493                         p_DG = new Graph();
01494                         p_fPG_to_nDG = OGDF_NEW List<node>();
01495                         p_nDG_to_fPG = OGDF_NEW NodeArray<int>();
01496                         p_adjacencyList = OGDF_NEW NodeArray< List<adjEntry> >();
01497                         p_faces = OGDF_NEW List< List<adjEntry> >();
01498                         p_dist_f_ref = OGDF_NEW NodeArray<T>();
01499                         p_dist_f_ext = OGDF_NEW NodeArray<T>();
01500                         p_ae_to_face = OGDF_NEW AdjEntryArray<int>(S.getGraph());
01501                         EdgeArray<T> edgeLengthDG(*p_DG);
01502                         DGcomputed = true;
01503 
01504                         //compute dual graph of skeleton graph:
01505                         p_adjacencyList->init(S.getGraph());
01506                         node nBG;
01507                         forall_nodes(nBG, S.getGraph())
01508                         {
01509                             adjEntry ae_nBG;
01510                             forall_adj(ae_nBG, nBG)
01511                                 (*p_adjacencyList)[nBG].pushBack(ae_nBG);
01512                         }
01513 
01514                         NodeArray< List<adjEntry> > adjEntryTreated(S.getGraph());
01515                         forall_nodes(nBG, S.getGraph())
01516                         {
01517                             adjEntry adj;
01518                             forall_adj(adj, nBG)
01519                             {
01520                                 if (adjEntryTreated[nBG].search(adj) != -1)
01521                                     continue;
01522 
01523                                 List<adjEntry> newFace;
01524                                 adjEntry adj2 = adj;
01525                                 do
01526                                 {
01527                                     newFace.pushBack(adj2);
01528                                     (*p_ae_to_face)[adj2] = p_faces->size();
01529                                     adjEntryTreated[adj2->theNode()].pushBack(adj2);
01530                                     node tn = adj2->twinNode();
01531                                     int idx = (*p_adjacencyList)[tn].search(adj2->twin());
01532                                     if (idx - 1 < 0)
01533                                         idx = (*p_adjacencyList)[tn].size() - 1;
01534                                     else
01535                                         idx -= 1;
01536                                     adj2 = *((*p_adjacencyList)[tn].get(idx));
01537                                 } while (adj2 != adj);
01538                                 p_faces->pushBack(newFace);
01539                             }
01540                         }
01541 
01542                         p_nDG_to_fPG->init(*p_DG);
01543                         
01544                         for (ListIterator< List<adjEntry> > it = p_faces->begin(); it.valid(); it++)
01545                         {
01546                             node nn = p_DG->newNode();
01547                             (*p_nDG_to_fPG)[nn] = p_fPG_to_nDG->search(*(p_fPG_to_nDG->pushBack(nn)));
01548                         }
01549 
01550                         NodeArray< List<node> > adjFaces(*p_DG);
01551                         int i = 0;
01552                         for (ListIterator< List<adjEntry> > it = p_faces->begin(); it.valid(); it++)
01553                         {
01554                             int f1_id = i;
01555                             for (ListIterator<adjEntry> it2 = (*it).begin(); it2.valid(); it2++)
01556                             {
01557                                 int f2_id = 0;
01558                                 int j = 0;
01559                                 for (ListIterator< List<adjEntry> > it3 = p_faces->begin(); it3.valid(); it3++)
01560                                 {
01561                                     bool do_break = false;
01562                                     for (ListIterator<adjEntry> it4 = (*it3).begin(); it4.valid(); it4++)
01563                                     {
01564                                         if ((*it4) == (*it2)->twin())
01565                                         {
01566                                             f2_id = j;
01567                                             do_break = true;
01568                                             break;
01569                                         }
01570                                     }
01571                                     if (do_break)
01572                                         break;
01573                                     j++;
01574                                 }
01575 
01576                                 if (   f1_id != f2_id
01577                                         && adjFaces[*(p_fPG_to_nDG->get(f1_id))].search(*(p_fPG_to_nDG->get(f2_id))) == -1
01578                                         && adjFaces[*(p_fPG_to_nDG->get(f2_id))].search(*(p_fPG_to_nDG->get(f1_id))) == -1)
01579                                 {
01580                                     adjFaces[*(p_fPG_to_nDG->get(f1_id))].pushBack(*(p_fPG_to_nDG->get(f2_id)));
01581                                     edge e1 = p_DG->newEdge(*(p_fPG_to_nDG->get(f1_id)), *(p_fPG_to_nDG->get(f2_id)));
01582                                     edge e2 = p_DG->newEdge(*(p_fPG_to_nDG->get(f2_id)), *(p_fPG_to_nDG->get(f1_id)));
01583                                     
01584                                     //set edge length:
01585                                     T e_length = -1;
01586                                     for (ListIterator<adjEntry> it_f1 = (*it).begin(); it_f1.valid(); it_f1++)
01587                                     {
01588                                         edge e = (*it_f1)->theEdge();
01589                                         for (ListIterator<adjEntry> it_f2 = (*(p_faces->get(f2_id))).begin();
01590                                                  it_f2.valid();
01591                                                  it_f2++)
01592                                         {
01593                                             if ((*it_f2)->theEdge() == e)
01594                                             {
01595                                                 if (e_length == -1 || edgeLength[mu][e] < e_length)
01596                                                     e_length = edgeLength[mu][e];
01597                                             }
01598                                         }
01599                                     }
01600                                     edgeLengthDG[e1] = e_length;
01601                                     edgeLengthDG[e2] = e_length;
01602                                 }
01603                                 
01604                                 if (*it2 == adjMaxFace)
01605                                     f_ext_id = f1_id;
01606                                 if (!(referenceEdge == 0) && *it2 == adjMaxFace->twin())
01607                                     f_ref_id = f1_id;
01608                             }
01609                             i++;
01610                         } //for (ListIterator< List<adjEntry> > it = faces.begin(); it.valid(); it++)
01611 
01612                         //compute shortest path from every face to the external face:
01613                         node f_ext_DG = *(p_fPG_to_nDG->get(f_ext_id));
01614                         p_dist_f_ext->init(*p_DG);
01615                         sssp(*p_DG, f_ext_DG, edgeLengthDG, *p_dist_f_ext);
01616                         if (!(referenceEdge == 0))
01617                         {
01618                             node f_ref_DG = *(p_fPG_to_nDG->get(f_ref_id));
01619                             p_dist_f_ref->init(*p_DG);
01620                             sssp(*p_DG, f_ref_DG, edgeLengthDG, *p_dist_f_ref);
01621                         }
01622                     } //if (!DGcomputed)
01623 
01624                     //choose face with minimal shortest path:
01625                     T min1, min2;
01626                     T pi_f_0_f_ext = (*p_dist_f_ext)[*(p_fPG_to_nDG->get((*p_ae_to_face)[ae]))];
01627                     T pi_f_1_f_ext = (*p_dist_f_ext)[*(p_fPG_to_nDG->get((*p_ae_to_face)[ae->twin()]))];
01628                     if (!(referenceEdge == 0))
01629                     {
01630                         T pi_f_0_f_ref = (*p_dist_f_ref)[*(p_fPG_to_nDG->get((*p_ae_to_face)[ae]))];
01631                         T pi_f_1_f_ref = (*p_dist_f_ref)[*(p_fPG_to_nDG->get((*p_ae_to_face)[ae->twin()]))];
01632 
01633                         if (delta_u + pi_f_0_f_ref < delta_d + pi_f_0_f_ext)
01634                             min1 = delta_u + pi_f_0_f_ref;
01635                         else
01636                             min1 = delta_d + pi_f_0_f_ext;
01637                         
01638                         if (delta_u + pi_f_1_f_ref < delta_d + pi_f_1_f_ext)
01639                             min2 = delta_u + pi_f_1_f_ref;
01640                         else
01641                             min2 = delta_d + pi_f_1_f_ext;
01642                     
01643                         if (min1 > min2)
01644                         {
01645                             delta_u_nu = delta_u;
01646                             if (pi_f_0_f_ref < pi_f_0_f_ext)
01647                                 delta_u_nu += pi_f_0_f_ref;
01648                             else
01649                                 delta_u_nu += pi_f_0_f_ext;
01650                             delta_d_nu = delta_d;
01651                             if (pi_f_1_f_ref < pi_f_1_f_ext)
01652                                 delta_d_nu += pi_f_1_f_ref;
01653                             else
01654                                 delta_d_nu += pi_f_1_f_ext;
01655                         }
01656                         else
01657                         {
01658                             frauenlinks = true;
01659                             delta_u_nu = delta_u;
01660                             if (pi_f_1_f_ref < pi_f_1_f_ext)
01661                                 delta_u_nu += pi_f_1_f_ref;
01662                             else
01663                                 delta_u_nu += pi_f_1_f_ext;
01664                             delta_d_nu = delta_d;
01665                             if (pi_f_0_f_ref < pi_f_0_f_ext)
01666                                 delta_d_nu += pi_f_0_f_ref;
01667                             else
01668                                 delta_d_nu += pi_f_0_f_ext;
01669                         }
01670                     }
01671                     else
01672                     {
01673                         min1 = delta_d + pi_f_0_f_ext;
01674                         min2 = delta_d + pi_f_1_f_ext;
01675                     
01676                         if (min1 > min2)
01677                         {
01678                             delta_u_nu = delta_u + pi_f_0_f_ext;
01679                             delta_d_nu = delta_d + pi_f_1_f_ext;
01680                         }
01681                         else
01682                         {
01683                             frauenlinks = true;
01684                             delta_u_nu = delta_u + pi_f_1_f_ext;
01685                             delta_d_nu = delta_d + pi_f_0_f_ext;
01686                         }
01687                     }
01688                 }
01689 
01690                 if (frauenlinks)
01691                 {
01692                     node nu = S.twinTreeNode(ae->theEdge());
01693                         
01694                     //buffer computed embedding:
01695                     NodeArray< List<adjEntry> > tmp_newOrder(spqrTree.originalGraph());
01696                     ListIterator<adjEntry> tmp_before;
01697                     
01698                     adjEntryForNode(ae, tmp_before, spqrTree, treeNodeTreated, mu,
01699                                     v, nodeLength, edgeLength, thickness, tmp_newOrder,
01700                                     adjBeforeNodeArraySource, adjBeforeNodeArrayTarget,
01701                                     delta_u_nu, delta_d_nu, adjExternal);
01702 
01703                     //copy buffered embedding reversed into newOrder:
01704                     //node m_leftNode = v;
01705                     node m_rightNode = ae->twinNode();
01706                     node leftOrg = v_original;
01707                     node rightOrg = S.original(m_rightNode);
01708                     node nOG;
01709                     forall_nodes(nOG, spqrTree.originalGraph())
01710                     {
01711                         List<adjEntry> nOG_tmp_adjList = tmp_newOrder[nOG];
01712                         if (nOG_tmp_adjList.size() == 0)
01713                             continue;
01714 
01715                         ListIterator<adjEntry>* m_before;
01716                         if (nOG == leftOrg)
01717                             m_before = &before;
01718                         else
01719                             m_before = OGDF_NEW ListIterator<adjEntry>();
01720                         
01721                         for (ListIterator<adjEntry> ae_it = nOG_tmp_adjList.begin(); ae_it.valid(); ae_it++)
01722                         {
01723                             adjEntry adjaEnt = *ae_it;
01724                             if (!m_before->valid())
01725                                 *m_before = newOrder[nOG].pushBack(adjaEnt);
01726                             else
01727                                 *m_before = newOrder[nOG].insertBefore(adjaEnt, *m_before);
01728 
01729                             if (nOG == leftOrg || nOG == rightOrg)
01730                             {
01731                                 if (S.original(ae->theEdge()->source()) == nOG)
01732                                     adjBeforeNodeArraySource[nu] = *m_before;
01733                                 else
01734                                     adjBeforeNodeArrayTarget[nu] = *m_before;
01735                             }
01736                         }
01737 
01738                         if (nOG != leftOrg)
01739                             delete m_before;
01740                     } //forall_nodes(nOG, spqrTree.originalGraph())
01741                 }
01742                 else
01743                     adjEntryForNode(ae, before, spqrTree, treeNodeTreated, mu,
01744                         v, nodeLength, edgeLength, thickness, newOrder,
01745                         adjBeforeNodeArraySource, adjBeforeNodeArrayTarget,
01746                         delta_u_nu, delta_d_nu, adjExternal);
01747 
01748                 if (!nodeTreated[ae->twinNode()])
01749                 {
01750                     node orig_ae_twin_theNode = S.original(ae->twinNode());
01751                     buffer[ae->theEdge()] = newOrder[orig_ae_twin_theNode];
01752                     newOrder[orig_ae_twin_theNode].clear();
01753                 }
01754             }
01755             else
01756             {
01757                 buffer[ae->theEdge()].reverse();
01758                 for (ListIterator<adjEntry> it = buffer[ae->theEdge()].begin(); it.valid(); it++)
01759                 {
01760                     if (!before.valid())
01761                         before = newOrder[v_original].pushFront(*it);
01762                     else
01763                         before = newOrder[v_original].insertBefore(*it, before);
01764                 }
01765             }
01766         }
01767     }
01768 
01769     if (DGcomputed)
01770     {
01771         delete p_DG;
01772         delete p_fPG_to_nDG;
01773         delete p_nDG_to_fPG;
01774         delete p_adjacencyList;
01775         delete p_faces;
01776         delete p_dist_f_ext;
01777         delete p_dist_f_ref;
01778         delete p_ae_to_face;
01779     }
01780 }
01781 
01782 template<class T>
01783 void EmbedderMaxFaceBiconnectedGraphsLayers<T>::compute(
01784     const Graph& G,
01785     const NodeArray<T>& nodeLength,
01786     const EdgeArray<T>& edgeLength,
01787     StaticSPQRTree& spqrTree,
01788     NodeArray< EdgeArray<T> >& edgeLengthSkel)
01789 {
01790     //base cases (SPQR-tree implementation would crash for such graphs):
01791     if (G.empty() || G.numberOfNodes() == 1 || G.numberOfEdges() == 1)
01792         return;
01793 
01794     //set length for all real edges in skeletons to length of the original edge
01795     //and initialize edge lengths for virtual edges with 0:
01796     edgeLengthSkel.init(spqrTree.tree());
01797     node v;
01798     forall_nodes(v, spqrTree.tree())
01799     {
01800         edgeLengthSkel[v].init(spqrTree.skeleton(v).getGraph());
01801         edge e;
01802         forall_edges(e, spqrTree.skeleton(v).getGraph())
01803         {
01804             if (spqrTree.skeleton(v).isVirtual(e))
01805                 edgeLengthSkel[v][e] = 0;
01806             else
01807                 edgeLengthSkel[v][e] = edgeLength[spqrTree.skeleton(v).realEdge(e)];
01808         }
01809     }
01810 
01811     //set component-length for all non-reference edges:
01812     bottomUpTraversal(spqrTree, spqrTree.rootNode(), nodeLength, edgeLengthSkel);
01813     //set component length for all reference edges:
01814     topDownTraversal(spqrTree, spqrTree.rootNode(), nodeLength, edgeLengthSkel);
01815 }
01816 
01817 template<class T>
01818 T EmbedderMaxFaceBiconnectedGraphsLayers<T>::computeSize(
01819     const Graph& G,
01820     const NodeArray<T>& nodeLength,
01821     const EdgeArray<T>& edgeLength)
01822 {
01823     //base cases (SPQR-tree implementation would crash for such graphs):
01824     if (G.empty())
01825         return 0;
01826     if (G.numberOfNodes() == 1)
01827         return nodeLength[G.chooseNode()];
01828     if (G.numberOfEdges() == 1)
01829     {
01830         edge e = G.chooseEdge();
01831         return edgeLength[e] + nodeLength[e->source()]+ nodeLength[e->target()];
01832     }
01833     StaticSPQRTree spqrTree(G);
01834     NodeArray< EdgeArray<T> > edgeLengthSkel;
01835     return computeSize(G, nodeLength, edgeLength, spqrTree, edgeLengthSkel);
01836 }
01837 
01838 template<class T>
01839 T EmbedderMaxFaceBiconnectedGraphsLayers<T>::computeSize(
01840     const Graph& G,
01841     const NodeArray<T>& nodeLength,
01842     const EdgeArray<T>& edgeLength,
01843     StaticSPQRTree& spqrTree,
01844     NodeArray< EdgeArray<T> >& edgeLengthSkel)
01845 {
01846     //base cases (SPQR-tree implementation would crash for such graphs):
01847     if (G.empty())
01848         return 0;
01849     if (G.numberOfNodes() == 1)
01850         return nodeLength[G.chooseNode()];
01851     if (G.numberOfEdges() == 1)
01852     {
01853         edge e = G.chooseEdge();
01854         return edgeLength[e] + nodeLength[e->source()]+ nodeLength[e->target()];
01855     }
01856 
01857     //set length for all real edges in skeletons to length of the original edge
01858     //and initialize edge lengths for virtual edges with 0:
01859     edgeLengthSkel.init(spqrTree.tree());
01860     node v;
01861     forall_nodes(v, spqrTree.tree())
01862     {
01863         edgeLengthSkel[v].init(spqrTree.skeleton(v).getGraph());
01864         edge e;
01865         forall_edges(e, spqrTree.skeleton(v).getGraph())
01866         {
01867             if (spqrTree.skeleton(v).isVirtual(e))
01868                 edgeLengthSkel[v][e] = 0;
01869             else
01870                 edgeLengthSkel[v][e] = edgeLength[spqrTree.skeleton(v).realEdge(e)];
01871         }
01872     }
01873 
01874     //set component-length for all non-reference edges:
01875     bottomUpTraversal(spqrTree, spqrTree.rootNode(), nodeLength, edgeLengthSkel);
01876     //set component length for all reference edges:
01877     topDownTraversal(spqrTree, spqrTree.rootNode(), nodeLength, edgeLengthSkel);
01878 
01879     T biggestFace = -1;
01880     node mu;
01881     forall_nodes(mu, spqrTree.tree())
01882     {
01883         //Expand all faces in skeleton(mu) and get size of the largest of them:
01884         T sizeMu = largestFaceInSkeleton(spqrTree, mu, nodeLength, edgeLengthSkel);
01885         if (sizeMu > biggestFace)
01886             biggestFace = sizeMu;
01887     }
01888 
01889     return biggestFace;
01890 }
01891 
01892 template<class T>
01893 T EmbedderMaxFaceBiconnectedGraphsLayers<T>::computeSize(
01894     const Graph& G,
01895     const node& n,
01896     const NodeArray<T>& nodeLength,
01897     const EdgeArray<T>& edgeLength)
01898 {
01899     //base cases (SPQR-tree implementation would crash for such graphs):
01900     if (G.empty())
01901         return 0;
01902     if (G.numberOfNodes() == 1)
01903         return nodeLength[n];
01904     if (G.numberOfEdges() == 1)
01905     {
01906         edge e = G.chooseEdge();
01907         return edgeLength[e] + nodeLength[e->source()] + nodeLength[e->target()];
01908     }
01909 
01910     StaticSPQRTree spqrTree(G);
01911     NodeArray< EdgeArray<T> > edgeLengthSkel;
01912     compute(G, nodeLength, edgeLength, spqrTree, edgeLengthSkel);
01913     return computeSize(G, n, nodeLength, edgeLength, spqrTree, edgeLengthSkel);
01914 }
01915 
01916 template<class T>
01917 T EmbedderMaxFaceBiconnectedGraphsLayers<T>::computeSize(
01918     const Graph& G,
01919     const node& n,
01920     const NodeArray<T>& nodeLength,
01921     const EdgeArray<T>& edgeLength,
01922     StaticSPQRTree& spqrTree)
01923 {
01924     NodeArray< EdgeArray<T> > edgeLengthSkel;
01925     compute(G, nodeLength, edgeLength, spqrTree, edgeLengthSkel);
01926     return computeSize(G, n, nodeLength, edgeLength, spqrTree, edgeLengthSkel);
01927 }
01928 
01929 template<class T>
01930 T EmbedderMaxFaceBiconnectedGraphsLayers<T>::computeSize(
01931     const Graph& G,
01932     const node& n,
01933     const NodeArray<T>& nodeLength,
01934     const EdgeArray<T>& edgeLength,
01935     StaticSPQRTree& spqrTree,
01936     const NodeArray< EdgeArray<T> >& edgeLengthSkel)
01937 {
01938     //base cases (SPQR-tree implementation would crash for such graphs):
01939     if (G.empty())
01940         return 0;
01941     if (G.numberOfNodes() == 1)
01942         return nodeLength[n];
01943     if (G.numberOfEdges() == 1)
01944     {
01945         edge e = G.chooseEdge();
01946         return edgeLength[e] + nodeLength[e->source()] + nodeLength[e->target()];
01947     }
01948 
01949     edge nAdjEdges;
01950     node* mus = new node[n->degree()];
01951     int i = 0;
01952     T biggestFace = -1;
01953     forall_adj_edges(nAdjEdges, n)
01954     {
01955         mus[i] = spqrTree.skeletonOfReal(nAdjEdges).treeNode();
01956         bool alreadySeenMu = false;
01957         for (int j = 0; j < i && !alreadySeenMu; j++)
01958         {
01959             if (mus[i] == mus[j])
01960                 alreadySeenMu = true;
01961         }
01962         if (alreadySeenMu)
01963         {
01964             i++;
01965             continue;
01966         }
01967         else
01968         {
01969             //Expand all faces in skeleton(mu) containing n and get size of the largest of them:
01970             T sizeInMu = largestFaceContainingNode(spqrTree, mus[i], n, nodeLength, edgeLengthSkel);
01971             if (sizeInMu > biggestFace)
01972                 biggestFace = sizeInMu;
01973 
01974             i++;
01975         }
01976     }
01977     delete mus;
01978 
01979     return biggestFace;
01980 }
01981 
01982 template<class T>
01983 void EmbedderMaxFaceBiconnectedGraphsLayers<T>::bottomUpTraversal(
01984     StaticSPQRTree& spqrTree,
01985     const node& mu,
01986     const NodeArray<T>& nodeLength,
01987     NodeArray< EdgeArray<T> >& edgeLength)
01988 {
01989     //Recursion:
01990     edge ed;
01991     forall_adj_edges(ed, mu)
01992     {
01993         if (ed->source() == mu)
01994             bottomUpTraversal(spqrTree, ed->target(), nodeLength, edgeLength);
01995     }
01996 
01997     edge e;
01998     forall_edges(e, spqrTree.skeleton(mu).getGraph())
01999     {
02000         //do not treat real edges here and do not treat reference edges:
02001         if (!spqrTree.skeleton(mu).isVirtual(e) || e == spqrTree.skeleton(mu).referenceEdge())
02002             continue;
02003 
02004         //pertinent node of e in the SPQR-tree:
02005         node nu = spqrTree.skeleton(mu).twinTreeNode(e);
02006         //reference edge of nu (virtual edge in nu associated with mu):
02007         edge er = spqrTree.skeleton(nu).referenceEdge();
02008         //sum of the lengths of the two poles of mu:
02009         node refEdgeSource = spqrTree.skeleton(nu).referenceEdge()->source();
02010         node origRefEdgeSource = spqrTree.skeleton(nu).original(refEdgeSource);
02011         node refEdgeTarget = spqrTree.skeleton(nu).referenceEdge()->target();
02012         node origRefEdgeTarget = spqrTree.skeleton(nu).original(refEdgeTarget);
02013         T ell = nodeLength[origRefEdgeSource] + nodeLength[origRefEdgeTarget];
02014 
02015         if (spqrTree.typeOf(nu) == SPQRTree::SNode)
02016         {
02017             //size of a face in skeleton(nu) minus ell
02018             T sizeOfFace = 0;
02019             node nS;
02020             forall_nodes(nS, spqrTree.skeleton(nu).getGraph())
02021                 sizeOfFace += nodeLength[spqrTree.skeleton(nu).original(nS)];
02022 
02023             edge eS;
02024             forall_edges(eS, spqrTree.skeleton(nu).getGraph())
02025                 sizeOfFace += edgeLength[nu][eS];
02026 
02027             edgeLength[mu][e] = sizeOfFace - ell;
02028         }
02029         else if (spqrTree.typeOf(nu) == SPQRTree::PNode)
02030         {
02031             //length of the longest edge different from er in skeleton(nu)
02032             edge longestEdge = 0;
02033             forall_edges(ed, spqrTree.skeleton(nu).getGraph())
02034             {
02035                 if (!(ed == er) && (   longestEdge == 0
02036                                     || edgeLength[nu][ed] > edgeLength[nu][longestEdge]))
02037                 {
02038                     longestEdge = ed;
02039                 }
02040             }
02041             edgeLength[mu][e] = edgeLength[nu][longestEdge];
02042         }
02043         else if (spqrTree.typeOf(nu) == SPQRTree::RNode)
02044         {
02045             //size of the largest face containing er in skeleton(nu) minus ell
02046             //Calculate an embedding of the graph (it exists only two which are
02047             //mirror-symmetrical):
02048             PlanarModule pm;
02049             pm.planarEmbed(spqrTree.skeleton(nu).getGraph());
02050             CombinatorialEmbedding combinatorialEmbedding(spqrTree.skeleton(nu).getGraph());
02051             T biggestFaceSize = -1;
02052             face f;
02053             forall_faces(f, combinatorialEmbedding)
02054             {
02055                 T sizeOfFace = 0;
02056                 bool containsEr = false;
02057                 adjEntry ae;
02058                 forall_face_adj(ae, f)
02059                 {
02060                     if (ae->theEdge() == er)
02061                         containsEr = true;
02062                     sizeOfFace += edgeLength[nu][ae->theEdge()]
02063                                +  nodeLength[spqrTree.skeleton(nu).original(ae->theNode())];
02064                 }
02065                 
02066                 if (containsEr && sizeOfFace > biggestFaceSize)
02067                     biggestFaceSize = sizeOfFace;
02068             }
02069 
02070             edgeLength[mu][e] = biggestFaceSize - ell;
02071         }
02072         else //should never happen
02073             edgeLength[mu][e] = 1;
02074     }
02075 }
02076 
02077 template<class T>
02078 void EmbedderMaxFaceBiconnectedGraphsLayers<T>::topDownTraversal(
02079     StaticSPQRTree& spqrTree,
02080     const node& mu,
02081     const NodeArray<T>& nodeLength,
02082     NodeArray< EdgeArray<T> >& edgeLength)
02083 {
02084     //S: skeleton of mu
02085     Skeleton& S = spqrTree.skeleton(mu);
02086 
02087     //Get all reference edges of the children nu of mu and set their component length:
02088     edge ed;
02089     forall_adj_edges(ed, mu)
02090     {
02091         if (ed->source() != mu)
02092             continue;
02093 
02094         node nu = ed->target();
02095         edge referenceEdgeOfNu = spqrTree.skeleton(nu).referenceEdge();
02096         edge eSnu = spqrTree.skeleton(nu).twinEdge(referenceEdgeOfNu);
02097         if (spqrTree.typeOf(mu) == SPQRTree::SNode)
02098         {
02099             //Let L be the sum of the length of all vertices and edges in S. The component
02100             //length of the reference edge of nu is L minus the length of e_{S, nu} minus
02101             //the lengths of the two vertices incident to e_{S, nu}.
02102             T L = 0;
02103             edge ed2;
02104             forall_edges(ed2, S.getGraph())
02105                 L += edgeLength[mu][ed2];
02106             node no;
02107             forall_nodes(no, S.getGraph())
02108                 L += nodeLength[S.original(no)];
02109 
02110             edgeLength[nu][referenceEdgeOfNu] =   L - edgeLength[mu][eSnu]
02111                                                 - nodeLength[S.original(eSnu->source())]
02112                                                                                     - nodeLength[S.original(eSnu->target())];
02113         }
02114         else if (spqrTree.typeOf(mu) == SPQRTree::PNode)
02115         {
02116             //The component length of the reference edge of nu is the length of the longest
02117             //edge in S different from e_{S, nu}.
02118             edge ed2;
02119             edge longestEdge = 0;
02120             forall_edges(ed2, S.getGraph())
02121             {
02122                 if (ed2 != eSnu && (   longestEdge == 0
02123                                     || edgeLength[mu][ed2] > edgeLength[mu][longestEdge]))
02124                 {
02125                     longestEdge = ed2;
02126                 }
02127             }
02128             edgeLength[nu][referenceEdgeOfNu] = edgeLength[mu][longestEdge];
02129         }
02130         else if (spqrTree.typeOf(mu) == SPQRTree::RNode)
02131         {
02132             //Let f be the largest face in S containing e_{S, nu}. The component length of
02133             //the reference edge of nu is the size of f minus the length of e_{S, nu} minus
02134             //the lengths of the two vertices incident to e_{S, nu}.
02135             
02136             //Calculate an embedding of the graph (it exists only two which are
02137             //mirror-symmetrical):
02138             PlanarModule pm;
02139             pm.planarEmbed(S.getGraph());
02140             CombinatorialEmbedding combinatorialEmbedding(S.getGraph());
02141             T biggestFaceSize = -1;
02142             face f;
02143             forall_faces(f, combinatorialEmbedding)
02144             {
02145                 T sizeOfFace = 0;
02146                 bool containsESnu = false;
02147                 adjEntry ae;
02148                 forall_face_adj(ae, f)
02149                 {
02150                     if (ae->theEdge() == eSnu)
02151                         containsESnu = true;
02152                     sizeOfFace += edgeLength[mu][ae->theEdge()]
02153                                +  nodeLength[S.original(ae->theNode())];
02154                 }
02155                 if (containsESnu && sizeOfFace > biggestFaceSize)
02156                     biggestFaceSize = sizeOfFace;
02157             }
02158             edgeLength[nu][referenceEdgeOfNu] =   biggestFaceSize - edgeLength[mu][eSnu]
02159                                                 - nodeLength[S.original(eSnu->source())]
02160                                                 - nodeLength[S.original(eSnu->target())];
02161         }
02162         else //should never happen
02163             edgeLength[nu][referenceEdgeOfNu] = 0;
02164 
02165         //Recursion:
02166         topDownTraversal(spqrTree, ed->target(), nodeLength, edgeLength);
02167     }
02168 }
02169 
02170 template<class T>
02171 T EmbedderMaxFaceBiconnectedGraphsLayers<T>::largestFaceContainingNode(
02172     const StaticSPQRTree& spqrTree,
02173     const node& mu,
02174     const node& n,
02175     const NodeArray<T>& nodeLength,
02176     const NodeArray< EdgeArray<T> >& edgeLength)
02177 {
02178     bool containsARealEdge = false;
02179     if (spqrTree.typeOf(mu) == SPQRTree::RNode)
02180     {
02181         //The largest face containing n is the largest face containg n in any embedding of S.
02182         PlanarModule pm;
02183         pm.planarEmbed(spqrTree.skeleton(mu).getGraph());
02184         CombinatorialEmbedding combinatorialEmbedding(spqrTree.skeleton(mu).getGraph());
02185         T biggestFaceSize = -1;
02186         face f;
02187         forall_faces(f, combinatorialEmbedding)
02188         {
02189             T sizeOfFace = 0;
02190             bool containingN = false;
02191             bool m_containsARealEdge = false;
02192             adjEntry ae;
02193             forall_face_adj(ae, f)
02194             {
02195                 if (spqrTree.skeleton(mu).original(ae->theNode()) == n)
02196                     containingN = true;
02197                 if (!spqrTree.skeleton(mu).isVirtual(ae->theEdge()))
02198                     m_containsARealEdge = true;
02199                 sizeOfFace += edgeLength[mu][ae->theEdge()];
02200                 sizeOfFace += nodeLength[spqrTree.skeleton(mu).original(ae->theNode())];
02201             }
02202             if (containingN && sizeOfFace > biggestFaceSize)
02203             {
02204                 biggestFaceSize = sizeOfFace;
02205                 containsARealEdge = m_containsARealEdge;
02206             }
02207         }
02208 
02209         if (!containsARealEdge)
02210             return -1;
02211         return biggestFaceSize;
02212     }
02213     else if (spqrTree.typeOf(mu) == SPQRTree::PNode)
02214     {
02215         //Find the two longest edges, they define the largest face containg n.
02216         edge edgeWalker;
02217         edge longestEdges[2] = {0, 0};
02218         forall_edges(edgeWalker, spqrTree.skeleton(mu).getGraph())
02219         {
02220             if (   longestEdges[1] == 0
02221                 || edgeLength[mu][edgeWalker] > edgeLength[mu][longestEdges[1]])
02222             {
02223                 if (   longestEdges[0] == 0
02224                     || edgeLength[mu][edgeWalker] > edgeLength[mu][longestEdges[0]])
02225                 {
02226                     longestEdges[1] = longestEdges[0];
02227                     longestEdges[0] = edgeWalker;
02228                 }
02229                 else
02230                     longestEdges[1] = edgeWalker;
02231             }
02232         }
02233 
02234         if (   !spqrTree.skeleton(mu).isVirtual(longestEdges[0])
02235         || !spqrTree.skeleton(mu).isVirtual(longestEdges[1]))
02236         {
02237           containsARealEdge = true;
02238         }
02239 
02240         if (!containsARealEdge)
02241             return -1;
02242         
02243         return edgeLength[mu][longestEdges[0]] + edgeLength[mu][longestEdges[1]];
02244     }
02245     else if (spqrTree.typeOf(mu) == SPQRTree::SNode)
02246     {
02247         //The largest face containing n is any face in the single existing embedding of S.
02248         T sizeOfFace = 0;
02249         node nS;
02250         forall_nodes(nS, spqrTree.skeleton(mu).getGraph())
02251             sizeOfFace += nodeLength[spqrTree.skeleton(mu).original(nS)];
02252 
02253         edge eS;
02254         forall_edges(eS, spqrTree.skeleton(mu).getGraph())
02255         {
02256             if (!spqrTree.skeleton(mu).isVirtual(eS))
02257                 containsARealEdge = true;
02258             sizeOfFace += edgeLength[mu][eS];
02259         }
02260 
02261         if (!containsARealEdge)
02262             return -1;
02263 
02264         return sizeOfFace;
02265     }
02266 
02267     //should never end here...
02268     return 42;
02269 }
02270 
02271 template<class T>
02272 T EmbedderMaxFaceBiconnectedGraphsLayers<T>::largestFaceInSkeleton
02273     (const StaticSPQRTree& spqrTree,
02274      const node& mu,
02275      const NodeArray<T>& nodeLength,
02276      const NodeArray< EdgeArray<T> >& edgeLength)
02277 {
02278     bool containsARealEdge = false;
02279     if (spqrTree.typeOf(mu) == SPQRTree::RNode)
02280     {
02281         //The largest face is a largest face in any embedding of S.
02282         PlanarModule pm;
02283         pm.planarEmbed(spqrTree.skeleton(mu).getGraph());
02284         CombinatorialEmbedding combinatorialEmbedding(spqrTree.skeleton(mu).getGraph());
02285         T biggestFaceSize = -1;
02286         face f;
02287         forall_faces(f, combinatorialEmbedding)
02288         {
02289             bool m_containsARealEdge = false;
02290             T sizeOfFace = 0;
02291             adjEntry ae;
02292             forall_face_adj(ae, f)
02293             {
02294                 //node originalNode = spqrTree.skeleton(mu).original(ae->theNode());
02295                 if (!spqrTree.skeleton(mu).isVirtual(ae->theEdge()))
02296                     m_containsARealEdge = true;
02297                 sizeOfFace += edgeLength[mu][ae->theEdge()]
02298                            +  nodeLength[spqrTree.skeleton(mu).original(ae->theNode())];
02299             }
02300 
02301             if (sizeOfFace > biggestFaceSize)
02302             {
02303                 biggestFaceSize = sizeOfFace;
02304                 containsARealEdge = m_containsARealEdge;
02305             }
02306         }
02307 
02308         if (!containsARealEdge)
02309             return -1;
02310 
02311         return biggestFaceSize;
02312     }
02313     else if (spqrTree.typeOf(mu) == SPQRTree::PNode)
02314     {
02315         //Find the two longest edges, they define the largest face.
02316         edge edgeWalker;
02317         edge longestEdges[2] = {0, 0};
02318         forall_edges(edgeWalker, spqrTree.skeleton(mu).getGraph())
02319         {
02320             if (   longestEdges[1] == 0
02321                 || edgeLength[mu][edgeWalker] > edgeLength[mu][longestEdges[1]])
02322             {
02323                 if (   longestEdges[0] == 0
02324                     || edgeLength[mu][edgeWalker] > edgeLength[mu][longestEdges[0]])
02325                 {
02326                     longestEdges[1] = longestEdges[0];
02327                     longestEdges[0] = edgeWalker;
02328                 }
02329                 else
02330                     longestEdges[1] = edgeWalker;
02331             }
02332         }
02333 
02334         if (   !spqrTree.skeleton(mu).isVirtual(longestEdges[0])
02335         || !spqrTree.skeleton(mu).isVirtual(longestEdges[1]))
02336         {
02337             containsARealEdge = true;
02338         }
02339 
02340         if (!containsARealEdge)
02341             return -1;
02342 
02343         return edgeLength[mu][longestEdges[0]] + edgeLength[mu][longestEdges[1]];
02344     }
02345     else if (spqrTree.typeOf(mu) == SPQRTree::SNode)
02346     {
02347         //The largest face is any face in the single existing embedding of S.
02348         T sizeOfFace = 0;
02349         node nS;
02350         forall_nodes(nS, spqrTree.skeleton(mu).getGraph())
02351             sizeOfFace += nodeLength[spqrTree.skeleton(mu).original(nS)];
02352 
02353         edge eS;
02354         forall_edges(eS, spqrTree.skeleton(mu).getGraph())
02355         {
02356             if (!spqrTree.skeleton(mu).isVirtual(eS))
02357                 containsARealEdge = true;
02358             sizeOfFace += edgeLength[mu][eS];
02359         }
02360 
02361         if (!containsARealEdge)
02362             return -1;
02363 
02364         return sizeOfFace;
02365     }
02366 
02367     //should never end here...
02368     return 42;
02369 }
02370 
02371 template<class T>
02372 void EmbedderMaxFaceBiconnectedGraphsLayers<T>::bottomUpThickness(
02373     const StaticSPQRTree& spqrTree,
02374     const node& mu,
02375     NodeArray<T>& thickness,
02376     const NodeArray<T>& nodeLength,
02377     const NodeArray< EdgeArray<T> >& edgeLength)
02378 {
02379     //recursion:
02380     edge e_mu_to_nu;
02381     forall_adj_edges(e_mu_to_nu, mu)
02382     {
02383         if (e_mu_to_nu->source() != mu)
02384             continue;
02385         else
02386         {
02387             node nu = e_mu_to_nu->target();
02388             bottomUpThickness(spqrTree, nu, thickness, nodeLength, edgeLength);
02389         }
02390     }
02391 
02392     Skeleton& S = spqrTree.skeleton(mu);
02393     edge referenceEdge = S.referenceEdge();
02394 
02395     if (referenceEdge == 0) //root of SPQR-tree
02396     {
02397         thickness[mu] = 0;
02398         return;
02399     }
02400 
02401     //set dLengths for all edges in skeleton graph:
02402     EdgeArray<T> dLength(S.getGraph());
02403     edge eSG;
02404     forall_edges(eSG, S.getGraph())
02405     {
02406         if (eSG == referenceEdge)
02407             continue;
02408 
02409         if (S.isVirtual(eSG))
02410         {
02411             node twinTN = S.twinTreeNode(eSG);
02412             dLength[eSG] = thickness[twinTN];
02413         }
02414         else
02415             dLength[eSG] = edgeLength[mu][eSG];
02416     }
02417 
02418     //compute thickness of skeleton(mu):
02419     switch (spqrTree.typeOf(mu))
02420     {
02421     case SPQRTree::SNode:
02422         {
02423             //thickness(mu) = min_{edges e != referenceEdge} dLength(e)
02424             T min_dLength = -1;
02425             forall_edges(eSG, S.getGraph())
02426             {
02427                 if (eSG == referenceEdge)
02428                     continue;
02429                 if (min_dLength == -1 || dLength[eSG] < min_dLength)
02430                     min_dLength = dLength[eSG];
02431             }
02432             thickness[mu] = min_dLength;
02433         } break;
02434     case SPQRTree::PNode:
02435         {
02436             //thickness(mu) = sum_{edges e != referenceEdge} dLength(e)
02437             T sumof_dLength = 0;
02438             forall_edges(eSG, S.getGraph())
02439             {
02440                 if (eSG == referenceEdge)
02441                     continue;
02442                 sumof_dLength += dLength[eSG];
02443             }
02444             thickness[mu] = sumof_dLength;
02445         } break;
02446     case SPQRTree::RNode:
02447         {
02448             /* Let f^ref_0, ... , f^ref_k be the faces sharing at least one edge with
02449              * f_ref - the face adjacent to the reference edge not equal to the
02450              * external face f_ext. Compute the dual graph and set edge lengths for
02451              * two faces f_i, f_j, i != j, with at least one shared edge, to the
02452              * minimal dLength of the shared edges of f_i and f_j. Remove the node
02453              * related to face f_ref. thickness(mu) is then the length of the shortest
02454              * path from any of the faces f^ref_0, ... , f^ref_k to f_ext plus 1.
02455              */
02456             CombinatorialEmbedding CE(S.getGraph());
02457             adjEntry ae_f_ext = referenceEdge->adjSource();
02458             adjEntry ae_f_ref = referenceEdge->adjTarget();
02459             T faceSize_f_ext = 0;
02460             adjEntry ae_f_ext_walker = ae_f_ext;
02461             do
02462             {
02463                 faceSize_f_ext += nodeLength[S.original(ae_f_ext_walker->theNode())]
02464                                +  edgeLength[mu][ae_f_ext_walker->theEdge()];
02465                 ae_f_ext_walker = ae_f_ext_walker->faceCycleSucc();
02466             } while (ae_f_ext_walker != ae_f_ext);
02467             T faceSize_f_ref = 0;
02468             adjEntry ae_f_ref_walker = ae_f_ref;
02469             do
02470             {
02471                 faceSize_f_ref += nodeLength[S.original(ae_f_ref_walker->theNode())]
02472                                +  edgeLength[mu][ae_f_ref_walker->theEdge()];
02473                 ae_f_ref_walker = ae_f_ref_walker->faceCycleSucc();
02474             } while (ae_f_ref_walker != ae_f_ref);
02475             if (faceSize_f_ext < faceSize_f_ref)
02476             {
02477                 adjEntry ae_tmp = ae_f_ext;
02478                 ae_f_ext = ae_f_ref;
02479                 ae_f_ref = ae_tmp;
02480             }
02481 
02482             //compute dual graph:
02483             Graph DG;
02484             List<node> fPG_to_nDG;
02485             NodeArray<int> nDG_to_fPG(DG);
02486             NodeArray< List<adjEntry> > adjacencyList(S.getGraph());
02487             List< List<adjEntry> > faces;
02488             NodeArray<int> distances;
02489             EdgeArray<T> edgeLengthDG(DG);
02490             int f_ref_id = -1;
02491             int f_ext_id = -1;
02492 
02493             node nBG;
02494             forall_nodes(nBG, S.getGraph())
02495             {
02496                 adjEntry ae_nBG;
02497                 forall_adj(ae_nBG, nBG)
02498                     adjacencyList[nBG].pushBack(ae_nBG);
02499             }
02500 
02501             NodeArray< List<adjEntry> > adjEntryTreated(S.getGraph());
02502             forall_nodes(nBG, S.getGraph())
02503             {
02504                 adjEntry adj;
02505                 forall_adj(adj, nBG)
02506                 {
02507                     if (adjEntryTreated[nBG].search(adj) != -1)
02508                         continue;
02509 
02510                     List<adjEntry> newFace;
02511                     adjEntry adj2 = adj;
02512                     do
02513                     {
02514                         newFace.pushBack(adj2);
02515                         adjEntryTreated[adj2->theNode()].pushBack(adj2);
02516                         node tn = adj2->twinNode();
02517                         int idx = adjacencyList[tn].search(adj2->twin());
02518                         if (idx - 1 < 0)
02519                             idx = adjacencyList[tn].size() - 1;
02520                         else
02521                             idx -= 1;
02522                         adj2 = *(adjacencyList[tn].get(idx));
02523                     } while (adj2 != adj);
02524                     faces.pushBack(newFace);
02525                 }
02526             } //forall_nodes(nBG, blockG[bT])
02527 
02528             for (ListIterator< List<adjEntry> > it = faces.begin(); it.valid(); it++)
02529             {
02530                 node nn = DG.newNode();
02531                 nDG_to_fPG[nn] = fPG_to_nDG.search(*(fPG_to_nDG.pushBack(nn)));
02532             }
02533 
02534             NodeArray< List<node> > adjFaces(DG);
02535             int i = 0;
02536             for (ListIterator< List<adjEntry> > it = faces.begin(); it.valid(); it++)
02537             {
02538                 int f1_id = i;
02539                 for (ListIterator<adjEntry> it2 = (*it).begin(); it2.valid(); it2++)
02540                 {
02541                     int f2_id = 0;
02542                     int j = 0;
02543                     for (ListIterator< List<adjEntry> > it3 = faces.begin(); it3.valid(); it3++)
02544                     {
02545                         bool do_break = false;
02546                         for (ListIterator<adjEntry> it4 = (*it3).begin(); it4.valid(); it4++)
02547                         {
02548                             if ((*it4) == (*it2)->twin())
02549                             {
02550                                 f2_id = j;
02551                                 do_break = true;
02552                                 break;
02553                             }
02554                         }
02555                         if (do_break)
02556                             break;
02557                         j++;
02558                     }
02559 
02560                     if (   f1_id != f2_id
02561                             && adjFaces[*(fPG_to_nDG.get(f1_id))].search(*(fPG_to_nDG.get(f2_id))) == -1
02562                             && adjFaces[*(fPG_to_nDG.get(f2_id))].search(*(fPG_to_nDG.get(f1_id))) == -1)
02563                     {
02564                         adjFaces[*(fPG_to_nDG.get(f1_id))].pushBack(*(fPG_to_nDG.get(f2_id)));
02565                         adjFaces[*(fPG_to_nDG.get(f2_id))].pushBack(*(fPG_to_nDG.get(f1_id)));
02566                         edge e1 = DG.newEdge(*(fPG_to_nDG.get(f1_id)), *(fPG_to_nDG.get(f2_id)));
02567                         edge e2 = DG.newEdge(*(fPG_to_nDG.get(f2_id)), *(fPG_to_nDG.get(f1_id)));
02568                         
02569                         //set edge length:
02570                         T e_length = -1;
02571                         for (ListIterator<adjEntry> it_f1 = (*it).begin(); it_f1.valid(); it_f1++)
02572                         {
02573                             edge e = (*it_f1)->theEdge();
02574                             for (ListIterator<adjEntry> it_f2 = (*(faces.get(f2_id))).begin();
02575                                  it_f2.valid();
02576                                  it_f2++)
02577                             {
02578                                 if ((*it_f2)->theEdge() == e)
02579                                 {
02580                                     if (e_length == -1 || edgeLength[mu][e] < e_length)
02581                                         e_length = edgeLength[mu][e];
02582                                 }
02583                             }
02584                         }
02585                         edgeLengthDG[e1] = e_length;
02586                         edgeLengthDG[e2] = e_length;
02587                     }
02588                     
02589                     if (*it2 == ae_f_ext)
02590                         f_ext_id = f1_id;
02591                     if (*it2 == ae_f_ref)
02592                         f_ref_id = f1_id;
02593                 } //for (ListIterator<adjEntry> it2 = (*it).begin(); it2.valid(); it2++)
02594                 i++;
02595             } //for (ListIterator< List<adjEntry> > it = faces.begin(); it.valid(); it++)
02596 
02597             //the faces sharing at least one edge with f_ref:
02598             node nDG_f_ref = *(fPG_to_nDG.get(f_ref_id));
02599             List<node>& f_ref_adj_faces = adjFaces[nDG_f_ref];
02600 
02601             //remove node related to f_ref from dual graph:
02602             DG.delNode(*(fPG_to_nDG.get(f_ref_id)));
02603 
02604             //compute shortest path and set thickness:
02605             NodeArray<T> dist(DG);
02606             node nDG_f_ext = *(fPG_to_nDG.get(f_ext_id));
02607             sssp(DG, nDG_f_ext, edgeLengthDG, dist);
02608             T minDist = -1;
02609             for (ListIterator<node> it_adj_faces = f_ref_adj_faces.begin();
02610                  it_adj_faces.valid();
02611                  it_adj_faces++)
02612             {
02613                 node fDG = *it_adj_faces;
02614                 if (fDG != nDG_f_ext)
02615                 {
02616                     T d = dist[fDG];
02617                     if (minDist == -1 || d < minDist)
02618                         minDist = d;
02619                 }
02620             }
02621             thickness[mu] = minDist + 1;
02622         } break;
02623     OGDF_NODEFAULT
02624     }
02625 }
02626 
02627 template<class T>
02628 bool EmbedderMaxFaceBiconnectedGraphsLayers<T>::sssp(
02629     const Graph& G,
02630     const node& s,
02631     const EdgeArray<T>& length,
02632     NodeArray<T>& d)
02633 {
02634     const T infinity = 20000000; // big number. danger. think about it.
02635 
02636     //Initialize-Single-Source(G, s):
02637     d.init(G);
02638     node v;
02639     edge e;
02640     forall_nodes (v, G)
02641         d[v] = infinity;
02642 
02643     d[s] = 0;
02644     for (int i = 1; i < G.numberOfNodes(); ++i)
02645     {
02646         forall_edges (e, G)
02647         {
02648             //relax(u, v, w): // e == (u, v), length == w
02649             if (d[e->target()] > d[e->source()] + length[e])
02650                 d[e->target()] = d[e->source()] + length[e];
02651         }
02652     }
02653 
02654     //check for negative cycle:
02655     forall_edges (e, G)
02656     {
02657         if (d[e->target()] > d[e->source()] + length[e])
02658             return false;
02659     }
02660         
02661     return true;
02662 }
02663 
02664 
02665 } // end namespace ogdf
02666 
02667 #endif