/// <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(); }