/// <summary>
 /// constructor
 /// </summary>
 /// <param name="layeredGraph"></param>
 /// <param name="la"></param>
 /// <param name="database"></param>
 /// <param name="intGraphP"></param>
 LayerInserter(
   ProperLayeredGraph layeredGraph, LayerArrays la, Database database, BasicGraph<Node, IntEdge> intGraphP) {
     this.la = la;
     this.database = database;
     this.layeredGraph = layeredGraph;
     this.intGraph = intGraphP;
 }
        /// <summary>
        /// Returns the same arrays but with no empty layers.
        /// </summary>
        /// <returns></returns>
        internal LayerArrays DropEmptyLayers() {
            int[] drop = new int[this.Layers.Length];
            int dropVal = 0;
            for (int i = 0; i < this.Layers.Length; i++) {
                drop[i] = dropVal;
                if (this.Layers[i].Length == 0)
                    dropVal++;
            }

            if (dropVal == 0)
                return this;

            //we do have empty layers
            int[] ny = new int[Y.Length];
            for (int i = 0; i < ny.Length; i++)
                ny[i] = Y[i] - drop[Y[i]];


            //copy the layers itself
            int[][] nls = new int[this.layers.Length - dropVal][];
            for (int i = 0; i < layers.Length; i++) {
                if (layers[i].Length > 0)
                    nls[i - drop[i]] = (int[])layers[i].Clone();
            }

            LayerArrays la = new LayerArrays(ny);
            la.layers = nls;

            return la;

        }
Exemple #3
0
        static Dictionary <int, Point> BuildInitialNodePositions(ProperLayeredGraph properLayeredGraph,
                                                                 LayerArrays layerArrays)
        {
            var result = new Dictionary <int, Point>();

            for (int i = 0; i < layerArrays.Layers.Length; i++)
            {
                int prev = 0, curr = 0;
                while (curr < layerArrays.Layers[i].Length)
                {
                    while (curr < layerArrays.Layers[i].Length &&
                           properLayeredGraph.IsVirtualNode(layerArrays.Layers[i][curr]))
                    {
                        curr++;
                    }
                    for (int j = prev; j < curr; j++)
                    {
                        result[layerArrays.Layers[i][j]] = new Point(i, prev);
                    }

                    if (curr < layerArrays.Layers[i].Length)
                    {
                        result[layerArrays.Layers[i][curr]] = new Point(i, curr);
                    }
                    curr++;
                    prev = curr;
                }
            }

            return(result);
        }
Exemple #4
0
 /// <summary>
 /// constructor
 /// </summary>
 /// <param name="layeredGraph"></param>
 /// <param name="la"></param>
 /// <param name="database"></param>
 /// <param name="intGraphP"></param>
 LayerInserter(
   ProperLayeredGraph layeredGraph, LayerArrays la, Database database, BasicGraph<Node, IntEdge> intGraphP) {
     this.la = la;
     this.database = database;
     this.layeredGraph = layeredGraph;
     this.intGraph = intGraphP;
 }
Exemple #5
0
 MetroMapOrdering(ProperLayeredGraph properLayeredGraph, LayerArrays layerArrays,
                  Dictionary <int, Point> nodePositions)
 {
     this.properLayeredGraph = properLayeredGraph;
     this.layerArrays        = layerArrays;
     this.nodePositions      = nodePositions;
 }
 static internal void InsertPaths(
                                  ref ProperLayeredGraph layeredGraph, ref LayerArrays la,
                                  Database db, BasicGraph<Node, IntEdge> intGraphP) {
     EdgePathsInserter li = new EdgePathsInserter(layeredGraph, la, db, intGraphP);
     li.InsertPaths();
     layeredGraph = li.NLayeredGraph;
     la = li.Nla;
 }
        ///// <summary>
        ///// the entry point of the class
        ///// </summary>
        ///// <param name="layeredGraph"></param>
        ///// <param name="la"></param>
        ///// <param name="db"></param>
        static internal void InsertLayers(
          ref ProperLayeredGraph layeredGraph, ref LayerArrays la, Database db, BasicGraph<Node, IntEdge> intGraphP) {
            LayerInserter li = new LayerInserter(layeredGraph, la, db, intGraphP);
            li.InsertLayers();

            layeredGraph = li.NLayeredGraph;
            la = li.Nla.DropEmptyLayers();

        }
Exemple #8
0
        ///// <summary>
        ///// the entry point of the class
        ///// </summary>
        ///// <param name="layeredGraph"></param>
        ///// <param name="la"></param>
        ///// <param name="db"></param>
        static internal void InsertLayers(
          ref ProperLayeredGraph layeredGraph, ref LayerArrays la, Database db, BasicGraph<Node, IntEdge> intGraphP) {
            LayerInserter li = new LayerInserter(layeredGraph, la, db, intGraphP);
            li.InsertLayers();

            layeredGraph = li.NLayeredGraph;
            la = li.Nla.DropEmptyLayers();

        }
        static internal void InsertPaths(
            ref ProperLayeredGraph layeredGraph, ref LayerArrays la,
            Database db, BasicGraph <Node, IntEdge> intGraphP)
        {
            EdgePathsInserter li = new EdgePathsInserter(layeredGraph, la, db, intGraphP);

            li.InsertPaths();
            layeredGraph = li.NLayeredGraph;
            la           = li.Nla;
        }
 internal AdjacentSwapsWithConstraints(LayerArrays layerArray,
                                       bool hasCrossWeights,
                                       ProperLayeredGraph properLayeredGraph,
                                       LayerInfo[] layerInfos) {
     X = layerArray.X;
     layering = layerArray.Y;
     layers = layerArray.Layers;
     this.properLayeredGraph = properLayeredGraph;
     this.hasCrossWeights = hasCrossWeights;
     this.layerInfos = layerInfos;
 }
