/// <summary>
        /// Simple unconstrained layout of graph used by multiscale layout
        /// </summary>
        /// <param name="graph"></param>
        /// <param name="edgeLengthMultiplier"></param>
        /// <param name="level">double in range [0,1] indicates how far down the multiscale stack we are
        /// 1 is at the top, 0 at the bottom, controls repulsive force strength and ideal edge length</param>
        private void SimpleLayout(GeometryGraph graph, double level, double edgeLengthMultiplier)
        {
            var settings = new FastIncrementalLayoutSettings
            {
                MaxIterations          = 10,
                MinorIterations        = 3,
                GravityConstant        = 1.0 - level,
                RepulsiveForceConstant =
                    Math.Log(edgeLengthMultiplier * level * 500 + Math.E),
                InitialStepSize = 0.6
            };

            foreach (var e in graph.Edges)
            {
                e.Length *= Math.Log(level * 500 + Math.E);
            }
            settings.InitializeLayout(graph, settings.MinConstraintLevel);

            do
            {
#pragma warning disable 618
                LayoutHelpers.CalculateLayout(graph, settings, null);
#pragma warning restore 618
            } while (settings.Iterations < settings.MaxIterations);
        }
Beispiel #2
0
        public void VisualizeNeuralNetToFile(string neuralNetPicFilePath)
        {
            FastIncrementalLayoutSettings fastSettings = new FastIncrementalLayoutSettings
            {
                AvoidOverlaps  = true,
                NodeSeparation = 30,
                RouteEdges     = true
            };

            SugiyamaLayoutSettings settings = new SugiyamaLayoutSettings
            {
                FallbackLayoutSettings = fastSettings
            };

            m_opsViz.LayoutAlgorithmSettings = settings;

            Microsoft.Msagl.GraphViewerGdi.GraphRenderer renderer = new Microsoft.Msagl.GraphViewerGdi.GraphRenderer(m_opsViz);
            renderer.CalculateLayout();

            System.Drawing.Bitmap bitmap = new System.Drawing.Bitmap((int)m_opsViz.Width, (int)m_opsViz.Height, System.Drawing.Imaging.PixelFormat.Format32bppPArgb);
            renderer.Render(bitmap);

            bitmap.Save(neuralNetPicFilePath);

            bitmap.Dispose();
        }
Beispiel #3
0
        static Graph CtreateDrawingGraph(out FastIncrementalLayoutSettings settings)
        {
            settings = new FastIncrementalLayoutSettings {
                RouteEdges = true, NodeSeparation = 30
            };
            var drawingGraph = new Graph();

            AddEdge(drawingGraph, "0", "1");
            AddEdge(drawingGraph, "0", "2");
            AddEdge(drawingGraph, "1", "3");
            AddEdge(drawingGraph, "2", "4");
            AddEdge(drawingGraph, "2", "5");
            AddEdge(drawingGraph, "2", "6");
            AddEdge(drawingGraph, "5", "7");
            AddEdge(drawingGraph, "5", "6");
            AddEdge(drawingGraph, "7", "8");
            AddEdge(drawingGraph, "8", "6");


            drawingGraph.CreateGeometryGraph();
            foreach (DrawingNode node in drawingGraph.Nodes)
            {
                double w, h;
                var    label = node.Label;
                var    font  = new Font(label.FontName, (float)label.FontSize);
                StringMeasure.MeasureWithFont(label.Text, font, out w, out h);
                node.Label.Width  = w;
                node.Label.Height = h;
                node.Attr.Shape   = Shape.DrawFromGeometry;
                node.GeometryNode.BoundaryCurve = CurveFactory.CreateRectangleWithRoundedCorners(1.2 * w, 1.2 * h, 3, 3, new Point());
            }

            return(drawingGraph);
        }
