Exemple #1
0
        /// <summary>
        /// Initializes the positions of the vertices. Assign a random position inside the 'bounding box' to the vertices without positions.
        /// It does NOT modify the position of the other vertices.
        ///
        /// It generates an <code>IterationEnded</code> event.
        ///
        /// Bounding box:
        /// x coordinates: double.Epsilon - <code>width</code>
        /// y coordinates: double.Epsilon - <code>height</code>
        /// </summary>
        /// <param name="width">Width of the bounding box.</param>
        /// <param name="height">Height of the bounding box.</param>
        /// <param name="translate_x">Translates the generated x coordinate.</param>
        /// <param name="translate_y">Translates the generated y coordinate.</param>
        protected virtual void InitializeWithRandomPositions(double width, double height, double translate_x, double translate_y)
        {
            var rnd = new Random(Parameters.Seed);

            //initialize with random position
            foreach (TVertex v in VisitedGraph.Vertices)
            {
                //for vertices without assigned position
                if (!VertexPositions.ContainsKey(v))
                {
                    if (EnsureUniqueRandomInitialPositions)
                    {
                        Point newPoint;
                        do
                        {
                            newPoint =
                                new Point(
                                    Math.Max(double.Epsilon, rnd.NextDouble() * width + translate_x),
                                    Math.Max(double.Epsilon, rnd.NextDouble() * height + translate_y));
                        } while (VertexPositions.Values.Contains(newPoint));
                        VertexPositions[v] = newPoint;
                    }
                    else
                    {
                        VertexPositions[v] =
                            new Point(
                                Math.Max(double.Epsilon, rnd.NextDouble() * width + translate_x),
                                Math.Max(double.Epsilon, rnd.NextDouble() * height + translate_y));
                    }
                }
            }
        }
 public void Dispose()
 {
     Graph = default(TGraph);
     VertexPositions.Clear();
     VisibleEdges.Clear();
     AlgorithmStorage = null;
 }
        /// <summary>
        /// Initializes the data of the compound vertices.
        /// </summary>
        /// <param name="vertexBorders">Dictionary of the border thicknesses.</param>
        /// <param name="vertexSizes">Dictionary of the vertex sizes.</param>
        /// <param name="layoutTypes">Dictionary of the layout types.</param>
        /// <param name="movableParentUpdateQueue">The compound vertices with fixed layout
        /// should be added to this queue.</param>
        private void InitCompoundVertices(
            IDictionary <TVertex, Thickness> vertexBorders,
            IDictionary <TVertex, Size> vertexSizes,
            IDictionary <TVertex, CompoundVertexInnerLayoutType> layoutTypes,
            Queue <TVertex> movableParentUpdateQueue)
        {
            for (int i = _levels.Count - 1; i >= 0; i--)
            {
                foreach (var vertex in _levels[i])
                {
                    if (!_compoundGraph.IsCompoundVertex(vertex))
                    {
                        continue;
                    }

                    //get the data of the vertex
                    Thickness border;
                    vertexBorders.TryGetValue(vertex, out border);

                    Size vertexSize;
                    vertexSizes.TryGetValue(vertex, out vertexSize);
                    var layoutType = CompoundVertexInnerLayoutType.Automatic;
                    layoutTypes.TryGetValue(vertex, out layoutType);

                    if (layoutType == CompoundVertexInnerLayoutType.Fixed)
                    {
                        movableParentUpdateQueue.Enqueue(vertex);
                    }

                    var position = new Point();
                    VertexPositions.TryGetValue(vertex, out position);

                    //create the information container for this compound vertex
                    var dataContainer = new CompoundVertexData(vertex, _rootCompoundVertex, false, position, vertexSize, border, layoutType);
                    if (i == 0)
                    {
                        dataContainer.Parent = _rootCompoundVertex;
                        _rootCompoundVertex.Children.Add(dataContainer);
                    }

                    _compoundVertexDatas[vertex] = dataContainer;
                    _vertexDatas[vertex]         = dataContainer;

                    //add the datas of the childrens
                    var children     = _compoundGraph.GetChildrenVertices(vertex);
                    var childrenData = children.Select(v => _vertexDatas[v]).ToList();
                    dataContainer.Children = childrenData;
                    foreach (var child in dataContainer.Children)
                    {
                        _rootCompoundVertex.Children.Remove(child);
                        child.Parent = dataContainer;
                    }
                }
            }
        }
Exemple #4
0
        /// <summary>
        /// It computes the layout of the vertices.
        /// </summary>
        public override void Compute(CancellationToken cancellationToken)
        {
            if (VisitedGraph.VertexCount == 1)
            {
                VertexPositions.Add(VisitedGraph.Vertices.First(), new Point(0, 0));
                return;
            }

            //initializing the positions
            if (Parameters is BoundedFRLayoutParameters)
            {
                var param = Parameters as BoundedFRLayoutParameters;
                InitializeWithRandomPositions(param.Width, param.Height);
                _maxWidth  = param.Width;
                _maxHeight = param.Height;
            }
            else
            {
                InitializeWithRandomPositions(1000.0, 1000.0);
            }
            Parameters.VertexCount = VisitedGraph.VertexCount;

            // Actual temperature of the 'mass'. Used for cooling.
            var minimalTemperature = Parameters.InitialTemperature * 0.01;

            _temperature = Parameters.InitialTemperature;
            for (int i = 0;
                 i < Parameters._iterationLimit &&
                 _temperature > minimalTemperature;
                 i++)
            {
                IterateOne(cancellationToken);

                //make some cooling
                switch (Parameters._coolingFunction)
                {
                case FRCoolingFunction.Linear:
                    _temperature *= (1.0 - i / (double)Parameters._iterationLimit);
                    break;

                case FRCoolingFunction.Exponential:
                    _temperature *= Parameters._lambda;
                    break;
                }

                //iteration ended, do some report

                /*if (ReportOnIterationEndNeeded)
                 * {
                 *  double statusInPercent = (double)i / (double)Parameters._iterationLimit;
                 *  OnIterationEnded(i, statusInPercent, string.Empty, true);
                 * }*/
            }
        }
