Example #1
0
        // Abstract the creation of the GeometryGraph and the node.CreateBoundary calls away in
        // a single call on the Diagram.
        public void Run()
        {
            drawingGraph.CreateGeometryGraph();

            foreach (var node in drawingGraph.Nodes)
            {
                if (node is LabeledNode ln)
                {
                    ln.CreateBoundary();
                }
            }

            var routingSettings = new Microsoft.Msagl.Core.Routing.EdgeRoutingSettings {
                UseObstacleRectangles = true,
                BendPenalty           = 100,
                EdgeRoutingMode       = Microsoft.Msagl.Core.Routing.EdgeRoutingMode.StraightLine
            };
            var settings = new SugiyamaLayoutSettings {
                ClusterMargin      = 50,
                PackingAspectRatio = 3,
                PackingMethod      = Microsoft.Msagl.Core.Layout.PackingMethod.Columns,
                RepetitionCoefficientForOrdering = 0,
                EdgeRoutingSettings = routingSettings,
                NodeSeparation      = 50,
                LayerSeparation     = 150
            };

            LayoutHelpers.CalculateLayout(drawingGraph.GeometryGraph, settings, null);

            _run();
        }
Example #2
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();
        }
Example #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;
        }
Example #4
0
        static void Main(string[] args)
        {
            var drawingGraph = new Graph();

            drawingGraph.AddNode("A").LabelText = "AText";
            drawingGraph.AddNode("B").LabelText = "BText";

            var e = drawingGraph.AddEdge("A", "B"); // now the drawing graph has nodes A,B and and an edge A -> B\

            // the geometry graph is still null, so we are going to create it
            e.LabelText = "from " + e.SourceNode.LabelText + " to " + e.TargetNode.LabelText;
            drawingGraph.CreateGeometryGraph();


            // Now the drawing graph elements point to the corresponding geometry elements,
            // however the node boundary curves are not set.
            // Setting the node boundaries
            foreach (var n in drawingGraph.Nodes)
            {
                // Ideally we should look at the drawing node attributes, and figure out, the required node size
                // I am not sure how to find out the size of a string rendered in SVG. Here, we just blindly assign to each node a rectangle with width 60 and height 40, and round its corners.
                n.GeometryNode.BoundaryCurve = CurveFactory.CreateRectangleWithRoundedCorners(60, 40, 3, 2, new Point(0, 0));
            }

            AssignLabelsDimensions(drawingGraph);

            LayoutHelpers.CalculateLayout(drawingGraph.GeometryGraph, new SugiyamaLayoutSettings(), null);
            PrintSvgAsString(drawingGraph);
        }
        /// <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);
        }
Example #6
0
        private static void LayoutGraph(GeometryGraph geometryGraph)
        {
            var settings = new Microsoft.Msagl.Layout.MDS.MdsLayoutSettings();

            settings.EdgeRoutingSettings.EdgeRoutingMode = Microsoft.Msagl.Core.Routing.EdgeRoutingMode.StraightLine;
            LayoutHelpers.CalculateLayout(geometryGraph, settings, null);
            Console.WriteLine("layout done");
        }
Example #7
0
        private void LayoutLinkedShapes(Graph graph, out Microsoft.Msagl.Core.Layout.GeometryGraph geometry)
        {
            var geomGraph      = new Microsoft.Msagl.Core.Layout.GeometryGraph();
            var layoutSettings = new Microsoft.Msagl.Layout.Layered.SugiyamaLayoutSettings();

            Microsoft.Msagl.Core.Layout.Node EnsureNode(Node node)
            {
                var res = geomGraph.Nodes.FirstOrDefault(n => n.UserData == node);

                if (res == null)
                {
                    var geomNode = new Microsoft.Msagl.Core.Layout.Node(
                        Microsoft.Msagl.Core.Geometry.Curves.CurveFactory.CreateRectangle(
                            ShapeSize,
                            ShapeSize,
                            new Microsoft.Msagl.Core.Geometry.Point()
                            ),
                        node
                        );

                    geomGraph.Nodes.Add(geomNode);

                    return(geomNode);
                }

                return(res);
            }

            foreach (var l in graph.Links)
            {
                var n1 = EnsureNode(l.Node1);
                var n2 = EnsureNode(l.Node2);
                var e  = new Microsoft.Msagl.Core.Layout.Edge(n1, n2);
                geomGraph.Edges.Add(e);
            }

            LayoutHelpers.CalculateLayout(geomGraph, layoutSettings, null);

            foreach (var kv in nodesAndShapes)
            {
                var pos = geomGraph.Nodes.FirstOrDefault(n => n.UserData == kv.Key)?.Center;
                if (pos.HasValue)
                {
                    kv.Value.X = (int)pos.Value.X + ShapeSize;
                    kv.Value.Y = Diagram.Height - (int)pos.Value.Y + ShapeSize / 2;
                }
            }

            geometry = geomGraph;
        }