Exemple #11
0
        internal static int GetCrossingsTotal(ProperLayeredGraph properLayeredGraph, LayerArrays layerArrays)
        {
            int x = 0;

            for (int i = 0; i < layerArrays.Layers.Length - 1; i++)
            {
                x += GetCrossingCountFromStrip(i, properLayeredGraph, layerArrays);
            }

            return(x);
        }
 /// <summary>
 /// Creates a smoothed polyline
 /// </summary>
 internal SmoothedPolylineCalculator(IntEdge edgePathPar, Anchor[] anchorsP, GeometryGraph origGraph, SugiyamaLayoutSettings settings, LayerArrays la, ProperLayeredGraph layerGraph, Database databaseP) {
     this.database = databaseP;
     edgePath = edgePathPar;
     anchors = anchorsP;
     this.layerArrays = la;
     this.originalGraph = origGraph;
     this.settings = settings;
     this.layeredGraph = layerGraph;
     rightHierarchy = BuildRightHierarchy();
     leftHierarchy = BuildLeftHierarchy();
 }
        int weightMultiplierOfTwoVirtual       = 8;       //weight multiplier for edges with two virtual nodes

        internal XLayoutGraph(BasicGraph <IntEdge> graph, //DAG of the original graph with no multiple edges
                              ProperLayeredGraph layeredGraph,
                              LayerArrays layerArrays,
                              List <IntEdge> edges,
                              int nov)
        {
            this.SetEdges(edges, nov);
            this.virtualVerticesStart = graph.NodeCount;
            this.virtualVerticesEnd   = layeredGraph.NodeCount - 1;
            this.layeredGraph         = layeredGraph;
            this.layerArrays          = layerArrays;
        }
 internal AdjacentSwapsWithConstraints(LayerArrays layerArray,
                                       bool hasCrossWeights,
                                       ProperLayeredGraph properLayeredGraph,
                                       LayerInfo[] layerInfos)
 {
     X        = layerArray.X;
     layering = layerArray.Y;
     layers   = layerArray.Layers;
     this.properLayeredGraph = properLayeredGraph;
     this.hasCrossWeights    = hasCrossWeights;
     this.layerInfos         = layerInfos;
 }
 /// <summary>
 /// Creates a smoothed polyline
 /// </summary>
 internal SmoothedPolylineCalculator(IntEdge edgePathPar, Anchor[] anchorsP, GeometryGraph origGraph, SugiyamaLayoutSettings settings, LayerArrays la, ProperLayeredGraph layerGraph, Database databaseP)
 {
     this.database      = databaseP;
     edgePath           = edgePathPar;
     anchors            = anchorsP;
     this.layerArrays   = la;
     this.originalGraph = origGraph;
     this.settings      = settings;
     this.layeredGraph  = layerGraph;
     rightHierarchy     = BuildRightHierarchy();
     leftHierarchy      = BuildLeftHierarchy();
 }
 internal Routing(SugiyamaLayoutSettings settings, GeometryGraph originalGraph, Database dbP,
                  LayerArrays yLayerArrays,
                  ProperLayeredGraph properLayeredGraph,
                  BasicGraph<Node, PolyIntEdge> intGraph
     ) {
     this.settings = settings;
     OriginalGraph = originalGraph;
     Database = dbP;
     ProperLayeredGraph = properLayeredGraph;
     LayerArrays = yLayerArrays;
     IntGraph = intGraph;
 }
 internal Routing(SugiyamaLayoutSettings settings, GeometryGraph originalGraph, Database dbP,
                  LayerArrays yLayerArrays,
                  ProperLayeredGraph properLayeredGraph,
                  BasicGraph<Node, IntEdge> intGraph
     ) {
     this.settings = settings;
     OriginalGraph = originalGraph;
     Database = dbP;
     ProperLayeredGraph = properLayeredGraph;
     LayerArrays = yLayerArrays;
     IntGraph = intGraph;
 }
        void InitNewLayering()
        {
            nla = new LayerArrays(new int[this.NLayeredGraph.NodeCount]);

            for (int i = 0; i < layeredGraph.NodeCount; i++)
            {
                NLayering[i] = la.Y[i];
            }

            foreach (KeyValuePair <IntPair, List <IntEdge> > kv in database.Multiedges)
            {
                if (kv.Key.First != kv.Key.Second && la.Y[kv.Key.First] != la.Y[kv.Key.Second]) //not a self edge and not a flat edge
                {
                    int            layer = 0;
                    bool           first = true;
                    List <IntEdge> list  = kv.Value;
                    foreach (IntEdge e in list)
                    {
                        if (first)
                        {
                            first = false;
                            layer = la.Y[e.Source];
                        }
                        int cl = layer - 1;
                        foreach (LayerEdge le in e.LayerEdges)
                        {
                            NLayering[le.Target] = cl--;
                        }
                    }
                }
            }

            int[][] newLayers = new int[la.Layers.Length][];

            //count new layer widths
            int[] counts = new int[newLayers.Length];

            foreach (int l in NLayering)
            {
                counts[l]++;
            }


            for (int i = 0; i < counts.Length; i++)
            {
                newLayers[i] = new int[counts[i]];
            }


            nla        = new LayerArrays(NLayering);
            nla.Layers = newLayers;
        }
 Ordering(ProperLayeredGraph graphPar, bool tryReverse, LayerArrays layerArraysParam, int startOfVirtualNodes, bool balanceVirtualAndOrigNodes, bool hasCrossWeights, SugiyamaLayoutSettings settings) {
     this.tryReverse = tryReverse;
     startOfVirtNodes = startOfVirtualNodes;
     layerArrays = layerArraysParam;
     layering = layerArraysParam.Y;
     nOfLayers = layerArraysParam.Layers.Length;
     layers = layerArraysParam.Layers;
     balanceVirtAndOrigNodes = balanceVirtualAndOrigNodes;
     properLayeredGraph = graphPar;
     this.hasCrossWeights = hasCrossWeights;
     this.settings = settings;
     random = new Random(SeedOfRandom);
 }