Exemple #5
0
        protected override Point OnOriginalPosition(YodiiGraphVertex v, Point p)
        {
            // Keep existing positions
            if (p.IsValid())
            {
                return(p);
            }

            Point newPoint = new Point(0, 0);

            if (VertexPositions == null)
            {
                return(newPoint);
            }
            if (v.IsService)
            {
                if (v.LabServiceInfo.ServiceInfo.Generalization != null)
                {
                    // Find & get point of generalization
                    var generalizationQuery = VertexPositions.Where(kvp => kvp.Key.IsService && kvp.Key.LabServiceInfo.ServiceInfo == v.LabServiceInfo.ServiceInfo.Generalization);

                    if (generalizationQuery.Count() > 0)
                    {
                        Point generalizationPoint = generalizationQuery.First().Value;
                        if (generalizationPoint.IsValid())
                        {
                            newPoint.X = generalizationPoint.X;
                            newPoint.Y = generalizationPoint.Y + VERTICAL_MARGIN_SIZE;
                        }
                    }
                }
            }
            else if (v.IsPlugin)
            {
                if (v.LabPluginInfo.PluginInfo.Service != null)
                {
                    // Find & get point of service
                    var serviceQuery = VertexPositions.Where(kvp => kvp.Key.IsService && kvp.Key.LabServiceInfo.ServiceInfo == v.LabPluginInfo.PluginInfo.Service);

                    if (serviceQuery.Count() > 0)
                    {
                        Point generalizationPoint = serviceQuery.First().Value;
                        if (generalizationPoint.IsValid())
                        {
                            newPoint.X = generalizationPoint.X;
                            newPoint.Y = generalizationPoint.Y + VERTICAL_MARGIN_SIZE;
                        }
                    }
                }
            }

            return(newPoint);
        }
Exemple #6
0
        public override void Compute(CancellationToken cancellationToken)
        {
            if (VisitedGraph.VertexCount == 1)
            {
                if (!VertexPositions.ContainsKey(VisitedGraph.Vertices.First()))
                {
                    VertexPositions.Add(VisitedGraph.Vertices.First(), new Point(0, 0));
                }
                return;
            }

            //initialize vertex positions
            InitializeWithRandomPositions(Parameters.Width, Parameters.Height);

            //initialize ISOM data
            foreach (var vertex in VisitedGraph.Vertices)
            {
                ISOMData isomData;
                if (!_isomDataDict.TryGetValue(vertex, out isomData))
                {
                    isomData = new ISOMData();
                    _isomDataDict[vertex] = isomData;
                }
            }

            _radius = Parameters.InitialRadius;
            var rnd = new Random(Parameters.Seed);

            for (var epoch = 0; epoch < Parameters.MaxEpoch; epoch++)
            {
                cancellationToken.ThrowIfCancellationRequested();

                Adjust(cancellationToken, rnd);

                //Update Parameters
                var factor = Math.Exp(-1 * Parameters.CoolingFactor * (1.0 * epoch / Parameters.MaxEpoch));
                _adaptation = Math.Max(Parameters.MinAdaption, factor * Parameters.InitialAdaption);
                if (_radius > Parameters.MinRadius && epoch % Parameters.RadiusConstantTime == 0)
                {
                    _radius--;
                }

                //report

                /*if ( ReportOnIterationEndNeeded )
                 *      OnIterationEnded( epoch, (double)epoch / (double)Parameters.MaxEpoch, "Iteration " + epoch + " finished.", true );
                 * else if (ReportOnProgressChangedNeeded)
                 * OnProgressChanged( (double)epoch / (double)Parameters.MaxEpoch * 100 );*/
            }
        }
Exemple #7
0
        public override void Compute(CancellationToken cancellationToken)
        {
            InitTheGraph();

            //first step
            DoPreparing();

            BuildSparseNormalizedGraph(cancellationToken);
            DoCrossingMinimizations(cancellationToken);
            CalculatePositions();
            var offsetY = 0d;

            if (Parameters.Direction == LayoutDirection.LeftToRight)
            {
                offsetY = VertexPositions.Values.Min(p => p.X);
                if (offsetY < 0)
                {
                    offsetY = -offsetY;
                }
                foreach (var item in VertexPositions.ToDictionary(a => a.Key, b => b.Value))
                {
                    VertexPositions[item.Key] = new Point(item.Value.Y * 1.5 + 0, item.Value.X + offsetY);
                }
            }

            if (Parameters.Direction == LayoutDirection.RightToLeft)
            {
                offsetY = VertexPositions.Values.Min(p => p.X);
                if (offsetY < 0)
                {
                    offsetY = -offsetY;
                }
                foreach (var item in VertexPositions.ToDictionary(a => a.Key, b => b.Value))
                {
                    VertexPositions[item.Key] = new Point(-item.Value.Y * 1.5, -item.Value.X + offsetY);
                }
            }

            if (Parameters.Direction == LayoutDirection.BottomToTop)
            {
                foreach (var item in VertexPositions.ToDictionary(a => a.Key, b => b.Value))
                {
                    VertexPositions[item.Key] = new Point(item.Value.X, -item.Value.Y);
                }
            }

            DoEdgeRouting(offsetY);
        }