Example #8
0
 private void Update()
 {
     if (reposition)
     {
         PositionNodes();
         Center();
         reposition = false;
     }
     if (redraw)
     {
         RedrawEdges();
         redraw = false;
     }
     if (relayout)
     {
         if (graphTask == null)
         {
             UpdateNodes();
             graphTask = Task.Run(() =>
             {
                 LayoutHelpers.CalculateLayout(graph, settings, null);
                 LayoutHelpers.RouteAndLabelEdges(graph, settings, graph.Edges);
             });
             Forget(graphTask, () =>
             {
                 graphTask  = null;
                 reposition = true;
                 redraw     = true;
             });
             relayout = false;
         }
     }
     if (reroute)
     {
         if (graphTask == null)
         {
             UpdateNodes();
             graphTask = Task.Run(() => LayoutHelpers.RouteAndLabelEdges(graph, settings, graph.Edges));
             Forget(graphTask, () =>
             {
                 graphTask = null;
                 redraw    = true;
             });
             reroute = false;
         }
     }
 }
Example #9
0
        private static void DoCustomLayout(List <NodeShape> nodeShapes, List <BinaryLinkShape> linkShapes, ModelRoot modelRoot)
        {
            GeometryGraph graph = new GeometryGraph();

            CreateDiagramNodes(nodeShapes, graph);
            CreateDiagramLinks(linkShapes, graph);

            AddDesignConstraints(linkShapes, modelRoot, graph);

            LayoutHelpers.CalculateLayout(graph, modelRoot.LayoutAlgorithmSettings, null);

            // Move model to positive axis.
            graph.UpdateBoundingBox();
            graph.Translate(new Point(-graph.Left, -graph.Bottom));

            UpdateNodePositions(graph);
            UpdateConnectors(graph);
        }
        private void LayoutGraph(GeometryGraph geometryGraph)
        {
            if (this.NeedToCalculateLayout)
            {
                try
                {
                    LayoutHelpers.CalculateLayout(geometryGraph, this.Graph.LayoutAlgorithmSettings, this.CancelToken);

                    //if (MsaglFileToSave != null)
                    //{
                    //    drawingGraph.Write(MsaglFileToSave);
                    //    Console.WriteLine("saved into {0}", MsaglFileToSave);
                    //    Environment.Exit(0);
                    //}
                }
                catch (OperationCanceledException)
                {
                    //swallow this exception
                }
            }
        }
