summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorantirez <antirez@gmail.com>2015-06-25 18:05:45 +0200
committerantirez <antirez@gmail.com>2015-06-26 10:58:27 +0200
commitfa9d62d34fd739160b2a45b713e912a6c4dabb75 (patch)
tree20e15aa95be84c04239de9610a1d4b42740ba190
parent03ce18962848fdd1b7a8427a7365096a0c7b3d4f (diff)
downloadredis-fa9d62d34fd739160b2a45b713e912a6c4dabb75.tar.gz
Geo: from lat,lon API to lon,lat API according to GIS standard
The GIS standard and all the major DBs implementing GIS related functions take coordinates as x,y that is longitude,latitude. It was a bad start for Redis to do things differently, so even if this means that existing users of the Geo module will be required to change their code, Redis now conforms to the standard. Usually Redis is very backward compatible, but this is not an exception to this rule, since this is the first Geo implementation entering the official Redis source code. It is not wise to try to be backward compatible with code forks... :-) Close #2637.
-rw-r--r--deps/geohash-int/geohash.c48
-rw-r--r--deps/geohash-int/geohash.h24
-rw-r--r--deps/geohash-int/geohash_helper.c60
-rw-r--r--deps/geohash-int/geohash_helper.h19
-rw-r--r--src/geo.c113
-rw-r--r--src/geo.h2
-rw-r--r--tests/unit/geo.tcl56
7 files changed, 146 insertions, 176 deletions
diff --git a/deps/geohash-int/geohash.c b/deps/geohash-int/geohash.c
index 66cff082c..e797fbc8f 100644
--- a/deps/geohash-int/geohash.c
+++ b/deps/geohash-int/geohash.c
@@ -43,17 +43,17 @@
* -----------------
*/
-void geohashGetCoordRange(GeoHashRange *lat_range, GeoHashRange *long_range) {
+void geohashGetCoordRange(GeoHashRange *long_range, GeoHashRange *lat_range) {
/* These are constraints from EPSG:900913 / EPSG:3785 / OSGEO:41001 */
/* We can't geocode at the north/south pole. */
- lat_range->max = 85.05112878;
- lat_range->min = -85.05112878;
long_range->max = 180.0;
long_range->min = -180.0;
+ lat_range->max = 85.05112878;
+ lat_range->min = -85.05112878;
}
-int geohashEncode(GeoHashRange *lat_range, GeoHashRange *long_range,
- double latitude, double longitude, uint8_t step,
+int geohashEncode(GeoHashRange *long_range, GeoHashRange *lat_range,
+ double longitude, double latitude, uint8_t step,
GeoHashBits *hash) {
uint8_t i;
@@ -96,22 +96,22 @@ int geohashEncode(GeoHashRange *lat_range, GeoHashRange *long_range,
return 1;
}
-int geohashEncodeType(double latitude, double longitude, uint8_t step, GeoHashBits *hash) {
+int geohashEncodeType(double longitude, double latitude, uint8_t step, GeoHashBits *hash) {
GeoHashRange r[2] = { { 0 } };
geohashGetCoordRange(&r[0], &r[1]);
- return geohashEncode(&r[0], &r[1], latitude, longitude, step, hash);
+ return geohashEncode(&r[0], &r[1], longitude, latitude, step, hash);
}
-int geohashEncodeWGS84(double latitude, double longitude, uint8_t step,
+int geohashEncodeWGS84(double longitude, double latitude, uint8_t step,
GeoHashBits *hash) {
- return geohashEncodeType(latitude, longitude, step, hash);
+ return geohashEncodeType(longitude, latitude, step, hash);
}
static inline uint8_t get_bit(uint64_t bits, uint8_t pos) {
return (bits >> pos) & 0x01;
}
-int geohashDecode(const GeoHashRange lat_range, const GeoHashRange long_range,
+int geohashDecode(const GeoHashRange long_range, const GeoHashRange lat_range,
const GeoHashBits hash, GeoHashArea *area) {
uint8_t i;
@@ -121,10 +121,10 @@ int geohashDecode(const GeoHashRange lat_range, const GeoHashRange long_range,
}
area->hash = hash;
- area->latitude.min = lat_range.min;
- area->latitude.max = lat_range.max;
area->longitude.min = long_range.min;
area->longitude.max = long_range.max;
+ area->latitude.min = lat_range.min;
+ area->latitude.max = lat_range.max;
for (i = 0; i < hash.step; i++) {
uint8_t lat_bit, long_bit;
@@ -159,28 +159,22 @@ int geohashDecodeWGS84(const GeoHashBits hash, GeoHashArea *area) {
return geohashDecodeType(hash, area);
}
-int geohashDecodeAreaToLatLong(const GeoHashArea *area, double *latlong) {
- double y, x;
-
- if (!latlong) return 0;
-
- y = (area->latitude.min + area->latitude.max) / 2;
- x = (area->longitude.min + area->longitude.max) / 2;
-
- latlong[0] = y;
- latlong[1] = x;
+int geohashDecodeAreaToLongLat(const GeoHashArea *area, double *xy) {
+ if (!xy) return 0;
+ xy[0] = (area->longitude.min + area->longitude.max) / 2;
+ xy[1] = (area->latitude.min + area->latitude.max) / 2;
return 1;
}
-int geohashDecodeToLatLongType(const GeoHashBits hash, double *latlong) {
+int geohashDecodeToLongLatType(const GeoHashBits hash, double *xy) {
GeoHashArea area = { { 0 } };
- if (!latlong || !geohashDecodeType(hash, &area))
+ if (!xy || !geohashDecodeType(hash, &area))
return 0;
- return geohashDecodeAreaToLatLong(&area, latlong);
+ return geohashDecodeAreaToLongLat(&area, xy);
}
-int geohashDecodeToLatLongWGS84(const GeoHashBits hash, double *latlong) {
- return geohashDecodeToLatLongType(hash, latlong);
+int geohashDecodeToLongLatWGS84(const GeoHashBits hash, double *xy) {
+ return geohashDecodeToLongLatType(hash, xy);
}
static void geohash_move_x(GeoHashBits *hash, int8_t d) {
diff --git a/deps/geohash-int/geohash.h b/deps/geohash-int/geohash.h
index 78310715f..2bf1f5df8 100644
--- a/deps/geohash-int/geohash.h
+++ b/deps/geohash-int/geohash.h
@@ -62,14 +62,14 @@ typedef struct {
} GeoHashBits;
typedef struct {
- double max;
double min;
+ double max;
} GeoHashRange;
typedef struct {
GeoHashBits hash;
- GeoHashRange latitude;
GeoHashRange longitude;
+ GeoHashRange latitude;
} GeoHashArea;
typedef struct {
@@ -87,22 +87,22 @@ typedef struct {
* 0:success
* -1:failed
*/
-void geohashGetCoordRange(GeoHashRange *lat_range, GeoHashRange *long_range);
-int geohashEncode(GeoHashRange *lat_range, GeoHashRange *long_range,
- double latitude, double longitude, uint8_t step,
+void geohashGetCoordRange(GeoHashRange *long_range, GeoHashRange *lat_range);
+int geohashEncode(GeoHashRange *long_range, GeoHashRange *lat_range,
+ double longitude, double latitude, uint8_t step,
GeoHashBits *hash);
-int geohashEncodeType(double latitude, double longitude,
+int geohashEncodeType(double longitude, double latitude,
uint8_t step, GeoHashBits *hash);
-int geohashEncodeWGS84(double latitude, double longitude, uint8_t step,
+int geohashEncodeWGS84(double longitude, double latitude, uint8_t step,
GeoHashBits *hash);
-int geohashDecode(const GeoHashRange lat_range, const GeoHashRange long_range,
+int geohashDecode(const GeoHashRange long_range, const GeoHashRange lat_range,
const GeoHashBits hash, GeoHashArea *area);
int geohashDecodeType(const GeoHashBits hash, GeoHashArea *area);
int geohashDecodeWGS84(const GeoHashBits hash, GeoHashArea *area);
-int geohashDecodeAreaToLatLong(const GeoHashArea *area, double *latlong);
-int geohashDecodeToLatLongType(const GeoHashBits hash, double *latlong);
-int geohashDecodeToLatLongWGS84(const GeoHashBits hash, double *latlong);
-int geohashDecodeToLatLongMercator(const GeoHashBits hash, double *latlong);
+int geohashDecodeAreaToLongLat(const GeoHashArea *area, double *xy);
+int geohashDecodeToLongLatType(const GeoHashBits hash, double *xy);
+int geohashDecodeToLongLatWGS84(const GeoHashBits hash, double *xy);
+int geohashDecodeToLongLatMercator(const GeoHashBits hash, double *xy);
void geohashNeighbors(const GeoHashBits *hash, GeoHashNeighbors *neighbors);
#if defined(__cplusplus)
diff --git a/deps/geohash-int/geohash_helper.c b/deps/geohash-int/geohash_helper.c
index b6a00b7b5..729f010ea 100644
--- a/deps/geohash-int/geohash_helper.c
+++ b/deps/geohash-int/geohash_helper.c
@@ -80,13 +80,13 @@ int geohashBitsComparator(const GeoHashBits *a, const GeoHashBits *b) {
return a->step != b->step ? a->step - b->step : a->bits - b->bits;
}
-int geohashBoundingBox(double latitude, double longitude, double radius_meters,
+int geohashBoundingBox(double longitude, double latitude, double radius_meters,
double *bounds) {
if (!bounds) return 0;
- double latr, lonr;
- latr = deg_rad(latitude);
+ double lonr, latr;
lonr = deg_rad(longitude);
+ latr = deg_rad(latitude);
double distance = radius_meters / EARTH_RADIUS_IN_METERS;
double min_latitude = latr - distance;
@@ -98,37 +98,36 @@ int geohashBoundingBox(double latitude, double longitude, double radius_meters,
min_longitude = lonr - difference_longitude;
max_longitude = lonr + difference_longitude;
- bounds[0] = rad_deg(min_latitude);
- bounds[1] = rad_deg(min_longitude);
- bounds[2] = rad_deg(max_latitude);
- bounds[3] = rad_deg(max_longitude);
-
+ bounds[0] = rad_deg(min_longitude);
+ bounds[1] = rad_deg(min_latitude);
+ bounds[2] = rad_deg(max_longitude);
+ bounds[3] = rad_deg(max_latitude);
return 1;
}
-GeoHashRadius geohashGetAreasByRadius(double latitude, double longitude, double radius_meters) {
- GeoHashRange lat_range, long_range;
+GeoHashRadius geohashGetAreasByRadius(double longitude, double latitude, double radius_meters) {
+ GeoHashRange long_range, lat_range;
GeoHashRadius radius = { { 0 } };
GeoHashBits hash = { 0 };
GeoHashNeighbors neighbors = { { 0 } };
GeoHashArea area = { { 0 } };
- double min_lat, max_lat, min_lon, max_lon;
+ double min_lon, max_lon, min_lat, max_lat;
double bounds[4];
int steps;
- geohashBoundingBox(latitude, longitude, radius_meters, bounds);
- min_lat = bounds[0];
- min_lon = bounds[1];
- max_lat = bounds[2];
- max_lon = bounds[3];
+ geohashBoundingBox(longitude, latitude, radius_meters, bounds);
+ min_lon = bounds[0];
+ min_lat = bounds[1];
+ max_lon = bounds[2];
+ max_lat = bounds[3];
steps = geohashEstimateStepsByRadius(radius_meters,latitude);
- geohashGetCoordRange(&lat_range, &long_range);
- geohashEncode(&lat_range, &long_range, latitude, longitude, steps, &hash);
+ geohashGetCoordRange(&long_range, &lat_range);
+ geohashEncode(&long_range, &lat_range, longitude, latitude, steps, &hash);
geohashNeighbors(&hash, &neighbors);
- geohashGetCoordRange(&lat_range, &long_range);
- geohashDecode(lat_range, long_range, hash, &area);
+ geohashGetCoordRange(&long_range, &lat_range);
+ geohashDecode(long_range, lat_range, hash, &area);
if (area.latitude.min < min_lat) {
GZERO(neighbors.south);
@@ -156,9 +155,9 @@ GeoHashRadius geohashGetAreasByRadius(double latitude, double longitude, double
return radius;
}
-GeoHashRadius geohashGetAreasByRadiusWGS84(double latitude, double longitude,
+GeoHashRadius geohashGetAreasByRadiusWGS84(double longitude, double latitude,
double radius_meters) {
- return geohashGetAreasByRadius(latitude, longitude, radius_meters);
+ return geohashGetAreasByRadius(longitude, latitude, radius_meters);
}
GeoHashFix52Bits geohashAlign52Bits(const GeoHashBits hash) {
@@ -167,8 +166,8 @@ GeoHashFix52Bits geohashAlign52Bits(const GeoHashBits hash) {
return bits;
}
-/* calculate distance using haversin great circle distance formula */
-double distanceEarth(double lat1d, double lon1d, double lat2d, double lon2d) {
+/* Calculate distance using haversin great circle distance formula. */
+double distanceEarth(double lon1d, double lat1d, double lon2d, double lat2d) {
double lat1r, lon1r, lat2r, lon2r, u, v;
lat1r = deg_rad(lat1d);
lon1r = deg_rad(lon1d);
@@ -183,7 +182,7 @@ double distanceEarth(double lat1d, double lon1d, double lat2d, double lon2d) {
int geohashGetDistanceIfInRadius(double x1, double y1,
double x2, double y2, double radius,
double *distance) {
- *distance = distanceEarth(y1, x1, y2, x2);
+ *distance = distanceEarth(x1, y1, x2, y2);
if (*distance > radius) return 0;
return 1;
}
@@ -193,14 +192,3 @@ int geohashGetDistanceIfInRadiusWGS84(double x1, double y1, double x2,
double *distance) {
return geohashGetDistanceIfInRadius(x1, y1, x2, y2, radius, distance);
}
-
-int geohashVerifyCoordinates(double x, double y) {
- GeoHashRange lat_range, long_range;
- geohashGetCoordRange(&lat_range, &long_range);
-
- if (x < long_range.min || x > long_range.max || y < lat_range.min ||
- y > lat_range.max) {
- return 0;
- }
- return 1;
-}
diff --git a/deps/geohash-int/geohash_helper.h b/deps/geohash-int/geohash_helper.h
index 9354a3238..0e38740de 100644
--- a/deps/geohash-int/geohash_helper.h
+++ b/deps/geohash-int/geohash_helper.h
@@ -49,29 +49,20 @@ typedef struct {
int GeoHashBitsComparator(const GeoHashBits *a, const GeoHashBits *b);
uint8_t geohashEstimateStepsByRadius(double range_meters, double lat);
-int geohashBoundingBox(double latitude, double longitude, double radius_meters,
+int geohashBoundingBox(double longitude, double latitude, double radius_meters,
double *bounds);
-GeoHashRadius geohashGetAreasByRadius(double latitude,
- double longitude, double radius_meters);
-GeoHashRadius geohashGetAreasByRadiusWGS84(double latitude, double longitude,
+GeoHashRadius geohashGetAreasByRadius(double longitude,
+ double latitude, double radius_meters);
+GeoHashRadius geohashGetAreasByRadiusWGS84(double longitude, double latitude,
double radius_meters);
-GeoHashRadius geohashGetAreasByRadiusMercator(double latitude, double longitude,
+GeoHashRadius geohashGetAreasByRadiusMercator(double longitude, double latitude,
double radius_meters);
GeoHashFix52Bits geohashAlign52Bits(const GeoHashBits hash);
-double geohashGetXMercator(double longtitude);
-double geohashGetYMercator(double latitude);
-double geohashGetXWGS84(double x);
-double geohashGetYWGS84(double y);
-int geohashVerifyCoordinates(double x, double y);
int geohashGetDistanceIfInRadius(double x1, double y1,
double x2, double y2, double radius,
double *distance);
int geohashGetDistanceIfInRadiusWGS84(double x1, double y1, double x2,
double y2, double radius,
double *distance);
-int geohashGetDistanceSquaredIfInRadiusMercator(double x1, double y1,
- double x2, double y2,
- double radius,
- double *distance);
#endif /* GEOHASH_HELPER_HPP_ */
diff --git a/src/geo.c b/src/geo.c
index eb813473e..40d962f31 100644
--- a/src/geo.c
+++ b/src/geo.c
@@ -82,18 +82,18 @@ void geoArrayFree(geoArray *ga) {
/* ====================================================================
* Helpers
* ==================================================================== */
-static inline int decodeGeohash(double bits, double *latlong) {
+static inline int decodeGeohash(double bits, double *xy) {
GeoHashBits hash = { .bits = (uint64_t)bits, .step = GEO_STEP_MAX };
- return geohashDecodeToLatLongWGS84(hash, latlong);
+ return geohashDecodeToLongLatWGS84(hash, xy);
}
/* Input Argument Helper */
/* Take a pointer to the latitude arg then use the next arg for longitude.
* On parse error REDIS_ERR is returned, otherwise REDIS_OK. */
-static inline int extractLatLongOrReply(redisClient *c, robj **argv,
- double *latlong) {
+static inline int extractLongLatOrReply(redisClient *c, robj **argv,
+ double *xy) {
for (int i = 0; i < 2; i++) {
- if (getDoubleFromObjectOrReply(c, argv[i], latlong + i, NULL) !=
+ if (getDoubleFromObjectOrReply(c, argv[i], xy + i, NULL) !=
REDIS_OK) {
return REDIS_ERR;
}
@@ -104,11 +104,11 @@ static inline int extractLatLongOrReply(redisClient *c, robj **argv,
/* Input Argument Helper */
/* Decode lat/long from a zset member's score.
* Returns REDIS_OK on successful decoding, otherwise REDIS_ERR is returned. */
-static int latLongFromMember(robj *zobj, robj *member, double *latlong) {
+static int longLatFromMember(robj *zobj, robj *member, double *xy) {
double score = 0;
if (zsetScore(zobj, member, &score) == REDIS_ERR) return REDIS_ERR;
- if (!decodeGeohash(score, latlong)) return REDIS_ERR;
+ if (!decodeGeohash(score, xy)) return REDIS_ERR;
return REDIS_OK;
}
@@ -166,13 +166,13 @@ static inline void addReplyDoubleDistance(redisClient *c, double d) {
* only if the point is within the search area.
*
* returns REDIS_OK if the point is included, or REIDS_ERR if it is outside. */
-int geoAppendIfWithinRadius(geoArray *ga, double lat, double lon, double radius, double score, sds member) {
- double distance, latlong[2];
+int geoAppendIfWithinRadius(geoArray *ga, double lon, double lat, double radius, double score, sds member) {
+ double distance, xy[2];
- if (!decodeGeohash(score,latlong)) return REDIS_ERR; /* Can't decode. */
+ if (!decodeGeohash(score,xy)) return REDIS_ERR; /* Can't decode. */
/* Note that geohashGetDistanceIfInRadiusWGS84() takes arguments in
* reverse order: longitude first, latitude later. */
- if (!geohashGetDistanceIfInRadiusWGS84(lon,lat,latlong[1], latlong[0],
+ if (!geohashGetDistanceIfInRadiusWGS84(lon,lat, xy[0], xy[1],
radius, &distance))
{
return REDIS_ERR;
@@ -180,8 +180,8 @@ int geoAppendIfWithinRadius(geoArray *ga, double lat, double lon, double radius,
/* Append the new element. */
geoPoint *gp = geoArrayAppend(ga);
- gp->latitude = latlong[0];
- gp->longitude = latlong[1];
+ gp->longitude = xy[0];
+ gp->latitude = xy[1];
gp->dist = distance;
gp->member = member;
gp->score = score;
@@ -200,7 +200,7 @@ int geoAppendIfWithinRadius(geoArray *ga, double lat, double lon, double radius,
* using multiple queries to the sorted set, that we later need to sort
* via qsort. Similarly we need to be able to reject points outside the search
* radius area ASAP in order to allocate and process more points than needed. */
-int geoGetPointsInRange(robj *zobj, double min, double max, double lat, double lon, double radius, geoArray *ga) {
+int geoGetPointsInRange(robj *zobj, double min, double max, double lon, double lat, double radius, geoArray *ga) {
/* minex 0 = include min in range; maxex 1 = exclude max in range */
/* That's: min <= val < max */
zrangespec range = { .min = min, .max = max, .minex = 0, .maxex = 1 };
@@ -232,7 +232,7 @@ int geoGetPointsInRange(robj *zobj, double min, double max, double lat, double l
ziplistGet(eptr, &vstr, &vlen, &vlong);
member = (vstr == NULL) ? sdsfromlonglong(vlong) :
sdsnewlen(vstr,vlen);
- if (geoAppendIfWithinRadius(ga,lat,lon,radius,score,member)
+ if (geoAppendIfWithinRadius(ga,lon,lat,radius,score,member)
== REDIS_ERR) sdsfree(member);
zzlNext(zl, &eptr, &sptr);
}
@@ -255,7 +255,7 @@ int geoGetPointsInRange(robj *zobj, double min, double max, double lat, double l
member = (o->encoding == REDIS_ENCODING_INT) ?
sdsfromlonglong((long)o->ptr) :
sdsdup(o->ptr);
- if (geoAppendIfWithinRadius(ga,lat,lon,radius,ln->score,member)
+ if (geoAppendIfWithinRadius(ga,lon,lat,radius,ln->score,member)
== REDIS_ERR) sdsfree(member);
ln = ln->level[0].forward;
}
@@ -266,7 +266,7 @@ int geoGetPointsInRange(robj *zobj, double min, double max, double lat, double l
/* Obtain all members between the min/max of this geohash bounding box.
* Populate a geoArray of GeoPoints by calling geoGetPointsInRange().
* Return the number of points added to the array. */
-int membersOfGeoHashBox(robj *zobj, GeoHashBits hash, geoArray *ga, double lat, double lon, double radius) {
+int membersOfGeoHashBox(robj *zobj, GeoHashBits hash, geoArray *ga, double lon, double lat, double radius) {
GeoHashFix52Bits min, max;
/* We want to compute the sorted set scores that will include all the
@@ -293,11 +293,11 @@ int membersOfGeoHashBox(robj *zobj, GeoHashBits hash, geoArray *ga, double lat,
hash.bits++;
max = geohashAlign52Bits(hash);
- return geoGetPointsInRange(zobj, min, max, lat, lon, radius, ga);
+ return geoGetPointsInRange(zobj, min, max, lon, lat, radius, ga);
}
/* Search all eight neighbors + self geohash box */
-int membersOfAllNeighbors(robj *zobj, GeoHashRadius n, double lat, double lon, double radius, geoArray *ga) {
+int membersOfAllNeighbors(robj *zobj, GeoHashRadius n, double lon, double lat, double radius, geoArray *ga) {
GeoHashBits neighbors[9];
unsigned int i, count = 0;
@@ -316,7 +316,7 @@ int membersOfAllNeighbors(robj *zobj, GeoHashRadius n, double lat, double lon, d
for (i = 0; i < sizeof(neighbors) / sizeof(*neighbors); i++) {
if (HASHISZERO(neighbors[i]))
continue;
- count += membersOfGeoHashBox(zobj, neighbors[i], ga, lat, lon, radius);
+ count += membersOfGeoHashBox(zobj, neighbors[i], ga, lon, lat, radius);
}
return count;
}
@@ -342,9 +342,9 @@ static int sort_gp_desc(const void *a, const void *b) {
* Commands
* ==================================================================== */
void geoAddCommand(redisClient *c) {
- /* args 0-4: [cmd, key, lat, lng, val]; optional 5-6: [radius, units]
+ /* args 0-4: [cmd, key, lng, lat, val]; optional 5-6: [radius, units]
* - OR -
- * args 0-N: [cmd, key, lat, lng, val, lat2, lng2, val2, ...] */
+ * args 0-N: [cmd, key, lng, lat, val, lng2, lat2, val2, ...] */
/* Prepare for the three different forms of the add command. */
double radius_meters = 0;
@@ -358,8 +358,8 @@ void geoAddCommand(redisClient *c) {
return;
} else if ((c->argc - 2) % 3 != 0) {
/* Need an odd number of arguments if we got this far... */
- addReplyError(c, "format is: geoadd [key] [lat1] [long1] [member1] "
- "[lat2] [long2] [member2] ... ");
+ addReplyError(c, "format is: geoadd [key] [x1] [y1] [member1] "
+ "[x2] [y2] [member2] ... ");
return;
}
@@ -376,9 +376,9 @@ void geoAddCommand(redisClient *c) {
uint8_t step = geohashEstimateStepsByRadius(radius_meters,0);
int i;
for (i = 0; i < elements; i++) {
- double latlong[elements * 2];
+ double xy[2];
- if (extractLatLongOrReply(c, (c->argv+2)+(i*3),latlong) == REDIS_ERR) {
+ if (extractLongLatOrReply(c, (c->argv+2)+(i*3),xy) == REDIS_ERR) {
for (i = 0; i < argc; i++)
if (argv[i]) decrRefCount(argv[i]);
zfree(argv);
@@ -391,10 +391,7 @@ void geoAddCommand(redisClient *c) {
/* Turn the coordinates into the score of the element. */
GeoHashBits hash;
- double latitude = latlong[0];
- double longitude = latlong[1];
- geohashEncodeWGS84(latitude, longitude, step, &hash);
-
+ geohashEncodeWGS84(xy[0], xy[1], step, &hash);
GeoHashFix52Bits bits = geohashAlign52Bits(hash);
robj *score = createObject(REDIS_STRING, sdsfromlonglong(bits));
robj *val = c->argv[2 + i * 3 + 2];
@@ -416,7 +413,7 @@ void geoAddCommand(redisClient *c) {
#define RADIUS_MEMBER 2
static void geoRadiusGeneric(redisClient *c, int type) {
- /* type == cords: [cmd, key, lat, long, radius, units, [optionals]]
+ /* type == cords: [cmd, key, long, lat, radius, units, [optionals]]
* type == member: [cmd, key, member, radius, units, [optionals]] */
robj *key = c->argv[1];
@@ -427,17 +424,17 @@ static void geoRadiusGeneric(redisClient *c, int type) {
return;
}
- /* Find lat/long to use for radius search based on inquiry type */
+ /* Find long/lat to use for radius search based on inquiry type */
int base_args;
- double latlong[2] = { 0 };
+ double xy[2] = { 0 };
if (type == RADIUS_COORDS) {
base_args = 6;
- if (extractLatLongOrReply(c, c->argv + 2, latlong) == REDIS_ERR)
+ if (extractLongLatOrReply(c, c->argv + 2, xy) == REDIS_ERR)
return;
} else if (type == RADIUS_MEMBER) {
base_args = 5;
robj *member = c->argv[2];
- if (latLongFromMember(zobj, member, latlong) == REDIS_ERR) {
+ if (longLatFromMember(zobj, member, xy) == REDIS_ERR) {
addReplyError(c, "could not decode requested zset member");
return;
}
@@ -483,7 +480,7 @@ static void geoRadiusGeneric(redisClient *c, int type) {
/* Get all neighbor geohash boxes for our radius search */
GeoHashRadius georadius =
- geohashGetAreasByRadiusWGS84(latlong[0], latlong[1], radius_meters);
+ geohashGetAreasByRadiusWGS84(xy[0], xy[1], radius_meters);
#ifdef DEBUG
printf("Searching with step size: %d\n", georadius.hash.step);
@@ -491,7 +488,7 @@ static void geoRadiusGeneric(redisClient *c, int type) {
/* Search the zset for all matching points */
geoArray *ga = geoArrayCreate();
- membersOfAllNeighbors(zobj, georadius, latlong[0], latlong[1], radius_meters, ga);
+ membersOfAllNeighbors(zobj, georadius, xy[0], xy[1], radius_meters, ga);
/* If no matching results, the user gets an empty reply. */
if (ga->used == 0) {
@@ -549,15 +546,15 @@ static void geoRadiusGeneric(redisClient *c, int type) {
if (withcoords) {
addReplyMultiBulkLen(c, 2);
- addReplyDouble(c, gp->latitude);
addReplyDouble(c, gp->longitude);
+ addReplyDouble(c, gp->latitude);
}
}
geoArrayFree(ga);
}
void geoRadiusCommand(redisClient *c) {
- /* args 0-5: ["georadius", key, lat, long, radius, units];
+ /* args 0-5: ["georadius", key, long, lat, radius, units];
* optionals: [withdist, withcoords, asc|desc] */
geoRadiusGeneric(c, RADIUS_COORDS);
}
@@ -578,30 +575,30 @@ void geoDecodeCommand(redisClient *c) {
geohash.step = GEO_STEP_MAX;
geohashDecodeWGS84(geohash, &area);
- double lat = (area.latitude.min + area.latitude.max) / 2;
double lon = (area.longitude.min + area.longitude.max) / 2;
+ double lat = (area.latitude.min + area.latitude.max) / 2;
/* Returning three nested replies */
addReplyMultiBulkLen(c, 3);
/* First, the minimum corner */
addReplyMultiBulkLen(c, 2);
- addReplyDouble(c, area.latitude.min);
addReplyDouble(c, area.longitude.min);
+ addReplyDouble(c, area.latitude.min);
/* Next, the maximum corner */
addReplyMultiBulkLen(c, 2);
- addReplyDouble(c, area.latitude.max);
addReplyDouble(c, area.longitude.max);
+ addReplyDouble(c, area.latitude.max);
/* Last, the averaged center of this bounding box */
addReplyMultiBulkLen(c, 2);
- addReplyDouble(c, lat);
addReplyDouble(c, lon);
+ addReplyDouble(c, lat);
}
void geoEncodeCommand(redisClient *c) {
- /* args 0-2: ["geoencode", lat, long];
+ /* args 0-2: ["geoencode", long, lat];
* optionals: [radius, units] */
double radius_meters = 0;
@@ -613,13 +610,13 @@ void geoEncodeCommand(redisClient *c) {
return;
}
- double latlong[2];
- if (extractLatLongOrReply(c, c->argv + 1, latlong) == REDIS_ERR) return;
+ double xy[2];
+ if (extractLongLatOrReply(c, c->argv + 1, xy) == REDIS_ERR) return;
/* Encode lat/long into our geohash */
GeoHashBits geohash;
uint8_t step = geohashEstimateStepsByRadius(radius_meters,0);
- geohashEncodeWGS84(latlong[0], latlong[1], step, &geohash);
+ geohashEncodeWGS84(xy[0], xy[1], step, &geohash);
/* Align the hash to a valid 52-bit integer based on step size */
GeoHashFix52Bits bits = geohashAlign52Bits(geohash);
@@ -631,8 +628,8 @@ void geoEncodeCommand(redisClient *c) {
GeoHashArea area;
geohashDecodeWGS84(geohash, &area);
- double lat = (area.latitude.min + area.latitude.max) / 2;
double lon = (area.longitude.min + area.longitude.max) / 2;
+ double lat = (area.latitude.min + area.latitude.max) / 2;
/* Return four nested multibulk replies. */
addReplyMultiBulkLen(c, 4);
@@ -642,18 +639,18 @@ void geoEncodeCommand(redisClient *c) {
/* Return the minimum corner */
addReplyMultiBulkLen(c, 2);
- addReplyDouble(c, area.latitude.min);
addReplyDouble(c, area.longitude.min);
+ addReplyDouble(c, area.latitude.min);
/* Return the maximum corner */
addReplyMultiBulkLen(c, 2);
- addReplyDouble(c, area.latitude.max);
addReplyDouble(c, area.longitude.max);
+ addReplyDouble(c, area.latitude.max);
/* Return the averaged center */
addReplyMultiBulkLen(c, 2);
- addReplyDouble(c, lat);
addReplyDouble(c, lon);
+ addReplyDouble(c, lat);
}
/* GEOHASH key ele1 ele2 ... eleN
@@ -684,8 +681,8 @@ void geoHashCommand(redisClient *c) {
* standard ranges in order to output a valid geohash string. */
/* Decode... */
- double latlong[2];
- if (!decodeGeohash(score,latlong)) {
+ double xy[2];
+ if (!decodeGeohash(score,xy)) {
addReply(c,shared.nullbulk);
continue;
}
@@ -693,11 +690,11 @@ void geoHashCommand(redisClient *c) {
/* Re-encode */
GeoHashRange r[2];
GeoHashBits hash;
- r[0].min = -90;
- r[0].max = 90;
- r[1].min = -180;
- r[1].max = 180;
- geohashEncode(&r[0],&r[1],latlong[0],latlong[1],26,&hash);
+ r[0].min = -180;
+ r[0].max = 180;
+ r[1].min = -90;
+ r[1].max = 90;
+ geohashEncode(&r[0],&r[1],xy[0],xy[1],26,&hash);
char buf[12];
int i;
diff --git a/src/geo.h b/src/geo.h
index 9cd1f56b4..4f5c5e6fe 100644
--- a/src/geo.h
+++ b/src/geo.h
@@ -12,8 +12,8 @@ void geoAddCommand(redisClient *c);
/* Structures used inside geo.c in order to represent points and array of
* points on the earth. */
typedef struct geoPoint {
- double latitude;
double longitude;
+ double latitude;
double dist;
double score;
char *member;
diff --git a/tests/unit/geo.tcl b/tests/unit/geo.tcl
index eedc40c96..a049804ae 100644
--- a/tests/unit/geo.tcl
+++ b/tests/unit/geo.tcl
@@ -2,46 +2,46 @@
# verify the Redis implementation with a fuzzy test.
proc geo_degrad deg {expr {$deg*atan(1)*8/360}}
-proc geo_distance {lat1d lon1d lat2d lon2d} {
- set lat1r [geo_degrad $lat1d]
+proc geo_distance {lon1d lat1d lon2d lat2d} {
set lon1r [geo_degrad $lon1d]
- set lat2r [geo_degrad $lat2d]
+ set lat1r [geo_degrad $lat1d]
set lon2r [geo_degrad $lon2d]
- set u [expr {sin(($lat2r - $lat1r) / 2)}]
+ set lat2r [geo_degrad $lat2d]
set v [expr {sin(($lon2r - $lon1r) / 2)}]
+ set u [expr {sin(($lat2r - $lat1r) / 2)}]
expr {2.0 * 6372797.560856 * \
asin(sqrt($u * $u + cos($lat1r) * cos($lat2r) * $v * $v))}
}
-proc geo_random_point {latvar lonvar} {
- upvar 1 $latvar lat
+proc geo_random_point {lonvar latvar} {
upvar 1 $lonvar lon
+ upvar 1 $latvar lat
# Note that the actual latitude limit should be -85 to +85, we restrict
# the test to -70 to +70 since in this range the algorithm is more precise
# while outside this range occasionally some element may be missing.
- set lat [expr {-70 + rand()*140}]
set lon [expr {-180 + rand()*360}]
+ set lat [expr {-70 + rand()*140}]
}
start_server {tags {"geo"}} {
test {GEOADD create} {
- r geoadd nyc 40.747533 -73.9454966 "lic market"
+ r geoadd nyc -73.9454966 40.747533 "lic market"
} {1}
test {GEOADD update} {
- r geoadd nyc 40.747533 -73.9454966 "lic market"
+ r geoadd nyc -73.9454966 40.747533 "lic market"
} {0}
test {GEOADD invalid coordinates} {
catch {
- r geoadd nyc 40.747533 -73.9454966 "lic market" \
+ r geoadd nyc -73.9454966 40.747533 "lic market" \
foo bar "luck market"
} err
set err
} {*valid*}
test {GEOADD multi add} {
- r geoadd nyc 40.7648057 -73.9733487 "central park n/q/r" 40.7362513 -73.9903085 "union square" 40.7126674 -74.0131604 "wtc one" 40.6428986 -73.7858139 "jfk" 40.7498929 -73.9375699 "q4" 40.7480973 -73.9564142 4545
+ r geoadd nyc -73.9733487 40.7648057 "central park n/q/r" -73.9903085 40.7362513 "union square" -74.0131604 40.7126674 "wtc one" -73.7858139 40.6428986 "jfk" -73.9375699 40.7498929 "q4" -73.9564142 40.7480973 4545
} {6}
test {Check geoset values} {
@@ -49,11 +49,11 @@ start_server {tags {"geo"}} {
} {{wtc one} 1791873972053020 {union square} 1791875485187452 {central park n/q/r} 1791875761332224 4545 1791875796750882 {lic market} 1791875804419201 q4 1791875830079666 jfk 1791895905559723}
test {GEORADIUS simple (sorted)} {
- r georadius nyc 40.7598464 -73.9798091 3 km ascending
+ r georadius nyc -73.9798091 40.7598464 3 km ascending
} {{central park n/q/r} 4545 {union square}}
test {GEORADIUS withdistance (sorted)} {
- r georadius nyc 40.7598464 -73.9798091 3 km withdistance ascending
+ r georadius nyc -73.9798091 40.7598464 3 km withdistance ascending
} {{{central park n/q/r} 0.7750} {4545 2.3651} {{union square} 2.7697}}
test {GEORADIUSBYMEMBER simple (sorted)} {
@@ -65,21 +65,21 @@ start_server {tags {"geo"}} {
} {{{wtc one} 0.0000} {{union square} 3.2544} {{central park n/q/r} 6.7000} {4545 6.1975} {{lic market} 6.8969}}
test {GEOENCODE simple} {
- r geoencode 41.2358883 1.8063239
- } {3471579339700058 {41.235888125243704 1.8063229322433472}\
- {41.235890659964866 1.806328296661377}\
- {41.235889392604285 1.8063256144523621}}
+ r geoencode 1.8063239 41.2358883
+ } {3471579339700058 {1.8063229322433472 41.235888125243704}\
+ {1.806328296661377 41.235890659964866}\
+ {1.8063256144523621 41.235889392604285}}
test {GEODECODE simple} {
r geodecode 3471579339700058
- } {{41.235888125243704 1.8063229322433472}\
- {41.235890659964866 1.806328296661377}\
- {41.235889392604285 1.8063256144523621}}
+ } {{1.8063229322433472 41.235888125243704}\
+ {1.806328296661377 41.235890659964866}\
+ {1.8063256144523621 41.235889392604285}}
test {GEOHASH is able to return geohash strings} {
# Example from Wikipedia.
r del points
- r geoadd points 42.6 -5.6 test
+ r geoadd points -5.6 42.6 test
lindex [r geohash points test] 0
} {ezs42e44yx0}
@@ -93,20 +93,20 @@ start_server {tags {"geo"}} {
r del mypoints
set radius_km [expr {[randomInt 200]+10}]
set radius_m [expr {$radius_km*1000}]
- geo_random_point search_lat search_lon
- lappend debuginfo "Search area: $search_lat,$search_lon $radius_km km"
+ geo_random_point search_lon search_lat
+ lappend debuginfo "Search area: $search_lon,$search_lat $radius_km km"
set tcl_result {}
set argv {}
for {set j 0} {$j < 20000} {incr j} {
- geo_random_point lat lon
- lappend argv $lat $lon "place:$j"
- if {[geo_distance $lat $lon $search_lat $search_lon] < $radius_m} {
+ geo_random_point lon lat
+ lappend argv $lon $lat "place:$j"
+ if {[geo_distance $lon $lat $search_lon $search_lat] < $radius_m} {
lappend tcl_result "place:$j"
- lappend debuginfo "place:$j $lat $lon [expr {[geo_distance $lat $lon $search_lat $search_lon]/1000}] km"
+ lappend debuginfo "place:$j $lon $lat [expr {[geo_distance $lon $lat $search_lon $search_lat]/1000}] km"
}
}
r geoadd mypoints {*}$argv
- set res [lsort [r georadius mypoints $search_lat $search_lon $radius_km km]]
+ set res [lsort [r georadius mypoints $search_lon $search_lat $radius_km km]]
set res2 [lsort $tcl_result]
set test_result OK
if {$res != $res2} {