Exemple #8
0
        private void ArrangeRectangle(Rect rectangle, int groupId, Rect originalRect)
        {
            var offsetX = rectangle.X - originalRect.X;
            var offsetY = rectangle.Y - originalRect.Y;

            VertexPositions.Where(a => a.Key.GroupId == groupId).Select(a => a.Key).ToList().ForEach(a =>
            {
                VertexPositions[a] = new Point(VertexPositions[a].X + offsetX, VertexPositions[a].Y + offsetY);
            });
            var gp = _params.GroupParametersList.FirstOrDefault(a => a.GroupId == groupId);

            if (gp == null)
            {
                throw new GX_ObjectNotFoundException("Grouped graph -> Can't find group data after calc!");
            }
            gp.ZoneRectangle = rectangle;
        }
        protected override void InitializeWithRandomPositions(double width, double height, double translate_x, double translate_y)
        {
            var rnd = GetRandomWithCurrentSeed();

            //initialize with random position
            foreach (TVertex v in VisitedGraph.Vertices)
            {
                //for vertices without assigned position
                if (!VertexPositions.ContainsKey(v))
                {
                    VertexPositions[v] =
                        new Point(
                            Math.Max(double.Epsilon, rnd.NextDouble() * width + translate_x),
                            Math.Max(double.Epsilon, rnd.NextDouble() * height + translate_y));
                }
            }
        }
Exemple #10
0
        /// <summary>
        /// Initializes the positions of the vertices. Assign a random position inside the 'bounding box' to the vertices without positions.
        /// It does NOT modify the position of the other vertices.
        ///
        /// It generates an <code>IterationEnded</code> event.
        ///
        /// Bounding box:
        /// x coordinates: double.Epsilon - <code>width</code>
        /// y coordinates: double.Epsilon - <code>height</code>
        /// </summary>
        /// <param name="width">Width of the bounding box.</param>
        /// <param name="height">Height of the bounding box.</param>
        /// <param name="translate_x">Translates the generated x coordinate.</param>
        /// <param name="translate_y">Translates the generated y coordinate.</param>
        protected virtual void InitializeWithRandomPositions(double width, double height, double translate_x, double translate_y)
        {
            var rnd = new Random(DateTime.Now.Millisecond);

            //initialize with random position
            foreach (TVertex v in VisitedGraph.Vertices)
            {
                //for vertices without assigned position
                if (!VertexPositions.ContainsKey(v))
                {
                    VertexPositions[v] =
                        new Point(
                            Math.Max(double.Epsilon, rnd.NextDouble() * width + translate_x),
                            Math.Max(double.Epsilon, rnd.NextDouble() * height + translate_y));
                }
            }
        }
        /// <summary>
        /// Initializes the data of the simple vertices.
        /// </summary>
        /// <param name="vertexSizes">Dictionary of the vertex sizes.</param>
        private void InitSimpleVertices(IDictionary <TVertex, Size> vertexSizes)
        {
            foreach (var vertex in _compoundGraph.SimpleVertices)
            {
                Size vertexSize;
                vertexSizes.TryGetValue(vertex, out vertexSize);

                var position = new Point();
                VertexPositions.TryGetValue(vertex, out position);

                //create the information container for this simple vertex
                var dataContainer = new SimpleVertexData(vertex, _rootCompoundVertex, false, position, vertexSize);
                dataContainer.Parent       = _rootCompoundVertex;
                _simpleVertexDatas[vertex] = dataContainer;
                _vertexDatas[vertex]       = dataContainer;
                _rootCompoundVertex.Children.Add(dataContainer);
            }
        }
Exemple #12
0
        public IDictionary <HyperEdge, Point[]> RouteEdges()
        {
            var edges   = Graph.HyperEdges;
            var resDict = new Dictionary <HyperEdge, Point[]>();

            foreach (var edge in edges)
            {
                var vertexPositions = VertexPositions
                                      .Where(pair => edge.Vertices.Contains(pair.Key))
                                      .Select(pair => pair.Value).ToList();
                var medianPoint = new Point
                {
                    X = vertexPositions.Average(p => p.X),
                    Y = vertexPositions.Average(p => p.Y)
                };
                resDict.Add(edge, vertexPositions.Append(medianPoint).ToArray());
            }

            return(resDict);
        }
Exemple #13
0
        protected override void InternalCompute()
        {
            if (_graph.VertexCount == 0)
            {
                return;
            }
            if (_graph.VertexCount == 1)
            {
                VertexPositions.Clear();
                VertexPositions[_graph.Vertices.First().Original] = new Point(0, 0);
                return;
            }
            //
            //Phase 1 - Filters & Removals
            //
            FiltersAndRemovals();
            _statusInPercent = percentOfPreparation;

            //
            //Phase 2 - Layer assignment
            //
            AssignLayers();

            //
            //Phase 3 - Crossing reduction
            //
            PrepareForSugiyama();
            SugiyamaLayout();
            _statusInPercent = percentOfPreparation + percentOfSugiyama;

            //
            //Phase 4 - Horizontal position assignment
            //
            CopyPositions();
            OnIterationEnded("Position adjusting finished");

            //Phase 5 - Incremental extension, add vertices connected with only general edges
            //IncrementalExtensionImproved();
            _statusInPercent = percentOfPreparation + percentOfSugiyama + percentOfIncrementalExtension;
            _statusInPercent = 100;
        }
        public override void Compute(CancellationToken cancellationToken)
        {
            if (_graph.VertexCount == 0)
            {
                return;
            }
            if (_graph.VertexCount == 1)
            {
                VertexPositions.Clear();
                VertexPositions[_graph.Vertices.First().Original] = new Point(0, 0);
                return;
            }
            //
            //Phase 1 - Filters & Removals
            //
            FiltersAndRemovals();
            _statusInPercent = PERCENT_OF_PREPARATION;

            //
            //Phase 2 - Layer assignment
            //
            AssignLayers();

            //
            //Phase 3 - Crossing reduction
            //
            PrepareForSugiyama(cancellationToken);
            SugiyamaLayout(cancellationToken);
            _statusInPercent = PERCENT_OF_PREPARATION + PERCENT_OF_SUGIYAMA;

            //
            //Phase 4 - Horizontal position assignment
            //
            CopyPositions(cancellationToken);
            OnIterationEnded("Position adjusting finished");

            //Phase 5 - Incremental extension, add vertices connected with only general edges
            //IncrementalExtensionImproved();
            _statusInPercent = PERCENT_OF_PREPARATION + PERCENT_OF_SUGIYAMA + PERCENT_OF_INCREMENTAL_EXTENSION;
            _statusInPercent = 100;
        }
        public override void Compute(CancellationToken cancellationToken)
        {
            VertexPositions.Clear();
            var bounds       = _parameters == null ? new RandomLayoutAlgorithmParams().Bounds : _parameters.Bounds;
            var boundsWidth  = (int)bounds.Width;
            var boundsHeight = (int)bounds.Height;
            var seed         = _parameters == null?Guid.NewGuid().GetHashCode() : _parameters.Seed;

            var rnd = new Random(seed);

            foreach (var item in VisitedGraph.Vertices)
            {
                if (item.SkipProcessing != ProcessingOptionEnum.Freeze || VertexPositions.Count == 0)
                {
                    var x    = (int)bounds.X;
                    var y    = (int)bounds.Y;
                    var size = VertexSizes.FirstOrDefault(a => a.Key == item).Value;
                    VertexPositions.Add(item,
                                        new Point(rnd.Next(x, x + boundsWidth - (int)size.Width),
                                                  rnd.Next(y, y + boundsHeight - (int)size.Height)));
                }
            }
        }