Exemple #20
0
 Ordering(ProperLayeredGraph graphPar, bool tryReverse, LayerArrays layerArraysParam, int startOfVirtualNodes, bool hasCrossWeights, SugiyamaLayoutSettings settings)
 {
     this.tryReverse      = tryReverse;
     startOfVirtNodes     = startOfVirtualNodes;
     layerArrays          = layerArraysParam;
     layering             = layerArraysParam.Y;
     nOfLayers            = layerArraysParam.Layers.Length;
     layers               = layerArraysParam.Layers;
     properLayeredGraph   = graphPar;
     this.hasCrossWeights = hasCrossWeights;
     this.settings        = settings;
     random               = new Random(SeedOfRandom);
 }
 ///// <summary>
 ///// private constructor
 ///// </summary>
 ///// <param name="layerArrays"></param>
 ///// <param name="anchs"></param>
 ///// <param name="layeredGraph"></param>
 ///// <param name="nOfOriginalVs"></param>
 XCoordsWithAlignment(LayerArrays layerArrays, ProperLayeredGraph layeredGraph,
                      int nOfOriginalVs, Anchor[] anchorsP, double ns)
 {
     this.la    = layerArrays;
     this.graph = layeredGraph;
     this.nOfOriginalVertices = nOfOriginalVs;
     this.nOfVertices         = graph.NodeCount;
     this.h     = la.Layers.Length;
     this.root  = new int[nOfVertices];
     this.align = new int[nOfVertices];
     // this.sink = new int[nOfVertices];
     // this.shift = new double[nOfVertices];
     this.anchors = anchorsP;
     this.nodeSep = ns;
 }
        internal static void OrderLayers(ProperLayeredGraph graph,
                                         LayerArrays layerArrays,
                                         int startOfVirtualNodes,
                                         bool balanceVirtualAndOriginalNodes, 
                                         SugiyamaLayoutSettings settings, CancelToken cancelToken) {
            bool hasCrossWeight = false;
            foreach (LayerEdge le in graph.Edges)
                if (le.CrossingWeight != 1) {
                    hasCrossWeight = true;
                    break;
                }

            var o = new Ordering(graph, true, layerArrays, startOfVirtualNodes, balanceVirtualAndOriginalNodes, hasCrossWeight, settings);
            o.Run(cancelToken);
        }
 internal static void Refine(
     int topNodeP,
     int bottomNode,
     Site topSiteP,
     Anchor[] anchors,
     LayerArrays layerArraysP,
     ProperLayeredGraph layeredGraph,
     GeometryGraph originalGraph,
     double layerSeparation) {
     RefinerBetweenTwoLayers refiner = new RefinerBetweenTwoLayers(topNodeP,
                                                                   bottomNode, topSiteP, layerArraysP,
                                                                   layeredGraph, originalGraph, anchors,
                                                                   layerSeparation);
     refiner.Refine();
 }
 /// <summary>
 /// it is a special recovery constructor to recreate the engine from the recovery engine
 /// </summary>
 internal LayeredLayoutEngine(LayerArrays engineLayerArrays, GeometryGraph originalGraph, ProperLayeredGraph properLayeredGraph, SugiyamaLayoutSettings sugiyamaSettings, Database database, BasicGraph<Node, IntEdge> intGraph, Dictionary<Node, int> nodeIdToIndex, BasicGraph<Node, IntEdge> gluedDagSkeletonForLayering, bool layersAreDoubled, ConstrainedOrdering constrainedOrdering, bool brandes, XLayoutGraph xLayoutGraph) {
     this.engineLayerArrays = engineLayerArrays;
     this.originalGraph = originalGraph;
     this.properLayeredGraph = properLayeredGraph;
     this.sugiyamaSettings = sugiyamaSettings;
     this.database = database;
     IntGraph = intGraph;
     this.nodeIdToIndex = nodeIdToIndex;
     GluedDagSkeletonForLayering = gluedDagSkeletonForLayering;
     LayersAreDoubled = layersAreDoubled;
     this.constrainedOrdering = constrainedOrdering;
     Brandes = brandes;
     anchors = database.anchors;
     this.xLayoutGraph = xLayoutGraph;
 }
        /// <summary>
        /// Allocating new layering and filling its y-layers
        /// </summary>
        void InitNewLayering()
        {
            nla = new LayerArrays(new int[totalNodes]);

            for (int i = 0; i < layeredGraph.NodeCount; i++)
            {
                NLayering[i] = la.Y[i] * 2;
            }

            foreach (KeyValuePair <IntPair, List <IntEdge> > kv in database.Multiedges)
            {
                IntPair ip = kv.Key;

                if (ip.First != ip.Second && la.Y[ip.First] != la.Y[ip.Second])  //not a self edge and not a flat edge
                {
                    int top = la.Y[ip.x] * 2;
                    foreach (IntEdge e in kv.Value)
                    {
                        int layer = top - 1;
                        foreach (LayerEdge le in e.LayerEdges)
                        {
                            if (le.Target != e.Target)
                            {
                                NLayering[le.Target] = layer--;
                            }
                        }
                    }
                }
            }

            int[][] newLayers = new int[2 * la.Layers.Length - 1][];

            //count new layer widths
            int[] counts = new int[newLayers.Length];

            foreach (int l in NLayering)
            {
                counts[l]++;
            }

            for (int i = 0; i < counts.Length; i++)
            {
                newLayers[i] = new int[counts[i]];
            }

            nla        = new LayerArrays(NLayering);
            nla.Layers = newLayers;
        }
Exemple #26
0
        internal static void Refine(
            int topNodeP,
            int bottomNode,
            Site topSiteP,
            Anchor[] anchors,
            LayerArrays layerArraysP,
            ProperLayeredGraph layeredGraph,
            GeometryGraph originalGraph,
            double layerSeparation)
        {
            RefinerBetweenTwoLayers refiner = new RefinerBetweenTwoLayers(topNodeP,
                                                                          bottomNode, topSiteP, layerArraysP,
                                                                          layeredGraph, originalGraph, anchors,
                                                                          layerSeparation);

            refiner.Refine();
        }
 RefinerBetweenTwoLayers(
         int topNodeP,
         int bottomNodeP,
         Site topSiteP,
         LayerArrays layerArraysP,
         ProperLayeredGraph layeredGraphP, GeometryGraph originalGraphP, Anchor[] anchorsP, double layerSeparation) {
     this.topNode = topNodeP;
     this.bottomNode = bottomNodeP;
     this.topSite = topSiteP;
     this.bottomSite = topSiteP.Next;
     this.currentTopSite = topSiteP;
     this.currentBottomSite = topSiteP.Next;
     this.layerArrays = layerArraysP;
     this.layeredGraph = layeredGraphP;
     this.originalGraph = originalGraphP;
     this.anchors = anchorsP;
     this.layerSeparation = layerSeparation;
 }
        /// <summary>
        /// Returns the same arrays but with no empty layers.
        /// </summary>
        /// <returns></returns>
        internal LayerArrays DropEmptyLayers()
        {
            int[] drop    = new int[this.Layers.Length];
            int   dropVal = 0;

            for (int i = 0; i < this.Layers.Length; i++)
            {
                drop[i] = dropVal;
                if (this.Layers[i].Length == 0)
                {
                    dropVal++;
                }
            }

            if (dropVal == 0)
            {
                return(this);
            }

            //we do have empty layers
            int[] ny = new int[Y.Length];
            for (int i = 0; i < ny.Length; i++)
            {
                ny[i] = Y[i] - drop[Y[i]];
            }


            //copy the layers itself
            int[][] nls = new int[this.layers.Length - dropVal][];
            for (int i = 0; i < layers.Length; i++)
            {
                if (layers[i].Length > 0)
                {
                    nls[i - drop[i]] = (int[])layers[i].Clone();
                }
            }

            LayerArrays la = new LayerArrays(ny);

            la.layers = nls;

            return(la);
        }
        void CreateExtendedLayerArrays()
        {
            var layeringExt = new int[numberOfNodesOfProperGraph];

            Array.Copy(initialLayering, layeringExt, initialLayering.Length);
            foreach (IntEdge edge in ProperLayeredGraph.BaseGraph.Edges)
            {
                var ledges = (LayerEdge[])edge.LayerEdges;
                if (ledges != null && ledges.Length > 1)
                {
                    int layerIndex = initialLayering[edge.Source] - 1;
                    for (int i = 0; i < ledges.Length - 1; i++)
                    {
                        layeringExt[ledges[i].Target] = layerIndex--;
                    }
                }
            }
            LayerArrays = new LayerArrays(layeringExt);
        }
