private void AddAlternatingLayerToSparseCompactionGraph(AlternatingLayer nextAlternatingLayer, int layerIndex) { var _sparseCompationGraphEdgesOfLayer = _sparseCompactionByLayerBackup[layerIndex]; if (_sparseCompationGraphEdgesOfLayer != null) { foreach (var edge in _sparseCompationGraphEdgesOfLayer) { _sparseCompactionGraph.RemoveEdge(edge); } } _sparseCompationGraphEdgesOfLayer = new List <Edge <Data> >(); SugiVertex vertex = null, prevVertex = null; for (int i = 1; i < nextAlternatingLayer.Count; i += 2) { vertex = nextAlternatingLayer[i] as SugiVertex; var prevContainer = nextAlternatingLayer[i - 1] as SegmentContainer; var nextContainer = nextAlternatingLayer[i + 1] as SegmentContainer; if (prevContainer != null && prevContainer.Count > 0) { var lastSegment = prevContainer[prevContainer.Count - 1]; var edge = new Edge <Data>(lastSegment, vertex); _sparseCompationGraphEdgesOfLayer.Add(edge); _sparseCompactionGraph.AddVerticesAndEdge(edge); } else if (prevVertex != null) { var edge = new Edge <Data>(prevVertex, vertex); _sparseCompationGraphEdgesOfLayer.Add(edge); _sparseCompactionGraph.AddVerticesAndEdge(edge); } if (nextContainer != null && nextContainer.Count > 0) { var firstSegment = nextContainer[0]; var edge = new Edge <Data>(vertex, firstSegment); _sparseCompationGraphEdgesOfLayer.Add(edge); _sparseCompactionGraph.AddVerticesAndEdge(edge); } if (vertex != null && !_sparseCompactionGraph.ContainsVertex(vertex)) { _sparseCompactionGraph.AddVertex(vertex); } prevVertex = vertex; } _sparseCompactionByLayerBackup[layerIndex] = _sparseCompationGraphEdgesOfLayer; }
/// <summary> /// Long edges ( span(e) > 1 ) will be replaced by /// span(e) edges (1 edge between every 2 neighbor layer) /// and span(e)-1 dummy vertices will be added to graph. /// </summary> protected void ReplaceLongEdges(CancellationToken cancellationToken) { //if an edge goes through multiple layers, we split the edge at every layer and insert a dummy node // (only for the hierarchical edges) foreach (var edge in _graph.HierarchicalEdges.ToArray()) { int sourceLayerIndex = edge.Source.LayerIndex; int targetLayerIndex = edge.Target.LayerIndex; if (Math.Abs(sourceLayerIndex - targetLayerIndex) <= 1) { continue; //span(e) <= 1, not long edge } //the edge goes through multiple layers edge.IsLongEdge = true; _graph.HideEdge(edge, LONG_EDGES_TAG); //sourcelayer must be above the targetlayer if (targetLayerIndex < sourceLayerIndex) { int c = targetLayerIndex; targetLayerIndex = sourceLayerIndex; sourceLayerIndex = c; } SugiVertex prev = edge.Source; for (int i = sourceLayerIndex + 1; i <= targetLayerIndex; i++) { cancellationToken.ThrowIfCancellationRequested(); //the last vertex is the Target, the other ones are dummy vertices SugiVertex dummy; if (i == targetLayerIndex) { dummy = edge.Target; } else { dummy = new SugiVertex(null, new Size(0, 0)); _graph.AddVertex(dummy); _layers[i].Add(dummy); edge.DummyVertices.Add(dummy); } _graph.AddEdge(new SugiEdge(edge.Original, prev, dummy, EdgeTypes.Hierarchical)); prev = dummy; } } }
/// <summary> /// Adds a dummy vertex to the sparse compaction graph. /// </summary> /// <param name="type">The type of the dummy vertex (p,q,r).</param> /// <param name="layerIndex">The index of the layer of the vertex.</param> /// <returns>The new vertex which has been added to the graph and the /// layers.</returns> private SugiVertex AddDummyVertex(VertexTypes type, int layerIndex) { Contract.Requires(layerIndex < _layers.Count); Contract.Ensures(Contract.Result <SugiVertex>() != null); var vertex = new SugiVertex() { Type = type, LayerIndex = layerIndex }; _layers[layerIndex].Add(vertex); _graph.AddVertex(vertex); return(vertex); }
private void DoTraditionalEdgeRouting() { foreach (KeyValuePair <TEdge, IList <SugiVertex> > pair in _dummyVerticesOfEdges) { var routePoints = new Point[pair.Value.Count]; for (int i = 0; i < pair.Value.Count; ++i) { SugiVertex vertex = pair.Value[i]; routePoints[i] = IsVerticalLayout() ? new Point(vertex.SlicePosition, vertex.LayerPosition) : new Point(vertex.LayerPosition, vertex.SlicePosition); } EdgeRoutes[pair.Key] = routePoints; } }
private void DoOrthogonalEdgeRouting() { foreach (TEdge edge in VisitedGraph.Edges) { var orthogonalRoutePoints = new Point[2]; SugiVertex sourceVertex = _verticesMap[edge.Source]; SugiVertex targetVertex = _verticesMap[edge.Target]; bool notSwitched = sourceVertex.LayerIndex < targetVertex.LayerIndex; int sourceIndex = notSwitched ? 0 : 1; int targetIndex = notSwitched ? 1 : 0; orthogonalRoutePoints[sourceIndex] = new Point { X = sourceVertex.SlicePosition, Y = _layerPositions[sourceVertex.LayerIndex] + _layerSizes[sourceVertex.LayerIndex] + Parameters.LayerGap / 2.0 }; orthogonalRoutePoints[targetIndex] = new Point { X = targetVertex.SlicePosition, Y = _layerPositions[targetVertex.LayerIndex] - Parameters.LayerGap / 2.0 }; EdgeRoutes[edge] = orthogonalRoutePoints; } foreach (KeyValuePair <TEdge, IList <SugiVertex> > pair in _dummyVerticesOfEdges) { Point[] orthogonalRoutePoints = EdgeRoutes[pair.Key]; var routePoints = new Point[pair.Value.Count + 4]; routePoints[0] = orthogonalRoutePoints[0]; routePoints[pair.Value.Count + 3] = orthogonalRoutePoints[1]; for (int i = 0; i < pair.Value.Count; ++i) { SugiVertex vertex = pair.Value[i]; routePoints[i + 2] = new Point(vertex.SlicePosition, vertex.LayerPosition); } routePoints[1] = new Point(routePoints[2].X, routePoints[0].Y); routePoints[pair.Value.Count + 2] = new Point( routePoints[pair.Value.Count + 1].X, routePoints[pair.Value.Count + 3].Y); EdgeRoutes[pair.Key] = routePoints; } }
private void AssignMeasuresOnNextLayer([NotNull, ItemNotNull] IEnumerable <SugiVertex> layer, bool straightSweep) { Debug.Assert(layer != null); // Measures of the containers is the same as their positions // So we should set the measures only for the vertices foreach (SugiVertex vertex in layer) { if (straightSweep && vertex.Type == VertexTypes.QVertex || !straightSweep && vertex.Type == VertexTypes.PVertex) { continue; } IEnumerable <SugiEdge> edges = straightSweep ? _graph.InEdges(vertex) : _graph.OutEdges(vertex); double oldMeasuredPosition = vertex.MeasuredPosition; vertex.MeasuredPosition = 0; vertex.DoNotOptimize = false; int count = 0; foreach (SugiEdge edge in edges) { ThrowIfCancellationRequested(); SugiVertex otherVertex = edge.GetOtherVertex(vertex); vertex.MeasuredPosition += otherVertex.Position; ++count; } if (count > 0) { vertex.MeasuredPosition /= count; } else { vertex.MeasuredPosition = oldMeasuredPosition; vertex.DoNotOptimize = true; } } }
private static IEnumerable <CrossCounterPair> ConvertRealEdgesToCrossCounterPairs( [NotNull, ItemNotNull] IEnumerable <SugiEdge> edges, bool clearMark) { foreach (SugiEdge edge in edges) { SugiVertex source = edge.Source; SugiVertex target = edge.Target; if (clearMark) { edge.Marked = false; } yield return(new CrossCounterPair(EdgeTypes.NonInnerSegment) { First = source.Position, Second = target.Position, Weight = 1, NonInnerSegment = edge }); } }
/// <summary> /// Initializes the <see cref="_graph"/> field which stores the graph that we operate on. /// </summary> private void CopyToWorkingGraph() { // Make a copy of the original graph _graph = new BidirectionalGraph <SugiVertex, SugiEdge>(); // Copy the vertices foreach (TVertex vertex in VisitedGraph.Vertices) { var size = default(Size); _verticesSizes?.TryGetValue(vertex, out size); var vertexWrapper = new SugiVertex(vertex, size); _graph.AddVertex(vertexWrapper); _verticesMap[vertex] = vertexWrapper; } // Copy the edges foreach (TEdge edge in VisitedGraph.Edges) { var edgeWrapper = new SugiEdge(edge, _verticesMap[edge.Source], _verticesMap[edge.Target]); _graph.AddEdge(edgeWrapper); } }
protected void HorizontalPositionAssignmentOnLayer(int layerIndex, BaryCenter baryCenter) { var layer = _layers[layerIndex]; //compute where the vertices should be placed layer.Measure(baryCenter, true); layer.CalculateSubPriorities(); //set the RealPositions to NaN foreach (var v in layer) { v.RealPosition.X = float.NaN; } //set the positions in the order of the priorities, start with the lower priorities foreach (var v in from vertex in layer orderby vertex.Priority ascending, vertex.SubPriority ascending select vertex) { //first set the new position v.RealPosition.X = v.Measure; //check if there's any overlap between the actual vertex and the vertices which position has already been set SugiVertex v1 = v; var alreadySetVertices = layer.Where(vertex => (!double.IsNaN(vertex.RealPosition.X) && vertex != v1)).ToArray(); if (alreadySetVertices.Length == 0) { //there can't be any overlap continue; } //get the index of the 'v' vertex between the vertices which position has already been set int indexOfV; for (indexOfV = 0; indexOfV < alreadySetVertices.Length && alreadySetVertices[indexOfV].Position < v.Position; indexOfV++) { } SugiVertex leftNeighbor = null, rightNeighbor = null; double leftOverlap = 0, rightOverlap = 0; //check the overlap with vertex on the left if (indexOfV > 0) { leftNeighbor = alreadySetVertices[indexOfV - 1]; leftOverlap = CalculateOverlap(leftNeighbor, v); } if (indexOfV < alreadySetVertices.Length) { rightNeighbor = alreadySetVertices[indexOfV]; rightOverlap = CalculateOverlap(v, rightNeighbor); } // ReSharper disable PossibleNullReferenceException //only one neighbor overlaps if (leftOverlap > 0 && rightOverlap == 0) { if (leftNeighbor.Priority == v.Priority) { double leftMove = leftOverlap * 0.5; if (rightNeighbor != null) { rightOverlap = CalculateOverlap(v, rightNeighbor, leftMove); } leftNeighbor.RealPosition.X -= leftMove; v.RealPosition.X += leftMove; if (rightOverlap > 0) { if (v.Priority == rightNeighbor.Priority) { double rightMove = rightOverlap * 0.5; rightNeighbor.RealPosition.X += rightMove; v.RealPosition.X -= rightMove; leftNeighbor.RealPosition.X -= rightMove; } else { rightNeighbor.RealPosition.X += rightOverlap; } } } else { leftNeighbor.RealPosition.X -= leftOverlap; } } else if (leftOverlap == 0 && rightOverlap > 0) { if (v.Priority == rightNeighbor.Priority) { double rightMove = rightOverlap * 0.5; if (leftNeighbor != null) { leftOverlap = CalculateOverlap(leftNeighbor, v, rightMove); } rightNeighbor.RealPosition.X += rightMove; v.RealPosition.X -= rightMove; if (leftOverlap > 0) { if (leftNeighbor.Priority == v.Priority) { double leftMove = leftOverlap * 0.5; leftNeighbor.RealPosition.X -= leftMove; v.RealPosition.X += leftMove; rightNeighbor.RealPosition.X += leftMove; } else { leftNeighbor.RealPosition.X -= leftOverlap; } } } else { rightNeighbor.RealPosition.X += rightOverlap; } } else if (leftOverlap > 0 && rightOverlap > 0) { //if both neighbor overlapped //priorities equals, 1 priority lower, 2 priority lower if (leftNeighbor.Priority < v.Priority && v.Priority == rightNeighbor.Priority) { double rightMove = rightOverlap * 0.5; rightNeighbor.RealPosition.X += rightMove; v.RealPosition.X -= rightMove; leftNeighbor.RealPosition.X -= (leftOverlap + rightMove); } else if (leftNeighbor.Priority == v.Priority && v.Priority > rightNeighbor.Priority) { double leftMove = leftOverlap * 0.5; leftNeighbor.RealPosition.X -= leftMove; v.RealPosition.X += leftMove; rightNeighbor.RealPosition.X = (rightOverlap + leftMove); } else { //priorities of the neighbors are lower, or equal leftNeighbor.RealPosition.X -= leftOverlap; rightNeighbor.RealPosition.X += rightOverlap; } } // ReSharper restore PossibleNullReferenceException //the vertices on the left side of the leftNeighbor will be moved, if they overlap if (leftOverlap > 0) { for (int index = indexOfV - 1; index > 0 && (leftOverlap = CalculateOverlap(alreadySetVertices[index - 1], alreadySetVertices[index])) > 0; index--) { alreadySetVertices[index - 1].RealPosition.X -= leftOverlap; } } //the vertices on the right side of the rightNeighbor will be moved, if they overlap if (rightOverlap > 0) { for (int index = indexOfV; index < alreadySetVertices.Length - 1 && (rightOverlap = CalculateOverlap(alreadySetVertices[index], alreadySetVertices[index + 1])) > 0; index++) { alreadySetVertices[index + 1].RealPosition.X += rightOverlap; } } } }
private double CalculateOverlap(SugiVertex a, SugiVertex b, double plusGap) { return(Math.Max(0, ((b.Size.Width + a.Size.Width) * 0.5 + plusGap + Parameters.HorizontalGap) - (b.RealPosition.X - a.RealPosition.X))); }
private double CalculateOverlap(SugiVertex a, SugiVertex b) { return(CalculateOverlap(a, b, 0)); }
private void PlaceBlock(int modeIndex, LeftRightMode leftRightMode, UpperLowerEdges upperLowerEdges, SugiVertex v) { if (!double.IsNaN(v.HorizontalPositions[modeIndex])) { return; } double delta = Parameters.VertexDistance; v.HorizontalPositions[modeIndex] = 0; Data w = v; do { SugiVertex wVertex = w as SugiVertex; Segment wSegment = w as Segment; if (_sparseCompactionGraph.ContainsVertex(w) && ((leftRightMode == LeftRightMode.Left && _sparseCompactionGraph.InDegree(w) > 0) || (leftRightMode == LeftRightMode.Right && _sparseCompactionGraph.OutDegree(w) > 0))) { var edges = leftRightMode == LeftRightMode.Left ? _sparseCompactionGraph.InEdges(w) : _sparseCompactionGraph.OutEdges(w); foreach (var edge in edges) { SugiVertex u = null; Data pred = leftRightMode == LeftRightMode.Left ? edge.Source : edge.Target; if (pred is SugiVertex) { u = ((SugiVertex)pred).Roots[modeIndex]; } else { var segment = (Segment)pred; u = upperLowerEdges == UpperLowerEdges.Upper ? segment.PVertex.Roots[modeIndex] : segment.QVertex.Roots[modeIndex]; } PlaceBlock(modeIndex, leftRightMode, upperLowerEdges, u); if (v.Sinks[modeIndex] == v) { v.Sinks[modeIndex] = u.Sinks[modeIndex]; } //var xDelta = delta + (v.Roots[modeIndex].BlockWidths[modeIndex] + u.BlockWidths[modeIndex]) / 2.0; var xDelta = delta + ((wVertex != null ? wVertex.Size.Width : 0.0) + ((pred is SugiVertex) ? ((SugiVertex)pred).Size.Width : u.BlockWidths[modeIndex])) / 2.0; if (v.Sinks[modeIndex] != u.Sinks[modeIndex]) { var s = leftRightMode == LeftRightMode.Left ? v.HorizontalPositions[modeIndex] - u.HorizontalPositions[modeIndex] - xDelta : u.HorizontalPositions[modeIndex] - v.HorizontalPositions[modeIndex] - xDelta; u.Sinks[modeIndex].Shifts[modeIndex] = leftRightMode == LeftRightMode.Left ? Math.Min(u.Sinks[modeIndex].Shifts[modeIndex], s) : Math.Max(u.Sinks[modeIndex].Shifts[modeIndex], s); } else { v.HorizontalPositions[modeIndex] = leftRightMode == LeftRightMode.Left ? Math.Max(v.HorizontalPositions[modeIndex], u.HorizontalPositions[modeIndex] + xDelta) : Math.Min(v.HorizontalPositions[modeIndex], u.HorizontalPositions[modeIndex] - xDelta); } } } if (wSegment != null) { w = (upperLowerEdges == UpperLowerEdges.Upper) ? wSegment.QVertex : wSegment.PVertex; } else if (wVertex.Type == VertexTypes.PVertex && upperLowerEdges == UpperLowerEdges.Upper) { w = wVertex.Segment; } else if (wVertex.Type == VertexTypes.QVertex && upperLowerEdges == UpperLowerEdges.Lower) { w = wVertex.Segment; } else { w = wVertex.Aligns[modeIndex]; } } while (w != v); }
/// <summary> /// Initializes a new instance of the <see cref="Segment"/> class. /// </summary> /// <param name="pVertex">P vertex.</param> /// <param name="qVertex">Q vertex.</param> public Segment([NotNull] SugiVertex pVertex, [NotNull] SugiVertex qVertex) { PVertex = pVertex; QVertex = qVertex; }
private void PlaceBlock( int modeIndex, LeftRightMode leftRightMode, UpperLowerEdges upperLowerEdges, [NotNull] SugiVertex v) { if (!double.IsNaN(v.SlicePositions[modeIndex])) { return; } double delta = Parameters.SliceGap; v.SlicePositions[modeIndex] = 0; Data w = v; do { var wVertex = w as SugiVertex; var wSegment = w as Segment; if (_sparseCompactionGraph.ContainsVertex(w) && (leftRightMode == LeftRightMode.Left && _sparseCompactionGraph.InDegree(w) > 0 || leftRightMode == LeftRightMode.Right && _sparseCompactionGraph.OutDegree(w) > 0)) { IEnumerable <IEdge <Data> > edges = leftRightMode == LeftRightMode.Left ? _sparseCompactionGraph.InEdges(w) : _sparseCompactionGraph.OutEdges(w); foreach (IEdge <Data> edge in edges) { SugiVertex u; Data predecessor = leftRightMode == LeftRightMode.Left ? edge.Source : edge.Target; if (predecessor is SugiVertex vertex) { u = vertex.Roots[modeIndex]; } else { var segment = (Segment)predecessor; u = upperLowerEdges == UpperLowerEdges.Upper ? segment.PVertex.Roots[modeIndex] : segment.QVertex.Roots[modeIndex]; } PlaceBlock(modeIndex, leftRightMode, upperLowerEdges, u); if (v.Sinks[modeIndex] == v) { v.Sinks[modeIndex] = u.Sinks[modeIndex]; } double xDelta = delta + ( (wVertex?.Size.Width ?? 0.0) + (predecessor is SugiVertex sugiVertex ? sugiVertex.Size.Width : u.BlockWidths[modeIndex]) ) / 2.0; if (v.Sinks[modeIndex] != u.Sinks[modeIndex]) { double s = leftRightMode == LeftRightMode.Left ? v.SlicePositions[modeIndex] - u.SlicePositions[modeIndex] - xDelta : u.SlicePositions[modeIndex] - v.SlicePositions[modeIndex] - xDelta; u.Sinks[modeIndex].Shifts[modeIndex] = leftRightMode == LeftRightMode.Left ? Math.Min(u.Sinks[modeIndex].Shifts[modeIndex], s) : Math.Max(u.Sinks[modeIndex].Shifts[modeIndex], s); } else { v.SlicePositions[modeIndex] = leftRightMode == LeftRightMode.Left ? Math.Max(v.SlicePositions[modeIndex], u.SlicePositions[modeIndex] + xDelta) : Math.Min(v.SlicePositions[modeIndex], u.SlicePositions[modeIndex] - xDelta); } } } if (wSegment != null) { w = upperLowerEdges == UpperLowerEdges.Upper ? wSegment.QVertex : wSegment.PVertex; } // ReSharper disable once PossibleNullReferenceException // Justification: If not a segment then it's a vertex else if (wVertex.Type == VertexTypes.PVertex && upperLowerEdges == UpperLowerEdges.Upper) { w = wVertex.Segment; } else if (wVertex.Type == VertexTypes.QVertex && upperLowerEdges == UpperLowerEdges.Lower) { w = wVertex.Segment; } else { w = wVertex.Aligns[modeIndex]; } } while (w != v); }
private void DoAlignment(int modeIndex, LeftRightMode leftRightMode, UpperLowerEdges upperLowerEdges) { int layerStart, layerEnd, layerStep; if (upperLowerEdges == UpperLowerEdges.Upper) { layerStart = 0; layerEnd = _layers.Count; layerStep = 1; } else { layerStart = _layers.Count - 1; layerEnd = -1; layerStep = -1; } for (int i = layerStart; i != layerEnd; i += layerStep) { int r = leftRightMode == LeftRightMode.Left ? int.MinValue : int.MaxValue; IList <SugiVertex> layer = _layers[i]; int vertexStart, vertexEnd, vertexStep; if (leftRightMode == LeftRightMode.Left) { vertexStart = 0; vertexEnd = layer.Count; vertexStep = 1; } else { vertexStart = layer.Count - 1; vertexEnd = -1; vertexStep = -1; } for (int j = vertexStart; j != vertexEnd; j += vertexStep) { SugiVertex vertex = layer[j]; switch (vertex.Type) { case VertexTypes.Original: case VertexTypes.RVertex: case VertexTypes.PVertex when upperLowerEdges == UpperLowerEdges.Upper: case VertexTypes.QVertex when upperLowerEdges == UpperLowerEdges.Lower: { SugiEdge[] neighborEdges = upperLowerEdges == UpperLowerEdges.Upper ? _graph.InEdges(vertex).OrderBy(e => e.Source.Position).ToArray() : _graph.OutEdges(vertex).OrderBy(e => e.Target.Position).ToArray(); if (neighborEdges.Length <= 0) { continue; } int c1 = (int)Math.Floor((neighborEdges.Length + 1) / 2.0) - 1; int c2 = (int)Math.Ceiling((neighborEdges.Length + 1) / 2.0) - 1; int[] medians; if (c1 == c2) { medians = new[] { c1 }; } else { medians = leftRightMode == LeftRightMode.Left ? new[] { c1, c2 } : new[] { c2, c1 }; } foreach (int median in medians) { if (vertex.Aligns[modeIndex] != vertex) { continue; } SugiEdge edge = neighborEdges[median]; SugiVertex neighbor = edge.GetOtherVertex(vertex); if (!edge.Marked && (leftRightMode == LeftRightMode.Left && r < neighbor.Position || leftRightMode == LeftRightMode.Right && r > neighbor.Position)) { neighbor.Aligns[modeIndex] = vertex; neighbor.BlockWidths[modeIndex] = Math.Max(neighbor.BlockWidths[modeIndex], vertex.Size.Width); vertex.Roots[modeIndex] = neighbor.Roots[modeIndex]; vertex.Aligns[modeIndex] = vertex.Roots[modeIndex]; r = neighbor.Position; } } break; } case VertexTypes.PVertex: // Align the segment of the PVertex vertex.Roots[modeIndex] = vertex.Segment.QVertex.Roots[modeIndex]; vertex.Aligns[modeIndex] = vertex.Roots[modeIndex]; r = vertex.Segment.Position; break; case VertexTypes.QVertex: // Align the segment of the QVertex vertex.Roots[modeIndex] = vertex.Segment.PVertex.Roots[modeIndex]; vertex.Aligns[modeIndex] = vertex.Roots[modeIndex]; r = vertex.Segment.Position; break; } } } }
private static AlternatingLayer InitialOrderingOfNextLayer( [NotNull, ItemNotNull] AlternatingLayer alternatingLayer, [NotNull, ItemNotNull] IEnumerable <SugiVertex> nextLayer, bool straightSweep) { Debug.Assert(alternatingLayer != null); Debug.Assert(nextLayer != null); // Get the list of the containers and vertices var segmentContainerStack = new Stack <ISegmentContainer>(alternatingLayer.OfType <ISegmentContainer>().Reverse()); VertexTypes ignorableVertexType = straightSweep ? VertexTypes.QVertex : VertexTypes.PVertex; var vertexStack = new Stack <SugiVertex>( nextLayer .Where(v => v.Type != ignorableVertexType) .OrderBy(v => v.MeasuredPosition) .Reverse()); var newAlternatingLayer = new AlternatingLayer(); while (vertexStack.Count > 0 && segmentContainerStack.Count > 0) { SugiVertex vertex = vertexStack.Peek(); ISegmentContainer segmentContainer = segmentContainerStack.Peek(); if (vertex.MeasuredPosition <= segmentContainer.Position) { newAlternatingLayer.Add(vertexStack.Pop()); } else if (vertex.MeasuredPosition >= segmentContainer.Position + segmentContainer.Count - 1) { newAlternatingLayer.Add(segmentContainerStack.Pop()); } else { vertexStack.Pop(); segmentContainerStack.Pop(); int k = (int)Math.Ceiling(vertex.MeasuredPosition - segmentContainer.Position); segmentContainer.Split(k, out ISegmentContainer container1, out ISegmentContainer container2); newAlternatingLayer.Add(container1); newAlternatingLayer.Add(vertex); container2.Position = segmentContainer.Position + k; segmentContainerStack.Push(container2); } } if (vertexStack.Count > 0) { newAlternatingLayer.AddRange( vertexStack #if !SUPPORTS_ENUMERABLE_COVARIANT .OfType <IData>() #endif ); } if (segmentContainerStack.Count > 0) { newAlternatingLayer.AddRange( segmentContainerStack #if !SUPPORTS_ENUMERABLE_COVARIANT .OfType <IData>() #endif ); } return(newAlternatingLayer); }
private float CalculateOverlap(SugiVertex a, SugiVertex b) { return(CalculateOverlap(a, b, 0)); }