Exemplo n.º 1
0
        /// <summary>
        /// Select the next vertex from the queue.
        /// </summary>
        /// <returns></returns>
        private uint?SelectNext()
        {
            // first check the first of the current queue.
            while (_queue.Count > 0)
            { // get the first vertex and check.
                uint first_queued = _queue.Peek();
                if (this.IsContracted(first_queued))
                { // already contracted, priority was updated.
                    _queue.Pop();
                    continue;
                }
                float current_priority = _queue.PeekWeight();

                // the lazy updating part!
                // calculate priority
                float priority = _calculator.Calculate(first_queued);
                if (priority != current_priority)
                { // a succesfull update.
                    _missesQueue.Enqueue(true);
                    _misses++;
                }
                else
                { // an unsuccessfull update.
                    _missesQueue.Enqueue(false);
                }
                if (_missesQueue.Count > _k)
                { // dequeue and update the misses.
                    if (_missesQueue.Dequeue())
                    {
                        _misses--;
                    }
                }

                // if the misses are _k
                if (_misses == _k)
                { // recalculation.
                    this.RecalculateQueue();

                    //int totalCadinality = 0;
                    //for (uint vertex = 0; vertex < _target.VertexCount; vertex++)
                    //{
                    //    var edges =  _target.GetEdges(vertex);
                    //    if (arcs != null)
                    //    {
                    //        totalCadinality = arcs.Count() + totalCadinality;
                    //    }
                    //}
                    //OsmSharp.Logging.Log.TraceEvent("CHPreProcessor", TraceEventType.Information,
                    //    "Average card: {0}", (double)totalCadinality / (double)_target.VertexCount);

                    _missesQueue.Clear();
                    _misses = 0;

                    _target.Compress();
                }
                else
                {     // no recalculation.
                    if (priority != current_priority)
                    { // re-enqueue.
                        _queue.Pop();
                        _queue.Push(first_queued, priority);
                    }
                    else
                    { // try to select another.
                        return(_queue.Pop());
                    }
                }
            }

            // check the queue.
            if (_queue.Count > 0)
            {
                throw new Exception("Unqueued items left!, CanBeContracted is too restrictive!");
            }
            return(null); // all nodes have been contracted.
        }
        /// <summary>
        /// Compresses the graph by deleting vertices.
        /// </summary>
        private void CompressGraph()
        {
            // initialize status variables.
            uint vertex = 1;
            uint nextCompressedPosition = 1;

            // search edge until a real node.
            float latitude, longitude;
            float latestProgress = -1;

            while (vertex <= _graph.VertexCount)
            {
                var edges = _graph.GetEdges(vertex).ToList();
                if (edges != null && edges.Count > 0)
                {     // ok, this vertex has edges.
                    if (nextCompressedPosition != vertex)
                    { // this vertex should go in another place.
                        _graph.GetVertex(vertex, out latitude, out longitude);

                        // set the next coordinates.
                        _graph.SetVertex(nextCompressedPosition, latitude, longitude);

                        // set the new edges.
                        _graph.RemoveEdges(nextCompressedPosition);
                        foreach (var edge in edges)
                        {     // add all arcs.
                            if (edge.Neighbour != vertex)
                            { // this edge is not an edge that has the same end-start point.
                                if (edge.EdgeData.Forward)
                                {
                                    _graph.AddEdge(nextCompressedPosition, edge.Neighbour, edge.EdgeData, null);
                                }
                                else
                                {
                                    _graph.AddEdge(nextCompressedPosition, edge.Neighbour, (Edge)edge.EdgeData.Reverse(), null);
                                }
                            }
                            else
                            { // this edge is an edge that has the same end-start point.
                                _graph.AddEdge(nextCompressedPosition, nextCompressedPosition, edge.EdgeData, null);
                            }

                            // update other arcs.
                            if (edge.Neighbour != vertex)
                            { // do not update other arcs if other vertex is the same.
                                var reverseEdges = _graph.GetEdges(edge.Neighbour).ToList();
                                if (reverseEdges != null)
                                { // there are reverse edges, check if there is a reference to vertex.
                                    reverseEdges = new List <Edge <Edge> >(reverseEdges);
                                    foreach (var reverseEdge in reverseEdges)
                                    {     // check each edge for vertex.
                                        if (reverseEdge.Neighbour == vertex)
                                        { // ok, replace this edge.
                                            ICoordinateCollection reverseEdgeCoordinates;
                                            if (!_graph.GetEdgeShape(edge.Neighbour, reverseEdge.Neighbour, out reverseEdgeCoordinates))
                                            {
                                                reverseEdgeCoordinates = null;
                                            }

                                            _graph.RemoveEdge(edge.Neighbour, vertex);
                                            if (reverseEdgeCoordinates == null)
                                            {
                                                _graph.AddEdge(edge.Neighbour, nextCompressedPosition, (Edge)reverseEdge.EdgeData.Reverse(), null);
                                            }
                                            else if (reverseEdge.EdgeData.Forward)
                                            {
                                                _graph.AddEdge(edge.Neighbour, nextCompressedPosition, reverseEdge.EdgeData, reverseEdgeCoordinates);
                                            }
                                            else
                                            {
                                                _graph.AddEdge(edge.Neighbour, nextCompressedPosition, (Edge)reverseEdge.EdgeData.Reverse(), reverseEdgeCoordinates.Reverse());
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    }

                    nextCompressedPosition++;
                }

                // move to the next vertex.
                vertex++;

                // report progress.
                float progress = (float)System.Math.Round((((double)vertex / (double)_graph.VertexCount) * 100));
                if (progress != latestProgress)
                {
                    OsmSharp.Logging.Log.TraceEvent("Preprocessor", TraceEventType.Information,
                                                    "Compressing graph... {0}%", progress);
                    latestProgress = progress;
                }
            }

            // remove all extra space.
            _graph.Compress();
            _graph.Trim();
        }