Exemple #16
0
        protected override void Initialize()
        {
            VertexPositions.Initialize();
            EventInput.Initialize(Window);
            Blocks.InitialzizeBlocks();

            _graphics.PreferredBackBufferWidth  = Config.Width;
            _graphics.PreferredBackBufferHeight = Config.Height;

            if (!Config.VSync)
            {
                IsFixedTimeStep = false;
                _graphics.SynchronizeWithVerticalRetrace = false;
            }
            _graphics.ApplyChanges();

            _camera      = new Camera(0.3f, 0.002f, GraphicsDevice); //move speed, rotate speed, ...
            _spriteBatch = new SpriteBatch(GraphicsDevice);

            _statistics = new StatisticOverlay(Content.Load <SpriteFont>("NormalFont"), new Vector2(48, 48)); //debug
            _mainMenu   = new MainMenu(Content);

            base.Initialize();
        }
Exemple #17
0
        public override void Compute(CancellationToken cancellationToken)
        {
            var groups   = _params.GroupParametersList.Select(a => a.GroupId).OrderByDescending(a => a).ToList();
            var listRect = new Dictionary <object, Rect>();

            foreach (var group in groups)
            {
                cancellationToken.ThrowIfCancellationRequested();
                var groupId = group;
                var gp      = _params.GroupParametersList.First(a => a.GroupId == groupId);
                //get vertices of the same group
                //var vertices = new List<TVertex>();
                var vertices = VisitedGraph.Vertices.Where(a => a.GroupId == groupId).ToList();
                //skip processing if there are no vertices in this group
                if (vertices.Count == 0)
                {
                    continue;
                }
                //get edges between vertices in the same group
                var edges = VisitedGraph.Edges.Where(a => a.Source.GroupId == a.Target.GroupId && a.Target.GroupId == groupId).ToList();
                //create and compute graph for a group
                var graph = GenerateGroupGraph(vertices, edges);
                //inject custom vertex and edge set into existing algorithm
                gp.LayoutAlgorithm.ResetGraph(graph.Vertices, graph.Edges);

                //assign vertex sizes to internal algorithm if needed
                if (gp.LayoutAlgorithm.NeedVertexSizes)
                {
                    gp.LayoutAlgorithm.VertexSizes = VertexSizes.Where(a => a.Key.GroupId == groupId)
                                                     .ToDictionary(a => a.Key, b => b.Value);
                }
                gp.LayoutAlgorithm.Compute(cancellationToken);

                //Move vertices to bound box if layout algorithm don't use bounds
                if (gp.ZoneRectangle.HasValue && !gp.IsAlgorithmBounded)
                {
                    var offsetX = gp.ZoneRectangle.Value.X;
                    var offsetY = gp.ZoneRectangle.Value.Y;
                    gp.LayoutAlgorithm.VertexPositions.ForEach(a =>
                    {
                        a.Value.Offset(offsetX, offsetY);
                    });
                }

                //write results to global positions storage
                double?[] left   = { null };
                double?[] top    = { null };
                double?[] right  = { null };
                double?[] bottom = { null };
                gp.LayoutAlgorithm.VertexPositions.ForEach(a =>
                {
                    left[0]   = left[0].HasValue ? (a.Value.X < left[0] ? a.Value.X : left[0]) : a.Value.X;
                    var w     = a.Value.X + VertexSizes[a.Key].Width;
                    var h     = a.Value.Y + VertexSizes[a.Key].Height;
                    right[0]  = right[0].HasValue ? (w > right[0] ? w : right[0]) : w;
                    top[0]    = top[0].HasValue ? (a.Value.Y < top[0] ? a.Value.Y : top[0]) : a.Value.Y;
                    bottom[0] = bottom[0].HasValue ? (h > bottom[0] ? h : bottom[0]) : h;

                    if (VertexPositions.ContainsKey(a.Key))
                    {
                        VertexPositions[a.Key] = a.Value;
                    }
                    else
                    {
                        VertexPositions.Add(a.Key, a.Value);
                    }
                });
                if (_params.ArrangeGroups)
                {
                    if (left[0] == null)
                    {
                        left[0] = 0;
                    }
                    if (right[0] == null)
                    {
                        right[0] = 0;
                    }
                    if (top[0] == null)
                    {
                        top[0] = 0;
                    }
                    if (bottom[0] == null)
                    {
                        bottom[0] = 0;
                    }
                    listRect.Add(gp.GroupId, gp.ZoneRectangle ?? new Rect(new Point(left[0].Value, top[0].Value), new Point(right[0].Value, bottom[0].Value)));
                }
            }

            if (_params.ArrangeGroups)
            {
                cancellationToken.ThrowIfCancellationRequested();
                var origList = listRect.ToDictionary(a => a.Key, a => a.Value);
                var ora      = _params != null && _params.OverlapRemovalAlgorithm != null ? _params.OverlapRemovalAlgorithm : new FSAAlgorithm <object>(listRect, new OverlapRemovalParameters {
                    HorizontalGap = 10, VerticalGap = 10
                });
                ora.Initialize(listRect);
                ora.Compute(cancellationToken);
                cancellationToken.ThrowIfCancellationRequested();
                ora.Rectangles.ForEach(a =>
                {
                    int group = (int)a.Key;
                    //_params.GroupParametersList.FirstOrDefault(b => b.GroupId == (int)a.Key).ZoneRectangle = origList[a.Key];
                    ArrangeRectangle(a.Value, group, origList[a.Key]);
                });
            }
        }
