Beispiel #1
0
        static void ProcessSugiamaLayout(GeometryGraph geometryGraph, SugiyamaLayoutSettings sugiyamaLayoutSettings, CancelToken cancelToken)
        {
            PlaneTransformation originalTransform;
            var transformIsNotIdentity = HandleTransformIsNotIdentity(geometryGraph, sugiyamaLayoutSettings, out originalTransform);

            if (geometryGraph.RootCluster.Clusters.Any())
            {
                PrepareGraphForInitialLayoutByCluster(geometryGraph, sugiyamaLayoutSettings);
                var initialBc = new InitialLayoutByCluster(geometryGraph, a => sugiyamaLayoutSettings);
                initialBc.Run(cancelToken);
                //route the rest of the edges, those between the clusters
                RouteAndLabelEdges(geometryGraph, sugiyamaLayoutSettings,
                                   geometryGraph.Edges.Where(e => e.Curve == null).ToArray());
            }
            else
            {
                geometryGraph.AlgorithmData = SugiyamaLayoutSettings.CalculateLayout(geometryGraph,
                                                                                     sugiyamaLayoutSettings, cancelToken);
            }

            if (transformIsNotIdentity)
            {
                sugiyamaLayoutSettings.Transformation = originalTransform;
            }

            PostRunTransform(geometryGraph, sugiyamaLayoutSettings);
        }
Beispiel #2
0
        public void DenseClusteringNoEdges()
        {
            GeometryGraph graph = new GeometryGraph();
            const double Scale = 100;
            const double Margin = 5;
            for (int i = 0; i < 9; ++i)
            {
                graph.Nodes.Add(new Node(CurveFactory.CreateRectangle(Scale, Scale, new Point())));
            }
            Cluster innerCluster = CreateCluster(graph.Nodes.Take(2), Margin);
            Cluster outerCluster = CreateCluster(graph.Nodes.Take(4).Except(innerCluster.Nodes), Margin);
            outerCluster.AddChild(innerCluster);
            graph.RootCluster = new Cluster(graph.Nodes.Except(graph.Nodes.Take(4)));
            graph.RootCluster.AddChild(outerCluster);
            var initialLayout = new InitialLayoutByCluster(
                graph, new FastIncrementalLayoutSettings { NodeSeparation = Margin, ClusterMargin = Margin / 2, PackingAspectRatio = 1 });
            initialLayout.Run();

            EnableDebugViewer();
            ShowGraphInDebugViewer(graph);

            Assert.IsTrue(
                ApproximateComparer.Close(graph.BoundingBox.LeftBottom, new Point()), "Graph origin is not 0,0");
            Assert.AreEqual(340, graph.BoundingBox.Width, 0.1, "Width is incorrect");
            Assert.AreEqual(340, graph.BoundingBox.Height, 0.1, "Height is incorrect");

        }
Beispiel #3
0
        void LayoutOneComponent(GeometryGraph component)
        {
            PrepareGraphForLayout(component);
            if (component.RootCluster.Clusters.Any())
            {
                var layoutSettings = new SugiyamaLayoutSettings {
                    FallbackLayoutSettings =
                        new FastIncrementalLayoutSettings {
                        AvoidOverlaps = true
                    },
                    NodeSeparation      = lgLayoutSettings.NodeSeparation,
                    LayerSeparation     = lgLayoutSettings.NodeSeparation,
                    EdgeRoutingSettings = lgLayoutSettings.EdgeRoutingSettings,
                    LayeringOnly        = true
                };
                var initialBc = new InitialLayoutByCluster(component, a => layoutSettings);
                initialBc.Run();
            }
            else
            {
                LayoutHelpers.CalculateLayout(component, GetMdsLayoutSettings(), cancelToken);
            }

            var box = component.BoundingBox;

            box.Pad(lgLayoutSettings.NodeSeparation / 2);
            component.BoundingBox = box;
        }
        static void ProcessSugiamaLayout(GeometryGraph geometryGraph, SugiyamaLayoutSettings sugiyamaLayoutSettings, CancelToken cancelToken)
        {
            PlaneTransformation originalTransform;
            var transformIsNotIdentity = HandleTransformIsNotIdentity(geometryGraph, sugiyamaLayoutSettings, out originalTransform);

            if (geometryGraph.RootCluster.Clusters.Any())
            {
                PrepareGraphForInitialLayoutByCluster(geometryGraph, sugiyamaLayoutSettings);
                var initialBc =
                    new InitialLayoutByCluster(
                        geometryGraph,
                        //use different settings per each Cluster if available
                        c => sugiyamaLayoutSettings.ClusterSettings.ContainsKey(c.UserData)
                                 ? sugiyamaLayoutSettings.ClusterSettings[c.UserData]
                                 : sugiyamaLayoutSettings);
                initialBc.Run(cancelToken);
                //route the rest of the edges, those between the clusters
                var edgesToRoute = sugiyamaLayoutSettings.EdgeRoutingSettings.EdgeRoutingMode == EdgeRoutingMode.SplineBundling ? geometryGraph.Edges.ToArray() : geometryGraph.Edges.Where(e => e.Curve == null).ToArray();
                RouteAndLabelEdges(geometryGraph, sugiyamaLayoutSettings, edgesToRoute, 0, cancelToken);
            }
            else
            {
                geometryGraph.AlgorithmData = SugiyamaLayoutSettings.CalculateLayout(geometryGraph,
                                                                                     sugiyamaLayoutSettings, cancelToken);
            }

            if (transformIsNotIdentity)
            {
                sugiyamaLayoutSettings.Transformation = originalTransform;
            }

            PostRunTransform(geometryGraph, sugiyamaLayoutSettings);
        }
