Opened 12 years ago
Closed 12 years ago
#2250 closed enhancement (fixed)
ST_PointFromGeohash()
Reported by: | darkblueb | Owned by: | pramsey |
---|---|---|---|
Priority: | low | Milestone: | PostGIS 2.1.0 |
Component: | postgis | Version: | master |
Keywords: | Cc: |
Description
a round-trip for the geohash type would be useful.. this project is MIT license and has a simple function to do this..
this code uses a struct that resembles a box, to return the result..
some adoption might be made for PostGIS LWGeom conventions..
excerpt from geohash.c The MIT License Copyright © 2011 lyo.kato@…
—
static const char BASE32_DECODE_TABLE[44] = {
/* 0 */ 0, /* 1 */ 1, /* 2 */ 2, /* 3 */ 3, /* 4 */ 4, /* 5 */ 5, /* 6 */ 6, /* 7 */ 7, /* 8 */ 8, /* 9 */ 9, /* : */ -1, /* ; */ -1, /* < */ -1, /* = */ -1, /* > */ -1, /* ? */ -1, /* @ */ -1, /* A */ -1, /* B */ 10, /* C */ 11, /* D */ 12, /* E */ 13, /* F */ 14, /* G */ 15, /* H */ 16, /* I */ -1, /* J */ 17, /* K */ 18, /* L */ -1, /* M */ 19, /* N */ 20, /* O */ -1, /* P */ 21, /* Q */ 22, /* R */ 23, /* S */ 24, /* T */ 25, /* U */ 26, /* V */ 27, /* W */ 28, /* X */ 29, /* Y */ 30, /* Z */ 31
};
#define MAX_HASH_LENGTH 22
#define REFINE_RANGE(range, bits, offset) \
if (((bits) & (offset)) == (offset)) \
(range)→min = ((range)→max + (range)→min) / 2.0; \
else \
(range)→max = ((range)→max + (range)→min) / 2.0;
#define SET_BIT(bits, mid, range, value, offset) \
mid = ((range)→max + (range)→min) / 2.0; \ if ((value) ≥ mid) { \
(range)→min = mid; \ (bits) |= (0x1 << (offset)); \
} else { \
(range)→max = mid; \ (bits) |= (0x0 << (offset)); \
}
typedef struct {
double max; double min;
} GEOHASH_range;
typedef struct {
GEOHASH_range latitude; GEOHASH_range longitude;
} GEOHASH_area;
bool GEOHASH_verify_hash(const char *hash) {
const char *p; unsigned char c; p = hash; while (*p != '\0') {
c = toupper(*p++); if (c < 0x30)
return false;
c -= 0x30; if (c > 43)
return false;
if (BASE32_DECODE_TABLE[c] == -1)
return false;
} return true;
}
GEOHASH_area* GEOHASH_decode(const char *hash) {
const char *p; unsigned char c; char bits; GEOHASH_area *area; GEOHASH_range *range1, *range2, *range_tmp;
area = (GEOHASH_area *)malloc(sizeof(GEOHASH_area)); if (area == NULL)
return NULL;
area→latitude.max = 90; area→latitude.min = -90; area→longitude.max = 180; area→longitude.min = -180;
range1 = &area→longitude; range2 = &area→latitude;
p = hash;
while (*p != '\0') {
c = toupper(*p++); if (c < 0x30) {
free(area); return NULL;
} c -= 0x30; if (c > 43) {
free(area); return NULL;
} bits = BASE32_DECODE_TABLE[c]; if (bits == -1) {
free(area); return NULL;
}
REFINE_RANGE(range1, bits, 0x10); REFINE_RANGE(range2, bits, 0x08); REFINE_RANGE(range1, bits, 0x04); REFINE_RANGE(range2, bits, 0x02); REFINE_RANGE(range1, bits, 0x01);
range_tmp = range1; range1 = range2; range2 = range_tmp;
} return area;
}
Change History (2)
comment:1 by , 12 years ago
comment:2 by , 12 years ago
Milestone: | PostGIS Future → PostGIS 2.1.0 |
---|---|
Resolution: | → fixed |
Status: | new → closed |
was committed in #1818 patch.
I actually wrote a patch for ST_GeomFromGeoHash and ST_PointFromGeoHash and the implementation is available in ticket #1818 - "C implementation for GeoHash input".