Beispiel #4
0
        /// <summary>
        /// Apply the appropriate layout to the specified cluster
        /// </summary>
        /// <param name="cluster">the root of the cluster hierarchy to lay out</param>
        /// <returns>list of edges external to the cluster</returns>
        void LayoutCluster(Cluster cluster)
        {
            ProgressStep();
            cluster.UnsetInitialLayoutState();
            FastIncrementalLayoutSettings settings = null;
            LayoutAlgorithmSettings       s        = clusterSettings(cluster);
            Directions layoutDirection             = Directions.None;

            if (s is SugiyamaLayoutSettings)
            {
                var ss = s as SugiyamaLayoutSettings;
                settings = ss.FallbackLayoutSettings != null
                    ? new FastIncrementalLayoutSettings((FastIncrementalLayoutSettings)ss.FallbackLayoutSettings)
                    : new FastIncrementalLayoutSettings();
                layoutDirection = LayeredLayoutEngine.GetLayoutDirection(ss);
            }
            else
            {
                settings = new FastIncrementalLayoutSettings((FastIncrementalLayoutSettings)s);
            }

            settings.ApplyForces          = true;
            settings.MinorIterations      = 10;
            settings.AvoidOverlaps        = true;
            settings.InterComponentForces = false;
            settings.IdealEdgeLength      = new IdealEdgeLengthSettings {
                EdgeDirectionConstraints  = layoutDirection,
                ConstrainedEdgeSeparation = 30
            };
            settings.EdgeRoutingSettings.EdgeRoutingMode = EdgeRoutingMode.Spline;

            HashSet <Node> addedNodes;

            if (addedNodesByCluster.TryGetValue(cluster, out addedNodes))
            {
                // if the structure of the cluster has changed then we apply unconstrained layout first,
                // then introduce structural constraints, and then all constraints
                settings.MinConstraintLevel = 0;
                settings.MaxConstraintLevel = 2;
            }
            else
            {
                settings.MinConstraintLevel = 2;
            }

            GeometryGraph newGraph = GetShallowCopyGraphUnderCluster(cluster);

            LayoutAlgorithmHelpers.ComputeDesiredEdgeLengths(settings.IdealEdgeLength, newGraph);

            // orthogonal ordering constraints preserve the left-of, above-of relationships between existing nodes
            // (we do not apply these to the newly added nodes)
            GenerateOrthogonalOrderingConstraints(
                newGraph.Nodes.Where(v => !addedNodes.Contains(v.UserData as Node)).ToList(), settings);

            LayoutComponent(newGraph, settings);
            //LayoutAlgorithmSettings.ShowGraph(newGraph);
            InitialLayoutByCluster.FixOriginalGraph(newGraph, true);

            cluster.UpdateBoundary(newGraph.BoundingBox);
        }
Beispiel #5
0
        public static void Layout(GeometryGraph graph)
        {
            foreach (Node n in graph.Nodes)
            {
                n.BoundaryCurve = CurveFactory.CreateEllipse(20.0, 10.0, new Point());
            }
            foreach (Cluster c in graph.RootCluster.AllClustersDepthFirst())
            {
                c.BoundaryCurve = c.BoundingBox.Perimeter();
            }

            var settings = new FastIncrementalLayoutSettings();

            settings.AvoidOverlaps  = true;
            settings.NodeSeparation = 30;
            settings.RouteEdges     = true;

            LayoutHelpers.CalculateLayout(graph, settings, new CancelToken());
            foreach (Cluster c in graph.RootCluster.AllClustersDepthFirst())
            {
                c.BoundaryCurve = c.BoundingBox.Perimeter();
            }

            var bundlingsettings = new BundlingSettings()
            {
                EdgeSeparation = 5, CreateUnderlyingPolyline = true
            };
            var router = new SplineRouter(graph, 10.0, 1.25, Math.PI / 6.0, bundlingsettings);

            router.Run();

            graph.UpdateBoundingBox();
        }
Beispiel #6
0
        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 + "%");
        }