Example #11
0
 int ProcessMsaglFile(string inputFile)
 {
     try {
         LayoutAlgorithmSettings ls;
         var geomGraph = GeometryGraphReader.CreateFromFile(inputFile, out ls);
         if (ls == null)
         {
             ls = PickLayoutAlgorithmSettings(geomGraph.Edges.Count, geomGraph.Nodes.Count);
         }
         LayoutHelpers.CalculateLayout(geomGraph, ls, null);
         inputFile = SetMsaglOutputFileName(inputFile);
         WriteGeomGraph(inputFile, geomGraph);
         DumpFileToConsole(inputFile);
     }
     catch (Exception e) {
         //Console.WriteLine(e.ToString());
         Console.WriteLine(e.Message);
         return(-1);
     }
     return(0);
 }
        void ProcessGraph()
        {
            try {
                selectedObject = null;
                if (drawingGraph == null)
                {
                    return;
                }

                graphCanvas.Visibility = Visibility.Hidden; // hide canvas while we lay it out asynchronously.
                ClearGraphViewer();

                // Make nodes and edges

                if (LargeGraphBrowsing)
                {
                    LayoutEditingEnabled = false;
                    var lgsettings = new LgLayoutSettings(
                        () => new Rectangle(0, 0, graphCanvas.RenderSize.Width, graphCanvas.RenderSize.Height),
                        () => Transform, DpiX, DpiY, () => 0.1 * DpiX / CurrentScale /*0.1 inch*/);
                    drawingGraph.LayoutAlgorithmSettings = lgsettings;
                    lgsettings.ViewerChangeTransformAndInvalidateGraph += OGraphChanged;
                }
                if (NeedToCalculateLayout)
                {
                    drawingGraph.CreateGeometryGraph(); //forcing the layout recalculation
                    geometryGraphUnderLayout = drawingGraph.GeometryGraph;
                }

                PushGeometryIntoLayoutGraph();
                graphCanvas.RaiseEvent(new RoutedEventArgs(LayoutStartEvent));
                LayoutHelpers.CalculateLayout(geometryGraphUnderLayout, drawingGraph.LayoutAlgorithmSettings);

                TransferLayoutDataToWpf();
            }
            catch
            (Exception e) {
                MessageBox.Show(e.ToString());
            }
        }
Example #13
0
        static internal GeometryGraph CreateAndLayoutGraph()
        {
            double        w     = 30;
            double        h     = 20;
            GeometryGraph graph = new GeometryGraph();
            Node          a     = new Node(new Ellipse(w, h, new P()), "a");
            Node          b     = new Node(CurveFactory.CreateRectangle(w, h, new P()), "b");
            Node          c     = new Node(CurveFactory.CreateRectangle(w, h, new P()), "c");
            Node          d     = new Node(CurveFactory.CreateRectangle(w, h, new P()), "d");

            graph.Nodes.Add(a);
            graph.Nodes.Add(b);
            graph.Nodes.Add(c);
            graph.Nodes.Add(d);
            Edge e = new Edge(a, b)
            {
                Length = 10
            };

            graph.Edges.Add(e);
            graph.Edges.Add(new Edge(b, c)
            {
                Length = 3
            });
            graph.Edges.Add(new Edge(b, d)
            {
                Length = 4
            });

            //graph.Save("c:\\tmp\\saved.msagl");
            var settings = new Microsoft.Msagl.Layout.MDS.MdsLayoutSettings();

            LayoutHelpers.CalculateLayout(graph, settings, null);

            return(graph);
        }
    //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();
    }
Example #15
0
        public static void LayeredLayoutAbc()
        {
            double        w     = 30;
            double        h     = 20;
            GeometryGraph graph = new GeometryGraph();

            MSAGLNode a = new MSAGLNode(new Ellipse(w, h, new Point()), "a");
            MSAGLNode b = new MSAGLNode(CurveFactory.CreateRectangle(w, h, new Point()), "b");
            MSAGLNode c = new MSAGLNode(CurveFactory.CreateRectangle(w, h, new Point()), "c");

            graph.Nodes.Add(a);
            graph.Nodes.Add(b);
            graph.Nodes.Add(c);
            Edge ab = new Edge(a, b)
            {
                Length = 10
            };
            Edge bc = new Edge(b, c)
            {
                Length = 3
            };

            graph.Edges.Add(ab);
            graph.Edges.Add(bc);

            var settings = new SugiyamaLayoutSettings();

            LayoutHelpers.CalculateLayout(graph, settings, null);


            WriteMessage("Layout progressed");

            /*WriteMessage("");
             * WriteMessage("Segments A->B");
             * //OutputCurve(ab.Curve);
             *
             * WriteMessage("");
             * WriteMessage("Segments B->C");
             * //OutputCurve(bc.Curve);
             *
             * WriteMessage("");
             * WriteMessage("Segments C->A");
             * //OutputCurve(ca.Curve);
             *
             * foreach (var node in graph.Nodes)
             * {
             *  WriteMessage(string.Format("{0}: {1} {2}", node.UserData, node.Center.X, node.Center.Y));
             * }*/

            /*var canvas = HtmlContext.document.getElementById("drawing").As<HtmlCanvasElement>();
             * var ctx = canvas.getContext("2d").As<CanvasRenderingContext2D>();
             *
             * var canvasHeight = canvas.height;
             *
             * var bounds = calcBounds(graph.Nodes);
             *
             * var xScale = canvas.width / bounds.Width;
             * var yScale = canvas.height / bounds.Height;
             *
             * var xShift = -bounds.Left * xScale;
             * var yShift = -(canvas.height - bounds.Top) * yScale;
             *
             * WriteMessage(string.Format("Scaling : {0} {1}", xScale, yScale));
             * WriteMessage(string.Format("Shifting : {0} {1}", xShift, yShift));
             *
             * foreach (var msaglEdge in graph.Edges)
             * {
             *  DrawEdge(ctx, msaglEdge, xShift, yShift, xScale, yScale, canvasHeight);
             * }
             *
             * foreach (var msaglNode in graph.Nodes)
             * {
             *  DrawNode(ctx, msaglNode, xShift, yShift, xScale, yScale, canvasHeight);
             * }*/
        }
