internal ConstrainedOrdering(
            GeometryGraph geomGraph,
            BasicGraph<Node, IntEdge> basicIntGraph,
            int[] layering,
            Dictionary<Node, int> nodeIdToIndex,
            Database database,
            SugiyamaLayoutSettings settings) {

            this.settings = settings;
            horizontalConstraints = settings.HorizontalConstraints;

            horizontalConstraints.PrepareForOrdering(nodeIdToIndex, layering);

            geometryGraph = geomGraph;
            this.database = database;
            intGraph = basicIntGraph;
            initialLayering = layering;
            //this has to be changed only to insert layers that are needed
            if (NeedToInsertLayers(layering)) {
                for (int i = 0; i < layering.Length; i++)
                    layering[i] *= 2;
                LayersAreDoubled = true;
                numberOfLayers = -1;
            }

            PrepareProperLayeredGraphAndFillLayerInfos();

            adjSwapper = new AdjacentSwapsWithConstraints(
                LayerArrays,
                HasCrossWeights(),
                ProperLayeredGraph,
                layerInfos);
        }
 internal PhyloTreeLayoutCalclulation(PhyloTree phyloTreeP, SugiyamaLayoutSettings settings, BasicGraph<Node, IntEdge> intGraphP, Database dataBase) {
     this.dataBase = dataBase;
     this.tree = phyloTreeP;
     this.LayoutSettings = settings;
     this.intGraph = intGraphP;
     originalNodeToGridLayerIndices = new int[intGraph.Nodes.Count];
 }
 /// <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;
 }
 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();

        }
 /// <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, IntEdge> intGraph
     ) {
     this.settings = settings;
     OriginalGraph = originalGraph;
     Database = dbP;
     ProperLayeredGraph = properLayeredGraph;
     LayerArrays = yLayerArrays;
     IntGraph = intGraph;
 }
 /// <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;
 }
        static double WidthOfSelfEdge(Database database, int i, ref double rightAnchor, ref double topAnchor,
                                      ref double bottomAnchor, SugiyamaLayoutSettings settings) {
            double delta = 0;
            List<IntEdge> multiedges = database.GetMultiedge(i, i);
            //it could be a multiple self edge
            if (multiedges.Count > 0) {
                foreach (IntEdge e in multiedges)
                    if (e.Edge.Label != null) {
                        rightAnchor += e.Edge.Label.Width;
                        if (topAnchor < e.Edge.Label.Height/2.0)
                            topAnchor = bottomAnchor = e.Edge.Label.Height/2.0f;
                    }

                delta += (settings.NodeSeparation + settings.MinNodeWidth)*multiedges.Count;
            }
            return delta;
        }
 void CreateDatabaseAndRegisterIntEdgesInMultiEdges() {
     Database = new Database();
     foreach (IntEdge e in IntGraph.Edges)
         database.RegisterOriginalEdgeInMultiedges(e);
 }
        static void CalcAnchorsForOriginalNode(int i, BasicGraph<Node, IntEdge> intGraph, Anchor[] anchors,
                                               Database database, SugiyamaLayoutSettings settings) {
            double leftAnchor = 0;
            double rightAnchor = leftAnchor;
            double topAnchor = 0;
            double bottomAnchor = topAnchor;

            //that's what we would have without the label and multiedges 

            if (intGraph.Nodes != null) {
                Node node = intGraph.Nodes[i];
                ExtendStandardAnchors(ref leftAnchor, ref rightAnchor, ref topAnchor, ref bottomAnchor, node, settings);
            }

            RightAnchorMultiSelfEdges(i, ref rightAnchor, ref topAnchor, ref bottomAnchor, database, settings);

            double hw = settings.MinNodeWidth/2;
            if (leftAnchor < hw)
                leftAnchor = hw;
            if (rightAnchor < hw)
                rightAnchor = hw;
            double hh = settings.MinNodeHeight/2;

            if (topAnchor < hh)
                topAnchor = hh;
            if (bottomAnchor < hh)
                bottomAnchor = hh;

            anchors[i] = new Anchor(leftAnchor, rightAnchor, topAnchor, bottomAnchor, intGraph.Nodes[i],
                                    settings.LabelCornersPreserveCoefficient) {Padding = intGraph.Nodes[i].Padding};
#if TEST_MSAGL
            anchors[i].UserData = intGraph.Nodes[i].UserData;
#endif
        }
        static void RightAnchorMultiSelfEdges(int i, ref double rightAnchor, ref double topAnchor,
                                              ref double bottomAnchor, Database database,
                                              SugiyamaLayoutSettings settings) {
            double delta = WidthOfSelfEdge(database, i, ref rightAnchor, ref topAnchor, ref bottomAnchor, settings);

            rightAnchor += delta;
        }
 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;
 }
 static double SetFlatEdgesLabelsHeightAndPositionts(IntPair pair, double ymax, double dy, Database database) {
     double height = 0;
     List<IntEdge> list = database.GetMultiedge(pair);
     foreach (IntEdge edge in list) {
         height += dy;
         Label label = edge.Edge.Label;
         if (label != null) {
             label.Center = new Point(label.Center.X, ymax + height + label.Height/2);
             height += label.Height;
         }
     }
     return height;
 }
        /// <summary>
        /// Simpler constructor which initializes the internal graph representation automatically
        /// </summary>
        /// <param name="originalGraph"></param>
        /// <param name="settings"></param>
        internal LayeredLayoutEngine(GeometryGraph originalGraph, SugiyamaLayoutSettings settings) {
            if (originalGraph != null) {
                //enumerate the nodes - maps node indices to strings 
                nodeIdToIndex = new Dictionary<Node, int>();

                IList<Node> nodes = originalGraph.Nodes;

                int index = 0;
                foreach (Node n in nodes) {
                    nodeIdToIndex[n] = index;
                    index++;
                }

                var edges = originalGraph.Edges;

                var intEdges = new IntEdge[edges.Count];
                int i = 0;
                foreach(var edge in edges){
                
                    if (edge.Source == null || edge.Target == null)
                        throw new InvalidOperationException(); //"creating an edge with null source or target");

                    var intEdge = new IntEdge(nodeIdToIndex[edge.Source], nodeIdToIndex[edge.Target], edge);

                    intEdges[i] = intEdge;
                    i++;
                }

                IntGraph = new BasicGraph<Node, IntEdge>(intEdges, originalGraph.Nodes.Count) {Nodes = nodes};
                this.originalGraph = originalGraph;
                sugiyamaSettings = settings;
                Database = new Database();
                foreach (IntEdge e in IntGraph.Edges)
                    database.RegisterOriginalEdgeInMultiedges(e);

                CycleRemoval();
            }
        }
        /// <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);
        }
        internal static void CalculateAnchorSizes(Database database, out Anchor[] anchors,
                                                  ProperLayeredGraph properLayeredGraph, GeometryGraph originalGraph,
                                                  BasicGraph<Node, IntEdge> intGraph, SugiyamaLayoutSettings settings) {
            database.Anchors = anchors = new Anchor[properLayeredGraph.NodeCount];

            for (int i = 0; i < anchors.Length; i++)
                anchors[i] = new Anchor(settings.LabelCornersPreserveCoefficient);

            //go over the old vertices
            for (int i = 0; i < originalGraph.Nodes.Count; i++)
                CalcAnchorsForOriginalNode(i, intGraph, anchors, database, settings);

            //go over virtual vertices
            foreach (IntEdge intEdge in database.AllIntEdges)
                if (intEdge.LayerEdges != null) {
                    foreach (LayerEdge layerEdge in intEdge.LayerEdges) {
                        int v = layerEdge.Target;
                        if (v != intEdge.Target) {
                            Anchor anchor = anchors[v];
                            if (!database.MultipleMiddles.Contains(v)) {
                                anchor.LeftAnchor = anchor.RightAnchor = VirtualNodeWidth/2.0f;
                                anchor.TopAnchor = anchor.BottomAnchor = VirtualNodeHeight(settings)/2.0f;
                            } else {
                                anchor.LeftAnchor = anchor.RightAnchor = VirtualNodeWidth*4;
                                anchor.TopAnchor = anchor.BottomAnchor = VirtualNodeHeight(settings)/2.0f;
                            }
                        }
                    }
                    //fix label vertices      
                    if (intEdge.HasLabel) {
                        int lj = intEdge.LayerEdges[intEdge.LayerEdges.Count/2].Source;
                        Anchor a = anchors[lj];
                        double w = intEdge.LabelWidth, h = intEdge.LabelHeight;
                        a.RightAnchor = w;
                        a.LeftAnchor = VirtualNodeWidth*8;

                        if (a.TopAnchor < h/2.0)
                            a.TopAnchor = a.BottomAnchor = h/2.0;

                        a.LabelToTheRightOfAnchorCenter = true;
                    }
                }
        }
        /// <summary>
        /// constructor
        /// </summary>
        internal LayeredLayoutEngine(GeometryGraph originalGraph, BasicGraph<Node, IntEdge> graph,
                                     Dictionary<Node, int> nodeIdToIndex, SugiyamaLayoutSettings settings) {
            if (originalGraph != null) {
                this.originalGraph = originalGraph;
                sugiyamaSettings = settings;
                IntGraph = graph;
                Database = new Database();
                this.nodeIdToIndex = nodeIdToIndex;
                foreach (IntEdge e in graph.Edges)
                    database.RegisterOriginalEdgeInMultiedges(e);
#if REPORTING
                if (sugiyamaSettings.Reporting && SugiyamaLayoutLogger == null)
                    SugiyamaLayoutLogger = new SugiyamaLayoutLogger();
#endif
                CycleRemoval();
            }
        }
        /// <summary>
        /// displays the database
        /// </summary>
        /// <param name="db"></param>
        /// <param name="curves"></param>
        public static void ShowDataBase(Database db, params ICurve[] curves){
            var g = new Graph("");
            AllocateDebugCurves(g);

            var graphBox = new Rectangle(db.Anchors[0].LeftTop);

            var cl = new List<ICurve>(curves);

            foreach (Anchor a in db.Anchors){
                graphBox.Add(a.LeftTop);
                graphBox.Add(a.RightBottom);
                cl.Add(a.PolygonalBoundary);
            }

            AddCurvesToGraph(cl, g);

            Point del = (graphBox.LeftBottom - graphBox.RightTop)/10;
            graphBox.Add(graphBox.LeftBottom + del);
            graphBox.Add(graphBox.RightTop - del);
            var gg = new GeometryGraph{BoundingBox = graphBox};
            g.DataBase = db;
            g.GeometryGraph = gg;
            
            DisplayGraph(g, new Form());
            db.nodesToShow = null;
        }
        /// <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);
        }
 ///// <summary>
 ///// mark the vertex as one representing a label
 ///// or a middle of a multi edge
 ///// </summary>
 ///// <param name="db"></param>
 ///// <param name="bucket"></param>
 ///// <param name="parent"></param>
 ///// <param name="i"></param>
 internal static void RegisterDontStepOnVertex(Database db, IntEdge parent) {
     if (db.Multiedges[new IntPair(parent.Source, parent.Target)].Count > 1) {
         LayerEdge e = parent.LayerEdges[parent.LayerEdges.Count / 2];
         db.MultipleMiddles.Insert(e.Source);
     }
 }