Beispiel #7
0
        internal void LayoutComponent(GeometryGraph component, FastIncrementalLayoutSettings settings)
        {
            // for small graphs (below 100 nodes) do extra iterations
            settings.MaxIterations = LayoutAlgorithmHelpers.NegativeLinearInterpolation(
                component.Nodes.Count,
                /*lowerThreshold:*/ 50, /*upperThreshold:*/ 500, /*minIterations:*/ 3, /*maxIterations:*/ 5);
            settings.MinorIterations = LayoutAlgorithmHelpers.NegativeLinearInterpolation(component.Nodes.Count,
                                                                                          /*lowerThreshold:*/ 50, /*upperThreshold:*/ 500, /*minIterations:*/ 2, /*maxIterations:*/ 10);

            FastIncrementalLayout fil = new FastIncrementalLayout(component, settings, settings.MinConstraintLevel,
                                                                  anyCluster => settings);

            Debug.Assert(settings.Iterations == 0);

            foreach (var level in Enumerable.Range(settings.MinConstraintLevel, settings.MaxConstraintLevel + 1))
            {
                if (level != fil.CurrentConstraintLevel)
                {
                    fil.CurrentConstraintLevel = level;
                    if (level == 2)
                    {
                        settings.MinorIterations = 1;
                        settings.ApplyForces     = false;
                    }
                }
                do
                {
                    fil.Run();
                } while (!settings.IsDone);
            }

            // Pad the graph with margins so the packing will be spaced out.
            component.Margins = settings.ClusterMargin;
            component.UpdateBoundingBox();
        }
 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);
 }
 public override void Initialize()
 {
     EnableDebugViewer();
     base.Initialize();
     graph = GraphGenerator.GenerateOneSimpleGraph();
     GraphGenerator.SetRandomNodeShapes(graph, random);
     allNodes = graph.Nodes.ToList();
     settings = new FastIncrementalLayoutSettings();
     settings.AvoidOverlaps = true;
 }
 /// <summary>
 ///
 /// Non-overlap between nodes in the same cluster (or the root cluster), between the convex hulls
 /// of clusters and nodes that do belong to those clusters and between clusters and clusters.
 /// </summary>
 /// <param name="cluster"></param>
 /// <param name="settings">for padding extra space around nodes</param>
 public AllPairsNonOverlappingBoundaries(Cluster cluster, FastIncrementalLayoutSettings settings)
 {
     foreach (var v in cluster.nodes)
     {
         hulls.Add(new RCHull(null, v, settings.NodeSeparation));
     }
     foreach (var c in cluster.clusters)
     {
         traverseClusters(null, c, settings.NodeSeparation);
     }
 }
        static void MoveN0ToTheLeft(Node n0, GeometryGraph graph, FastIncrementalLayoutSettings settings)
        {
            n0.Center += new Point(-10, 0);
            LockPosition lockPosition = settings.CreateLock(n0, n0.BoundingBox);

            settings.IncrementalRun(graph);
            RouteEdges(graph, settings);
            //LayoutAlgorithmSettings.ShowGraph(graph);
            settings.ClearLocks();
            settings.RemoveLock(lockPosition);
        }
        /// <summary>
        /// Static layout of graph by gradually adding constraints.
        /// Uses PivotMds to find initial layout.
        /// Breaks the graph into connected components (nodes in the same cluster are considered
        /// connected whether or not there is an edge between them), then lays out each component
        /// individually.  Finally, a simple packing is applied.
        /// ratio as close as possible to the PackingAspectRatio property (not currently used).
        /// </summary>
        public InitialLayout(GeometryGraph graph, FastIncrementalLayoutSettings settings)
        {
            ValidateArg.IsNotNull(graph, "graph");
            ValidateArg.IsNotNull(settings, "settings");
            this.graph = graph;

            this.settings                       = new FastIncrementalLayoutSettings(settings);
            this.settings.ApplyForces           = true;
            this.settings.InterComponentForces  = true;
            this.settings.RungeKuttaIntegration = false;
            this.settings.RespectEdgePorts      = false;
        }
Beispiel #13
0
        public void TreeGraphFastIncrementalLayout()
        {
            GeometryGraph treeGraph = GraphGenerator.GenerateTree(20);
            treeGraph.RootCluster = new Cluster(treeGraph.Nodes);
            var settings = new FastIncrementalLayoutSettings { AvoidOverlaps = true, PackingAspectRatio = 1.6 };
            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));
            }
            foreach (var e in treeGraph.Edges)
            {
                e.EdgeGeometry.SourceArrowhead = new Arrowhead { Length = 4, Width = 4 };
                e.EdgeGeometry.TargetArrowhead = new Arrowhead { Length = 8, Width = 4 };
            }
            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, 0.2, "Aspect ratio too far from desired");

            Assert.AreEqual(1.0, progress, "Progress was never reported as 100%.  Last update was at " + progress + "%");
        }
Beispiel #14
0
        protected LayoutAlgorithmSettings GetLayoutSettings(string layoutMethod)
        {
            switch (layoutMethod)
            {
            case "MDS":
                return(new MdsLayoutSettings());

            case "Ranking":
                return(new RankingLayoutSettings());

            case "Incremental":
                return(FastIncrementalLayoutSettings.CreateFastIncrementalLayoutSettings());

            default:
                return(new SugiyamaLayoutSettings());
            }
        }
Beispiel #15
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 #16
0
        static void RouteEdges(GeometryGraph graph, FastIncrementalLayoutSettings settings)
        {
            if (graph.Edges.Count < 1000)
            {
                var router = new SplineRouter(graph, settings.EdgeRoutingSettings.Padding,
                                              settings.EdgeRoutingSettings.PolylinePadding,
                                              settings.EdgeRoutingSettings.ConeAngle,
                                              settings.EdgeRoutingSettings.BundlingSettings);

                router.Run();
            }
            else
            {
                var sr = new StraightLineEdges(graph.Edges, 1);
                sr.Run();
            }
        }