Beispiel #5
0
        public void LayeredLayoutOrientationByCluster()
        {
            var clusteredGraph = CreateClusteredGraph(padding: 1);

            foreach (var e in clusteredGraph.Edges)
            {
                e.Labels.Add(new Label(40, 10, e));
            }
            var defaultSettings = new SugiyamaLayoutSettings {
                NodeSeparation = 5, PackingAspectRatio = 1.3, LayerSeparation = 5
            };
            var settings = new Dictionary <Cluster, LayoutAlgorithmSettings>();

            foreach (var c in clusteredGraph.RootCluster.Clusters)
            {
                var localSettings = (SugiyamaLayoutSettings)defaultSettings.Clone();
                localSettings.Transformation = PlaneTransformation.Rotation(Math.PI / 2);
                settings[c] = localSettings;
            }
            var layout = new InitialLayoutByCluster(clusteredGraph, c => settings.ContainsKey(c) ? settings[c] : defaultSettings);

            double progress = 0.0;

            EnableDebugViewer();

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

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

            double aspectRatio = clusteredGraph.BoundingBox.Width / clusteredGraph.BoundingBox.Height;

            //Assert.AreEqual(1.0, progress, "Progress was never reported as 100%.  Last update was at " + progress + "%");
            //var router = new SplineRouter(clusteredGraph, settings.Padding, settings.Padding/2.1, Math.PI/6);
            //router.Run();
            ShowGraphInDebugViewer(clusteredGraph);

            // lots of components in this graph, it gets pretty close to the ideal aspect ratio
            Assert.AreEqual(defaultSettings.PackingAspectRatio, aspectRatio, 0.2, "Difference between actual and desired aspect ratios too large");

            foreach (var e in clusteredGraph.Edges)
            {
                if (e.Source.ClusterParents.Contains(clusteredGraph.RootCluster) || e.Target.ClusterParents.Contains(clusteredGraph.RootCluster))
                {
                    Assert.IsTrue(e.Source.Center.Y > e.Target.Center.Y, "Top level edges should be vertical");
                }
                else
                {
                    Assert.IsTrue(e.Source.Center.X < e.Target.Center.X, "Nested edges should be horizontal");
                }
            }
        }
Beispiel #6
0
        public void TreeGraphMdsLayout()
        {
            GeometryGraph treeGraph = GraphGenerator.GenerateTree(20);

            treeGraph.RootCluster = new Cluster(treeGraph.Nodes);
            var settings = new MdsLayoutSettings {
                ScaleX = 1, ScaleY = 1, RemoveOverlaps = true, PackingAspectRatio = 1.4
            };

            settings.EdgeRoutingSettings = new EdgeRoutingSettings {
                EdgeRoutingMode = EdgeRoutingMode.Spline, ConeAngle = Math.PI / 6, Padding = settings.NodeSeparation / 2.1
            };
            foreach (var v in treeGraph.Nodes)
            {
                v.BoundingBox = new Rectangle(0, 0, new Point(30, 30));
            }
            var layout = new InitialLayoutByCluster(treeGraph, settings);

            double progress = 0.0;

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

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

            EnableDebugViewer();
            ShowGraphInDebugViewer(treeGraph);

            const double EdgeLengthDelta = 0.5;

            foreach (var e in treeGraph.Edges)
            {
                Assert.IsNotNull(e.Curve, "Edge curves not populated");
                if (e.Source != e.Target)
                {
                    double actualLength       = (e.Source.Center - e.Target.Center).Length;
                    double actualDesiredRatio = e.Length / actualLength;
                    Assert.AreEqual(1, actualDesiredRatio, EdgeLengthDelta, "Edge length is not correct");
                }
            }

            double aspectRatio = treeGraph.BoundingBox.Width / treeGraph.BoundingBox.Height;

            Assert.AreEqual(settings.PackingAspectRatio, aspectRatio, 1.4, "Aspect ratio too far from desired");

            Assert.AreEqual(1.0, progress, "Progress was never reported as 100%.  Last update was at " + progress + "%");
        }
