internal static void FixBoundingBox(GeometryGraph component, LayoutAlgorithmSettings settings)
        {
            // Pad the graph with margins so the packing will be spaced out.
            component.Margins = settings.ClusterMargin;
            component.UpdateBoundingBox();

            // Zero the graph
            component.Translate(-component.BoundingBox.LeftBottom);
        }
 ///<summary>
 ///</summary>
 ///<param name="geomGraph"></param>
 static public void ShowGraph(GeometryGraph geomGraph) {
     var graph = new Graph();
     geomGraph.UpdateBoundingBox();
     var bb = geomGraph.BoundingBox;
     bb.Pad(geomGraph.Margins);
     geomGraph.BoundingBox = bb;
     BindGeomGraphToDrawingGraph(graph, geomGraph);
     DisplayGraph(graph, new Form());
 }
        internal static void PreRunTransform(GeometryGraph geomGraph, PlaneTransformation matrix) {
            if (matrix.IsIdentity) return;
            var matrixInverse = matrix.Inverse;
            foreach (Node n in geomGraph.Nodes)
                n.Transform(matrixInverse);
            //calculate new label widths and heights
            foreach (Edge e in geomGraph.Edges) {
                if (e.Label != null) {
                    e.OriginalLabelWidth = e.Label.Width;
                    e.OriginalLabelHeight = e.Label.Height;
                    var r = new Rectangle(matrixInverse*new Point(0, 0), matrixInverse*new Point(e.Label.Width, e.Label.Height));
                    e.Label.Width = r.Width;
                    e.Label.Height = r.Height;
                }
            }

            geomGraph.UpdateBoundingBox();
        }
