/// <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> /// Searches the graph for nearby vertices assuming it has been sorted. /// </summary> /// <typeparam name="TEdgeData"></typeparam> public static bool SearchHilbert <TEdgeData>(this GraphBase <TEdgeData> graph, long hilbert, int n, uint vertex1, uint vertex2, out uint vertex, out int count) where TEdgeData : struct, IGraphEdgeData { var hilbert1 = GraphExtensions.HilbertDistance(graph, n, vertex1); var hilbert2 = GraphExtensions.HilbertDistance(graph, n, vertex2); while (vertex1 <= vertex2) { // check the current hilbert distances. if (hilbert1 > hilbert2) { // situation is impossible and probably the graph is not sorted. throw new Exception("Graph not sorted: Binary search using hilbert distance not possible."); } if (hilbert1 == hilbert) { // found at hilbert1. var lower = vertex1; while (hilbert1 == hilbert) { lower--; if (lower == 0) { // stop here, not more vertices lower. break; } hilbert1 = GraphExtensions.HilbertDistance(graph, n, lower); } lower++; var upper = vertex1; hilbert1 = GraphExtensions.HilbertDistance(graph, n, upper); while (hilbert1 == hilbert) { upper++; if (upper > graph.VertexCount) { // stop here, no more vertices higher. break; } hilbert1 = GraphExtensions.HilbertDistance(graph, n, upper); } upper--; vertex = lower; count = (int)(upper - lower) + 1; return(true); } if (hilbert2 == hilbert) { // found at hilbert2. var lower = vertex2; while (hilbert2 == hilbert) { lower--; if (lower == 0) { // stop here, not more vertices lower. break; } hilbert2 = GraphExtensions.HilbertDistance(graph, n, lower); } lower++; var upper = vertex2; hilbert2 = GraphExtensions.HilbertDistance(graph, n, upper); while (hilbert2 == hilbert) { upper++; if (upper > graph.VertexCount) { // stop here, no more vertices higher. break; } hilbert2 = GraphExtensions.HilbertDistance(graph, n, upper); } upper--; vertex = lower; count = (int)(upper - lower) + 1; return(true); } if (hilbert1 == hilbert2 || vertex1 == vertex2 || vertex1 == vertex2 - 1) { // search is finished. vertex = vertex1; count = 0; return(true); } // Binary search: calculate hilbert distance of the middle. var vertexMiddle = vertex1 + (uint)((vertex2 - vertex1) / 2); var hilbertMiddle = GraphExtensions.HilbertDistance(graph, n, vertexMiddle); if (hilbert <= hilbertMiddle) { // target is in first part. vertex2 = vertexMiddle; hilbert2 = hilbertMiddle; } else { // target is in the second part. vertex1 = vertexMiddle; hilbert1 = hilbertMiddle; } } vertex = vertex1; count = 0; return(false); }
/// <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, float latitude, float longitude, float offset) where TEdgeData : struct, IGraphEdgeData { return(GraphExtensions.SearchHilbert(graph, GraphExtensions.DefaultHilbertSteps, latitude, longitude, offset)); }