/// <summary> /// Rebuilds the vertex index. /// </summary> public void RebuildVertexIndex() { _vertexIndex = new QuadTree <GeoCoordinate, uint>(); for (uint vertex = 0; vertex <= _graph.VertexCount; vertex++) { float latitude, longitude; if (_graph.GetVertex(vertex, out latitude, out longitude)) { _vertexIndex.Add(new GeoCoordinate(latitude, longitude), vertex); } } }
/// <summary> /// Switches the data around for the two given vertices. /// </summary> /// <typeparam name="TEdgeData"></typeparam> /// <param name="graph"></param> /// <param name="vertex1"></param> /// <param name="vertex2"></param> public static void Switch <TEdgeData>(this GraphBase <TEdgeData> graph, uint vertex1, uint vertex2) where TEdgeData : struct, IGraphEdgeData { // get all existing data. var edges1 = new List <Edge <TEdgeData> >(graph.GetEdges(vertex1)); var edges2 = new List <Edge <TEdgeData> >(graph.GetEdges(vertex2)); float vertex1Latitude, vertex1Longitude; graph.GetVertex(vertex1, out vertex1Latitude, out vertex1Longitude); float vertex2Latitude, vertex2Longitude; graph.GetVertex(vertex2, out vertex2Latitude, out vertex2Longitude); // remove all edges. graph.RemoveEdges(vertex1); graph.RemoveEdges(vertex2); // update location. graph.SetVertex(vertex1, vertex2Latitude, vertex2Longitude); graph.SetVertex(vertex2, vertex1Latitude, vertex1Longitude); // add edges again. foreach (var edge in edges1) { // update existing data. if (edge.Neighbour == vertex1) { edge.Neighbour = vertex2; } else if (edge.Neighbour == vertex2) { edge.Neighbour = vertex1; } graph.AddEdge(vertex2, edge.Neighbour, edge.EdgeData, edge.Intermediates); } foreach (var edge in edges2) { // update existing data. if (edge.Neighbour == vertex1) { edge.Neighbour = vertex2; } else if (edge.Neighbour == vertex2) { edge.Neighbour = vertex1; } graph.AddEdge(vertex1, edge.Neighbour, edge.EdgeData, edge.Intermediates); } }
/// <summary> /// Returns the hibert distance for n and the given vertex. /// </summary> /// <typeparam name="TEdgeData"></typeparam> /// <param name="graph"></param> /// <param name="n"></param> /// <param name="vertex"></param> /// <returns></returns> public static ulong HilbertDistance <TEdgeData>(this GraphBase <TEdgeData> graph, int n, uint vertex) where TEdgeData : struct, IGraphEdgeData { float latitude, longitude; graph.GetVertex(vertex, out latitude, out longitude); return(OsmSharp.Math.Algorithms.HilbertCurve.HilbertDistance(latitude, longitude, n)); }
/// <summary> /// Returns the hibert distance for n and the given vertex. /// </summary> /// <typeparam name="TEdgeData"></typeparam> /// <param name="graph"></param> /// <param name="n"></param> /// <param name="vertex"></param> /// <returns></returns> public static long HilbertDistance <TEdgeData>(this GraphBase <TEdgeData> graph, int n, uint vertex) where TEdgeData : struct, IGraphEdgeData { float latitude, longitude; if (!graph.GetVertex(vertex, out latitude, out longitude)) { throw new Exception(string.Format("Vertex {0} does not exist in graph.", vertex)); } return(HilbertCurve.HilbertDistance(latitude, longitude, n)); }
/// <summary> /// Returns all hibert distances for n. /// </summary> /// <typeparam name="TEdgeData"></typeparam> /// <returns></returns> public static long[] HilbertDistances <TEdgeData>(this GraphBase <TEdgeData> graph, int n) where TEdgeData : struct, IGraphEdgeData { var distances = new long[graph.VertexCount]; for (uint vertex = 1; vertex <= graph.VertexCount; vertex++) { float latitude, longitude; graph.GetVertex(vertex, out latitude, out longitude); distances[vertex - 1] = HilbertCurve.HilbertDistance(latitude, longitude, n); } return(distances); }
/// <summary> /// Searches the graph for nearby vertices assuming it has been sorted. /// </summary> /// <typeparam name="TEdgeData"></typeparam> public static List <uint> SearchHilbert <TEdgeData>(this GraphBase <TEdgeData> graph, int n, float latitude, float longitude, float offset) where TEdgeData : struct, IGraphEdgeData { var targets = HilbertCurve.HilbertDistances( System.Math.Max(latitude - offset, -90), System.Math.Max(longitude - offset, -180), System.Math.Min(latitude + offset, 90), System.Math.Min(longitude + offset, 180), n); targets.Sort(); var vertices = new List <uint>(); var targetIdx = 0; var vertex1 = (uint)1; var vertex2 = (uint)graph.VertexCount; float vertexLat, vertexLon; while (targetIdx < targets.Count) { uint vertex; int count; if (GraphExtensions.SearchHilbert(graph, targets[targetIdx], n, vertex1, vertex2, out vertex, out count)) { // the search was successful. while (count > 0) { // there have been vertices found. if (graph.GetVertex((uint)vertex + (uint)(count - 1), out vertexLat, out vertexLon)) { // the vertex was found. if (System.Math.Abs(latitude - vertexLat) < offset && System.Math.Abs(longitude - vertexLon) < offset) { // within offset. vertices.Add((uint)vertex + (uint)(count - 1)); } } count--; } // update vertex1. vertex1 = vertex; } // move to next target. targetIdx++; } return(vertices); }
/// <summary> /// Copies all data from the given graph. /// </summary> /// <typeparam name="TEdgeData"></typeparam> /// <param name="copyTo"></param> /// <param name="copyFrom"></param> public static void CopyFrom <TEdgeData>(this GraphBase <TEdgeData> copyTo, GraphBase <TEdgeData> copyFrom) where TEdgeData : struct, IGraphEdgeData { float latitude, longitude; for (uint vertex = 1; vertex <= copyFrom.VertexCount; vertex++) { copyFrom.GetVertex(vertex, out latitude, out longitude); uint newVertex = copyTo.AddVertex(latitude, longitude); if (newVertex != vertex) { throw new Exception("Graph should be empty when copy new data to it."); } } for (uint vertex = 1; vertex <= copyFrom.VertexCount; vertex++) { var edges = new List <Edge <TEdgeData> >(copyFrom.GetEdges(vertex)); foreach (var edge in edges) { copyTo.AddEdge(vertex, edge.Neighbour, edge.EdgeData, edge.Intermediates); } } }
/// <summary> /// Returns true if a given vertex is in the graph. /// </summary> /// <returns></returns> public override bool GetVertex(uint id, out float latitude, out float longitude) { return(_graph.GetVertex(id, out latitude, out longitude)); }
/// <summary> /// Switches the locations around for the two given vertices. /// </summary> /// <typeparam name="TEdgeData"></typeparam> public static void Switch <TEdgeData>(this GraphBase <TEdgeData> graph, uint vertex1, uint vertex2, IDictionary <uint, List <uint> > reverse) where TEdgeData : struct, IGraphEdgeData { if (graph.IsDirected && reverse == null) { throw new ArgumentException("Cannot switch two vertices on a directed graph without it's reverse index."); } if (vertex1 == vertex2) { // switching identical vertices (?). return; } float vertex1Latitude, vertex1Longitude; graph.GetVertex(vertex1, out vertex1Latitude, out vertex1Longitude); float vertex2Latitude, vertex2Longitude; graph.GetVertex(vertex2, out vertex2Latitude, out vertex2Longitude); // update location. graph.SetVertex(vertex1, vertex2Latitude, vertex2Longitude); graph.SetVertex(vertex2, vertex1Latitude, vertex1Longitude); // switch and update edges, this is easy! var edges1 = new List <Edge <TEdgeData> >(); foreach (var edge in graph.GetEdges(vertex1)) { edges1.Add(new Edge <TEdgeData>() { EdgeData = edge.EdgeData, Neighbour = edge.Neighbour, Intermediates = edge.Intermediates != null ? new CoordinateArrayCollection <GeoCoordinateSimple>( edge.Intermediates.ToSimpleArray()) : null }); } var edges2 = new List <Edge <TEdgeData> >(); foreach (var edge in graph.GetEdges(vertex2)) { edges2.Add(new Edge <TEdgeData>() { EdgeData = edge.EdgeData, Neighbour = edge.Neighbour, Intermediates = edge.Intermediates != null ? new CoordinateArrayCollection <GeoCoordinateSimple>( edge.Intermediates.ToSimpleArray()) : null }); } graph.RemoveEdges(vertex1); graph.RemoveEdges(vertex2); foreach (var edge in edges1) { // update existing data. var neighbour = edge.Neighbour; var newNeighbour = edge.Neighbour; if (newNeighbour == vertex2) { newNeighbour = vertex1; } graph.AddEdge(vertex2, newNeighbour, edge.EdgeData, edge.Intermediates); if (reverse != null) { // update reverse set if present. List <uint> neighbours = null; if (reverse.TryGetValue(neighbour, out neighbours)) { // remove. neighbours.Remove(vertex1); reverse[neighbour] = neighbours; } if (reverse.TryGetValue(newNeighbour, out neighbours)) { // add. neighbours.Add(vertex2); } else { // add new. neighbours = new List <uint>(); neighbours.Add(vertex2); } reverse[newNeighbour] = neighbours; } } foreach (var edge in edges2) { // update existing data. var neighbour = edge.Neighbour; var newNeighbour = edge.Neighbour; if (newNeighbour == vertex1) { newNeighbour = vertex2; } graph.AddEdge(vertex1, newNeighbour, edge.EdgeData, edge.Intermediates); if (reverse != null) { // update reverse set if present. List <uint> neighbours = null; if (reverse.TryGetValue(neighbour, out neighbours)) { // remove. neighbours.Remove(vertex2); reverse[neighbour] = neighbours; } if (reverse.TryGetValue(newNeighbour, out neighbours)) { // add. neighbours.Add(vertex1); } else { // add new. neighbours = new List <uint>(); neighbours.Add(vertex1); } reverse[newNeighbour] = neighbours; } } if (graph.IsDirected) { // in a directed graph, there is more work to be done. var toUpdateSet = new HashSet <uint>(); List <uint> neighbours1 = null; if (reverse.TryGetValue(vertex1, out neighbours1)) { for (var i = 0; i < neighbours1.Count; i++) { if (neighbours1[i] == vertex2) { neighbours1[i] = vertex1; } else { toUpdateSet.Add(neighbours1[i]); } } reverse[vertex1] = neighbours1; } List <uint> neighbours2 = null; if (reverse.TryGetValue(vertex2, out neighbours2)) { for (var i = 0; i < neighbours2.Count; i++) { if (neighbours2[i] == vertex1) { neighbours2[i] = vertex2; } else { toUpdateSet.Add(neighbours2[i]); } } reverse[vertex2] = neighbours2; } // switch reverses. if (neighbours2 == null) { reverse.Remove(vertex1); } else { reverse[vertex1] = neighbours2; } if (neighbours1 == null) { reverse.Remove(vertex2); } else { reverse[vertex2] = neighbours1; } // update all edges in these vertices. var updatedEdges = new List <Edge <TEdgeData> >(); foreach (var toUpdate in toUpdateSet) { updatedEdges.Clear(); foreach (var edge in graph.GetEdges(toUpdate)) { if (edge.Neighbour == vertex1) { updatedEdges.Add(new Edge <TEdgeData>() { EdgeData = edge.EdgeData, Neighbour = vertex2, Intermediates = edge.Intermediates != null ? new CoordinateArrayCollection <GeoCoordinateSimple>( edge.Intermediates.ToSimpleArray()) : null }); } else if (edge.Neighbour == vertex2) { updatedEdges.Add(new Edge <TEdgeData>() { EdgeData = edge.EdgeData, Neighbour = vertex1, Intermediates = edge.Intermediates != null ? new CoordinateArrayCollection <GeoCoordinateSimple>( edge.Intermediates.ToSimpleArray()) : null }); } } graph.RemoveEdge(toUpdate, vertex1); graph.RemoveEdge(toUpdate, vertex2); foreach (var updatedEdge in updatedEdges) { graph.AddEdge(toUpdate, updatedEdge.Neighbour, updatedEdge.EdgeData, updatedEdge.Intermediates); } } } }