Beispiel #17
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 #18
0
        static void FillClustersAndSettings(FastIncrementalLayoutSettings settings, GeometryGraph geometryGraph)
        {
            settings.AvoidOverlaps = true;
            // settings.RectangularClusters = true;
            var root    = new Cluster();
            var cluster = new Cluster();

            root.AddChild(cluster);

            for (int i = 0; i < 4; i++)
            {
                var istring = i.ToString();
                cluster.AddChild(geometryGraph.Nodes.First(n => n.UserData.ToString() == istring));
            }
            cluster.BoundaryCurve = cluster.BoundingBox.Perimeter();
            cluster = new Cluster();
            root.AddChild(cluster);
            geometryGraph.RootCluster.AddChild(root);



            //make a subcluster
            var parent = cluster;

            cluster = new Cluster();
            cluster.AddChild(geometryGraph.Nodes.First(n => n.UserData.ToString() == "4"));
            cluster.AddChild(geometryGraph.Nodes.First(n => n.UserData.ToString() == "5"));
            parent.AddChild(cluster);


            cluster = new Cluster();
            for (int i = 6; i < 9; i++)
            {
                var istring = i.ToString();
                cluster.AddChild(geometryGraph.Nodes.First(n => n.UserData.ToString() == istring));
            }
            parent.AddChild(cluster);
            foreach (var cl in geometryGraph.RootCluster.AllClustersDepthFirst())
            {
                if (cl.BoundaryCurve == null)
                {
                    cl.BoundaryCurve = cl.BoundingBox.Perimeter();
                }
            }
        }
Beispiel #19
0
        static void FillClustersAndSettings(FastIncrementalLayoutSettings settings, GeometryGraph geometryGraph)
        {
            settings.AvoidOverlaps = true;
            // settings.RectangularClusters = true;
            var root    = new Cluster();
            var cluster = new Cluster();

            root.AddChild(cluster);

            for (int i = 0; i < 4; i++)
            {
                cluster.AddChild(FindNode(geometryGraph, i));
            }
            cluster.BoundaryCurve = cluster.BoundingBox.Perimeter();
            cluster = new Cluster();
            root.AddChild(cluster);
            geometryGraph.RootCluster.AddChild(root);



            //make a subcluster
            var parent = cluster;

            cluster = new Cluster();
            cluster.AddChild(FindNode(geometryGraph, 4));
            cluster.AddChild(FindNode(geometryGraph, 5));
            parent.AddChild(cluster);


            cluster = new Cluster();
            for (int i = 6; i < 9; i++)
            {
                cluster.AddChild(FindNode(geometryGraph, i));
            }
            parent.AddChild(cluster);
            foreach (var cl in geometryGraph.RootCluster.AllClustersDepthFirst())
            {
                if (cl.BoundaryCurve == null)
                {
                    cl.BoundaryCurve = cl.BoundingBox.Perimeter();
                }
            }

            SetupDisplayNodeIds(geometryGraph);
        }
Beispiel #20
0
        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 TEST_MSAGL
            LayoutAlgorithmSettings.ShowGraph(graph);
#endif
            Environment.Exit(0);
        }
        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);
        }
Beispiel #22
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 #23
0
        void GenerateOrthogonalOrderingConstraints(IEnumerable <Node> nodes, FastIncrementalLayoutSettings settings)
        {
            Node p = null;

            foreach (var v in graph.Nodes.OrderBy(v => v.Center.X))
            {
                if (p != null)
                {
                    settings.AddStructuralConstraint(new HorizontalSeparationConstraint(p, v, 0.1));
                }
                p = v;
            }
            p = null;
            foreach (var v in graph.Nodes.OrderBy(v => v.Center.Y))
            {
                if (p != null)
                {
                    settings.AddStructuralConstraint(new VerticalSeparationConstraint(p, v, 0.1));
                }
                p = v;
            }
        }
