/// <summary> /// Calculates the slice positions based on the selected modes. /// </summary> /// <param name="leftRightMode">Mode of the vertical alignment.</param> /// <param name="upperLowerEdges">Alignment based on which edges (upper or lower ones).</param> private void CalculateSlicePositions(LeftRightMode leftRightMode, UpperLowerEdges upperLowerEdges) { int modeIndex = (byte)upperLowerEdges * 2 + (byte)leftRightMode; InitializeRootsAndAligns(modeIndex); DoAlignment(modeIndex, leftRightMode, upperLowerEdges); InitializeSinksAndShifts(modeIndex); DoSliceCompaction(modeIndex, leftRightMode, upperLowerEdges); }
/// <summary> /// Calculates the horizontal positions based on the selected modes. /// </summary> /// <param name="leftRightMode">Mode of the vertical alignment.</param> /// <param name="upperLowerEdges">Alignment based on which edges (upper or lower ones).</param> private void CalculateHorizontalPositions(LeftRightMode leftRightMode, UpperLowerEdges upperLowerEdges) { if (_graph.Vertices.Count() == 1) { _graph.Vertices.First().HorizontalPosition = 0; } else { int modeIndex = (byte)upperLowerEdges * 2 + (byte)leftRightMode; InitializeRootsAndAligns(modeIndex); DoAlignment(modeIndex, leftRightMode, upperLowerEdges); WriteOutAlignment(modeIndex); InitializeSinksAndShifts(modeIndex); DoHorizontalCompaction(modeIndex, leftRightMode, upperLowerEdges); } }
private void DoSliceCompaction(int modeIndex, LeftRightMode leftRightMode, UpperLowerEdges upperLowerEdges) { foreach (SugiVertex vertex in _graph.Vertices) { if (vertex.Roots[modeIndex] == vertex) { PlaceBlock(modeIndex, leftRightMode, upperLowerEdges, vertex); } } foreach (SugiVertex vertex in _graph.Vertices) { vertex.SlicePositions[modeIndex] = vertex.Roots[modeIndex].SlicePositions[modeIndex]; if (vertex.Roots[modeIndex].Sinks[modeIndex].Shifts[modeIndex] < double.PositiveInfinity && vertex.Roots[modeIndex] == vertex) { vertex.SlicePositions[modeIndex] += vertex.Roots[modeIndex].Sinks[modeIndex].Shifts[modeIndex]; } } }
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; var 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) { var vertex = layer[j]; if (vertex.Type == VertexTypes.Original || vertex.Type == VertexTypes.RVertex || (vertex.Type == VertexTypes.PVertex && upperLowerEdges == UpperLowerEdges.Upper) || (vertex.Type == VertexTypes.QVertex && upperLowerEdges == UpperLowerEdges.Lower)) { List <SugiEdge> neighbourEdges = null; neighbourEdges = upperLowerEdges == UpperLowerEdges.Upper ? _graph.InEdges(vertex).OrderBy(e => e.Source.Position).ToList() : _graph.OutEdges(vertex).OrderBy(e => e.Target.Position).ToList(); if (neighbourEdges.Count <= 0) { continue; } int c1 = (int)Math.Floor((neighbourEdges.Count + 1) / 2.0) - 1; int c2 = (int)Math.Ceiling((neighbourEdges.Count + 1) / 2.0) - 1; int[] medians = null; if (c1 == c2) { medians = new int[1] { c1 }; } else { medians = leftRightMode == LeftRightMode.Left ? new int[2] { c1, c2 } : new int[2] { c2, c1 }; } for (int m = 0; m < medians.Length; m++) { if (vertex.Aligns[modeIndex] != vertex) { continue; } var edge = neighbourEdges[medians[m]]; if (edge.Marked) { Debug.WriteLine("Edge marked: " + edge.Source.OriginalVertex + ", " + edge.Target.OriginalVertex); } var neighbour = edge.OtherVertex(vertex); if (!edge.Marked && ((leftRightMode == LeftRightMode.Left && r < neighbour.Position) || (leftRightMode == LeftRightMode.Right && r > neighbour.Position))) { neighbour.Aligns[modeIndex] = vertex; neighbour.BlockWidths[modeIndex] = Math.Max(neighbour.BlockWidths[modeIndex], vertex.Size.Width); vertex.Roots[modeIndex] = neighbour.Roots[modeIndex]; vertex.Aligns[modeIndex] = vertex.Roots[modeIndex]; r = neighbour.Position; } } } else if (vertex.Type == VertexTypes.PVertex /*&& upperLowerEdges == UpperLowerEdges.Lower*/) { //align the segment of the PVertex vertex.Roots[modeIndex] = vertex.Segment.QVertex.Roots[modeIndex]; vertex.Aligns[modeIndex] = vertex.Roots[modeIndex]; r = vertex.Segment.Position; } else if (vertex.Type == VertexTypes.QVertex /*&& upperLowerEdges == UpperLowerEdges.Upper*/) { //align the segment of the QVertex vertex.Roots[modeIndex] = vertex.Segment.PVertex.Roots[modeIndex]; vertex.Aligns[modeIndex] = vertex.Roots[modeIndex]; r = vertex.Segment.Position; } } } }
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); }
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; } } } }