void geohash(double longitude, double latitude, char* hash) { if ((fabs(longitude) > 180.0) || (fabs(latitude) > 90.0)) { strcpy(hash, "error"); return; } GeoHashRange r[2]; GeoHashBits h; geohashEncodeWGS84(longitude, latitude, GEO_STEP_MAX, &h); r[0].min = -180; r[0].max = 180; r[1].min = -90; r[1].max = 90; geohashEncode(&r[0], &r[1], longitude, latitude, 26, &h); for (int i = 0; i < 11; i++) { int idx = (h.bits >> (52-((i+1)*5))) & 0x1f; hash[i] = geoalphabet[idx]; } hash[11] = '\0'; }
uint64_t geohash64(double longitude, double latitude) { if ((fabs(longitude) > 180.0) || (fabs(latitude) > 90.0)) return 0; GeoHashBits h; geohashEncodeWGS84(longitude, latitude, GEO_STEP_MAX, &h); return geohashAlign52Bits(h); }
uint64_t geohash_decode64(char* buf) { double coords[2][2] = { { -90.0, 90.0 }, { -180.0, 180.0 } }; int bits[] = { 16, 8, 4, 2, 1 }; int flip = 1; for (int i = 0; i < 11; i++) { char* pch = strchr(geoalphabet, buf[i]); if (pch == NULL) return 0; int pos = pch - geoalphabet; for (int j = 0; j < 5; j++) { coords[flip][((pos & bits[j]) > 0) ? 0 : 1] = (coords[flip][0] + coords[flip][1]) / 2.0; flip = !flip; } } GeoHashBits hash; geohashEncodeWGS84(*coords[1,1], *coords[1,0], GEO_STEP_MAX, &hash); return geohashAlign52Bits(hash); }
bool ssdb_geo_set( SSDBSock *ssdb_sock, char *key, int key_len, char *member_key, int member_key_len, double latitude, double longitude, INTERNAL_FUNCTION_PARAMETERS) { GeoHashBits hash; if (!geohashEncodeWGS84(latitude, longitude, GEO_STEP_MAX, &hash)) { return false; } char *member_score_str = NULL, *cmd = NULL; GeoHashFix52Bits bits = geohashAlign52Bits(hash); int member_score_str_len = spprintf(&member_score_str, 0, "%lld", bits); int key_free = ssdb_key_prefix(ssdb_sock, &key, &key_len); int cmd_len = ssdb_cmd_format_by_str(ssdb_sock, &cmd, ZEND_STRL("zset"), key, key_len, member_key, member_key_len, member_score_str, member_score_str_len, NULL); efree(member_score_str); if (key_free) efree(key); if (0 == cmd_len) return false; if (ssdb_sock_write(ssdb_sock, cmd, cmd_len) < 0) { efree(cmd); return false; } efree(cmd); SSDBResponse *ssdb_response = ssdb_sock_read(ssdb_sock); if (ssdb_response == NULL || ssdb_response->status != SSDB_IS_OK) { ssdb_response_free(ssdb_response); return false; } ssdb_response_free(ssdb_response); RETVAL_LONG(bits); return true; }