/// <summary> /// Calculates the ordering. /// </summary> /// <param name="vertex"></param> /// <returns></returns> public float Calculate(uint vertex) { var neighbours = _data.GetEdges(vertex); // check the proper conditions. if (neighbours.Length == 2) { return(-1); } return(float.MaxValue); }
/// <summary> /// Moves to the next item. /// </summary> /// <returns></returns> public bool MoveNext() { if (_current == null) { _current = this.FindHighest(); _index.Add(_current.Vertex); _currentCount = 1; return(_current != null); } // search for the next arc. KeyValuePair <uint, CHEdgeData>[] edges = _graph.GetEdges(_current.Vertex); int arcIdx = _current.ArcIdx; arcIdx++; while (arcIdx < edges.Length) { // check if it is 'lower'. if (edges[arcIdx].Value.ToLower && !_index.Contains(edges[arcIdx].Key)) { // yes the arc is 'lower' take it! _current.ArcIdx = arcIdx; // move the arcIdx. Position newPosition = new Position(); newPosition.Parent = _current; newPosition.ArcIdx = -1; newPosition.Vertex = edges[arcIdx].Key; newPosition.Depth = _current.Depth + 1; _current = newPosition; _index.Add(_current.Vertex); _currentCount++; return(true); } arcIdx++; // move to the next arc. } // move to parent. if (_current.Parent != null) { // set parent as current and move next. _current = _current.Parent; return(this.MoveNext()); } // also enumerate all the other 'islands' of vertices unconnected to the current vertices. return(this.MoveToNextIsland()); }
/// <summary> /// Returns the arcs that point to lower vertices. /// </summary> /// <param name="graph"></param> /// <param name="vertexId"></param> /// <returns></returns> public static KeyValuePair <uint, CHEdgeData>[] GetArcsLower(this IDynamicGraph <CHEdgeData> graph, uint vertexId) { KeyValuePair <uint, CHEdgeData>[] arcs = graph.GetEdges(vertexId); KeyValuePair <uint, CHEdgeData>[] higherArcs = new KeyValuePair <uint, CHEdgeData> [arcs.Length]; int higherIdx = 0; for (int idx = 0; idx < arcs.Length; idx++) { if (!arcs[idx].Value.ToHigher) { higherArcs[higherIdx] = arcs[idx]; higherIdx++; } } Array.Resize(ref higherArcs, higherIdx); return(higherArcs); }
/// <summary> /// Starts pre-processing all nodes. /// </summary> public void Start() { // build the empty coordinate list. var emptyCoordinateList = new GeoCoordinateSimple[0]; var verticesList = new HashSet <uint>(); // initialize status variables. uint nextToProcess = 0; uint nextPosition = 0; // search edge until a real node. double latestProgress = 0; while (nextToProcess < _graph.VertexCount) { // keep looping until all vertices have been processed. // select a new vertext to select. var vertexToProcess = nextToProcess; var edges = _graph.GetEdges(vertexToProcess); if (edges.Length == 2) { // find one of the neighbours that is usefull. vertexToProcess = edges[0].Key; edges = _graph.GetEdges(vertexToProcess); verticesList.Clear(); verticesList.Add(vertexToProcess); while (edges.Length == 2) { // keep looping until there is a vertex that is usefull. vertexToProcess = edges[0].Key; if (verticesList.Contains(vertexToProcess)) { // take the other vertex. vertexToProcess = edges[1].Key; if (verticesList.Contains(vertexToProcess)) { // an island was detected with only vertices having two neighbours. // TODO: find a way to handle this! edges = new KeyValuePair <uint, LiveEdge> [0]; break; } } verticesList.Add(vertexToProcess); edges = _graph.GetEdges(vertexToProcess); } } if (edges.Length > 0) { // ok, the vertex was not already processed. nextPosition++; var oldEdges = edges.Clone() as KeyValuePair <uint, LiveEdge>[]; var ignoreList = new HashSet <uint>(); foreach (var oldEdge in oldEdges) { if (ignoreList.Contains(oldEdge.Key)) { // ignore this edge: already removed in a previous iteration. break; } // don't re-process edges that already have coordinates. GeoCoordinateSimple[] oldEdgeValueCoordinates; _graph.GetEdgeShape(vertexToProcess, oldEdge.Key, out oldEdgeValueCoordinates); if (oldEdgeValueCoordinates != null) { // this edge has already been processed. break; } // STEP1: Build list of vertices that are only for form. // set current/previous. var distance = oldEdge.Value.Distance; var current = oldEdge.Key; var previous = vertexToProcess; // build list of vertices. var vertices = new List <uint>(); vertices.Add(previous); vertices.Add(current); // get next edges list. var nextEdges = _graph.GetEdges(current); while (nextEdges.Length == 2) { // ok the current vertex can be removed. var nextEdge = nextEdges[0]; if (nextEdge.Key == previous) { // it's the other edge! nextEdge = nextEdges[1]; } // compare edges. if (nextEdge.Value.Forward != oldEdge.Value.Forward || nextEdge.Value.Tags != oldEdge.Value.Tags) { // oeps, edges are different! break; } // check for intermediates. GeoCoordinateSimple[] nextEdgeValueCoordinates; _graph.GetEdgeShape(current, nextEdge.Key, out nextEdgeValueCoordinates); if (nextEdgeValueCoordinates != null) { // oeps, there are intermediates already, this can occur when two osm-ways are drawn on top of eachother. break; } // add distance. distance = distance + nextEdge.Value.Distance; // set current/previous. previous = current; current = nextEdge.Key; vertices.Add(current); // get next edges. nextEdges = _graph.GetEdges(current); } // check if the edge contains intermediate points. if (vertices.Count == 2) { // no intermediate points: add the empty coordinate list. var oldEdgeValue = oldEdge.Value; // keep edges that already have intermediates. GeoCoordinateSimple[] edgeToKeepValueCoordinates = null; var edgesToKeep = new List <Tuple <uint, LiveEdge, GeoCoordinateSimple[]> >(); foreach (var edgeToKeep in _graph.GetEdges(vertexToProcess)) { edgeToKeepValueCoordinates = null; if (edgeToKeep.Key == oldEdge.Key && _graph.GetEdgeShape(vertexToProcess, edgeToKeep.Key, out edgeToKeepValueCoordinates)) { edgesToKeep.Add(new Tuple <uint, LiveEdge, GeoCoordinateSimple[]>( edgeToKeep.Key, edgeToKeep.Value, edgeToKeepValueCoordinates)); } } // delete olds arcs. _graph.RemoveEdge(vertexToProcess, oldEdge.Key); // add new arc. if (oldEdgeValue.Forward) { _graph.AddEdge(vertexToProcess, oldEdge.Key, oldEdgeValue, null); } else { _graph.AddEdge(vertexToProcess, oldEdge.Key, (LiveEdge)oldEdgeValue.Reverse(), null); } // add edges to keep. foreach (var edgeToKeep in edgesToKeep) { _graph.AddEdge(vertexToProcess, edgeToKeep.Item1, edgeToKeep.Item2, edgeToKeep.Item3); } } else { // intermediate points: build array. // STEP2: Build array of coordinates. var coordinates = new GeoCoordinateSimple[vertices.Count - 2]; float latitude, longitude; for (int idx = 1; idx < vertices.Count - 1; idx++) { _graph.GetVertex(vertices[idx], out latitude, out longitude); coordinates[idx - 1] = new GeoCoordinateSimple() { Latitude = latitude, Longitude = longitude }; } // STEP3: Remove all unneeded edges. _graph.RemoveEdge(vertices[0], vertices[1]); // remove first edge. for (int idx = 1; idx < vertices.Count - 1; idx++) { // delete all intermidiate arcs. _graph.RemoveEdges(vertices[idx]); } _graph.RemoveEdge(vertices[vertices.Count - 1], vertices[vertices.Count - 2]); // remove last edge. if (vertices[0] == vertices[vertices.Count - 1]) { // also remove outgoing edge. ignoreList.Add(vertices[vertices.Count - 2]); // make sure this arc is ignored in next iteration. } // STEP4: Add new edge. if (oldEdge.Value.Forward) { _graph.AddEdge(vertices[0], vertices[vertices.Count - 1], new LiveEdge() { Forward = oldEdge.Value.Forward, Tags = oldEdge.Value.Tags, Distance = distance }, coordinates, this); } else { var reverse = new GeoCoordinateSimple[coordinates.Length]; coordinates.CopyToReverse(reverse, 0); _graph.AddEdge(vertices[vertices.Count - 1], vertices[0], new LiveEdge() { Forward = !oldEdge.Value.Forward, Tags = oldEdge.Value.Tags, Distance = distance }, reverse, this); } } } } // move to the next position. nextToProcess++; // report progress. float progress = (float)System.Math.Round((((double)nextToProcess / (double)_graph.VertexCount) * 100)); if (progress != latestProgress) { OsmSharp.Logging.Log.TraceEvent("LiveEdgePreprocessor", TraceEventType.Information, "Removing edges... {0}%", progress); latestProgress = progress; } } // compress the graph. this.CompressGraph(); }
/// <summary> /// Returns all arcs starting at a given vertex. /// </summary> /// <param name="vertexId"></param> /// <returns></returns> public KeyValuePair <uint, TEdgeData>[] GetEdges(uint vertexId) { return(_graph.GetEdges(vertexId)); }
/// <summary> /// Returns a topologically sorted version of the given graph. /// </summary> /// <param name="graph"></param> /// <returns></returns> public IDynamicGraph <CHEdgeData> SortGraph(IDynamicGraph <CHEdgeData> graph) { //// also add all downward edges. //graph.AddDownwardEdges(); // sort the topologically ordered vertices into bins representing a certain height range. var heightBins = new List <uint> [1000]; foreach (var vertexDepth in new CHDepthFirstEnumerator(graph)) { // enumerates all vertixes depth-first. int binIdx = (int)(vertexDepth.Depth / _heightBinSize); if (heightBins.Length < binIdx) { // resize bin array if needed. Array.Resize(ref heightBins, System.Math.Max(heightBins.Length + 1000, binIdx + 1)); } // add to the current bin. var bin = heightBins[binIdx]; if (bin == null) { // create new bin. bin = new List <uint>(); heightBins[binIdx] = bin; } bin.Add(vertexDepth.VertexId); } // temp test. var sortedGraph = new MemoryDynamicGraph <CHEdgeData>(); var currentBinIds = new Dictionary <uint, uint>(); uint newVertexId; for (int idx = 0; idx < heightBins.Length; idx++) { var bin = heightBins[idx]; if (bin != null) { // translate ids. // fill current bin ids and add vertices to the new graph. foreach (uint binVertexId in bin) { float latitude, longitude; graph.GetVertex(binVertexId, out latitude, out longitude); newVertexId = sortedGraph.AddVertex(latitude, longitude); currentBinIds.Add(binVertexId, newVertexId); // add to the current bin index. } } } // rebuild the CH graph based on the new ordering and build the CHRegions. newVertexId = 0; for (int idx = 0; idx < heightBins.Length; idx++) { var bin = heightBins[idx]; if (bin != null) { // translate ids. foreach (uint binVertexId in bin) { currentBinIds.TryGetValue(binVertexId, out newVertexId); // get the higher arcs and convert their ids. KeyValuePair <uint, CHEdgeData>[] arcs = graph.GetEdges(binVertexId); foreach (KeyValuePair <uint, CHEdgeData> arc in arcs) { // get target vertex. uint nextVertexArcId = CHEdgeDataDataSourceSerializer.SearchVertex(arc.Key, currentBinIds, heightBins); // convert edge. var newEdge = new CHEdgeData(); newEdge.Direction = arc.Value.Direction; if (arc.Value.HasContractedVertex) { // contracted info. newEdge.ContractedVertexId = CHEdgeDataDataSourceSerializer.SearchVertex(arc.Value.ContractedVertexId, currentBinIds, heightBins); } else { // no contracted info. newEdge.ContractedVertexId = 0; } newEdge.Tags = arc.Value.Tags; newEdge.Weight = arc.Value.Weight; sortedGraph.AddEdge(newVertexId, nextVertexArcId, newEdge, null); } } } } return(sortedGraph); }