public override void ApplyLayout(LayoutGraph graph)
            {
                var affectedEdges = graph.GetDataProvider(BusRouter.DefaultAffectedEdgesDpKey);
                var selectedNodes = graph.GetDataProvider(SelectedNodesDpKey);
                var hider         = new LayoutGraphHider(graph);
                var hiddenEdges   = new HashSet <Edge>();

                foreach (var edge in graph.Edges)
                {
                    if (affectedEdges.GetBool(edge) &&
                        selectedNodes != null &&
                        !selectedNodes.GetBool(edge.Source) &&
                        !selectedNodes.GetBool(edge.Target))
                    {
                        var path = graph.GetPath(edge).ToArray();
                        for (var i = 1; i < path.Length; i++)
                        {
                            var p1 = path[i - 1];
                            var p2 = path[i];
                            if (Math.Abs(p1.X - p2.X) >= 0.0001 && Math.Abs(p1.Y - p2.Y) >= 0.0001)
                            {
                                hiddenEdges.Add(edge);
                            }
                        }
                    }
                }
                foreach (var edge in hiddenEdges)
                {
                    hider.Hide(edge);
                }

                ApplyLayoutCore(graph);

                hider.UnhideEdges();
            }
Пример #2
0
            public override void ApplyLayout(LayoutGraph graph)
            {
                // determine the single node to keep at the center.
                var  provider   = graph.GetDataProvider("NodeLayouts");
                Node centerNode = null;

                if (provider != null)
                {
                    centerNode = graph.Nodes.FirstOrDefault(n => provider.Get(n) != null);
                }
                if (CoreLayout != null)
                {
                    if (centerNode != null)
                    {
                        // remember old center
                        RectD oldLayout     = (RectD)provider.Get(centerNode);
                        var   fixedLocation = new YPoint(graph.GetX(centerNode) + graph.GetWidth(centerNode), graph.GetY(centerNode));
                        //Set to saved size (this is important for collapsed nodes to ensure correct size)
                        graph.SetSize(centerNode, oldLayout.Width, oldLayout.Height);
                        // run layout
                        CoreLayout.ApplyLayout(graph);
                        // obtain new center
                        var newFixedLocation = new YPoint(graph.GetX(centerNode) + graph.GetWidth(centerNode),
                                                          graph.GetY(centerNode));
                        // and adjust the layout
                        LayoutGraphUtilities.MoveSubgraph(graph, graph.GetNodeCursor(), fixedLocation.X - newFixedLocation.X,
                                                          fixedLocation.Y - newFixedLocation.Y);
                    }
                    else
                    {
                        CoreLayout.ApplyLayout(graph);
                    }
                }
            }
Пример #3
0
            private void RouteMarkedEdges(LayoutGraph graph, IDataMap markedEdgesMap)
            {
                if (MarkedEdgeRouter == null)
                {
                    return;
                }

                IDataProvider backupDp = null;

                if (EdgeSelectionKey != null)
                {
                    backupDp = graph.GetDataProvider(EdgeSelectionKey);
                    graph.AddDataProvider(EdgeSelectionKey, markedEdgesMap);
                }
                if (MarkedEdgeRouter is StraightLineEdgeRouter)
                {
                    var router = (StraightLineEdgeRouter)MarkedEdgeRouter;
                    router.Scope = Scope.RouteAffectedEdges;
                    router.AffectedEdgesDpKey = EdgeSelectionKey;
                }

                MarkedEdgeRouter.ApplyLayout(graph);

                if (EdgeSelectionKey != null)
                {
                    graph.RemoveDataProvider(EdgeSelectionKey);

                    if (backupDp != null)
                    {
                        graph.AddDataProvider(EdgeSelectionKey, backupDp);
                    }
                }
            }
