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();
            }
      /// <summary>
      /// Removes all edges that are incident to group nodes and passes it to the core layout algorithm.
      /// </summary>
      /// <remarks>
      /// This stage removes some edges from the graph such that no edges incident to group nodes
      /// exist. Then, it applies the core layout algorithm to the reduced graph.
      /// After it produces the result, it re-inserts the previously removed edges and routes them.
      /// </remarks>
      public override void ApplyLayout(LayoutGraph graph) {
        var groupingSupport = new yWorks.Layout.Grouping.GroupingSupport(graph);

        if (!GroupingSupport.IsGrouped(graph)) {
          ApplyLayoutCore(graph);
        } else {
          var hiddenEdgesMap = Maps.CreateHashedEdgeMap();

          var edgeHider = new LayoutGraphHider(graph);

          var existHiddenEdges = false;
          foreach (var edge in graph.Edges) {
            if (groupingSupport.IsGroupNode(edge.Source) || groupingSupport.IsGroupNode(edge.Target)) {
              hiddenEdgesMap.Set(edge, true);
              edgeHider.Hide(edge);
              existHiddenEdges = true;
            } else {
              hiddenEdgesMap.Set(edge, false);
            }
          }

          ApplyLayoutCore(graph);

          if (existHiddenEdges) {
            edgeHider.UnhideAll();

            // routes the marked edges
            RouteMarkedEdges(graph, hiddenEdgesMap);

            if (ConsiderEdgeLabels) {
              // all labels of hidden edges should be marked
              var affectedLabelsDpKey = "affectedLabelsDpKey";
              var nonTreeLabelsMap = Maps.CreateHashedDataMap();

              foreach (var edge in graph.Edges) {
                var ell = graph.GetLabelLayout(edge);
                foreach (var labelLayout in ell) {
                  nonTreeLabelsMap.Set(labelLayout, hiddenEdgesMap.Get(edge));
                }
              }

              // add selection marker
              graph.AddDataProvider(affectedLabelsDpKey, nonTreeLabelsMap);

              // place marked labels
              var labeling = new GenericLabeling {
                  PlaceNodeLabels = false,
                  PlaceEdgeLabels = true,
                  AffectedLabelsDpKey = affectedLabelsDpKey,
              };
              labeling.ApplyLayout(graph);

              // dispose selection key
              graph.RemoveDataProvider(affectedLabelsDpKey);
            }
          }
        }
      }
Пример #3
0
        /// <inheritdoc/>
        public override void AssignLayers(LayoutGraph graph, ILayers layers, ILayoutDataProvider ldp)
        {
            // get core layer assignment
            base.AssignLayers(graph, layers, ldp);

            // Hide all edges that are no sequence flows
            var graphHider = new LayoutGraphHider(graph);

            foreach (var edge in graph.GetEdgeArray())
            {
                if (!BpmnLayout.IsSequenceFlow(edge, graph))
                {
                    graphHider.Hide(edge);
                }
            }

            // determine current layer of all nodes
            currentLayers = new int[graph.NodeCount];
            for (int i = 0; i < layers.Size(); i++)
            {
                for (INodeCursor nc = layers.GetLayer(i).List.Nodes(); nc.Ok; nc.Next())
                {
                    currentLayers[nc.Node.Index] = i;
                }
            }

            // mark nodes on a back-loop and candidates that may be on a back loop if other back-loop nodes are reassigned
            nodeStates = new NodeState[graph.NodeCount];
            NodeList candidates    = new NodeList();
            NodeList backLoopNodes = new NodeList();

            for (int i = layers.Size() - 1; i >= 0; i--)
            {
                // check from last to first layer to detect candidates as well
                NodeList nodes = layers.GetLayer(i).List;
                UpdateNodeStates(nodes, backLoopNodes, candidates);
            }

            // swap layer for back-loop nodes
            while (backLoopNodes.Count > 0)
            {
                for (INodeCursor nc = backLoopNodes.Nodes(); nc.Ok; nc.Next())
                {
                    Node node         = nc.Node;
                    int  currentLayer = currentLayers[node.Index];
                    // the target layer is the next layer after the highest fixed target node layer
                    int targetLayer = 0;
                    for (Edge edge = node.FirstOutEdge; edge != null; edge = edge.NextOutEdge)
                    {
                        int targetNodeIndex = edge.Target.Index;
                        if (nodeStates[targetNodeIndex] == NodeState.Fixed)
                        {
                            targetLayer = Math.Max(targetLayer, currentLayers[targetNodeIndex] + 1);
                        }
                    }
                    if (targetLayer == 0)
                    {
                        // no fixed target found, so all targets must be candidates
                        // -> we skip the node as we don't know where the candidates will be placed at the end
                        continue;
                    }
                    if (targetLayer < currentLayer)
                    {
                        layers.GetLayer(currentLayer).Remove(node);
                        layers.GetLayer(targetLayer).Add(node);
                        currentLayers[node.Index] = targetLayer;
                        nodeStates[node.Index]    = NodeState.Fixed;
                    }
                }
                backLoopNodes.Clear();

                // update states of the candidates
                candidates = UpdateNodeStates(candidates, backLoopNodes, new NodeList());
            }

            // remove empty layers
            for (int i = layers.Size() - 1; i >= 0; i--)
            {
                if (layers.GetLayer(i).List.Count == 0)
                {
                    layers.Remove(i);
                }
            }

            // cleanup
            graphHider.UnhideAll();
            nodeStates    = null;
            currentLayers = null;
        }