Beispiel #7
0
        public void GraphModelGroupedForceDirectedSplineTest()
        {
            LayoutAlgorithmSettings settings;
            var graph = LoadGraph("GraphModelGrouped.msagl.geom", out settings);

            settings = new FastIncrementalLayoutSettings {
                NodeSeparation = 5, PackingAspectRatio = 1.2, AvoidOverlaps = true
            };
            settings.EdgeRoutingSettings.EdgeRoutingMode = EdgeRoutingMode.Spline;
            settings.EdgeRoutingSettings.Padding         = 2;
            var layout = new InitialLayoutByCluster(graph, settings);

            foreach (var c in graph.RootCluster.AllClustersDepthFirst().Where(c => c != graph.RootCluster))
            {
                c.RectangularBoundary = new RectangularClusterBoundary {
                    LeftMargin = 5, RightMargin = 5, BottomMargin = 5, TopMargin = 5
                };
                c.BoundaryCurve = CurveFactory.CreateRectangle(30, 30, new Point(15, 15));
            }

            double progress = 0.0;

            EnableDebugViewer();

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

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

            // Ignore this assertion due to bug: 688960 - One MSAGL unit test is failing due to Parallel Linq which affects the Progress accounting.
            //Assert.AreEqual(1.0, progress, "Progress was never reported as 100%.  Last update was at " + progress + "%");

            ShowGraphInDebugViewer(graph);

            foreach (var e in graph.Edges)
            {
                Assert.IsNotNull(e.Curve, "Edge was not routed");
            }
        }
Beispiel #8
0
        public void GraphModelGroupedLayeredTest()
        {
            LayoutAlgorithmSettings settings;
            var graph = LoadGraph("GraphModelGrouped.msagl.geom", out settings);

            foreach (var e in graph.Edges)
            {
                e.Labels.Add(new Label(40, 10, e));
            }
            settings = new SugiyamaLayoutSettings {
                NodeSeparation = 5, PackingAspectRatio = 1.2, LayerSeparation = 5
            };
            var layout = new InitialLayoutByCluster(graph, settings);

            foreach (var c in graph.RootCluster.AllClustersDepthFirst().Where(c => c != graph.RootCluster))
            {
                c.RectangularBoundary = new RectangularClusterBoundary {
                    LeftMargin = 5, RightMargin = 5, BottomMargin = 5, TopMargin = 5
                };
                c.BoundaryCurve = CurveFactory.CreateRectangle(30, 30, new Point(15, 15));
            }

            double progress = 0.0;

            EnableDebugViewer();

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

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

            Assert.AreEqual(1.0, progress, "Progress was never reported as 100%.  Last update was at " + progress + "%");
            ShowGraphInDebugViewer(graph);

            foreach (var e in graph.Edges)
            {
                Assert.IsNotNull(e.Curve, "Edge was not routed");
            }
        }
Beispiel #9
0
        public void GraphModelGroupedForceDirectedRectilinearTest()
        {
            LayoutAlgorithmSettings settings;
            var graph = LoadGraph("GraphModelGrouped.msagl.geom", out settings);

            settings = new FastIncrementalLayoutSettings {
                NodeSeparation = 5, PackingAspectRatio = 1.2, AvoidOverlaps = true, GravityConstant = 0.5
            };
            settings.EdgeRoutingSettings.EdgeRoutingMode = EdgeRoutingMode.Rectilinear;
            settings.EdgeRoutingSettings.Padding         = 2;
            settings.EdgeRoutingSettings.CornerRadius    = 2;
            var layout = new InitialLayoutByCluster(graph, settings);

            foreach (var c in graph.RootCluster.AllClustersDepthFirst().Where(c => c != graph.RootCluster))
            {
                c.RectangularBoundary = new RectangularClusterBoundary {
                    LeftMargin = 5, RightMargin = 5, BottomMargin = 5, TopMargin = 5
                };
                c.BoundaryCurve = CurveFactory.CreateRectangle(30, 30, new Point(15, 15));
            }

            double progress = 0.0;

            EnableDebugViewer();

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

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

            Assert.IsTrue(1.0 <= progress, "Progress was never reported as 100%.  Last update was at " + progress + "%");
            ShowGraphInDebugViewer(graph);

            foreach (var e in graph.Edges)
            {
                Assert.IsNotNull(e.Curve, "Edge was not routed");
            }
        }