Exemple #30
0
 RefinerBetweenTwoLayers(
     int topNodeP,
     int bottomNodeP,
     Site topSiteP,
     LayerArrays layerArraysP,
     ProperLayeredGraph layeredGraphP, GeometryGraph originalGraphP, Anchor[] anchorsP, double layerSeparation)
 {
     this.topNode           = topNodeP;
     this.bottomNode        = bottomNodeP;
     this.topSite           = topSiteP;
     this.bottomSite        = topSiteP.Next;
     this.currentTopSite    = topSiteP;
     this.currentBottomSite = topSiteP.Next;
     this.layerArrays       = layerArraysP;
     this.layeredGraph      = layeredGraphP;
     this.originalGraph     = originalGraphP;
     this.anchors           = anchorsP;
     this.layerSeparation   = layerSeparation;
 }
        static Dictionary<int, Point> BuildInitialNodePositions(ProperLayeredGraph properLayeredGraph,
                                                                LayerArrays layerArrays) {
            var result = new Dictionary<int, Point>();
            for (int i = 0; i < layerArrays.Layers.Length; i++) {
                int prev = 0, curr = 0;
                while (curr < layerArrays.Layers[i].Length) {
                    while (curr < layerArrays.Layers[i].Length &&
                           properLayeredGraph.IsVirtualNode(layerArrays.Layers[i][curr])) curr++;
                    for (int j = prev; j < curr; j++)
                        result[layerArrays.Layers[i][j]] = new Point(i, prev);

                    if (curr < layerArrays.Layers[i].Length)
                        result[layerArrays.Layers[i][curr]] = new Point(i, curr);
                    curr++;
                    prev = curr;
                }
            }

            return result;
        }
Exemple #32
0
        internal static void OrderLayers(ProperLayeredGraph graph,
                                         LayerArrays layerArrays,
                                         int startOfVirtualNodes,
                                         SugiyamaLayoutSettings settings, CancelToken cancelToken)
        {
            bool hasCrossWeight = false;

            foreach (LayerEdge le in graph.Edges)
            {
                if (le.CrossingWeight != 1)
                {
                    hasCrossWeight = true;
                    break;
                }
            }

            var o = new Ordering(graph, true, layerArrays, startOfVirtualNodes, hasCrossWeight, settings);

            o.Run(cancelToken);
        }