Beispiel #24
0
        static void Main(string[] args)
        {
#if TEST_MSAGL
            DisplayGeometryGraph.SetShowFunctions();
#endif
            ArgsParser.ArgsParser argsParser = SetArgsParser(args);
            if (argsParser.OptionIsUsed("-help"))
            {
                Console.WriteLine(argsParser.UsageString());
                Environment.Exit(0);
            }
            if (argsParser.OptionIsUsed(PolygonDistanceTestOption))
            {
                TestPolygonDistance();
            }
            else if (argsParser.OptionIsUsed(TestCdtThreaderOption))
            {
                TestCdtThreader();
            }
            else if (argsParser.OptionIsUsed(RandomBundlingTest))
            {
                RandomBundlingTests.RsmContent();
            }


            bundling = argsParser.OptionIsUsed(BundlingOption);

            var gviewer = new GViewer();
            gviewer.MouseMove += Draw.GviewerMouseMove;
            if (argsParser.OptionIsUsed(FdOption))
            {
                TestFD();
                gviewer.CurrentLayoutMethod = LayoutMethod.IcrementalLayout;
            }
            Form form = CreateForm(null, gviewer);
            if (argsParser.OptionIsUsed(AsyncLayoutOption))
            {
                gviewer.AsyncLayout = true;
            }

            string listOfFilesFile = argsParser.GetStringOptionValue(ListOfFilesOption);
            if (listOfFilesFile != null)
            {
                ProcessListOfFiles(listOfFilesFile, argsParser);
                return;
            }
            string fileName = argsParser.GetStringOptionValue(FileOption);
            string ext      = Path.GetExtension(fileName);
            if (ext != null)
            {
                ext = ext.ToLower();
                if (ext == ".dot")
                {
                    ProcessDotFile(gviewer, argsParser, fileName);
                }
                else
                {
                    if (ext == ".geom")
                    {
                        GeometryGraph geometryGraph = GeometryGraphReader.CreateFromFile(fileName);
                        geometryGraph.Margins = 10;

                        FixHookPorts(geometryGraph);
                        // if (argsParser.OptionIsUsed(BundlingOption)) {
                        for (int i = 0; i < 1; i++)
                        {
#if TEST_MSAGL
                            /*DisplayGeometryGraph.ShowGraph(geometryGraph);
                             *  var l = new List<DebugCurve>(); l.AddRange(geometryGraph.Nodes.Select(n=>new DebugCurve(100,1,"black",n.BoundaryCurve)));
                             *  l.AddRange(geometryGraph.Edges.Select(e=>new DebugCurve(100,1,"black", new LineSegment(e.Source.Center,e.Target.Center))));
                             *  foreach (var cl in geometryGraph.RootCluster.AllClustersDepthFirst()) {
                             *      l.Add(new DebugCurve(100,2,"blue",cl.BoundaryCurve));
                             *      foreach (var node in cl.Nodes)
                             *          l.Add(new DebugCurve(100, 2, "brown", node.BoundaryCurve));
                             *
                             *      foreach (var e in cl.Edges)
                             *          l.Add(new DebugCurve(100, 2, "pink", new LineSegment(e.Source.Center, e.Target.Center)));
                             *
                             *  }
                             *
                             *  DisplayGeometryGraph.ShowDebugCurves(l.ToArray());*/
#endif
                            BundlingSettings bs = GetBundlingSettings(argsParser);

                            double loosePadding;
                            double tightPadding = GetPaddings(argsParser, out loosePadding);
                            if (argsParser.OptionIsUsed(MdsOption))
                            {
                                var mdsLayoutSettings = new MdsLayoutSettings {
                                    RemoveOverlaps = true, NodeSeparation = loosePadding * 3
                                };
                                var mdsLayout = new MdsGraphLayout(mdsLayoutSettings, geometryGraph);
                                mdsLayout.Run();
                            }
                            else
                            {
                                if (argsParser.OptionIsUsed(FdOption))
                                {
                                    var settings = new FastIncrementalLayoutSettings {
                                        AvoidOverlaps = true
                                    };
                                    (new InitialLayout(geometryGraph, settings)).Run();
                                }
                            }
                            var splineRouter = new SplineRouter(geometryGraph, geometryGraph.Edges, tightPadding,
                                                                loosePadding,
                                                                Math.PI / 6, bs);
                            splineRouter.Run();
                        }
#if TEST_MSAGL
                        DisplayGeometryGraph.ShowGraph(geometryGraph);
#endif
                        return;
                    }
                    else
                    {
                        if (ext == ".msagl")
                        {
                            Graph graph = Graph.Read(fileName);
                            //           DisplayGeometryGraph.ShowGraph(graph.GeometryGraph);
                            if (graph != null)
                            {
                                if (argsParser.OptionIsUsed(BundlingOption))
                                {
                                    BundlingSettings bs = GetBundlingSettings(argsParser);

                                    double loosePadding;
                                    double tightPadding = GetPaddings(argsParser, out loosePadding);
                                    var    br           = new SplineRouter(graph.GeometryGraph, tightPadding, loosePadding, Math.PI / 6,
                                                                           bs);
                                    br.Run();
                                    //                 DisplayGeometryGraph.ShowGraph(graph.GeometryGraph);
                                }
                            }
                            gviewer.NeedToCalculateLayout = false;
                            gviewer.Graph = graph;
                            gviewer.NeedToCalculateLayout = true;
                        }
                    }
                }
            }
            else if (argsParser.OptionIsUsed(TestCdtOption))
            {
                Triangulation(argsParser.OptionIsUsed(ReverseXOption));
                Environment.Exit(0);
            }
            else if (argsParser.OptionIsUsed(TestCdtOption0))
            {
                TestTriangulationOnSmallGraph(argsParser);
                Environment.Exit(0);
            }
            else if (argsParser.OptionIsUsed(TestCdtOption2))
            {
                TestTriangulationOnPolys();
                Environment.Exit(0);
            }
            else if (argsParser.OptionIsUsed(TestCdtOption1))
            {
                ThreadThroughCdt();
                Environment.Exit(0);
            }
            else if (argsParser.OptionIsUsed(ConstraintsTestOption))
            {
                TestGraphWithConstraints();
            }
            if (!argsParser.OptionIsUsed(QuietOption))
            {
                Application.Run(form);
            }
        }
