[postgis-tickets] [PostGIS] #2250: ST_PointFromGeohash()
PostGIS
trac at osgeo.org
Tue Mar 26 10:44:35 PDT 2013
#2250: ST_PointFromGeohash()
-------------------------+--------------------------------------------------
Reporter: darkblueb | Owner: pramsey
Type: enhancement | Status: new
Priority: low | Milestone: PostGIS Future
Component: postgis | Version: trunk
Keywords: |
-------------------------+--------------------------------------------------
a round-trip for the geohash type would be useful..
this project is MIT license and has a simple function to do this..
https://github.com/lyokato/libgeohash
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 (c) 2011 lyo.kato at gmail.com
--
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;
}
--
Ticket URL: <http://trac.osgeo.org/postgis/ticket/2250>
PostGIS <http://trac.osgeo.org/postgis/>
The PostGIS Trac is used for bug, enhancement & task tracking, a user and developer wiki, and a view into the subversion code repository of PostGIS project.
More information about the postgis-tickets
mailing list