Exemple #33
0
        static int GetCrossingCountFromStripWhenBottomLayerIsShorter(int[] bottomVerts,
                                                                     ProperLayeredGraph properLayeredGraph,
                                                                     LayerArrays layerArrays)
        {
            LayerEdge[] edges = EdgesOfStrip(bottomVerts, properLayeredGraph);
            Array.Sort(edges, new EdgeComparerBySource(layerArrays.X));
            //find first n such that 2^n >=bottomVerts.Length
            int n = 1;

            while (n < bottomVerts.Length)
            {
                n *= 2;
            }
            //init accumulator

            var tree = new int[2 * n - 1];

            n--;        // the first bottom node starts from n now

            int cc = 0; //number of crossings

            foreach (LayerEdge edge in edges)
            {
                int index = n + layerArrays.X[edge.Target];
                int ew    = edge.CrossingWeight;
                tree[index] += ew;
                while (index > 0)
                {
                    if (index % 2 != 0)
                    {
                        cc += ew * tree[index + 1]; //intersect everything accumulated in the right sibling
                    }
                    index        = (index - 1) / 2;
                    tree[index] += ew;
                }
            }

            return(cc);
        }
        override protected void RunInternal() {
#if REPORTING
            Timer t = null;
            if (sugiyamaSettings.Reporting) {
                Report("removing cycles ... ");
                t = new Timer();
                t.Start();
            }
#endif
            if (originalGraph.Nodes.Count > 0) {
                engineLayerArrays = CalculateLayers();
  
                if (!sugiyamaSettings.LayeringOnly)
                    RunPostLayering();
            } else
                originalGraph.boundingBox.SetToEmpty();

#if REPORTING
            if (sugiyamaSettings.Reporting) {
                t.Stop();
                Report(String.Format(CultureInfo.InvariantCulture, "done for {0}, nodes {1} edges {2}", t.Duration,
                                     IntGraph.NodeCount, IntGraph.Edges.Count));
            }

            //SugiyamaLayoutSettings.ShowDatabase(database);
#endif
        }
 static double SetFlatEdgesForLayer(Database database, LayerArrays layerArrays, int i,
                                    BasicGraph<IntEdge> intGraph, SugiyamaLayoutSettings settings, double ymax) {
     double flatEdgesHeight = 0;
     if (i > 0) {
         //looking for flat edges on the previous level                
         //we stack labels of multiple flat edges on top of each other
         IEnumerable<IntPair> flatPairs = GetFlatPairs(layerArrays.Layers[i - 1], layerArrays.Y,
                                                       intGraph);
         if (flatPairs.Any()) {
             double dyOfFlatEdge = settings.LayerSeparation/3;
             double ym = ymax;
             flatEdgesHeight =
                 (from pair in flatPairs
                  select SetFlatEdgesLabelsHeightAndPositionts(pair, ym, dyOfFlatEdge, database)).
                     Max();
         }
     }
     return flatEdgesHeight;
 }
        ///// <summary>
        ///// A quote from Gansner93.
        ///// The method involves constructing an auxiliary graph as illustrated in figure 4-2.
        ///// This transformation is the graphical analogue of the algebraic 
        ///// transformation mentioned above for removing the absolute values 
        ///// from the optimization problem. The nodes of the auxiliary graph Gў are the nodes of 
        ///// the original graph G plus, for every edge e in G, there is a new node ne. 
        ///// There are two kinds of edges in Gў. One edge class encodes the 
        ///// cost of the original edges. Every edge e = (u,v) in G is replaced by two edges (ne ,u)
        ///// and (ne, v) with d = 0 and w = w(e)W(e). The other class of edges separates nodes in the same layer. 
        ///// If v is the left neighbor of w, then Gў has an edge f = e(v,w) with d( f ) = r(v,w) and 
        ///// w( f ) = 0. This edge forces the nodes to be sufficiently 
        ///// separated but does not affect the cost of the layout.
        XLayoutGraph CreateXLayoutGraph(LayerArrays layerArrays) {
            int nOfVerts = properLayeredGraph.NodeCount;

            //create edges of XLayoutGraph
            var edges = new List<IntEdge>();

            foreach (LayerEdge e in properLayeredGraph.Edges) {
                var n1 = new IntEdge(nOfVerts, e.Source);
                var n2 = new IntEdge(nOfVerts, e.Target);
                n1.Weight = n2.Weight = e.Weight;
                n1.Separation = 0; //these edge have 0 separation
                n2.Separation = 0;
                nOfVerts++;
                edges.Add(n1);
                edges.Add(n2);
            }

            foreach (var layer in layerArrays.Layers)
                for (int i = layer.Length - 1; i > 0; i--) {
                    int source = layer[i];
                    int target = layer[i - 1];
                    var ie = new IntEdge(source, target);
                    Anchor sourceAnchor = database.Anchors[source];
                    Anchor targetAnchor = database.Anchors[target];

                    double sep = sourceAnchor.LeftAnchor + targetAnchor.RightAnchor + sugiyamaSettings.NodeSeparation;

                    ie.Separation = (int) (sep + 1);

                    edges.Add(ie);
                }

            var ret = new XLayoutGraph(IntGraph, properLayeredGraph, layerArrays, edges, nOfVerts);
            ret.SetEdgeWeights();
            return ret;
        }
        void InsertVirtualEdgesIfNeeded(LayerArrays layerArrays) {
            if (constrainedOrdering != null) //if there are constraints we handle multiedges correctly
                return;

            foreach (var kv in database.Multiedges)
                // If there are an even number of multi-edges between two nodes then
                //  add a virtual edge in the multi-edge dict to improve the placement, but only in case when the edge goes down only one layer.         
                if (kv.Value.Count%2 == 0 && layerArrays.Y[kv.Key.First] - 1 == layerArrays.Y[kv.Key.Second]) {
                    var newVirtualEdge = new IntEdge(kv.Key.First, kv.Key.Second);
                    newVirtualEdge.Edge = new Edge();
                    newVirtualEdge.IsVirtualEdge = true;
                    kv.Value.Insert(kv.Value.Count/2, newVirtualEdge);
                    IntGraph.AddEdge(newVirtualEdge);
                }
        }
        /// <summary>
        /// 
        /// </summary>
        /// <returns>the height of the graph+spaceBeforeMargins</returns>
        internal static void CalcInitialYAnchorLocations(LayerArrays layerArrays, double spaceBeforeMargins,
                                                         GeometryGraph originalGraph, Database database,
                                                         BasicGraph<IntEdge> intGraph,
                                                         SugiyamaLayoutSettings settings,
                                                         bool layersAreDoubled) {
            Anchor[] anchors = database.Anchors;
            double ymax = originalGraph.Margins + spaceBeforeMargins; //setting up y coord - going up by y-layers
            int i = 0;
            foreach (var yLayer in layerArrays.Layers) {
                double bottomAnchorMax = 0;
                double topAnchorMax = 0;
                foreach (int j in yLayer) {
                    Anchor p = anchors[j];
                    if (p.BottomAnchor > bottomAnchorMax)
                        bottomAnchorMax = p.BottomAnchor;
                    if (p.TopAnchor > topAnchorMax)
                        topAnchorMax = p.TopAnchor;
                }

                MakeVirtualNodesTall(yLayer, bottomAnchorMax, topAnchorMax, originalGraph.Nodes.Count, database.Anchors);

                double flatEdgesHeight = SetFlatEdgesForLayer(database, layerArrays, i, intGraph, settings, ymax);

                double layerCenter = ymax + bottomAnchorMax + flatEdgesHeight;
                double layerTop = layerCenter + topAnchorMax;
                if (NeedToSnapTopsToGrid(settings)) {
                    layerTop += SnapDeltaUp(layerTop, settings.GridSizeByY);
                    foreach (int j in yLayer) anchors[j].Top = layerTop;                   
                } else if (NeedToSnapBottomsToGrid(settings)) {
                    double layerBottom = layerCenter - bottomAnchorMax;
                    layerBottom += SnapDeltaUp(layerBottom, layerBottom);
                    foreach (int j in yLayer)
                    {
                        anchors[j].Bottom = layerBottom;
                        layerTop = Math.Max(anchors[j].Top, layerTop);
                    }
                }
                else foreach (int j in yLayer) anchors[j].Y = layerCenter;
                
                double layerSep = settings.ActualLayerSeparation(layersAreDoubled);
                ymax = layerTop + layerSep;
                i++;
            }
            // for the last layer
            SetFlatEdgesForLayer(database, layerArrays, i, intGraph, settings, ymax);
        }
 void OrderLayers(LayerArrays layerArrays) {
     foreach (var layer in layerArrays.Layers)
         OrderLayerBasedOnRecoveredXCoords(layer);
 }
        void AnalyzeNeedToInsertLayersAndHasMultiedges(LayerArrays layerArrays, ref bool needToInsertLayers,
                                                       ref bool multipleEdges) {
            foreach (IntEdge ie in IntGraph.Edges)
                if (ie.HasLabel && layerArrays.Y[ie.Source] != layerArrays.Y[ie.Target]) {
                    //if an edge is a flat edge then
                    needToInsertLayers = true;
                    break;
                }

            if (needToInsertLayers == false && constrainedOrdering == null)
                //if we have constrains the multiple edges have been already represented in layers
                foreach (var kv in database.Multiedges)
                    if (kv.Value.Count > 1) {
                        multipleEdges = true;
                        if (layerArrays.Y[kv.Key.x] - layerArrays.Y[kv.Key.y] == 1) {
                            //there is a multi edge spanning exactly one layer; unfortunately we need to introduce virtual vertices for 
                            //the edges middle points 
                            needToInsertLayers = true;
                            break;
                        }
                    }
        }