Beispiel #25
0
            protected override void OnValueChanged(ModelRoot element, LayoutAlgorithm oldValue, LayoutAlgorithm newValue)
            {
                base.OnValueChanged(element, oldValue, newValue);

                if (!element.Store.InUndoRedoOrRollback)
                {
                    // if this is the first time we've been here, cache what's alread there
                    if (oldValue != LayoutAlgorithm.Default && !settingsCache.ContainsKey(oldValue) && element.LayoutAlgorithmSettings != null)
                    {
                        settingsCache[oldValue] = element.LayoutAlgorithmSettings;
                    }

                    // use the prior settings for this layout type if available
                    if (newValue != LayoutAlgorithm.Default && settingsCache.ContainsKey(newValue))
                    {
                        element.LayoutAlgorithmSettings = settingsCache[newValue];
                    }
                    else
                    {
                        // if not, set some defaults that make sense in our context
                        switch (newValue)
                        {
                        case LayoutAlgorithm.Default:
                            element.LayoutAlgorithmSettings = null;
                            return;

                        case LayoutAlgorithm.FastIncremental:
                            FastIncrementalLayoutSettings fastIncrementalLayoutSettings = new FastIncrementalLayoutSettings();
                            element.LayoutAlgorithmSettings = fastIncrementalLayoutSettings;

                            break;

                        case LayoutAlgorithm.MDS:
                            MdsLayoutSettings mdsLayoutSettings = new MdsLayoutSettings();
                            mdsLayoutSettings.ScaleX         = 1;
                            mdsLayoutSettings.ScaleY         = 1;
                            mdsLayoutSettings.AdjustScale    = true;
                            mdsLayoutSettings.RemoveOverlaps = true;
                            element.LayoutAlgorithmSettings  = mdsLayoutSettings;

                            break;

                        case LayoutAlgorithm.Ranking:
                            RankingLayoutSettings rankingLayoutSettings = new RankingLayoutSettings();
                            rankingLayoutSettings.ScaleX    = 1;
                            rankingLayoutSettings.ScaleY    = 1;
                            element.LayoutAlgorithmSettings = rankingLayoutSettings;

                            break;

                        case LayoutAlgorithm.Sugiyama:
                            SugiyamaLayoutSettings sugiyamaLayoutSettings = new SugiyamaLayoutSettings
                            {
                                LayerSeparation = 1,
                                MinNodeHeight   = 1,
                                MinNodeWidth    = 1
                            };

                            element.LayoutAlgorithmSettings = sugiyamaLayoutSettings;

                            break;
                        }

                        element.LayoutAlgorithmSettings.ClusterMargin  = 1;
                        element.LayoutAlgorithmSettings.NodeSeparation = 1;
                        element.LayoutAlgorithmSettings.EdgeRoutingSettings.Padding         = .3;
                        element.LayoutAlgorithmSettings.EdgeRoutingSettings.PolylinePadding = 1.5;
                        element.LayoutAlgorithmSettings.EdgeRoutingSettings.EdgeRoutingMode = EdgeRoutingMode.StraightLine;

                        settingsCache[newValue] = element.LayoutAlgorithmSettings;
                    }
                }
            }
    //takes a target Tree object and builds actual game nodes for it - using MSAGL as an intermediate representation for layout
    public void BuildTree(Tree target)
    {
        if (target == null)
        {
            return;                 //do not attempt to build a null tree - this means that a syntax error happened in a newick file
        }
        GameManager.DebugLog("Building tree with layout: " + eventManager.Current_Tree_State);

        ResetTreeContainer();

        GeometryGraph asMSAGL = ToMSALGraph(target);

        List <GameObject> generatedNodes = new List <GameObject>();

        //define how we want the tree to be layed out
        LayoutAlgorithmSettings settings;

        switch (eventManager.Current_Tree_State)
        {
        default:
        case InputEventManager.TreeState.BasicTree:
            settings = new Microsoft.Msagl.Layout.Layered.SugiyamaLayoutSettings();
            break;

        case InputEventManager.TreeState.TerrainTree:
        case InputEventManager.TreeState.CircularTree:
            settings = new FastIncrementalLayoutSettings();
            break;
        }

        //apply some extra settings and layout the graph according to all settings
        settings.EdgeRoutingSettings.EdgeRoutingMode = Microsoft.Msagl.Core.Routing.EdgeRoutingMode.StraightLine;
        settings.PackingMethod = PackingMethod.Compact;
        LayoutHelpers.CalculateLayout(asMSAGL, settings, null);

        //we want world space 0, 0 to be equivalent to graph space 0, 0
        float offSetX = (float)asMSAGL.Nodes[0].Center.X;
        float offSetY = (float)asMSAGL.Nodes[0].Center.Y;
        //msal graph edge weights are enormous, like hundreds of meters of in world space - scale it down
        float scaleFactor = eventManager.Current_Tree_State == InputEventManager.TreeState.TerrainTree ?
                            1f / 30f : 1f / 250f;

        //build game objects using msagl graph as spatial layout
        foreach (Microsoft.Msagl.Core.Layout.Node node in asMSAGL.Nodes)
        {
            float x = ((float)node.Center.X - offSetX) * scaleFactor;
            float y = ((float)node.Center.Y - offSetY) * scaleFactor;

            GameObject newNode = Instantiate(nodePrefab, new Vector3(
                                                 treeContainer.transform.position.x + x,
                                                 treeContainer.transform.position.y + y,
                                                 treeContainer.transform.position.z
                                                 ),
                                             Quaternion.identity);
            newNode.transform.SetParent(treeContainer.transform);
            newNode.GetComponent <BasicNodeBehaviour>().attachNodeInfo((Node)node.UserData);
            newNode.GetComponentInChildren <InfoOnHover>()._Init();
            node.UserData = newNode;

            generatedNodes.Add(newNode);

            foreach (Edge edge in node.Edges)
            {
                if (edge.Target == node)
                {
                    Line l = newNode.transform.Find("Renderer").gameObject.AddComponent <Line>();
                    l.gameObject1 = newNode;
                    l.gameObject2 = (GameObject)edge.Source.UserData;
                    newNode.transform.SetParent(((GameObject)edge.Source.UserData).transform);
                    if (newNode.GetComponent <BasicNodeBehaviour>().getAttachedNodeInfo().weightToParentSet())
                    {
                        l.setLabel("" + newNode.GetComponent <BasicNodeBehaviour>().getAttachedNodeInfo().getWeightToParent());
                    }
                    else
                    {
                        l.setLabel("");
                    }
                }
            }
        }

        if (eventManager.Current_Tree_State == InputEventManager.TreeState.TerrainTree)
        {
            Vector3 translation = new Vector3(0, -4, 0);
            treeContainer.transform.Translate(translation);
            treeContainer.transform.Rotate(90, 0, 0);

            List <GameObject> leafNodesList = new List <GameObject>();

            foreach (GameObject node in generatedNodes)
            {
                //scale up the nodes a bit to make them clearer within the terrain
                float scale = node.GetComponentInChildren <MaintainNodeScale>().targetScale;
                node.GetComponentInChildren <MaintainNodeScale>().targetScale = 2 * scale;
                node.transform.hasChanged = true;
                if (node.GetComponent <BasicNodeBehaviour>().getAttachedNodeInfo().getNumberOfChildren() == 0)
                {
                    leafNodesList.Add(node);
                }
            }

            generatedNodes[0].GetComponentInChildren <MaintainNodeScale>().targetScale = 4f;

            GameManager.DebugLog("Found " + leafNodesList.Count + " leaf nodes");

            TreeTerrainBehaviour.instance.Activate();
            TreeTerrainBehaviour.instance.ResetHeights();

            leafNodes = leafNodesList.ToArray();
            EnableOnFrameLoading();
        }
        else
        {
            DisableOnFrameLoading();
            //the player won't be moving while we aren't looking at terrain so we'll reset their position
        }

        if (eventManager.Draw_Tree_In_3D)
        {
            TreeConverter3D.Convert(treeContainer.transform.GetChild(0).gameObject);
        }

        //as a last step, reset the position of the player so they are close to the root of whatever tree they built
        player.GetComponent <PositionResetter>().ResetPosition();
    }
        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
        }