예제 #4
0
        private void DoEdgeRouting(GeometryGraph gg, EdgeRoutingSettings settings, double nodeSeparation)
        {
            var mode = settings.EdgeRoutingMode;
            if (mode == EdgeRoutingMode.SugiyamaSplines)
            {
            }
            else
            {
                if (mode == EdgeRoutingMode.Rectilinear || mode == EdgeRoutingMode.RectilinearToCenter)
                {
                    RectilinearInteractiveEditor.CreatePortsAndRouteEdges(
                        nodeSeparation / 3,
                        nodeSeparation / 3,
                        gg.Nodes,
                        gg.Edges,
                        mode,
                        true);
                }
                else if (mode == EdgeRoutingMode.Spline || mode == EdgeRoutingMode.SplineBundling)
                {
                    /*var coneAngle = Math.PI / 6.0;
                    var nodePadding = nodeSeparation / 3;
                    var loosePadding = SplineRouter.ComputeLooseSplinePadding(nodeSeparation, nodePadding);*/
                    //if (mode == EdgeRoutingMode.Spline)
                    if (mode == EdgeRoutingMode.Spline)
                        settings.BundlingSettings = null;
                    new SplineRouter(gg, settings).Run(CancelToken);
                    //else
                    //BundledEdgeRouter.RouteEdgesInMetroMapStyle(gg, coneAngle, nodePadding, loosePadding, settings.BundlingSettings);
                }
                else if (mode == EdgeRoutingMode.StraightLine)
                {
                    new StraightLineEdges(gg.Edges, settings.Padding).Run(CancelToken);
                }

                // Place labels
                new EdgeLabelPlacement(gg).Run(CancelToken);

                if (CancelToken == null || !CancelToken.Canceled)
                {
                    //                    foreach (GeometryEdge e in gg.Edges)
                    //                      TransformUnderlyingPolyline(gg, e, (dg.LayoutAlgorithmSettings as SugiyamaLayoutSettings).Transformation);
                    gg.UpdateBoundingBox();
                    Dispatcher.BeginInvoke(Invalidate);
                }
            }
        }
        static void PostRunTransform(GeometryGraph geometryGraph, SugiyamaLayoutSettings settings) {
            bool transform = !settings.Transformation.IsIdentity;
            if (transform) {
                foreach (Node n in geometryGraph.Nodes)
                    n.Transform(settings.Transformation);
                foreach (var n in geometryGraph.RootCluster.AllClustersDepthFirst()) {
                    n.Transform(settings.Transformation);
                    n.RectangularBoundary.Rect = n.BoundaryCurve.BoundingBox;
                }

                //restore labels widths and heights
                foreach (Edge e in geometryGraph.Edges) {
                    if (e.Label != null) {
                        e.Label.Width = e.OriginalLabelWidth;
                        e.Label.Height = e.OriginalLabelHeight;
                    }
                }

                TransformCurves(geometryGraph, settings);
            }
            geometryGraph.UpdateBoundingBox();
        }
 /// <summary>
 /// </summary>
 /// <param name="geometryGraph"></param>
 /// <param name="layoutSettings"></param>
 /// <param name="edgesToRoute"></param>
 public static void RouteAndLabelEdges(GeometryGraph geometryGraph, LayoutAlgorithmSettings layoutSettings, IEnumerable<Edge> edgesToRoute) {
     //todo: what about parent edges!!!!
     var filteredEdgesToRoute =
         edgesToRoute.Where(e => ! e.UnderCollapsedCluster()).ToArray();
     var ers = layoutSettings.EdgeRoutingSettings;
     if (ers.EdgeRoutingMode == EdgeRoutingMode.Rectilinear ||
         ers.EdgeRoutingMode == EdgeRoutingMode.RectilinearToCenter) {
         RectilinearInteractiveEditor.CreatePortsAndRouteEdges(
             layoutSettings.NodeSeparation/3,
             layoutSettings.NodeSeparation/3,
             geometryGraph.Nodes,
             edgesToRoute,
             ers.EdgeRoutingMode,
             true,
             ers.UseObstacleRectangles,
             ers.BendPenalty);
     } else if (ers.EdgeRoutingMode == EdgeRoutingMode.Spline || ers.EdgeRoutingMode==EdgeRoutingMode.SugiyamaSplines) {
         new SplineRouter(geometryGraph, filteredEdgesToRoute, ers.Padding, ers.PolylinePadding, ers.ConeAngle, null)
         {
             ContinueOnOverlaps = true, KeepOriginalSpline = ers.KeepOriginalSpline
         }.Run();
     } else if (ers.EdgeRoutingMode == EdgeRoutingMode.SplineBundling) {
         var edgeBundlingSettings = ers.BundlingSettings ?? new BundlingSettings();
         var bundleRouter = new SplineRouter(geometryGraph, filteredEdgesToRoute, ers.Padding, ers.PolylinePadding, ers.ConeAngle,
                                             edgeBundlingSettings) {
                                                 KeepOriginalSpline = ers.KeepOriginalSpline
                                             };
         bundleRouter.Run();
         if (bundleRouter.OverlapsDetected)
         {
             new SplineRouter(geometryGraph, filteredEdgesToRoute, ers.Padding, ers.PolylinePadding, ers.ConeAngle, null)
             {
                 ContinueOnOverlaps = true,
                 KeepOriginalSpline = ers.KeepOriginalSpline
             }.Run();
         }                
     } else if (ers.EdgeRoutingMode == EdgeRoutingMode.StraightLine) {
         var router = new StraightLineEdges(filteredEdgesToRoute, ers.Padding);
         router.Run();
     }
     var elb = new EdgeLabelPlacement(geometryGraph.Nodes, filteredEdgesToRoute);
     elb.Run();
     geometryGraph.UpdateBoundingBox();
 }
        private void LayoutComponent(GeometryGraph component)
        {
            if (component.Nodes.Count > 1 || component.RootCluster.Clusters.Any())
            {
                // for small graphs (below 100 nodes) do extra iterations
                settings.MaxIterations = LayoutAlgorithmHelpers.NegativeLinearInterpolation(
                    component.Nodes.Count,
                    /*lowerThreshold:*/ 50, /*upperThreshold:*/ 500, /*minIterations:*/ 5, /*maxIterations:*/ 10);
                settings.MinorIterations = LayoutAlgorithmHelpers.NegativeLinearInterpolation(component.Nodes.Count,
                    /*lowerThreshold:*/ 50, /*upperThreshold:*/ 500, /*minIterations:*/ 3, /*maxIterations:*/ 20);

                if (settings.MinConstraintLevel == 0)
                {
                    // run PivotMDS with a largish Scale so that the layout comes back oversized.
                    // subsequent incremental iterations do a better job of untangling when they're pulling it in
                    // rather than pushing it apart.
                    PivotMDS pivotMDS = new PivotMDS(component) { Scale = 2 };
                    this.RunChildAlgorithm(pivotMDS, 0.5 / componentCount);
                }
                FastIncrementalLayout fil = new FastIncrementalLayout(component, settings, settings.MinConstraintLevel, anyCluster => settings);
                Debug.Assert(settings.Iterations == 0);

                foreach (var level in GetConstraintLevels(component))
                {
                    if (level > settings.MaxConstraintLevel)
                    {
                        break;
                    }
                    if (level > settings.MinConstraintLevel)
                    {
                        fil.CurrentConstraintLevel = level;
                    }
                    do
                    {
                        fil.Run();
                    } while (!settings.IsDone);
                }
            }

            // Pad the graph with margins so the packing will be spaced out.
            component.Margins = settings.NodeSeparation;
            component.UpdateBoundingBox();

            // Zero the graph
            component.Translate(-component.BoundingBox.LeftBottom);
        }
        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();
        }
		/// <summary>
		/// 
		/// </summary>
		public void IncrementalRun(CancelToken cancelToken, GeometryGraph graph, Func<Cluster, LayoutAlgorithmSettings> clusterSettings)
        {
            if (cancelToken != null)
            {
                cancelToken.ThrowIfCanceled();
            }
            SetupIncrementalRun(graph, clusterSettings);
            algorithm.Run(cancelToken);
            graph.UpdateBoundingBox();
        }
 /// <summary>
 /// Run the FastIncrementalLayout instance incrementally
 /// </summary>
 public void IncrementalRun(GeometryGraph graph, Func<Cluster, LayoutAlgorithmSettings> clusterSettings)
 {
     SetupIncrementalRun(graph, clusterSettings);
     algorithm.Run();
     graph.UpdateBoundingBox();
 }
        static void FillGraph(Graph graph, DebugCurve[] debugCurves) {
            var gg = new GeometryGraph { DebugCurves = debugCurves};
            gg.Margins = 5;
            graph.GeometryGraph = gg;
            
            gg.UpdateBoundingBox();

           
          
        }
        /// <summary>
        /// Executes the algorithm.
        /// </summary>
        /// <summary>
        /// Executes the actual algorithm.
        /// </summary>
        protected override void RunInternal()
        {
            var g = new GeometryGraph();
            foreach (var v in graph.Nodes)
            {
                Debug.Assert(!(v is Cluster));
                var u = new Node(v.BoundaryCurve.Clone())
                {
                    UserData = v
                };
                v.AlgorithmData = new PivotMDSNodeWrap(u);
                g.Nodes.Add(u);
            }
            double avgLength = 0;
            foreach (var e in graph.Edges)
            {
                avgLength += e.Length;
                if (e.Source is Cluster || e.Target is Cluster) continue;
                var u = e.Source.AlgorithmData as PivotMDSNodeWrap;
                var v = e.Target.AlgorithmData as PivotMDSNodeWrap;
                var ee = new Edge(u.node, v.node)
                {
                    Length = e.Length
                };
                g.Edges.Add(ee);
            }
            if (graph.Edges.Count != 0)
            {
                avgLength /= graph.Edges.Count;
            }
            else
            {
                avgLength = 100;
            }

            // create edges from the children of each parent cluster to the parent cluster node
            foreach (var c in graph.RootCluster.AllClustersDepthFirst())
            {
                if (c == graph.RootCluster) continue;

                var u = new Node(CurveFactory.CreateRectangle(10, 10, new Point()));
                u.UserData = c;
                c.AlgorithmData = new PivotMDSNodeWrap(u);
                g.Nodes.Add(u);
                    
                foreach (var v in c.Nodes.Concat(from cc in c.Clusters select (Node)cc))
                {
                    var vv = v.AlgorithmData as PivotMDSNodeWrap;
                    g.Edges.Add(new Edge(u, vv.node)
                    {
                        Length = avgLength
                    });
                }
            }

            // create edges between clusters
            foreach (var e in graph.Edges)
            {
                if (e.Source is Cluster || e.Target is Cluster)
                {
                    var u = e.Source.AlgorithmData as PivotMDSNodeWrap;
                    var v = e.Target.AlgorithmData as PivotMDSNodeWrap;
                    var ee = new Edge(u.node, v.node)
                    {
                        Length = e.Length
                    };
                    g.Edges.Add(ee);
                }
            }

            // with 0 majorization iterations we just do PivotMDS
            MdsLayoutSettings settings = new MdsLayoutSettings
            {
                ScaleX = this.Scale,
                ScaleY = this.Scale,
                IterationsWithMajorization = 0,
                RemoveOverlaps = false,
                AdjustScale = false
            };

            MdsGraphLayout mdsLayout = new MdsGraphLayout(settings, g);
            this.RunChildAlgorithm(mdsLayout, 1.0);

            g.UpdateBoundingBox();
            foreach (var v in graph.Nodes)
            {
                var m = v.AlgorithmData as PivotMDSNodeWrap;
                v.Center = m.node.Center;
            }
        }
        static void PostRunTransform(GeometryGraph geometryGraph, PlaneTransformation transformation)
        {
            bool transform = !transformation.IsIdentity;
            if (transform)
            {
                foreach (Node n in geometryGraph.Nodes)
                {
                    n.Transform(transformation);
                }

                //restore labels widths and heights
                foreach (Edge e in geometryGraph.Edges)
                {
                    if (e.Label != null)
                    {
                        e.Label.Width = e.OriginalLabelWidth;
                        e.Label.Height = e.OriginalLabelHeight;
                    }
                }

                TransformCurves(geometryGraph, transformation);
            }

            geometryGraph.UpdateBoundingBox();
        }
예제 #14
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();
        }