Exemple #18
0
        private void EdgeRoutingTest(TEdge ctrl)
        {
            //bad edge data check
            if (ctrl.Source.ID == -1 || ctrl.Target.ID == -1)
            {
                throw new GX_InvalidDataException("SimpleEdgeRouting() -> You must assign unique ID for each vertex to use SimpleER algo!");
            }
            if (ctrl.Source.ID == ctrl.Target.ID || !VertexPositions.ContainsKey(ctrl.Target))
            {
                return;
            }

            var start_point = VertexPositions[ctrl.Source]; // new Point(GraphAreaBase.GetX(ctrl.Source), GraphAreaBase.GetY(ctrl.Source));
            var end_point   = VertexPositions[ctrl.Target]; // new Point(GraphAreaBase.GetX(ctrl.Target), GraphAreaBase.GetY(ctrl.Target));

            if (start_point == end_point)
            {
                return;
            }

            var originalSizes = getSizesCollection(ctrl, end_point);
            var CHECKLIST     = new Dictionary <TVertex, KeyValuePair <TVertex, Rect> >(originalSizes);
            var leftSIZES     = new Dictionary <TVertex, KeyValuePair <TVertex, Rect> >(originalSizes);


            var tempList = new List <Point>();

            tempList.Add(start_point);

            bool HaveIntersections = true;

            //while we have some intersections - proceed
            while (HaveIntersections)
            {
                var cur_drawback = drawback_distance;
                while (true)
                {
                    var item = CHECKLIST.Keys.FirstOrDefault();
                    //set last route point as current start point
                    start_point = tempList.Last();
                    if (item == null)
                    {
                        //checked all vertices and no intersection was found - quit
                        HaveIntersections = false;
                        break;
                    }
                    else
                    {
                        var   r = originalSizes[item].Value;
                        Point checkpoint;
                        //check for intersection point. if none found - remove vertex from checklist
                        if (MathHelper.GetIntersectionPoint(r, start_point, end_point, out checkpoint) == -1)
                        {
                            CHECKLIST.Remove(item); continue;
                        }
                        var    main_vector = new Vector(end_point.X - start_point.X, end_point.Y - start_point.Y);
                        double X = 0; double Y = 0;
                        //calculate drawback X coordinate
                        if (start_point.X == checkpoint.X || Math.Abs(start_point.X - checkpoint.X) < cur_drawback)
                        {
                            X = start_point.X;
                        }
                        else if (start_point.X < checkpoint.X)
                        {
                            X = checkpoint.X - cur_drawback;
                        }
                        else
                        {
                            X = checkpoint.X + cur_drawback;
                        }
                        //calculate drawback Y coordinate
                        if (start_point.Y == checkpoint.Y || Math.Abs(start_point.Y - checkpoint.Y) < cur_drawback)
                        {
                            Y = start_point.Y;
                        }
                        else if (start_point.Y < checkpoint.Y)
                        {
                            Y = checkpoint.Y - cur_drawback;
                        }
                        else
                        {
                            Y = checkpoint.Y + cur_drawback;
                        }
                        //set drawback checkpoint
                        checkpoint = new Point(X, Y);
                        bool isStartPoint = checkpoint == start_point;

                        bool routeFound        = false;
                        bool viceversa         = false;
                        int  counter           = 1;
                        var  joint             = new Point();
                        bool?blocked_direction = null;
                        while (!routeFound)
                        {
                            //choose opposite vector side each cycle
                            var signedDistance = viceversa ? side_distance : -side_distance;
                            //get new point coordinate
                            joint = new Point(
                                checkpoint.X + signedDistance * counter * (main_vector.Y / main_vector.Length),
                                checkpoint.Y - signedDistance * counter * (main_vector.X / main_vector.Length));

                            //now check if new point is in some other vertex
                            var iresult      = false;
                            var forced_break = false;
                            foreach (var sz in originalSizes)
                            {
                                if (sz.Value.Value.Contains(joint))
                                {
                                    iresult = true;
                                    //block this side direction
                                    if (blocked_direction == null)
                                    {
                                        blocked_direction = viceversa;
                                    }
                                    else
                                    {
                                        //both sides blocked - need to drawback
                                        forced_break = true;
                                    }
                                    break;
                                }
                            }
                            if (forced_break)
                            {
                                break;
                            }

                            //get vector intersection if its ok
                            if (!iresult)
                            {
                                iresult = MathHelper.IsIntersected(r, joint, end_point);
                            }

                            //if no vector intersection - we've found it!
                            if (!iresult)
                            {
                                routeFound        = true;
                                blocked_direction = null;
                            }
                            else
                            {
                                //still have an intersection with current vertex
                                HaveIntersections = true;
                                //skip point search if too many attempts was made (bad logic hack)
                                if (counter > 300)
                                {
                                    break;
                                }
                                counter++;
                                //switch vector search side
                                if (blocked_direction == null || (blocked_direction == viceversa))
                                {
                                    viceversa = !viceversa;
                                }
                            }
                        }

                        //if blocked and this is not start point (nowhere to drawback) - then increase drawback distance
                        if (blocked_direction != null && !isStartPoint)
                        {
                            //search has been blocked - need to drawback
                            cur_drawback += drawback_distance;
                        }
                        else
                        {
                            //add new route point if we found it
                            // if(routeFound)
                            tempList.Add(joint);
                            leftSIZES.Remove(item);
                        }
                    }
                    //remove currently evaded obstacle vertex from the checklist
                    CHECKLIST.Remove(item);
                }
                //assign possible left vertices as a new checklist if any intersections was found
                if (HaveIntersections)
                {
                    CHECKLIST = new Dictionary <TVertex, KeyValuePair <TVertex, Rect> >(leftSIZES);
                }
            }
            //finally, add an end route point

            tempList.Add(end_point);


            if (EdgeRoutes.ContainsKey(ctrl))
            {
                EdgeRoutes[ctrl] = tempList.Count > 2 ? tempList.ToArray() : null;
            }
            else
            {
                EdgeRoutes.Add(ctrl, tempList.Count > 2 ? tempList.ToArray() : null);
            }
        }
        public override void Compute(CancellationToken cancellationToken)
        {
            switch (VisitedGraph.VertexCount)
            {
            case 0:
                return;

            case 1:
                VertexPositions.Add(VisitedGraph.Vertices.First(), new Point(0, 0));
                return;
            }

            InitializeWithRandomPositions(1, 1, -0.5, -0.5);

            InitAlgorithm();

            var finalRepuExponent = Parameters.repulsiveExponent;
            var finalAttrExponent = Parameters.attractionExponent;

            for (var step = 1; step <= Parameters.iterationCount; step++)
            {
                cancellationToken.ThrowIfCancellationRequested();

                ComputeBaryCenter();
                var quadTree = BuildQuadTree();

                #region hûlési függvény meghatározása
                if (Parameters.iterationCount >= 50 && finalRepuExponent < 1.0)
                {
                    Parameters.attractionExponent = finalAttrExponent;
                    Parameters.repulsiveExponent  = finalRepuExponent;
                    if (step <= 0.6 * Parameters.iterationCount)
                    {
                        // use energy model with few local minima
                        Parameters.attractionExponent += 1.1 * (1.0 - finalRepuExponent);
                        Parameters.repulsiveExponent  += 0.9 * (1.0 - finalRepuExponent);
                    }
                    else if (step <= 0.9 * Parameters.iterationCount)
                    {
                        // gradually move to final energy model
                        Parameters.attractionExponent +=
                            1.1 * (1.0 - finalRepuExponent) * (0.9 - step / (double)Parameters.iterationCount) / 0.3;
                        Parameters.repulsiveExponent +=
                            0.9 * (1.0 - finalRepuExponent) * (0.9 - step / (double)Parameters.iterationCount) / 0.3;
                    }
                }
                #endregion

                #region Move each node
                for (var i = 0; i < _vertices.Length; i++)
                {
                    cancellationToken.ThrowIfCancellationRequested();

                    var v         = _vertices[i];
                    var oldEnergy = GetEnergy(i, quadTree);

                    // compute direction of the move of the node
                    Vector bestDir;
                    GetDirection(i, quadTree, out bestDir);

                    // line search: compute length of the move
                    var oldPos = v.Position;

                    var bestEnergy   = oldEnergy;
                    var bestMultiple = 0;
                    bestDir /= 32;
                    //kisebb mozgatások esetén a legjobb eset meghatározása
                    for (var multiple = 32;
                         multiple >= 1 && (bestMultiple == 0 || bestMultiple / 2 == multiple);
                         multiple /= 2)
                    {
                        cancellationToken.ThrowIfCancellationRequested();

                        v.Position = oldPos + bestDir * multiple;
                        var curEnergy = GetEnergy(i, quadTree);
                        if (curEnergy < bestEnergy)
                        {
                            bestEnergy   = curEnergy;
                            bestMultiple = multiple;
                        }
                    }

                    //nagyobb mozgatás esetén van-e jobb megoldás?
                    for (var multiple = 64;
                         multiple <= 128 && bestMultiple == multiple / 2;
                         multiple *= 2)
                    {
                        cancellationToken.ThrowIfCancellationRequested();

                        v.Position = oldPos + bestDir * multiple;
                        var curEnergy = GetEnergy(i, quadTree);
                        if (curEnergy < bestEnergy)
                        {
                            bestEnergy   = curEnergy;
                            bestMultiple = multiple;
                        }
                    }

                    //legjobb megoldással mozgatás
                    v.Position = oldPos + bestDir * bestMultiple;
                    if (bestMultiple > 0)
                    {
                        quadTree.MoveNode(oldPos, v.Position, v.RepulsionWeight);
                    }
                }
                #endregion

                /*if ( ReportOnIterationEndNeeded )
                 *      Report( step );*/
            }
            CopyPositions();
            NormalizePositions();
        }