Example #16
0
        public static void MDS()
        {
            WriteMessage("Starting test...");

            WriteMessage("Create GeometryGraph");

            GeometryGraph graph = AbcdeGraph();

            //graph.Save("c:\\tmp\\saved.msagl");
            var settings = new MdsLayoutSettings();

            settings.RunInParallel = false;

            settings.EdgeRoutingSettings.EdgeRoutingMode = EdgeRoutingMode.Rectilinear;

            LayoutHelpers.CalculateLayout(graph, settings, null);


            WriteMessage("Layout progressed");

            WriteMessage("");
            WriteMessage("Segments A->B");
            //OutputCurve(ab.Curve);

            WriteMessage("");
            WriteMessage("Segments B->C");
            //OutputCurve(bc.Curve);

            WriteMessage("");
            WriteMessage("Segments C->A");
            //OutputCurve(ca.Curve);

            foreach (var node in graph.Nodes)
            {
                WriteMessage(string.Format("{0}: {1} {2}", node.UserData, node.Center.X, node.Center.Y));
            }

            var canvas = HtmlContext.document.getElementById("drawing").As <HtmlCanvasElement>();
            var ctx    = canvas.getContext("2d").As <CanvasRenderingContext2D>();

            var canvasHeight = canvas.height;

            var bounds = calcBounds(graph.Nodes);

            var xScale = canvas.width / bounds.Width;
            var yScale = canvas.height / bounds.Height;

            var xShift = -bounds.Left * xScale;
            var yShift = -(canvas.height - bounds.Top) * yScale;

            WriteMessage(string.Format("Scaling : {0} {1}", xScale, yScale));
            WriteMessage(string.Format("Shifting : {0} {1}", xShift, yShift));

            foreach (var msaglEdge in graph.Edges)
            {
                DrawEdge(ctx, msaglEdge, xShift, yShift, xScale, yScale, canvasHeight);
            }

            foreach (var msaglNode in graph.Nodes)
            {
                DrawNode(ctx, msaglNode, xShift, yShift, xScale, yScale, canvasHeight);
            }
            * /
        }
