[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