Пример #4
0
        public override void ApplyLayout(LayoutGraph graph)
        {
            var dataProvider = graph.GetDataProvider(SelectedLabelsAtItemKey);

            graph.AddDataProvider(ProviderKey, new MyDataProviderAdapter(dataProvider, graph));
            ApplyLayoutCore(graph);
            graph.RemoveDataProvider(ProviderKey);
        }
        private void AdjustNodeSize(Node node, LayoutGraph graph)
        {
            double width  = 60;
            double height = 40;

            var leftEdgeSpace  = CalcRequiredSpace(node.InEdges, graph);
            var rightEdgeSpace = CalcRequiredSpace(node.OutEdges, graph);

            if (LayoutOrientation == LayoutOrientation.TopToBottom || LayoutOrientation == LayoutOrientation.BottomToTop)
            {
                // we have to enlarge the width such that the in-/out-edges can be placed side by side without overlaps
                width = Math.Max(width, leftEdgeSpace);
                width = Math.Max(width, rightEdgeSpace);
            }
            else
            {
                // we have to enlarge the height such that the in-/out-edges can be placed side by side without overlaps
                height = Math.Max(height, leftEdgeSpace);
                height = Math.Max(height, rightEdgeSpace);
            }

            // adjust size for edges with strong port constraints
            var edgeThicknessDP = graph.GetDataProvider(HierarchicLayout.EdgeThicknessDpKey);

            if (edgeThicknessDP != null)
            {
                foreach (var edge in node.Edges)
                {
                    var thickness = edgeThicknessDP.GetDouble(edge);

                    var spc = PortConstraint.GetSPC(graph, edge);
                    if (edge.Source == node && spc != null && spc.Strong)
                    {
                        var sourcePoint = graph.GetSourcePointRel(edge);
                        width  = Math.Max(width, Math.Abs(sourcePoint.X) * 2 + thickness);
                        height = Math.Max(height, Math.Abs(sourcePoint.Y) * 2 + thickness);
                    }

                    var tpc = PortConstraint.GetTPC(graph, edge);
                    if (edge.Target == node && tpc != null && tpc.Strong)
                    {
                        var targetPoint = graph.GetTargetPointRel(edge);
                        width  = Math.Max(width, Math.Abs(targetPoint.X) * 2 + thickness);
                        height = Math.Max(height, Math.Abs(targetPoint.Y) * 2 + thickness);
                    }
                }
            }
            graph.SetSize(node, width, height);
        }
        private double CalcRequiredSpace(IEnumerable <Edge> edges, LayoutGraph graph)
        {
            double requiredSpace   = 0;
            var    edgeThicknessDP = graph.GetDataProvider(HierarchicLayout.EdgeThicknessDpKey);
            var    count           = 0;

            foreach (var edge in edges)
            {
                var thickness = edgeThicknessDP?.GetDouble(edge) ?? 0;
                requiredSpace += Math.Max(thickness, 1);
                count++;
            }
            requiredSpace += (count - 1) * MinimumPortDistance;
            requiredSpace += 2 * PortBorderGapRatio * MinimumPortDistance;
            return(requiredSpace);
        }
Пример #7
0
        /// <inheritdoc/>
        public override void ApplyLayout(LayoutGraph graph)
        {
            // first layout the non-tree edges
            nonTreeEdgeRouter.Scope = Scope.RouteAffectedEdges;
            nonTreeEdgeRouter.ApplyLayout(graph);

            // the tree reduction stage only prepares a data provider to mark the non-tree edges but we need
            // a provider to mark the labels of all non-tree edges:
            // for t
            var nonTreeEdgeDp = graph.GetDataProvider(LayoutKeys.AffectedEdgesDpKey);

            graph.AddDataProvider("nonTreeLabels", new NonTeeEdgesDataProvider(graph, nonTreeEdgeDp));

            nonTreeEdgeLabelLayout.AffectedLabelsDpKey = "nonTreeLabels";
            nonTreeEdgeLabelLayout.ApplyLayout(graph);

            graph.RemoveDataProvider("nonTreeLabels");
        }
        /// <inheritdoc/>
        public void ApplyLayout(LayoutGraph graph)
        {
            var affectedNodesDP = graph.GetDataProvider(AffectedNodesDpKey);

            for (IEdgeCursor ec = graph.GetEdgeCursor(); ec.Ok; ec.Next())
            {
                Edge       e    = ec.Edge;
                YPointPath path = graph.GetPath(e);
                //adjust source point
                if (affectedNodesDP == null || affectedNodesDP.GetBool(e.Source))
                {
                    AdjustPortLocation(graph, e, path, true);
                }
                if (affectedNodesDP == null || affectedNodesDP.GetBool(e.Target))
                {
                    AdjustPortLocation(graph, e, path, false);
                }
            }
        }
Пример #9
0
        /// <summary>
        /// Returns if the edge is attached to a boundary interrupting event.
        /// </summary>
        /// <seealso cref="BoundaryInterruptingEdgesDpKey"/>.
        public static bool IsBoundaryInterrupting(Edge edge, LayoutGraph graph)
        {
            var isInterruptingDP = graph.GetDataProvider(BoundaryInterruptingEdgesDpKey);

            return(isInterruptingDP != null && isInterruptingDP.GetBool(edge));
        }
