public void CalculateLayout_ReportsAllProgress()
        {
            GeometryGraph treeGraph = GraphGenerator.GenerateTree(20);
            var settings = new FastIncrementalLayoutSettings();
            InitialLayout layout = new InitialLayout(treeGraph, settings);
            
            double progress = 0.0;

            EventHandler<ProgressChangedEventArgs> handler = (s, e) => progress = e.RatioComplete;

            try
            {
                layout.ProgressChanged += handler;
                layout.Run();
            }
            finally
            {
                layout.ProgressChanged -= handler;
            }

            Assert.AreEqual(0, treeGraph.BoundingBox.Bottom);
            Assert.AreEqual(0, treeGraph.BoundingBox.Left);

            foreach (var v in treeGraph.Nodes)
            {
                Assert.IsTrue(treeGraph.BoundingBox.Contains(v.BoundingBox));
            }

            Assert.AreEqual(1.0, progress, "Progress was never reported as 100%.  Last update was at " + progress + "%");
        }
        /// <summary>
        /// Calculates the graph layout
        /// </summary>
        /// <exception cref="CancelException">Thrown when the layout is canceled.</exception>
#else
        /// <summary>
        /// Calculates the graph layout
        /// </summary>
        /// <exception cref="System.OperationCanceledException">Thrown when the layout is canceled.</exception>
