private void ConfigureGrouping() { IOptionItem groupingItem = Handler.GetItemByName("GROUPING.GROUP_LAYOUT_POLICY"); switch ((string)groupingItem.Value) { case IGNORE_GROUPS: preStage = new HideGroupsStage(); organic.PrependStage(preStage); break; case LAYOUT_GROUPS: //do nothing... break; case FIX_GROUP_BOUNDS: IDataProvider groupDP = CurrentLayoutGraph.GetDataProvider(GroupingKeys.GroupDpKey); if (groupDP != null) { groupNodeContentDP = Maps.CreateHashedNodeMap(); foreach (Node node in CurrentLayoutGraph.Nodes) { if (groupDP.GetBool(node)) { groupNodeContentDP.Set(node, GroupNodeMode.FixBounds); } } CurrentLayoutGraph.AddDataProvider(OrganicLayout.GroupNodeModeDpKey, groupNodeContentDP); } break; case FIX_GROUP_CONTENTS: groupDP = CurrentLayoutGraph.GetDataProvider(GroupingKeys.GroupDpKey); if (groupDP != null) { groupNodeContentDP = Maps.CreateHashedNodeMap(); foreach (Node node in CurrentLayoutGraph.Nodes) { if (groupDP.GetBool(node)) { groupNodeContentDP.Set(node, GroupNodeMode.FixContents); } } CurrentLayoutGraph.AddDataProvider(OrganicLayout.GroupNodeModeDpKey, groupNodeContentDP); } break; } }
protected override void OptimizeAfterSequencing(IComparer <object> inEdgeOrder, IComparer <object> outEdgeOrder, LayoutGraph graph, ILayers layers, ILayoutDataProvider ldp, IItemFactory itemFactory) { edge2LaneCrossing = Maps.CreateHashedEdgeMap(); node2LaneAlignment = Maps.CreateHashedNodeMap(); var criticalEdges = Maps.CreateHashedEdgeMap(); // determine whether an edge crosses a swim lane border and if so in which direction foreach (var edge in graph.Edges) { var originalEdge = GetOriginalEdge(edge, ldp); // now we have a 'real' edge with valid valid source and target nodes var originalSourceId = GetLaneId(originalEdge.Source, ldp); var originalTargetId = GetLaneId(originalEdge.Target, ldp); LaneCrossing crossing = LaneCrossing.None; if (originalSourceId != originalTargetId) { // check if we need to flip the sides because edge and original edge have different directions var flipSides = edge.Source != originalEdge.Source; var sourceId = flipSides ? originalTargetId : originalSourceId; var targetId = flipSides ? originalSourceId : originalTargetId; crossing = sourceId > targetId ? LaneCrossing.ToWest : LaneCrossing.ToEast; } edge2LaneCrossing.Set(edge, crossing); } // determine basic node alignment foreach (var n in graph.Nodes) { LaneAlignment alignment = CalculateLaneAlignment(n); node2LaneAlignment.Set(n, alignment); } foreach (var n in graph.Nodes) { // sort the edges with the provided comparer n.SortInEdges(inEdgeOrder); n.SortOutEdges(outEdgeOrder); // calculate 'critical' in and out-edges whose nodes should be aligned in flow var bestInEdge = n.InDegree > 0 ? GetBestFlowEdge(n.InEdges, ldp, graph) : null; var bestOutEdge = n.OutDegree > 0 ? GetBestFlowEdge(n.OutEdges, ldp, graph) : null; if (bestInEdge != null) { criticalEdges.SetDouble(bestInEdge, criticalEdges.GetDouble(bestInEdge) + 0.5); } if (bestOutEdge != null) { criticalEdges.SetDouble(bestOutEdge, criticalEdges.GetDouble(bestOutEdge) + 0.5); } if (n.Degree <= 4) { // should usually be the case and we can distribute each edge to its own side // remember which node side is already taken by an in- or out-edge bool westTakenByInEdge = false; bool eastTakenByInEdge = false; bool westTakenByOutEdge = false; bool eastTakenByOutEdge = false; if (n.InDegree > 0 && n.OutDegree < 3) { // if there are at least three out-edges, we distribute those first, otherwise we start with the in-edges var firstInEdge = n.FirstInEdge; var lastInEdge = n.LastInEdge; if (GetLaneCrossing(firstInEdge) == LaneCrossing.ToEast && (n.InDegree > 1 || IsSameLayerEdge(firstInEdge, ldp))) { // the first in-edge comes from west and is either a same layer edge or there are other in-edges ConstrainWest(firstInEdge, false, itemFactory); westTakenByInEdge = true; } if (!westTakenByInEdge || n.OutDegree < 2) { // don't use west and east side for in-edges if there are at least 2 out-edges if (GetLaneCrossing(lastInEdge) == LaneCrossing.ToWest && (n.InDegree > 1 || IsSameLayerEdge(lastInEdge, ldp))) { // the last in-edge comes from east and is either // a same-layer edge or there are other in-edges ConstrainEast(lastInEdge, false, itemFactory); eastTakenByInEdge = true; } } } if (n.OutDegree > 0) { var firstOutEdge = n.FirstOutEdge; var lastOutEdge = n.LastOutEdge; if (!westTakenByInEdge) { // the west side is still free if (BpmnLayout.IsBoundaryInterrupting(firstOutEdge, graph) || (GetLaneCrossing(firstOutEdge) == LaneCrossing.ToWest) && (n.OutDegree > 1 || IsSameLayerEdge(firstOutEdge, ldp))) { // the first out-edge is either boundary interrupting or goes to west and // is either a same layer edge or there are other out-edges ConstrainWest(firstOutEdge, true, itemFactory); westTakenByOutEdge = true; } else if (eastTakenByInEdge && n.OutDegree >= 2 && !IsSameLayerEdge(firstOutEdge.NextOutEdge, ldp)) { // the east side is already taken but we have more then one out edge. // if the second out edge is a same layer edge, constraining the firstOutEdge could lead to // no in-flow edge ConstrainWest(firstOutEdge, true, itemFactory); westTakenByOutEdge = true; } } if (!eastTakenByInEdge) { // the east side is still free if (GetLaneCrossing(lastOutEdge) == LaneCrossing.ToEast && (n.OutDegree > 1 || IsSameLayerEdge(lastOutEdge, ldp))) { // the last out-edge goes to east and // is either a same layer edge or there are other out-edges ConstrainEast(lastOutEdge, true, itemFactory); eastTakenByOutEdge = true; } else if (westTakenByInEdge && n.OutDegree >= 2 && !IsSameLayerEdge(lastOutEdge.PrevOutEdge, ldp)) { // the west side is already taken but we have more then one out edge. // if the second last out edge is a same layer edge, constraining the lastOutEdge could lead to // no in-flow edge ConstrainEast(lastOutEdge, true, itemFactory); eastTakenByOutEdge = true; } } } // distribute remaining in-edges if (n.InDegree == 2 && !(eastTakenByInEdge || westTakenByInEdge)) { // two in-edges but none distributed, yet if (bestInEdge == n.FirstInEdge && !eastTakenByOutEdge) { // first in-edge is in-flow edge and east side is still free ConstrainEast(n.LastInEdge, false, itemFactory); eastTakenByInEdge = true; } else if (bestInEdge == n.LastInEdge && !westTakenByOutEdge) { // last in-edge is in-flow edge and west side is still free ConstrainWest(n.FirstInEdge, false, itemFactory); westTakenByInEdge = true; } } else if (n.InDegree == 3 && !(eastTakenByInEdge && westTakenByInEdge) && !(IsSameLayerEdge(n.FirstInEdge.NextInEdge, ldp))) { // three in-edges but not both sides taken, yet and the middle edge is no same layer edge if (!eastTakenByOutEdge) { // if not already taken, constraint the last in-edge to east ConstrainEast(n.LastInEdge, false, itemFactory); eastTakenByInEdge = true; } if (!westTakenByOutEdge) { // if not already taken, constraint the first in-edge to west ConstrainWest(n.FirstInEdge, false, itemFactory); westTakenByInEdge = true; } } // distribute remaining out-edges if (n.OutDegree == 2 && !(eastTakenByOutEdge || westTakenByOutEdge)) { // two out-edges but none distributed, yet if (bestOutEdge == n.FirstOutEdge && !eastTakenByInEdge) { // first out-edge is in-flow edge and east side is still free ConstrainEast(n.LastOutEdge, true, itemFactory); eastTakenByOutEdge = true; } else if (bestOutEdge == n.LastOutEdge && !westTakenByInEdge) { // last out-edge is in-flow edge and west side is still free ConstrainWest(n.FirstOutEdge, true, itemFactory); westTakenByOutEdge = true; } } else if (n.OutDegree == 3 && !(eastTakenByOutEdge && westTakenByOutEdge) && !(IsSameLayerEdge(n.FirstOutEdge.NextOutEdge, ldp))) { // three out-edges but not both sides taken, yet and the middle edge is no same layer edge if (!eastTakenByInEdge) { // if not already taken, constraint the last out-edge to east ConstrainEast(n.LastOutEdge, true, itemFactory); eastTakenByOutEdge = true; } if (!westTakenByInEdge) { // if not already taken, constraint the first out-edge to west ConstrainWest(n.FirstOutEdge, true, itemFactory); westTakenByOutEdge = true; } } } } // register the data provider for critical edge paths. It is deregistered again by BpmnLayout itself graph.AddDataProvider(HierarchicLayout.CriticalEdgePriorityDpKey, criticalEdges); sameLayerData = null; edge2LaneCrossing = null; node2LaneAlignment = null; }
public static void Main() { Graph graph = new Graph(); const int nodes = 30000; const int loops = 10; const int outerLoops = 20; for (int i = 0; i < nodes; i++) { graph.CreateNode(); } for (int loop = 0; loop < outerLoops; loop++) { Console.Write("."); t1.Start(); INodeMap map = graph.CreateNodeMap(); for (int i = 0; i < loops; i++) { for (INodeCursor nc = graph.GetNodeCursor(); nc.Ok; nc.Next()) { Node v = nc.Node; map.SetInt(v, i); i = map.GetInt(v); } } graph.DisposeNodeMap(map); t1.Stop(); t2.Start(); map = Maps.CreateIndexNodeMap(new int[graph.N]); for (int i = 0; i < loops; i++) { for (INodeCursor nc = graph.GetNodeCursor(); nc.Ok; nc.Next()) { Node v = nc.Node; map.SetInt(v, i); map.GetInt(v); } } t2.Stop(); t3.Start(); map = Maps.CreateHashedNodeMap(); for (int i = 0; i < loops; i++) { for (INodeCursor nc = graph.GetNodeCursor(); nc.Ok; nc.Next()) { Node v = nc.Node; map.SetInt(v, i); i = map.GetInt(v); } } t3.Stop(); t4.Start(); int[] array = new int[graph.N]; for (int i = 0; i < loops; i++) { for (INodeCursor nc = graph.GetNodeCursor(); nc.Ok; nc.Next()) { int vid = nc.Node.Index; array[vid] = i; i = array[vid]; } } t4.Stop(); t5.Start(); IDictionary <Node, int> dictionary = new Dictionary <Node, int>(2 * graph.N + 1); //use map with good initial size for (int i = 0; i < loops; i++) { for (INodeCursor nc = graph.GetNodeCursor(); nc.Ok; nc.Next()) { Node v = nc.Node; dictionary[v] = i; i = dictionary[v]; } } t5.Stop(); t6.Start(); IDictionary <Node, object> objectDictionary = new Dictionary <Node, object>(2 * graph.N + 1); //use map with good initial size for (int i = 0; i < loops; i++) { for (INodeCursor nc = graph.GetNodeCursor(); nc.Ok; nc.Next()) { Node v = nc.Node; objectDictionary[v] = i; i = (int)objectDictionary[v]; } } t6.Stop(); } Console.WriteLine(""); Console.WriteLine("TIME: standard NodeMap : " + t1); Console.WriteLine("TIME: index NodeMap : " + t2); Console.WriteLine("TIME: hashed NodeMap : " + t3); Console.WriteLine("TIME: plain array : " + t4); Console.WriteLine("TIME: Dictionary : " + t5); Console.WriteLine("TIME: object Dictionary : " + t6); Console.WriteLine("\nPress key to end demo."); Console.ReadKey(); }