Пример #10
0
        /// <summary>
        /// Executes the layout algorithm.
        /// </summary>
        /// <remarks>
        /// <para>
        /// Enlarges the node layout to fully encompass the rotated layout (the rotated layout's bounding box).
        /// If the <see cref="EdgeRoutingMode"/> is set to <see cref="RoutingMode.FixedPort"/>
        /// port constraints are created to keep the ports at their current location.
        /// Existing port constraints are adjusted to the rotation.
        /// </para>
        /// <para>
        /// Then, the <see cref="LayoutStageBase.CoreLayout"/> is executed.
        /// </para>
        /// <para>
        /// After the core layout the original node sizes are restored.
        /// If the <see cref="EdgeRoutingMode"/> is set to <see cref="RoutingMode.ShortestStraightPathToBorder"/>
        /// the last edge segment is extended from the bounding box to the rotated layout.
        /// </para>
        /// </remarks>
        public override void ApplyLayout(LayoutGraph graph)
        {
            if (CoreLayout == null)
            {
                return;
            }

            var boundsProvider = graph.GetDataProvider(RotatedNodeLayoutDpKey);

            if (boundsProvider == null)
            {
                // no provider: this stage adds nothing to the core layout
                CoreLayout.ApplyLayout(graph);
                return;
            }

            bool     addedSourcePortConstraints  = false;
            bool     addedTargetPortContstraints = false;
            IDataMap sourcePortConstraints       = (IDataMap)graph.GetDataProvider(PortConstraintKeys.SourcePortConstraintDpKey);
            IDataMap targetPortConstraints       = (IDataMap)graph.GetDataProvider(PortConstraintKeys.TargetPortConstraintDpKey);

            if (EdgeRoutingMode == RoutingMode.FixedPort)
            {
                // Fixed port: create port constraints to keep the ports at position
                // in this case: create data providers if there are none yet
                if (sourcePortConstraints == null)
                {
                    sourcePortConstraints = graph.CreateEdgeMap();
                    graph.AddDataProvider(PortConstraintKeys.SourcePortConstraintDpKey, sourcePortConstraints);
                    addedSourcePortConstraints = true;
                }
                if (targetPortConstraints == null)
                {
                    targetPortConstraints = graph.CreateEdgeMap();
                    graph.AddDataProvider(PortConstraintKeys.TargetPortConstraintDpKey, targetPortConstraints);
                    addedTargetPortContstraints = true;
                }
            }
            try {
                var originalDimensions = new Dictionary <Node, OldDimensions>();
                foreach (var node in graph.Nodes)
                {
                    var nodeShape      = (RotatedNodeShape)boundsProvider.Get(node);
                    var orientedLayout = nodeShape != null ? nodeShape.OrientedLayout : null;
                    var outline        = nodeShape != null ? nodeShape.Outline : null;
                    if (orientedLayout != null)
                    {
                        // if the current node is rotated: apply fixes
                        // remember old layout and size
                        var oldLayout     = graph.GetLayout(node);
                        var newLayout     = orientedLayout.GetBounds().ToYRectangle();
                        var offset        = new PointD(newLayout.X - oldLayout.X, newLayout.Y - oldLayout.Y);
                        var originalSize  = new SizeD(oldLayout.Width, oldLayout.Height);
                        var oldDimensions = new OldDimensions {
                            offset  = offset,
                            size    = originalSize,
                            outline = outline
                        };
                        if (EdgeRoutingMode == RoutingMode.FixedPort)
                        {
                            // EdgeRoutingMode: FixedPort: keep the ports at their current location

                            // The oriented layout's corners to find the best PortSide
                            var tl = new PointD(orientedLayout.AnchorX + orientedLayout.UpX * orientedLayout.Height, orientedLayout.AnchorY + orientedLayout.UpY * orientedLayout.Height);
                            var tr = new PointD(orientedLayout.AnchorX + orientedLayout.UpX * orientedLayout.Height - orientedLayout.UpY * orientedLayout.Width,
                                                orientedLayout.AnchorY + orientedLayout.UpY * orientedLayout.Height + orientedLayout.UpX * orientedLayout.Width);
                            var bl = new PointD(orientedLayout.AnchorX, orientedLayout.AnchorY);
                            var br = new PointD(orientedLayout.AnchorX - orientedLayout.UpY * orientedLayout.Width, orientedLayout.AnchorY + orientedLayout.UpX * orientedLayout.Width);

                            // for each out edge
                            foreach (var edge in node.OutEdges)
                            {
                                // create a strong port constraint for the side which is closest to the port location (without rotation)
                                var constraint = sourcePortConstraints.Get(edge);
                                if (constraint == null)
                                {
                                    var point = graph.GetSourcePointAbs(edge).ToPointD();
                                    var side  = FindBestSide(point, bl, br, tl, tr);
                                    sourcePortConstraints.Set(edge, PortConstraint.Create(side, true));
                                }
                            }
                            foreach (var edge in node.InEdges)
                            {
                                // create a strong port constraint for the side which is closest to the port location (without rotation)
                                var constraint = targetPortConstraints.Get(edge);
                                if (constraint == null)
                                {
                                    var point = graph.GetTargetPointAbs(edge).ToPointD();
                                    var side  = FindBestSide(point, bl, br, tl, tr);
                                    targetPortConstraints.Set(edge, PortConstraint.Create(side, true));
                                }
                            }
                        }

                        // For source and target port constraints: fix the PortSide according to the rotation
                        var angle = Math.Atan2(orientedLayout.UpY, orientedLayout.UpX);
                        if (sourcePortConstraints != null)
                        {
                            foreach (var edge in node.OutEdges)
                            {
                                FixPortConstraintSide(sourcePortConstraints, edge, angle);
                            }
                        }
                        if (targetPortConstraints != null)
                        {
                            foreach (var edge in node.InEdges)
                            {
                                FixPortConstraintSide(targetPortConstraints, edge, angle);
                            }
                        }

                        // enlarge the node layout
                        var position = new YPoint(newLayout.X, newLayout.Y);
                        oldDimensions.location = position;
                        originalDimensions.Add(node, oldDimensions);
                        graph.SetLocation(node, position);
                        graph.SetSize(node, newLayout);
                    }
                }

                // ===============================================================

                CoreLayout.ApplyLayout(graph);

                // ===============================================================

                var groups = graph.GetDataProvider(GroupingKeys.GroupDpKey);
                foreach (var node in graph.Nodes)
                {
                    if (groups != null && groups.GetBool(node))
                    {
                        // groups don't need to be adjusted to their former size and location because their bounds are entirely
                        // calculated by the layout algorithm and they are not rotated
                        continue;
                    }

                    // for each node which has been corrected: undo the correction
                    var oldDimensions = originalDimensions[node];
                    var offset        = oldDimensions.offset;
                    var originalSize  = oldDimensions.size;
                    var newLayout     = graph.GetLayout(node);

                    // create a general path representing the new roated layout
                    var path      = oldDimensions.outline;
                    var transform = new Matrix2D();
                    transform.Translate(new PointD(newLayout.X - oldDimensions.location.X, newLayout.Y - oldDimensions.location.Y));
                    path.Transform(transform);

                    // restore the original size
                    graph.SetLocation(node, new YPoint(newLayout.X - offset.X, newLayout.Y - offset.Y));
                    graph.SetSize(node, originalSize.ToYDimension());

                    if (EdgeRoutingMode == RoutingMode.NoRouting)
                    {
                        // NoRouting still needs fix for self-loops
                        foreach (var edge in node.Edges)
                        {
                            if (edge.SelfLoop)
                            {
                                FixPorts(graph, edge, path, false);
                                FixPorts(graph, edge, path, true);
                            }
                        }
                        continue;
                    }

                    if (EdgeRoutingMode != RoutingMode.ShortestStraightPathToBorder)
                    {
                        continue;
                    }

                    // enlarge the adjacent segment to the oriented rectangle (represented by the path)
                    // handling in and out edges separately will automatically cause selfloops to be handled correctly
                    foreach (var edge in node.InEdges)
                    {
                        FixPorts(graph, edge, path, false);
                    }
                    foreach (var edge in node.OutEdges)
                    {
                        FixPorts(graph, edge, path, true);
                    }
                }
            } finally {
                // if data provider for the port constraints have been added
                // remove and dispose them
                if (addedSourcePortConstraints)
                {
                    graph.RemoveDataProvider(PortConstraintKeys.SourcePortConstraintDpKey);
                    graph.DisposeEdgeMap((IEdgeMap)sourcePortConstraints);
                }
                if (addedTargetPortContstraints)
                {
                    graph.RemoveDataProvider(PortConstraintKeys.TargetPortConstraintDpKey);
                    graph.DisposeEdgeMap((IEdgeMap)targetPortConstraints);
                }
            }
        }