#endif
        public static void CalculateLayout(GeometryGraph geometryGraph, LayoutAlgorithmSettings settings, CancelToken cancelToken) {
            Console.WriteLine("starting CalculateLayout");
            if (settings is RankingLayoutSettings) {
                var rankingLayoutSettings = settings as RankingLayoutSettings;
                var rankingLayout = new RankingLayout(rankingLayoutSettings, geometryGraph);
                rankingLayout.Run(cancelToken);
                RouteAndLabelEdges(geometryGraph, settings, geometryGraph.Edges);
            }
            else if (settings is MdsLayoutSettings) {
                var mdsLayoutSettings = settings as MdsLayoutSettings;
                var mdsLayout = new MdsGraphLayout(mdsLayoutSettings, geometryGraph);
                mdsLayout.Run(cancelToken);
                if (settings.EdgeRoutingSettings.EdgeRoutingMode != EdgeRoutingMode.None)
                    RouteAndLabelEdges(geometryGraph, settings, geometryGraph.Edges);
            }
            else if (settings is FastIncrementalLayoutSettings) {
                var incrementalSettings = settings as FastIncrementalLayoutSettings;
                incrementalSettings.AvoidOverlaps = true;
                var initialLayout = new InitialLayout(geometryGraph, incrementalSettings);
                initialLayout.Run(cancelToken);
                if (settings.EdgeRoutingSettings.EdgeRoutingMode != EdgeRoutingMode.None)
                    RouteAndLabelEdges(geometryGraph, settings, geometryGraph.Edges);
                //incrementalSettings.IncrementalRun(geometryGraph);
            }
            else {
                var sugiyamaLayoutSettings = settings as SugiyamaLayoutSettings;
                if (sugiyamaLayoutSettings != null)
                    ProcessSugiamaLayout(geometryGraph, sugiyamaLayoutSettings, cancelToken);
                else {
                    Debug.Assert(settings is LgLayoutSettings);
                    LayoutLargeGraphWithLayers(geometryGraph, settings, cancelToken);
                }
            }
        }
 void ForceDirectedLayout(FastIncrementalLayoutSettings settings, GeometryGraph component) {
     LayoutAlgorithmHelpers.ComputeDesiredEdgeLengths(settings.IdealEdgeLength, component);
     var layout = new InitialLayout(component, settings) { SingleComponent = true };
     layout.Run(this.CancelToken);
     InitialLayoutHelpers.RouteEdges(component, settings, this.CancelToken);
     InitialLayoutHelpers.PlaceLabels(component, this.CancelToken);
     InitialLayoutHelpers.FixBoundingBox(component, settings);
 }
 void ForceDirectedLayout(FastIncrementalLayoutSettings settings, GeometryGraph component) {
     LayoutAlgorithmHelpers.ComputeDesiredEdgeLengths(settings.IdealEdgeLength, component);
     var layout = new InitialLayout(component, settings) {SingleComponent = true};
     layout.Run(this.CancelToken);
     InitialLayoutHelpers.RouteEdges(component, settings, this.CancelToken);
     InitialLayoutHelpers.PlaceLabels(component, this.CancelToken);
     InitialLayoutHelpers.FixBoundingBox(component, settings);
 }
        static void TestFD() {
            GeometryGraph graph = CreateGeometryGraphForFD();
            //LayoutAlgorithmSettings.ShowGraph(graph);
            var settings = new FastIncrementalLayoutSettings {
                                                                 AvoidOverlaps = true,
                                                                 ApplyForces = false,
                                                                 RungeKuttaIntegration = true
                                                             };

            var ir = new InitialLayout(graph, settings);
            ir.Run();
            RouteEdges(graph, settings);
            //LayoutAlgorithmSettings.ShowGraph(graph);
          //  AddNodeFd(graph);

            var n = new Node(CurveFactory.CreateDiamond(200, 200, new Point(350, 230)));
            var e = new Edge(n, graph.Nodes[42]);
            graph.Edges.Add(e);
            e = new Edge(n, graph.Nodes[6]);
            graph.Edges.Add(e);
            e = new Edge(n, graph.Nodes[12]);
            graph.Edges.Add(e);

            graph.Nodes.Add(n);
            graph.RootCluster.AddChild(n);
            settings.algorithm=new FastIncrementalLayout(graph, settings, settings.MaxConstraintLevel, f=>settings);
            settings.Unconverge();
            settings.CreateLock(n, new Rectangle(200, 400, 500, 100));
            do {
                settings.IncrementalRun(graph);
            } while (!settings.Converged);

            RouteEdges(graph, settings);
#if DEBUG
            LayoutAlgorithmSettings.ShowGraph(graph);
#endif
            Environment.Exit(0);
        }
 public void SimpleClusterGraphRectilinear()
 {
     var g = new GeometryGraph();
     var node0 = new Node(CurveFactory.CreateRectangle(10, 10, new Point()), 0);
     var node1 = new Node(CurveFactory.CreateRectangle(10, 10, new Point()), 1);
     var cluster = new Cluster(new[] { node1 });
     cluster.UserData = 2; 
     cluster.BoundaryCurve = CurveFactory.CreateRectangle(10, 10, new Point());
     var edge = new Edge(node0, node1) { Length = 100 };
     g.Nodes.Add(node0);
     g.Nodes.Add(node1);
     g.Edges.Add(edge);
     var cluster2 = new Cluster(new[] { node0 }, new[] { cluster });
     cluster2.UserData = 3;
     cluster2.BoundaryCurve = CurveFactory.CreateRectangle(10, 10, new Point());
     g.RootCluster = cluster2;
     InitialLayout initialLayout = new InitialLayout(g, new FastIncrementalLayoutSettings() { AvoidOverlaps = true });
     initialLayout.Run();
     
     RectilinearEdgeRouter router = new RectilinearEdgeRouter(g, 1, 1, false);
     router.Run();
     EnableDebugViewer();
     ShowGraphInDebugViewer(g);
     var bb0 = node0.BoundingBox;
     bb0.Pad(1);
     Assert.IsTrue(bb0.Contains(edge.EdgeGeometry.Curve.Start));
     var bb1 = node1.BoundingBox;
     bb1.Pad(1);
     Assert.IsTrue(bb1.Contains(edge.EdgeGeometry.Curve.End));
 }
        private void LayoutAndValidate(bool defaultSticky, double separation, double minSeparation, double maxSeparation)
        {
            InitialLayout initialLayout = new InitialLayout(graph, settings);
            initialLayout.Run();

            // Apply incremental layout to satisfy constraints.
            settings.IncrementalRun(graph);

            //ShowGraphInDebugViewer(graph);

            // stick constraints have a little slack in their projection
            const double StickDelta = 1;
            double distance = (constrainedNodes[0].Center - constrainedNodes[1].Center).Length;
            if (defaultSticky)
            {
                Assert.AreEqual(separation, distance, StickDelta, string.Format("Distance {3} between node {0} to node {1} not approximately equal to stickConstraint separation {2}", constrainedNodes[0].UserData, constrainedNodes[1].UserData, separation, distance));
            }
            else
            {
                Assert.IsTrue(distance >= minSeparation && distance <= maxSeparation, string.Format("Distance {4} between node {0} to node {1} not between min {2} and max {3}", constrainedNodes[0].UserData, constrainedNodes[1].UserData, minSeparation, maxSeparation, distance));
            }
        }
        private static void LayoutAndValidate(GeometryGraph graph, double separationRatio, ISet<Node> validationExcludedNodes)
        {
            const double downwardEdgeSeparation = 70;
            FastIncrementalLayoutSettings settings = new FastIncrementalLayoutSettings();
            settings.IdealEdgeLength = new IdealEdgeLengthSettings
            {
                ConstrainedEdgeSeparation = downwardEdgeSeparation,
                EdgeDirectionConstraints = Directions.South
            };
            settings.AvoidOverlaps = true;            

            InitialLayout initialLayout = new InitialLayout(graph, settings);
            initialLayout.Run();

            ShowGraphInDebugViewer(graph);

            ValidateDownwardEdgeConstraints(graph, downwardEdgeSeparation, validationExcludedNodes);
        }