Beispiel #10
0
 static void Layout(GeometryGraph graph, Random rnd)
 {
     if (rnd.Next() % 5 < 3)
     {
         var settings = new SugiyamaLayoutSettings();
         var layout   = new InitialLayoutByCluster(graph, settings)
         {
             RunInParallel = false
         };
         layout.Run();
     }
     else
     {
         var settings = new FastIncrementalLayoutSettings {
             AvoidOverlaps = true
         };
         var layout = new InitialLayoutByCluster(graph, settings);
         layout.Run();
     }
 }
Beispiel #11
0
        public void CalculateLayout_CorrectPacking()
        {
            var clusteredGraph = CreateClusteredGraph(padding: 1);
            var settings       = new SugiyamaLayoutSettings {
                NodeSeparation = 5, PackingAspectRatio = 1.2, LayerSeparation = 5
            };
            var layout = new InitialLayoutByCluster(clusteredGraph, settings);

            double progress = 0.0;

            EnableDebugViewer();

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

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

            double aspectRatio = clusteredGraph.BoundingBox.Width / clusteredGraph.BoundingBox.Height;

            //Assert.AreEqual(1.0, progress, "Progress was never reported as 100%.  Last update was at " + progress + "%");
            //var router = new SplineRouter(clusteredGraph, settings.Padding, settings.Padding/2.1, Math.PI/6);
            //router.Run();
            ShowGraphInDebugViewer(clusteredGraph);

            foreach (var e in clusteredGraph.Edges)
            {
                Assert.IsNotNull(e.Curve, "Edge was not routed");
            }
            // skinny aspect ratio specified above caused lots of vertical stacking in groups which actually leads
            // to a final aspect ratio close to 1
            Assert.AreEqual(settings.PackingAspectRatio, aspectRatio, 0.2, "Difference between actual and desired aspect ratios too large");
        }
        public void RoutingWithThreeGroups()
        {
            var graph = LoadGraph("abstract.msagl.geom");
            var root  = graph.RootCluster;
            var a     = new Cluster {
                UserData = "a"
            };

            foreach (string id in new[] { "17", "39", "13", "19", "28", "12" })
            {
                a.AddChild(graph.FindNodeByUserData(id));
            }

            var b = new Cluster {
                UserData = "b"
            };

            b.AddChild(a);
            b.AddChild(graph.FindNodeByUserData("18"));
            root.AddChild(b);

            var c = new Cluster {
                UserData = "c"
            };

            foreach (string id in new[] { "30", "5", "6", "7", "8" })
            {
                c.AddChild(graph.FindNodeByUserData(id));
            }
            root.AddChild(c);

            var clusterNodes = new Set <Node>(root.AllClustersDepthFirst().SelectMany(cl => cl.Nodes));

            foreach (var node in graph.Nodes.Where(n => clusterNodes.Contains(n) == false))
            {
                root.AddChild(node);
            }

            FixClusterBoundariesWithNoRectBoundaries(root, 5);
            var defaultSettings = new FastIncrementalLayoutSettings();
            var rootSettings    = new FastIncrementalLayoutSettings()
            {
                AvoidOverlaps = true
            };

            var initialLayout = new InitialLayoutByCluster(graph, new[] { graph.RootCluster }, cl => cl == root ? rootSettings : defaultSettings);

            initialLayout.Run();

            const double Padding = 5;

            SplineRouter splineRouter = new SplineRouter(graph, Padding / 3, Padding, Math.PI / 6);

            splineRouter.Run();
#if TEST_MSAGL
            if (!DontShowTheDebugViewer())
            {
                graph.UpdateBoundingBox();
                DisplayGeometryGraph.ShowGraph(graph);
            }
#endif
        }