/// <summary> /// Get the <see cref="Edge"/> representing the original edge on the graph. /// </summary> /// <remarks> /// As the core layout algorithm creates temporary edges for example for same-layer edges and edges spanning /// multiple layers, we need to lookup the original edge of the graph for example as key in data providers. /// </remarks> private Edge GetOriginalEdge(Edge edge, ILayoutDataProvider ldp) { var originalEdge = sameLayerData.GetOriginalEdge(edge.Source) ?? (sameLayerData.GetOriginalEdge(edge.Target) ?? edge); var edgeData = ldp.GetEdgeData(originalEdge); return(edgeData.AssociatedEdge ?? originalEdge); }
/// <summary> /// Returns the best suited edge in <paramref name="edges"/> for use as in-flow edge or <see langword="null"/> /// if no such edge could be found. /// </summary> private Edge GetBestFlowEdge(IEnumerable <Edge> edges, ILayoutDataProvider ldp, LayoutGraph graph) { List <Edge> weakCandidates = new List <Edge>(); List <Edge> candidates = new List <Edge>(); foreach (var edge in edges) { var originalEdge = GetOriginalEdge(edge, ldp); if ((LaneCrossing)edge2LaneCrossing.Get(edge) != LaneCrossing.None || BpmnLayout.IsBoundaryInterrupting(originalEdge, graph) || IsSameLayerEdge(originalEdge, ldp) || edge.SelfLoop) { // an edge should not be aligned if: // - it crosses stripe borders // - it is boundary interrupting // - it is a same-layer edge // - it is a self-loop continue; } if (ldp.GetEdgeData(edge).Reversed || !BpmnLayout.IsSequenceFlow(originalEdge, graph)) { // it is only a weak candidate if: // - it is reversed // - it is no sequence flow weakCandidates.Add(edge); } else { candidates.Add(edge); } } if (candidates.Count > 0) { // if there are several candidates, choose the one that would keep the LaneAlignment // of its source and target node consistent candidates.Sort((edge1, edge2) => { var ac1 = GetAlignmentConsistency(edge1); var ac2 = GetAlignmentConsistency(edge2); return(ac2 - ac1); }); return(candidates[0]); } if (weakCandidates.Count > 0) { return(weakCandidates[(int)Math.Floor(weakCandidates.Count / 2.0)]); } return(null); }