Example #17
0
        public Form1()
        {
            InitializeComponent();
            GViewer gViewer = new GViewer()
            {
                Dock = DockStyle.Fill
            };

            SuspendLayout();
            Controls.Add(gViewer);
            ResumeLayout();
            var graph            = new Graph();
            var sugiyamaSettings = (SugiyamaLayoutSettings)graph.LayoutAlgorithmSettings;

            var json     = System.IO.File.ReadAllText("fluentGraph.json");
            var typeName = "com.microsoft.azure.management.redis.RedisCache";

            var nodes = JsonConvert.DeserializeObject <List <FluentNode> >(json);

            foreach (var node in nodes)
            {
                if (node is FluentInterface ||
                    node is FluentMethod)
                {
                    AddNode(graph, node);
                }
                else
                {
                    throw new NotImplementedException($"'{node.GetType()}' is not supported");
                }
            }

            var path = ShortestPathByDijkstra.GetPath(nodes, $"{typeName}.Definition.Blank", typeName);

            // now add edges
            for (int i = 0; i < nodes.Count; i++)
            {
                var node = nodes[i];
                foreach (var childId in node.ChildrenIds)
                {
                    graph.AddEdge(node.Id, childId);
                }
            }

            graph.CreateGeometryGraph();

            foreach (var n in graph.Nodes)
            {
                CreateBoundaryCurve(n);
            }

            // This one throws index out of bounds exception
            sugiyamaSettings.AddUpDownVerticalConstraints(path.Select(nodeId => graph.FindNode(nodeId).GeometryNode).ToArray());

            for (int i = 0; i < path.Count - 1; i++)
            {
                var u = graph.FindNode(path[i]);
                var v = graph.FindNode(path[i + 1]);
                foreach (var e in u.OutEdges)
                {
                    if (e.TargetNode == v)
                    {
                        e.Attr.Color = Microsoft.Msagl.Drawing.Color.Red;
                    }
                }
            }
            LayoutHelpers.CalculateLayout(graph.GeometryGraph, sugiyamaSettings, new Microsoft.Msagl.Core.CancelToken());
            gViewer.NeedToCalculateLayout = false;
            gViewer.Graph = graph;
        }
Example #18
0
 public void CalculateLayout(GeometryGraph geometryGraph)
 {
     LayoutHelpers.CalculateLayout(geometryGraph, LayoutAlgorithmSettings, null);
 }
            private void Layout()
            {
                try
                {
                    var scenes = Controller.Instance.ChapterList.getSelectedChapterDataControl().getScenesList();

                    // Layout algorithm
                    var settings = new Microsoft.Msagl.Layout.Layered.SugiyamaLayoutSettings();
                    settings.MaxAspectRatioEccentricity = 1.6;
                    settings.NodeSeparation             = 10;
                    settings.PackingMethod = PackingMethod.Compact;

                    // Graph
                    GeometryGraph graph = new GeometryGraph();
                    graph.BoundingBox = new Microsoft.Msagl.Core.Geometry.Rectangle(0, 0, SpaceWidth, SpaceHeight);
                    graph.UpdateBoundingBox();

                    Dictionary <SceneDataControl, Node>         sceneToNode = new Dictionary <SceneDataControl, Node>();
                    Dictionary <UniRx.Tuple <Node, Node>, bool> present     = new Dictionary <UniRx.Tuple <Node, Node>, bool>();

                    foreach (var scene in scenes.getScenes())
                    {
                        sizes.Remove(scene.getPreviewBackground());
                        var rect = GetSceneRect(scene);
                        var node = new Node(CurveFactory.CreateRectangle(rect.width, rect.height, new Point()), scene.getId());
                        graph.Nodes.Add(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 UniRx.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).ToRect().center;
                                var originRect = GetSceneRect(scene);

                                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.AddLeftRightConstraint(t.Item2, t.Item1);
                                }
                                if (pos.x > 0.7)
                                {
                                    settings.AddLeftRightConstraint(t.Item1, t.Item2);
                                }
                            }
                        }
                    }


                    // Do the layouting
                    LayoutHelpers.CalculateLayout(graph, settings, null);

                    // Extract the results
                    var graphRect  = new Rect((float)graph.Left, (float)graph.Bottom, (float)graph.Width, (float)graph.Height);
                    var canvasRect = new Rect(0, 0, SpaceWidth, SpaceHeight);

                    foreach (var scene in scenes.getScenes())
                    {
                        var n = sceneToNode[scene];
                        positions[scene.getId()] = TransformPoint(new Vector2((float)(n.Center.X - n.Width / 2f), (float)(n.Center.Y + n.Height / 2f)), graphRect, canvasRect, true);

                        // Update in the project data
                        var id = GetScenePropertyId(Controller.Instance.SelectedChapterDataControl, scene);
                        ProjectConfigData.setProperty(id + ".X", ((int)positions[scene.getId()].x).ToString());
                        ProjectConfigData.setProperty(id + ".Y", ((int)positions[scene.getId()].y).ToString());
                    }
                }
                catch (Exception ex)
                {
                    Debug.LogError(ex.Message + " : " + ex.StackTrace);
                }
            }