Beispiel #28
0
            private void Layout(bool repositionateAll)
            {
                if (settings != null && repositionateAll)
                {
                    settings.ClearLocks();
                    return;
                }

                if (cancelToken != null)
                {
                    cancelToken.Canceled = true;
                }

                try
                {
                    var scenes = Controller.Instance.ChapterList.getSelectedChapterDataControl().getScenesList();
                    // Layout algorithm
                    settings = new Microsoft.Msagl.Layout.Incremental.FastIncrementalLayoutSettings
                    {
                        EdgeRoutingSettings = new EdgeRoutingSettings
                        {
                            EdgeRoutingMode = EdgeRoutingMode.StraightLine,
                            Padding         = 10
                        },
                        AvoidOverlaps         = true,
                        ApplyForces           = false,
                        RungeKuttaIntegration = true,
                        NodeSeparation        = 10,
                        PackingMethod         = PackingMethod.Compact
                    };

                    var canvasRect = new Rect(0, 0, SPACE_WIDTH, SPACE_HEIGHT);

                    // Graph
                    graph = new GeometryGraph
                    {
                        BoundingBox = new Microsoft.Msagl.Core.Geometry.Rectangle(0, 0, SPACE_WIDTH, SPACE_HEIGHT)
                    };

                    sceneToNode        = new Dictionary <SceneDataControl, Node>();
                    sceneLockPositions = new Dictionary <SceneDataControl, LockPosition>();
                    var present = new Dictionary <Tuple <Node, Node>, bool>();

                    foreach (var scene in scenes.getScenes())
                    {
                        sizes.Remove(scene.getPreviewBackground());
                        var rect = ToGraphRect(GetSceneRect(scene, true), canvasRect, graph.BoundingBox);
                        var node = new Node(CurveFactory.CreateRectangle(rect), scene.getId());

                        /*if (!repositionateAll && rect.LeftBottom != new Point(0,0))
                         * {
                         *  sceneLockPositions.Add(scene, settings.CreateLock(node, rect));
                         * }*/

                        graph.Nodes.Add(node);
                        graph.RootCluster.AddChild(node);
                        sceneToNode.Add(scene, node);
                    }

                    foreach (var scene in scenes.getScenes())
                    {
                        var node = sceneToNode[scene];
                        foreach (var exit in scene.getExitsList().getExits())
                        {
                            var index = scenes.getSceneIndexByID(exit.getNextSceneId());

                            // If the exit points to a cutscene it normally is out of the array
                            if (index < 0 || index >= scenes.getScenes().Count)
                            {
                                continue;
                            }

                            var nextScene = scenes.getScenes()[index];

                            var t = new Tuple <Node, Node>(node, sceneToNode[nextScene]);
                            if (!present.ContainsKey(t))
                            {
                                present.Add(t, true);
                                graph.Edges.Add(new Edge(node, sceneToNode[nextScene]));

                                var exitOrigin = GetExitArea(scene, exit, true).ToRect().center;
                                var originRect = GetSceneRect(scene, true);

                                var pos = exitOrigin - originRect.position;
                                pos.x = Mathf.Clamp01(pos.x / originRect.width);
                                pos.y = Mathf.Clamp01(pos.y / originRect.height);

                                // Positioning constraints

                                /*if (pos.x < 0.3)
                                 * {
                                 *  settings.AddStructuralConstraint(new LeftRightConstraint(t.Item2, t.Item1));
                                 * }
                                 * if (pos.x > 0.7)
                                 * {
                                 *  settings.AddStructuralConstraint(new LeftRightConstraint(t.Item1, t.Item2));
                                 * }*/
                            }
                        }
                    }

                    var ir = new InitialLayout(graph, settings);
                    ir.Run();

                    // Do the layouting
                    UpdatePositions();
                }
                catch (Exception ex)
                {
                    Debug.LogError(ex.Message + " : " + ex.StackTrace);
                }
            }