static private int GetSource(int i, IntEdge edge, ref int virtualNode)
        {
            if (i > 0)
            {
                return(virtualNode++);
            }

            return(edge.Source);
        }
        static private int GetTarget(int i, int span, IntEdge edge, int virtualNode)
        {
            if (i < span - 1)
            {
                return(virtualNode);
            }

            return(edge.Target);
        }
 /// <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();
 }
        private void InsertLayerEdgesForEdge(IntEdge edge, int[] layering, ref int virtualNode, List <int>[] layers)
        {
            int span = OriginalNodeLayer(edge.Source) - OriginalNodeLayer(edge.Target);

            edge.LayerEdges = new LayerEdge[span];
            for (int i = 0; i < span; i++)
            {
                edge.LayerEdges[i] = new LayerEdge(GetSource(i, edge, ref virtualNode), GetTarget(i, span, edge, virtualNode), edge.CrossingWeight);
            }

            int l = OriginalNodeLayer(edge.Source) - 1;

            for (int i = 0; i < span; i++)
            {
                int node = edge.LayerEdges[i].Target;
                layering[node] = l;
                layers[l--].Add(node);
            }

            WalkTreeAndInsertLayerEdges(layering, layers, edge.Target, ref virtualNode);
        }
 private IntPair GluedIntPair(IntEdge p) {
     return new IntPair(NodeToRepr(p.Source), NodeToRepr(p.Target));
 }
 private bool EdgeIsFlat(IntEdge ie) {
     return la.Y[ie.Source] == la.Y[ie.Target];
 }
 void DrawSplineBySmothingThePolyline(IntEdge edgePath) {
     var smoothedPolyline = new SmoothedPolylineCalculator(edgePath, Database.Anchors, OriginalGraph, settings,
                                                           LayerArrays,
                                                           ProperLayeredGraph, Database);
     ICurve spline = smoothedPolyline.GetSpline();
     if (edgePath.Reversed) {
         edgePath.Curve = spline.Reverse();
         edgePath.UnderlyingPolyline = smoothedPolyline.Reverse().GetPolyline;
     }
     else {
         edgePath.Curve = spline;
         edgePath.UnderlyingPolyline = smoothedPolyline.GetPolyline;
     }
 }
 internal static int EdgeSpan(int[] layers, IntEdge e) {
     return layers[e.Source] - layers[e.Target];
 }
        void RouteEdgeWithLabel(IntEdge intEdge, Label label) {
            //we allow here for the edge to cross its own label
            Node sourceNode = routing.IntGraph.Nodes[intEdge.Source];
            Node targetNode = routing.IntGraph.Nodes[intEdge.Target];
            var sourcePort = new FloatingPort(sourceNode.BoundaryCurve, sourceNode.Center);
            var targetPort = new FloatingPort(targetNode.BoundaryCurve, targetNode.Center);
            ICurve labelObstacle = labelsToLabelObstacles[label];
            var labelPort = new FloatingPort(labelObstacle, label.Center);
            SmoothedPolyline poly0;
            interactiveEdgeRouter.RouteSplineFromPortToPortWhenTheWholeGraphIsReady(sourcePort, labelPort, true, out poly0);
            SmoothedPolyline poly1;
            interactiveEdgeRouter.RouteSplineFromPortToPortWhenTheWholeGraphIsReady(labelPort, targetPort, true, out poly1);
            Site site = poly1.HeadSite.Next;

            Site lastSite = poly0.LastSite;
            lastSite.Next = site;
            site.Previous = lastSite;
            var eg = intEdge.Edge.EdgeGeometry;
            eg.SetSmoothedPolylineAndCurve(poly0);
            Arrowheads.TrimSplineAndCalculateArrowheads(eg,  intEdge.Edge.Source.BoundaryCurve,
                                                             intEdge.Edge.Target.BoundaryCurve, eg.Curve, false, 
                                                             settings.EdgeRoutingSettings.KeepOriginalSpline);
        }
 void GetXCoordinatesOfVirtualNodesOfTheProperLayeredGraphForSkeletonEdge(IntEdge intEdge, LayerArrays layerArrays) {
     if (intEdge.LayerEdges == null || intEdge.LayerEdges.Count < 2) return;
     var edgeCurve = intEdge.Edge.Curve;
     var layerIndex = layerArrays.Y[intEdge.Source] - 1;//it is the layer of the highest virtual node of the edge
     for (int i = 1; i < intEdge.LayerEdges.Count; i++) {
         var v = intEdge.LayerEdges[i].Source;
         var layerY = layerToRecoveredYCoordinates[layerIndex--];
         var layerLine = new LineSegment(new Point(originalGraph.Left, layerY), new Point(originalGraph.Right, layerY));
         var intersection=Curve.CurveCurveIntersectionOne(edgeCurve, layerLine, false);
        
         skeletonVirtualVerticesToX[v] =intersection.IntersectionPoint.X;
         
     }
 }
        internal void RegisterOriginalEdgeInMultiedges(IntEdge edge) {
            IntPair ip = new IntPair(edge.Source, edge.Target);
            List<IntEdge> o;
            if (multiedges.ContainsKey(ip) == false)
                multiedges[ip] = o = new List<IntEdge>();
            else
                o = multiedges[ip];

            o.Add(edge);
        }
 internal NetworkEdge(IntEdge e)
     : base(e.Source, e.Target) {
     Weight = e.Weight;
     Separation = e.Separation;
 }
        void CreateLayerEdgesUnderIntEdge(IntEdge ie) {
            int source = ie.Source;
            int target = ie.Target;

            int span = LayeredLayoutEngine.EdgeSpan(initialLayering, ie);
            ie.LayerEdges = new LayerEdge[span];
            Debug.Assert(span > 0);
            if (span == 1)
                ie.LayerEdges[0] = new LayerEdge(ie.Source, ie.Target, ie.CrossingWeight);
            else {
                ie.LayerEdges[0] = new LayerEdge(source, numberOfNodesOfProperGraph, ie.CrossingWeight);
                for (int i = 0; i < span - 2; i++)
                    ie.LayerEdges[i + 1] = new LayerEdge(numberOfNodesOfProperGraph++, numberOfNodesOfProperGraph,
                                                         ie.CrossingWeight);
                ie.LayerEdges[span - 1] = new LayerEdge(numberOfNodesOfProperGraph++, target, ie.CrossingWeight);
            }
        }
 static private int GetSource(int i, IntEdge edge, ref int virtualNode) {
     if (i > 0)
         return virtualNode++; 
     
     return edge.Source;
 }
        static private int GetTarget(int i, int span, IntEdge edge, int virtualNode) {
            if (i < span-1)
                return virtualNode;

            return edge.Target;
        }
        private void InsertLayerEdgesForEdge(IntEdge edge, int[] layering, ref int virtualNode, List<int>[] layers) {
            int span = OriginalNodeLayer(edge.Source) - OriginalNodeLayer(edge.Target);
            edge.LayerEdges=new LayerEdge[span];
            for (int i = 0; i < span; i++) 
                edge.LayerEdges[i] = new LayerEdge(GetSource(i, edge, ref virtualNode), GetTarget(i, span, edge, virtualNode), edge.CrossingWeight);
       
            int l = OriginalNodeLayer(edge.Source) - 1;
            for (int i = 0; i < span; i++) {
                int node=edge.LayerEdges[i].Target;
                layering[node] = l;
                layers[l--].Add(node);
            }

            WalkTreeAndInsertLayerEdges(layering, layers, edge.Target, ref virtualNode);

        }
 private int NumberOfVirtualNodesOnEdge(IntEdge edge) {
     return OriginalNodeLayer(edge.Source) - OriginalNodeLayer(edge.Target) - 1;
 }
 void RouteEdgeWithNoLabel(IntEdge intEdge) {
     Node sourceNode = routing.IntGraph.Nodes[intEdge.Source];
     Node targetNode = routing.IntGraph.Nodes[intEdge.Target];
     var sourcePort = new FloatingPort(sourceNode.BoundaryCurve, sourceNode.Center);
     var targetPort = new FloatingPort(targetNode.BoundaryCurve, targetNode.Center);
     var eg = intEdge.Edge.EdgeGeometry;
     SmoothedPolyline sp;
     eg.Curve = interactiveEdgeRouter.RouteSplineFromPortToPortWhenTheWholeGraphIsReady(sourcePort, targetPort, true, out sp);
     Arrowheads.TrimSplineAndCalculateArrowheads(eg,  intEdge.Edge.Source.BoundaryCurve,
                                                      intEdge.Edge.Target.BoundaryCurve, eg.Curve, false, 
                                                      settings.EdgeRoutingSettings.KeepOriginalSpline);
     intEdge.Edge.EdgeGeometry = eg;
 }
 internal IntEdge GluedIntEdge(IntEdge intEdge) {
     int sourceRepr = NodeToRepr(intEdge.Source);
     int targetRepr = NodeToRepr(intEdge.Target);
     IntEdge ie = new IntEdge(sourceRepr, targetRepr);
     ie.Separation = intEdge.Separation;
     ie.Weight = 0;
     ie.Edge = intEdge.Edge;
     return ie;
 }
 ///// <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);
     }
 }
 internal static NodeKind GetNodeKind(int vertexOffset, IntEdge edgePath) {
     return vertexOffset == 0
                ? NodeKind.Top
                : (vertexOffset < edgePath.Count ? NodeKind.Internal : NodeKind.Bottom);
 }
        IntEdge[] CreateIntEdges(GeometryGraph geometryGraph) {
            var edges = geometryGraph.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++;
            }

            return intEdges;
        }
        /// <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();
            }
        }
 private int NumberOfVirtualNodesOnEdge(IntEdge edge)
 {
     return(OriginalNodeLayer(edge.Source) - OriginalNodeLayer(edge.Target) - 1);
 }
 void RouteEdge(IntEdge edge) {
     if (edge.HasLabel)
         RouteEdgeWithLabel(edge, edge.Edge.Label);
     else
         RouteEdgeWithNoLabel(edge);
 }
        private static LayerEdge LastEdge(IntEdge e) {
            return e.LayerEdges[e.LayerEdges.Count - 1];

        }
 private static LayerEdge FirstEdge(IntEdge e) {
     return e.LayerEdges[0];
 }
        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);
                }
        }
 internal static int GetTarget(ref int currentVV, IntEdge e, int i, int span) {
     if (i < span - 1)
         return currentVV;
     return e.Target;
 }
        ///// <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;
        }
 internal static int GetSource(ref int currentVV, IntEdge e, int i) {
     if (i == 0)
         return e.Source;
     return currentVV++;
 }
 static IntEdge CreateUpDownConstrainedIntEdge(IntPair intPair) {
     var intEdge = new IntEdge(intPair.x, intPair.y);
     intEdge.Weight = 0;
     //we do not want the edge weight to contribute in to the sum but just take the constraint into account
     intEdge.Separation = 1;
     return intEdge;
 }
        void CreateSplineForNonSelfEdge(IntEdge es){
            this.ProgressStep();

            if (es.LayerEdges != null)
            {
                DrawSplineBySmothingThePolyline(es);
                if (!es.IsVirtualEdge)
                {
                    es.UpdateEdgeLabelPosition(Database.Anchors);
                    Arrowheads.TrimSplineAndCalculateArrowheads(es.Edge.EdgeGeometry, es.Edge.Source.BoundaryCurve,
                                                                     es.Edge.Target.BoundaryCurve, es.Curve, true, 
                                                                     settings.EdgeRoutingSettings.KeepOriginalSpline);
                }
            }
        }