Exemple #41
0
        /// <summary>
        /// Sort new odd layers by the sum of x-coordinatates of predecessors and the successors of 
        /// dummy nodes.
        /// </summary>
        void SortNewOddLayers() {

            for (int i = 1; i < nla.Layers.Length; i += 2) {
                SortedDictionary<int, object> sd = new SortedDictionary<int, object>();
                int[] layer = nla.Layers[i];
                foreach (int v in layer) {

                    //find unique predecessor and successor
                    int predecessor = -1;
                    foreach (LayerEdge ie in nLayeredGraph.InEdges(v))
                        predecessor = ie.Source;
                    int successor = -1;
                    foreach (LayerEdge ie in nLayeredGraph.OutEdges(v))
                        successor = ie.Target;

                    int x = nla.X[predecessor] + nla.X[successor];

                    if (sd.ContainsKey(x)) {
                        object o = sd[x];
#if SHARPKIT //https://code.google.com/p/sharpkit/issues/detail?id=347
                        if (o.GetType() == typeof(int)) {
#else
                        if (o is int) {
#endif
                            List<int> l = new List<int>();
                            l.Add((int)o);
                            l.Add(v);
                            sd[x] = l;
                        } else {
                            List<int> l = o as List<int>;
                            l.Add(v);
                        }
                    } else
                        sd[x] = v;
                }
                //fill the layer according to this order
                int c = 0;
                foreach (object v in sd.Values)
#if SHARPKIT //https://code.google.com/p/sharpkit/issues/detail?id=347
                    if (v.GetType() == typeof(int))
#else
                {
                   if (v is int)
                      #endif
                      layer[c++] = (int)v;
                   else
                   {
                      foreach (int k in v as List<int>)
                         layer[c++] = k;
                   }
                }

                //update X now
                for (int m = 0; m < layer.Length; m++)
                    nla.X[layer[m]] = m;
            }
        }

        /// <summary>
        /// Allocating new layering and filling its y-layers
        /// </summary>
        void InitNewLayering() {


            nla = new LayerArrays(new int[totalNodes]);

            for (int i = 0; i < layeredGraph.NodeCount; i++)
                NLayering[i] = la.Y[i] * 2;

            foreach (KeyValuePair<IntPair, List<IntEdge>> kv in database.Multiedges) {
                IntPair ip = kv.Key;

                if (ip.First != ip.Second && la.Y[ip.First] != la.Y[ip.Second]) {//not a self edge and not a flat edge
                    int top = la.Y[ip.x] * 2;
                    foreach (IntEdge e in kv.Value) {
                        int layer = top - 1;
                        foreach (LayerEdge le in e.LayerEdges)
                        {
                           if (le.Target != e.Target)
                              NLayering[le.Target] = layer--;
                        }
                    }
                }
            }

            int[][] newLayers = new int[2 * la.Layers.Length - 1][];

            //count new layer widths
            int[] counts = new int[newLayers.Length];

            foreach (int l in NLayering)
                counts[l]++;

            for (int i = 0; i < counts.Length; i++)
                newLayers[i] = new int[counts[i]];

            nla = new LayerArrays(NLayering);
            nla.Layers = newLayers;

        }
 public RecoveryLayerCalculator(LayerArrays recoveredLayerArrays)
 {
     layers = recoveredLayerArrays;
 }
        /*
                void CalculateXPositionsWithQP(LayerArrays layerArrays){
                    ISolverShell solver = ConstrainedOrdering.CreateSolver();
                    foreach (var layer in layerArrays.Layers)
                        AddNotOverlappingConstraints(layer, solver);
                    foreach (var list in database.Multiedges.Values)
                        foreach (IntEdge edge in list)
                            AddEdgeToSolverTarget(edge, solver, edge.Weight);


                    int j = -1;
                    for (int i = 0; i < intGraph.Nodes.Count; i++)
                        if(intGraph.OutEdgesCount(i) != 0 || intGraph.InEdgesCount(i) != 0){
                            j = i;
                            break;
                        }
                    if(j != -1){
                        for (int i = 0; i < intGraph.Nodes.Count; i++)
                            if(intGraph.OutEdgesCount(i) == 0 && intGraph.InEdgesCount(i) == 0)
                                solver.AddGoalTwoVariablesAreClose(i, j);
                    }

                    j = 0;
                    foreach (Anchor a in database.Anchors)
                        a.X = solver.GetVariableResolvedPosition(j++);

                }
        */

        void DecideIfUsingFastXCoordCalculation(LayerArrays layerArrays) {
            if (layerArrays.X.Length >= sugiyamaSettings.BrandesThreshold)
                Brandes = true;
#if !SILVERLIGHT && !SHARPKIT
            else {
                string s = Environment.GetEnvironmentVariable("Brandes");
                if (!String.IsNullOrEmpty(s) && String.Compare(s, "on", true, CultureInfo.CurrentCulture) == 0)
                    Brandes = true;
            }
#endif
        }
 /// <summary>
 /// The function calculates y-layers and x-layers, 
 /// thus, in fact, defining node, including dummy nodes, locations.
 /// </summary>
 /// <param name="layerArrays"></param>
 void CalculateXLayersByGansnerNorth(LayerArrays layerArrays) {
     xLayoutGraph = CreateXLayoutGraph(layerArrays);
     CalculateXLayersByGansnerNorthOnProperLayeredGraph();
 }
        /// <summary>
        ///
        /// </summary>
        static internal void CalculateXCoordinates(LayerArrays layerArrays, ProperLayeredGraph layeredGraph, int nOfOriginalVs, Anchor[] anchors, double nodeSeparation)
        {
            XCoordsWithAlignment x = new XCoordsWithAlignment(layerArrays, layeredGraph, nOfOriginalVs, anchors, nodeSeparation);

            x.Calculate();
        }
Exemple #46
0
 /// <summary>
 /// Reorder only points having identical nodePositions
 /// </summary>
 internal static void UpdateLayerArrays(ProperLayeredGraph properLayeredGraph, LayerArrays layerArrays,
                                        Dictionary <int, Point> nodePositions)
 {
     new MetroMapOrdering(properLayeredGraph, layerArrays, nodePositions).UpdateLayerArrays();
 }
Exemple #47
0
        /// <summary>
        /// Reorder virtual nodes between the same pair of real nodes
        /// </summary>
        internal static void UpdateLayerArrays(ProperLayeredGraph properLayeredGraph, LayerArrays layerArrays)
        {
            Dictionary <int, Point> nodePositions = BuildInitialNodePositions(properLayeredGraph, layerArrays);

            UpdateLayerArrays(properLayeredGraph, layerArrays, nodePositions);
        }
Exemple #48
0
 ///// <summary>
 ///// This method can be improved: see the paper Simple And Efficient ...
 ///// </summary>
 ///// <param name="graph"></param>
 ///// <param name="layerArrays"></param>
 ///// <param name="bottom">bottom of the strip</param>
 ///// <returns></returns>
 static int GetCrossingCountFromStrip(int bottom, ProperLayeredGraph properLayeredGraph, LayerArrays layerArrays)
 {
     int[] topVerts    = layerArrays.Layers[bottom + 1];
     int[] bottomVerts = layerArrays.Layers[bottom];
     if (bottomVerts.Length <= topVerts.Length)
     {
         return(GetCrossingCountFromStripWhenBottomLayerIsShorter(bottomVerts, properLayeredGraph, layerArrays));
     }
     else
     {
         return(GetCrossingCountFromStripWhenTopLayerIsShorter(topVerts, bottomVerts, properLayeredGraph,
                                                               layerArrays));
     }
 }
        LayerArrays InsertLayersIfNeeded(LayerArrays layerArrays) {
            bool needToInsertLayers = false;
            bool multipleEdges = false;

            InsertVirtualEdgesIfNeeded(layerArrays);

            AnalyzeNeedToInsertLayersAndHasMultiedges(layerArrays, ref needToInsertLayers, ref multipleEdges);

            if (needToInsertLayers) {
                LayerInserter.InsertLayers(ref properLayeredGraph, ref layerArrays, database, IntGraph);
                LayersAreDoubled = true;
            } else if (multipleEdges)
                EdgePathsInserter.InsertPaths(ref properLayeredGraph, ref layerArrays, database, IntGraph);

            RecreateIntGraphFromDataBase();

            return layerArrays;
        }
        LayerArrays CalculateLayerArrays() {
            LayerArrays layerArrays = CalculateYLayers();

            if (constrainedOrdering == null) {
                DecideIfUsingFastXCoordCalculation(layerArrays);

                CalculateAnchorsAndYPositions(layerArrays);

                if (Brandes)
                    CalculateXPositionsByBrandes(layerArrays);
                else
                    CalculateXLayersByGansnerNorth(layerArrays);
            } else
                anchors = database.Anchors;

            OptimizeEdgeLabelsLocations();

            engineLayerArrays = layerArrays;
            StraightensShortEdges();

            double aspectRatio;
            CalculateOriginalGraphBox(out aspectRatio);

            if (sugiyamaSettings.AspectRatio != 0)
                StretchToDesiredAspectRatio(aspectRatio, sugiyamaSettings.AspectRatio);

            return layerArrays;
        }
        /// <summary>
        /// 
        /// </summary>
        /// <returns>the height of the graph+spaceBeforeMargins</returns>
        internal static void CalcInitialYAnchorLocations(LayerArrays layerArrays, double spaceBeforeMargins,
                                                         GeometryGraph originalGraph, Database database,
                                                         BasicGraph<IntEdge> intGraph,
                                                         SugiyamaLayoutSettings settings,
                                                         bool layersAreDoubled) {
            Anchor[] anchors = database.Anchors;
            double ymax = originalGraph.Margins + spaceBeforeMargins; //setting up y coord - going up by y-layers
            int i = 0;
            foreach (var yLayer in layerArrays.Layers) {
                double bottomAnchorMax = 0;
                double topAnchorMax = 0;
                foreach (int j in yLayer) {
                    Anchor p = anchors[j];
                    if (p.BottomAnchor > bottomAnchorMax)
                        bottomAnchorMax = p.BottomAnchor;
                    if (p.TopAnchor > topAnchorMax)
                        topAnchorMax = p.TopAnchor;
                }

                MakeVirtualNodesHigh(yLayer, bottomAnchorMax, topAnchorMax, originalGraph.Nodes.Count, database.Anchors);

                double flatEdgesHeight = SetFlatEdgesForLayer(database, layerArrays, i, intGraph, settings, ymax);

                double y = ymax + bottomAnchorMax + flatEdgesHeight;
                foreach (int j in yLayer)
                    anchors[j].Y = y;
                double layerSep = settings.ActualLayerSeparation(layersAreDoubled);
                ymax = y + topAnchorMax + layerSep;
                i++;
            }
            SetFlatEdgesForLayer(database, layerArrays, i, intGraph, settings, ymax);
        }
 void CalculateAnchorsAndYPositions(LayerArrays layerArrays) {
     CalculateAnchorSizes(database, out anchors, properLayeredGraph, originalGraph, IntGraph, sugiyamaSettings);
     CalcInitialYAnchorLocations(layerArrays, 500, originalGraph, database, IntGraph, sugiyamaSettings,
                                 LayersAreDoubled);
 }
        LayerArrays YLayeringAndOrdering(LayerCalculator layering) {
            #region reporting

#if REPORTING
            Timer t = null;
            if (sugiyamaSettings.Reporting) {
                t = new Timer();
                Report("ylayering ... ");
                t.Start();
            }
#endif

            #endregion

            int[] yLayers = layering.GetLayers();
            Balancing.Balance(GluedDagSkeletonForLayering, yLayers, GetNodeCountsOfGluedDag(), null);
            yLayers = ExtendLayeringToUngluedSameLayerVertices(yLayers);

            #region reporting

#if REPORTING
            if (sugiyamaSettings.Reporting) {
                t.Stop();
                Report(String.Format(CultureInfo.CurrentCulture, "{0}\n", t.Duration));
                Report("ordering ... ");
                t.Start();
            }
#endif

            #endregion

            var layerArrays = new LayerArrays(yLayers);
            //if (!SugiyamaSettings.UseEdgeBundling && (HorizontalConstraints == null || HorizontalConstraints.IsEmpty)) {
            if (HorizontalConstraints == null || HorizontalConstraints.IsEmpty) {
                layerArrays = YLayeringAndOrderingWithoutHorizontalConstraints(layerArrays);

                #region reporting

#if REPORTING
                if (sugiyamaSettings.Reporting) {
                    t.Stop();
                    Report(String.Format(CultureInfo.CurrentCulture, "{0}\n", t.Duration));
                }
#endif

                #endregion

                return layerArrays;
            }
            constrainedOrdering = new ConstrainedOrdering(originalGraph, IntGraph, layerArrays.Y, nodeIdToIndex,
                                                          database, sugiyamaSettings);
            constrainedOrdering.Calculate();
            properLayeredGraph = constrainedOrdering.ProperLayeredGraph;

            #region reporting

#if REPORTING
            if (sugiyamaSettings.Reporting) {
                t.Stop();
                Report(String.Format(CultureInfo.CurrentCulture, "{0}\n", t.Duration));
            }
#endif

            #endregion

            // SugiyamaLayoutSettings.ShowDatabase(this.database);
            return constrainedOrdering.LayerArrays;
        }
        //[System.Diagnostics.Conditional("DEBUGGLEE")]
        //private void TestYXLayers(LayerArrays layerArrays, int[] xLayers) {
        //    foreach (IntEdge e in this.xLayoutGraph.Edges) {
        //        int s = e.Source; int targ = e.Target;
        //        if (e.Source >= layeredGraph.Nodes.Count) {
        //            if (xLayoutGraph.OutEdges(s).Count != 2 || xLayoutGraph.InEdges(s).Count != 0)
        //                Report("must be two out edges and none incoming");

        //            if (targ >= layeredGraph.Nodes.Count)
        //                Report("an illegal edge");

        //        } else {

        //            if (layerArrays.Y[s] != layerArrays.Y[targ])
        //                Report("layers don't coincide");

        //            if (layerArrays.X[s] - 1 != layerArrays.X[targ])
        //                Report("wrong input");

        //            if (xLayers[s] <= xLayers[targ])
        //                Report("wrong xlayering");

        //        }
        //    }
        //}

        /// <summary>
        /// Creating a proper layered graph, a graph where each 
        /// edge goes only one layer down from the i+1-th layer to the i-th layer.
        /// </summary>
        /// <param name="layering"></param>
        /// <param name="layerArrays"></param>
        void CreaeteProperLayeredGraph(int[] layering, out LayerArrays layerArrays) {
            int n = layering.Length;
            int nOfVV = 0;


            foreach (IntEdge e in database.SkeletonEdges()) {
                int span = EdgeSpan(layering, e);

                Debug.Assert(span >= 0);

                if (span > 0)
                    e.LayerEdges = new LayerEdge[span];
                int pe = 0; //offset in the string

                if (span > 1) {
                   
                    //we create span-2 dummy nodes and span new edges
                    int d0 = n + nOfVV++;
                   
                    var layerEdge = new LayerEdge(e.Source, d0, e.CrossingWeight,e.Weight);

                    e.LayerEdges[pe++] = layerEdge;


                    //create span-2 internal edges all from dummy nodes
                    for (int j = 0; j < span - 2; j++) {
                        d0++;
                        nOfVV++;
                        layerEdge = new LayerEdge(d0 - 1, d0, e.CrossingWeight,e.Weight);
                        e.LayerEdges[pe++] = layerEdge;
                    }

                    layerEdge = new LayerEdge(d0, e.Target, e.CrossingWeight, e.Weight);
                    e.LayerEdges[pe] = layerEdge;
                } else if (span == 1) {
                    var layerEdge = new LayerEdge(e.Source, e.Target, e.CrossingWeight, e.Weight);
                    e.LayerEdges[pe] = layerEdge;
                }
            }

            var extendedVertexLayering = new int[originalGraph.Nodes.Count + nOfVV];

            foreach (IntEdge e in database.SkeletonEdges())
                if (e.LayerEdges != null) {
                    int l = layering[e.Source];
                    extendedVertexLayering[e.Source] = l--;
                    foreach (LayerEdge le in e.LayerEdges)
                        extendedVertexLayering[le.Target] = l--;
                } else {
                    extendedVertexLayering[e.Source] = layering[e.Source];
                    extendedVertexLayering[e.Target] = layering[e.Target];
                }

            properLayeredGraph =
                new ProperLayeredGraph(new BasicGraph<Node, IntEdge>(database.SkeletonEdges(), layering.Length));
            properLayeredGraph.BaseGraph.Nodes = IntGraph.Nodes;
            layerArrays = new LayerArrays(extendedVertexLayering);
        }
 LayerArrays YLayeringAndOrderingWithoutHorizontalConstraints(LayerArrays layerArrays) {
     CreaeteProperLayeredGraph(layerArrays.Y, out layerArrays);
     Ordering.OrderLayers(properLayeredGraph, layerArrays, originalGraph.Nodes.Count,
         sugiyamaSettings.AspectRatio != 0, sugiyamaSettings, CancelToken);
     MetroMapOrdering.UpdateLayerArrays(properLayeredGraph, layerArrays);
     return layerArrays;
 }
 void CalculateXPositionsByBrandes(LayerArrays layerArrays) {
     XCoordsWithAlignment.CalculateXCoordinates(layerArrays, properLayeredGraph, originalGraph.Nodes.Count,
                                                database.Anchors, sugiyamaSettings.NodeSeparation);
 }
Exemple #57
0
        protected override void RunInternal()
        {
#if DEBUGORDERING
            if (graph.NumberOfVertices != layering.Length)
            {
                throw new System.Exception("the layering does not correspond to the graph");
            }
            foreach (IntEdge e in graph.Edges)
            {
                if (layering[e.Source] - layering[e.Target] != 1)
                {
                    throw new System.Exception("the edge in the graph does not span exactly one layer:" + e);
                }
            }
#endif

#if PPC // Parallel -- susanlwo
            LayerArrays secondLayers      = null;
            Ordering    revOrdering       = null;
            System.Threading.Tasks.Task t = null;

            if (/*orderingMeasure.x>0 &&*/ tryReverse)
            {
                secondLayers = layerArrays.ReversedClone();

                revOrdering = new Ordering(properLayeredGraph.ReversedClone(), false, secondLayers, startOfVirtNodes, balanceVirtAndOrigNodes, this.hasCrossWeights, settings);

                // note: below we need to pass the CancelToken from this thread into the new thread, to make sure a previous thread from the ThreadPool's
                // thread static token (that may be in a cancelled state) is picked up.
                t = System.Threading.Tasks.Task.Factory.StartNew(() => revOrdering.Run(this.CancelToken));
            }

            Calculate();

            if (/*orderingMeasure.x>0 &&*/ tryReverse)
            {
                t.Wait();

                if (revOrdering.measure < measure)
                {
                    for (int j = 0; j < nOfLayers; j++)
                    {
                        secondLayers.Layers[j].CopyTo(layerArrays.Layers[nOfLayers - 1 - j], 0);
                    }

                    layerArrays.UpdateXFromLayers();
                }
            }
#else
            Calculate();

            if (/*orderingMeasure.x>0 &&*/ tryReverse)
            {
                LayerArrays secondLayers = layerArrays.ReversedClone();

                var revOrdering = new Ordering(properLayeredGraph.ReversedClone(), false, secondLayers, startOfVirtNodes, balanceVirtAndOrigNodes,
                                               hasCrossWeights, settings);

                revOrdering.Run();

                if (revOrdering.measure < measure)
                {
                    for (int j = 0; j < nOfLayers; j++)
                    {
                        secondLayers.Layers[j].CopyTo(layerArrays.Layers[nOfLayers - 1 - j], 0);
                    }

                    layerArrays.UpdateXFromLayers();
                }
            }
#endif
        }