diff --git a/src/geohash_helper.c b/src/geohash_helper.c index 77d8ab392..e23f17b4e 100644 --- a/src/geohash_helper.c +++ b/src/geohash_helper.c @@ -85,7 +85,21 @@ uint8_t geohashEstimateStepsByRadius(double range_meters, double lat) { /* Return the bounding box of the search area centered at latitude,longitude * having a radius of radius_meter. bounds[0] - bounds[2] is the minimum * and maxium longitude, while bounds[1] - bounds[3] is the minimum and - * maximum latitude. */ + * maximum latitude. + * + * This function does not behave correctly with very large radius values, for + * instance for the coordinates 81.634948934258375 30.561509253718668 and a + * radius of 7083 kilometers, it reports as bounding boxes: + * + * min_lon 7.680495, min_lat -33.119473, max_lon 155.589402, max_lat 94.242491 + * + * However, for instance, a min_lon of 7.680495 is not correct, because the + * point -1.27579540014266968 61.33421815228281559 is at less than 7000 + * kilometers away. + * + * Since this function is currently only used as an optimization, the + * optimization is not used for very big radiuses, however the function + * should be fixed. */ int geohashBoundingBox(double longitude, double latitude, double radius_meters, double *bounds) { if (!bounds) return 0; @@ -154,25 +168,27 @@ GeoHashRadius geohashGetAreasByRadius(double longitude, double latitude, double } /* Exclude the search areas that are useless. */ - if (area.latitude.min < min_lat) { - GZERO(neighbors.south); - GZERO(neighbors.south_west); - GZERO(neighbors.south_east); - } - if (area.latitude.max > max_lat) { - GZERO(neighbors.north); - GZERO(neighbors.north_east); - GZERO(neighbors.north_west); - } - if (area.longitude.min < min_lon) { - GZERO(neighbors.west); - GZERO(neighbors.south_west); - GZERO(neighbors.north_west); - } - if (area.longitude.max > max_lon) { - GZERO(neighbors.east); - GZERO(neighbors.south_east); - GZERO(neighbors.north_east); + if (steps >= 2) { + if (area.latitude.min < min_lat) { + GZERO(neighbors.south); + GZERO(neighbors.south_west); + GZERO(neighbors.south_east); + } + if (area.latitude.max > max_lat) { + GZERO(neighbors.north); + GZERO(neighbors.north_east); + GZERO(neighbors.north_west); + } + if (area.longitude.min < min_lon) { + GZERO(neighbors.west); + GZERO(neighbors.south_west); + GZERO(neighbors.north_west); + } + if (area.longitude.max > max_lon) { + GZERO(neighbors.east); + GZERO(neighbors.south_east); + GZERO(neighbors.north_east); + } } radius.hash = hash; radius.neighbors = neighbors; diff --git a/tests/unit/geo.tcl b/tests/unit/geo.tcl index fdbfbf139..604697be4 100644 --- a/tests/unit/geo.tcl +++ b/tests/unit/geo.tcl @@ -49,6 +49,9 @@ proc compare_lists {List1 List2} { # # The format is: seed km lon lat set regression_vectors { + {1482225976969 7083 81.634948934258375 30.561509253718668} + {1482340074151 5416 -70.863281847379767 -46.347003465679947} + {1499014685896 6064 -89.818768962202014 -40.463868561416803} {1412 156 149.29737817929004 15.95807862745508} {441574 143 59.235461856813856 66.269555127373678} {160645 187 -101.88575239939883 49.061997951502917}