Exemple #20
0
        public override void Compute(CancellationToken cancellationToken)
        {
            if (VisitedGraph.VertexCount == 1)
            {
                VertexPositions.Add(VisitedGraph.Vertices.First(), new Point(0, 0));
                return;
            }

            #region Initialization
            _distances       = new double[VisitedGraph.VertexCount, VisitedGraph.VertexCount];
            _edgeLengths     = new double[VisitedGraph.VertexCount, VisitedGraph.VertexCount];
            _springConstants = new double[VisitedGraph.VertexCount, VisitedGraph.VertexCount];
            _vertices        = new TVertex[VisitedGraph.VertexCount];
            _positions       = new Point[VisitedGraph.VertexCount];

            //initializing with random positions
            InitializeWithRandomPositions(Parameters.Width, Parameters.Height);

            //copy positions into array (speed-up)
            int index = 0;
            foreach (var v in VisitedGraph.Vertices)
            {
                _vertices[index]  = v;
                _positions[index] = VertexPositions[v];
                index++;
            }

            //calculating the diameter of the graph
            //TODO check the diameter algorithm
            _diameter = VisitedGraph.GetDiameter <TVertex, TEdge, TGraph>(out _distances);

            //L0 is the length of a side of the display area
            double l0 = Math.Min(Parameters.Width, Parameters.Height);

            //ideal length = L0 / max d_i,j
            _idealEdgeLength = (l0 / _diameter) * Parameters.LengthFactor;

            //calculating the ideal distance between the nodes
            for (int i = 0; i < VisitedGraph.VertexCount - 1; i++)
            {
                cancellationToken.ThrowIfCancellationRequested();
                for (int j = i + 1; j < VisitedGraph.VertexCount; j++)
                {
                    cancellationToken.ThrowIfCancellationRequested();
                    //distance between non-adjacent vertices
                    double dist = _diameter * Parameters.DisconnectedMultiplier;

                    //calculating the minimal distance between the vertices
                    if (_distances[i, j] != double.MaxValue)
                    {
                        dist = Math.Min(_distances[i, j], dist);
                    }
                    if (_distances[j, i] != double.MaxValue)
                    {
                        dist = Math.Min(_distances[j, i], dist);
                    }
                    _distances[i, j]       = _distances[j, i] = dist;
                    _edgeLengths[i, j]     = _edgeLengths[j, i] = _idealEdgeLength * dist;
                    _springConstants[i, j] = _springConstants[j, i] = Parameters.K / Math.Pow(dist, 2);
                }
            }
            #endregion

            int n = VisitedGraph.VertexCount;
            if (n == 0)
            {
                return;
            }

            //TODO check this condition
            for (int currentIteration = 0; currentIteration < Parameters.MaxIterations; currentIteration++)
            {
                cancellationToken.ThrowIfCancellationRequested();

                #region An iteration
                double maxDeltaM = double.NegativeInfinity;
                int    pm        = -1;

                //get the 'p' with the max delta_m
                for (int i = 0; i < n; i++)
                {
                    cancellationToken.ThrowIfCancellationRequested();

                    double deltaM = CalculateEnergyGradient(i);
                    if (maxDeltaM < deltaM)
                    {
                        maxDeltaM = deltaM;
                        pm        = i;
                    }
                }
                //TODO is needed?
                if (pm == -1)
                {
                    return;
                }

                //calculating the delta_x & delta_y with the Newton-Raphson method
                //there is an upper-bound for the while (deltaM > epsilon) {...} cycle (100)
                for (int i = 0; i < 100; i++)
                {
                    _positions[pm] += CalcDeltaXY(pm);

                    double deltaM = CalculateEnergyGradient(pm);
                    //real stop condition
                    if (deltaM < double.Epsilon)
                    {
                        break;
                    }
                }

                //what if some of the vertices would be exchanged?
                if (Parameters.ExchangeVertices && maxDeltaM < double.Epsilon)
                {
                    double energy = CalcEnergy();
                    for (int i = 0; i < n - 1; i++)
                    {
                        cancellationToken.ThrowIfCancellationRequested();

                        for (int j = i + 1; j < n; j++)
                        {
                            cancellationToken.ThrowIfCancellationRequested();

                            double xenergy = CalcEnergyIfExchanged(i, j);
                            if (energy > xenergy)
                            {
                                Point p = _positions[i];
                                _positions[i] = _positions[j];
                                _positions[j] = p;
                                return;
                            }
                        }
                    }
                }
                #endregion

                /* if ( ReportOnIterationEndNeeded )
                 *   Report( currentIteration );*/
            }
            Report(Parameters.MaxIterations);
        }
 public override void UpdateVertexData(TVertex vertex, Point position, Rect size)
 {
     VertexPositions.AddOrUpdate(vertex, position);
     VertexSizes.AddOrUpdate(vertex, size);
 }
        /// <summary>
        /// Converts the record/s into a Unity GameObject structure with meshes,
        /// materials etc and imports into the scene.
        /// </summary>
        public override void ImportIntoScene()
        {
            // Create an empty gameobject
            UnityGameObject = new GameObject(ID);
            // DuckbearLab: FIX!
            //UnityGameObject.transform.localScale = Vector3.one;

            // Apply transformations
            UnityGameObject.transform.localPosition = Position;
            UnityGameObject.transform.localRotation = Rotation;
            if (Scale != Vector3.one)
            {
                UnityGameObject.transform.localScale = Scale;
            }

            // Assign parent
            if (Parent != null && Parent is InterRecord)
            {
                // DuckbearLab: FIX!
                UnityGameObject.transform.SetParent((Parent as InterRecord).UnityGameObject.transform, false);
                //UnityGameObject.transform.parent = (Parent as InterRecord).UnityGameObject.transform;
            }

            // Add Comment
            if (!string.IsNullOrEmpty(Comment))
            {
                UnityGameObject.AddComponent <UFLT.MonoBehaviours.Comment>().Value = Comment;
            }

            // Processes children
            base.ImportIntoScene();

            // Create mesh
            if (Vertices != null && Vertices.Count > 0)
            {
                Mesh m = new Mesh();
                m.name     = ID;
                m.vertices = VertexPositions.ToArray();
                m.normals  = Normals.ToArray();
                m.uv       = UVS.ToArray();

                // DuckbearLab: Fix for very large meshes
                if (VertexPositions.Count >= ushort.MaxValue)
                {
                    m.indexFormat = UnityEngine.Rendering.IndexFormat.UInt32;
                }

                MeshRenderer mr   = UnityGameObject.AddComponent <MeshRenderer>();
                Material[]   mats = new Material[SubMeshes.Count];
                MeshFilter   mf   = UnityGameObject.AddComponent <MeshFilter>();

                // Set submeshes
                m.subMeshCount = SubMeshes.Count;
                for (int i = 0; i < SubMeshes.Count; i++)
                {
                    mats[i] = SubMeshes[i].Key.UnityMaterial;
                    m.SetTriangles(SubMeshes[i].Value.ToArray(), i);
                }


                // DuckbearLab: OPTIMIZE!
                //mr.materials = mats;
                ;
                {
                    bool equal = true;
                    foreach (var material in mats)
                    {
                        if (material != mats[0])
                        {
                            equal = false;
                        }
                    }

                    if (equal && SubMeshes.Count > 1)
                    {
                        CombineInstance[] combine = new CombineInstance[SubMeshes.Count];
                        for (int i = 0; i < combine.Length; i++)
                        {
                            combine[i].mesh         = m;
                            combine[i].subMeshIndex = i;
                        }
                        var newMesh = new Mesh();
                        newMesh.name = ID;
                        newMesh.CombineMeshes(combine, true, false);
                        m = newMesh;

                        Material[] newMats = new Material[1];
                        newMats[0]   = mats[0];
                        mr.materials = newMats;
                    }
                    else
                    {
                        mr.materials = mats;
                    }
                }

#if UNITY_EDITOR
                UnityEditor.MeshUtility.Optimize(m);
#endif
                mf.mesh = m;
            }
        }
        protected void CopyPositionsSilent(bool shouldTranslate)
        {
            //calculate the topLeft position
            var translation = new Vector(float.PositiveInfinity, float.PositiveInfinity);

            if (shouldTranslate)
            {
                foreach (var v in _graph.Vertices)
                {
                    if (double.IsNaN(v.RealPosition.X) || double.IsNaN(v.RealPosition.Y))
                    {
                        continue;
                    }

                    translation.X = Math.Min(v.RealPosition.X, translation.X);
                    translation.Y = Math.Min(v.RealPosition.Y, translation.Y);
                }
                translation   *= -1;
                translation.X += Parameters.VerticalGap / 2;
                translation.Y += Parameters.HorizontalGap / 2;

                //translate with the topLeft position
                foreach (var v in _graph.Vertices)
                {
                    v.RealPosition += translation;
                }
            }
            else
            {
                translation = new Vector(0, 0);
            }

            //copy the positions of the vertices
            VertexPositions.Clear();
            foreach (var v in _graph.Vertices)
            {
                if (v.IsDummyVertex)
                {
                    continue;
                }

                Point pos = v.RealPosition;
                if (!shouldTranslate)
                {
                    pos.X += v.Size.Width * 0.5 + translation.X;
                    pos.Y += v.Size.Height * 0.5 + translation.Y;
                }
                VertexPositions[v.Original] = pos;
            }

            //copy the edge routes
            EdgeRoutes.Clear();
            foreach (var e in _graph.HiddenEdges)
            {
                if (!e.IsLongEdge)
                {
                    continue;
                }

                EdgeRoutes[e.Original] =
                    e.IsReverted
                        ? e.DummyVertices.Reverse().Select(dv => dv.RealPosition).ToArray()
                        : e.DummyVertices.Select(dv => dv.RealPosition).ToArray();
            }
        }
        public override void Compute(CancellationToken cancellationToken)
        {
            //calculate the size of the circle
            double perimeter      = 0;
            var    usableVertices = VisitedGraph.Vertices.Where(v => v.SkipProcessing != ProcessingOptionEnum.Freeze).ToList();

            //if we have empty input positions list we have to fill positions for frozen vertices manualy
            if (VertexPositions.Count == 0)
            {
                foreach (var item in VisitedGraph.Vertices.Where(v => v.SkipProcessing == ProcessingOptionEnum.Freeze))
                {
                    VertexPositions.Add(item, new Point());
                }
            }
            double[] halfSize = new double[usableVertices.Count];
            int      i        = 0;

            foreach (var v in usableVertices)
            {
                cancellationToken.ThrowIfCancellationRequested();

                Size s = _sizes[v];
                halfSize[i] = Math.Sqrt(s.Width * s.Width + s.Height * s.Height) * 0.5;
                perimeter  += halfSize[i] * 2;
                i++;
            }

            double radius = perimeter / (2 * Math.PI);

            //
            //precalculation
            //
            double angle = 0, a;

            i = 0;
            foreach (var v in usableVertices)
            {
                cancellationToken.ThrowIfCancellationRequested();

                a      = Math.Sin(halfSize[i] * 0.5 / radius) * 2;
                angle += a;
                //if ( ReportOnIterationEndNeeded )
                VertexPositions[v] = new Point(Math.Cos(angle) * radius + radius, Math.Sin(angle) * radius + radius);
                angle += a;
            }

            //if ( ReportOnIterationEndNeeded )
            //    OnIterationEnded( 0, 50, "Precalculation done.", false );

            //recalculate radius
            radius = angle / (2 * Math.PI) * radius;

            //calculation
            angle = 0;
            i     = 0;
            foreach (var v in usableVertices)
            {
                cancellationToken.ThrowIfCancellationRequested();

                a      = Math.Sin(halfSize[i] * 0.5 / radius) * 2;
                angle += a;
                VertexPositions[v] = new Point(Math.Cos(angle) * radius + radius, Math.Sin(angle) * radius + radius);
                angle += a;
            }
        }