/// <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>
 /// 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>
        ///// 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;
        }