Пример #1
0
        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);
        }
Пример #4
0
        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;
            }
        }
Пример #5
0
        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;
            }
        }
Пример #6
0
        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;
                }
            }
        }
Пример #7
0
        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;
                    }
                }
            }
        }
Пример #10
0
 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)));
 }
Пример #11
0
 private double CalculateOverlap(SugiVertex a, SugiVertex b)
 {
     return(CalculateOverlap(a, b, 0));
 }
Пример #12
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);
        }
Пример #13
0
 /// <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;
 }
Пример #14
0
        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);
        }
Пример #15
0
        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;
                    }
                }
            }
        }
Пример #16
0
        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));
 }