From 4ab040c95d8a4749af2fcb464eec3e22a5aaebdb Mon Sep 17 00:00:00 2001 From: Regina Obe Date: Fri, 3 May 2013 04:04:22 +0000 Subject: [PATCH] #1818: geohash patch hashbox to geom git-svn-id: http://svn.osgeo.org/postgis/trunk@11341 b70326c6-7e19-0410-871a-916f4a2858ee --- doc/reference_output.xml | 166 +++++++++++++++++++++++++++++++++ liblwgeom/liblwgeom_internal.h | 1 + liblwgeom/lwalgorithm.c | 46 +++++++++ postgis/Makefile.in | 1 + postgis/postgis.sql.in | 22 +++++ regress/Makefile.in | 1 + utils/postgis_restore.pl.in | 6 ++ 7 files changed, 243 insertions(+) diff --git a/doc/reference_output.xml b/doc/reference_output.xml index 14ed7761d..aeff8cfdf 100644 --- a/doc/reference_output.xml +++ b/doc/reference_output.xml @@ -985,6 +985,172 @@ SELECT ST_GeoHash(ST_SetSRID(ST_MakePoint(-126,48),4326),5); + + + ST_Box2dFromGeoHash + + Return a BOX2D from a GeoHash string. + + + + + + box2d ST_Box2dFromGeoHash + text geohash + integer precision=full_precision_of_geohash + + + + + + Description + + Return a BOX2D from a GeoHash string. + + If no precision is specficified ST_Box2dFromGeoHash returns a BOX2D based on full precision of the input GeoHash string. + + If precision is specified ST_Box2dFromGeoHash will use that many characters from the GeoHash to create the BOX2D. Lower precision values results in larger BOX2Ds and larger values increase the precision. + + Availability: 2.1.0 + + + + Examples + + + + + See Also + + , + + + + + + ST_PointFromGeoHash + + Return a point from a GeoHash string. + + + + + + point ST_PointFromGeoHash + text geohash + integer precision=full_precision_of_geohash + + + + + + Description + + Return a point from a GeoHash string. The point represents the center point of the GeoHash. + + If no precision is specficified ST_PointFromGeoHash returns a point based on full precision of the input GeoHash string. + + If precision is specified ST_PointFromGeoHash will use that many characters from the GeoHash to create the point. + + Availability: 2.1.0 + + + + Examples + + + + + See Also + + , + + + + + + ST_GeomFromGeoHash + + Return a geometry from a GeoHash string. + + + + + + geometry ST_GeomFromGeoHash + text geohash + integer precision=full_precision_of_geohash + + + + + + Description + + Return a geometry from a GeoHash string. The geometry will be a polygon representing the GeoHash bounds. + + If no precision is specficified ST_GeomFromGeoHash returns a polygon based on full precision of the input GeoHash string. + + If precision is specified ST_GeomFromGeoHash will use that many characters from the GeoHash to create the polygon. + + Availability: 2.1.0 + + + + Examples + + + + + See Also + + , + + diff --git a/liblwgeom/liblwgeom_internal.h b/liblwgeom/liblwgeom_internal.h index 5cff2944a..0e63d1a09 100644 --- a/liblwgeom/liblwgeom_internal.h +++ b/liblwgeom/liblwgeom_internal.h @@ -260,6 +260,7 @@ LWCOLLECTION *lwpoint_clip_to_ordinate_range(const LWPOINT *mpoint, char ordinat */ int lwgeom_geohash_precision(GBOX bbox, GBOX *bounds); char *geohash_point(double longitude, double latitude, int precision); +void decode_geohash_bbox(char *geohash, double *lat, double *lon, int precision); /* * Point comparisons diff --git a/liblwgeom/lwalgorithm.c b/liblwgeom/lwalgorithm.c index 17aeadc0b..db0d7014f 100644 --- a/liblwgeom/lwalgorithm.c +++ b/liblwgeom/lwalgorithm.c @@ -687,6 +687,52 @@ unsigned int geohash_point_as_int(POINT2D *pt) return ch; } +/* +** Decode a GeoHash into a bounding box. The lat and lon arguments should +** both be passed as double arrays of length 2 at a minimum where the values +** set in them will be the southwest and northeast coordinates of the bounding +** box accordingly. A precision less than 0 indicates that the entire length +** of the GeoHash should be used. +*/ +void decode_geohash_bbox(char *geohash, double *lat, double *lon, int precision) +{ + int i, j, hashlen; + char c, cd, mask, is_even = 1; + static char bits[] = {16, 8, 4, 2, 1}; + + lat[0] = -90.0; + lat[1] = 90.0; + lon[0] = -180.0; + lon[1] = 180.0; + + hashlen = strlen(geohash); + + if (precision < 0 || precision > hashlen) + { + precision = hashlen; + } + + for (i = 0; i < precision; i++) + { + c = tolower(geohash[i]); + cd = strchr(base32, c) - base32; + + for (j = 0; j < 5; j++) + { + mask = bits[j]; + if (is_even) + { + lon[!(cd & mask)] = (lon[0] + lon[1]) / 2; + } + else + { + lat[!(cd & mask)] = (lat[0] + lat[1]) / 2; + } + is_even = !is_even; + } + } +} + int lwgeom_geohash_precision(GBOX bbox, GBOX *bounds) { double minx, miny, maxx, maxy; diff --git a/postgis/Makefile.in b/postgis/Makefile.in index cc6b5fde9..c0976fd5b 100644 --- a/postgis/Makefile.in +++ b/postgis/Makefile.in @@ -43,6 +43,7 @@ PG_OBJS= \ lwgeom_export.o \ lwgeom_in_gml.o \ lwgeom_in_kml.o \ + lwgeom_in_geohash.o \ lwgeom_in_geojson.o \ lwgeom_triggers.o \ lwgeom_dump.o \ diff --git a/postgis/postgis.sql.in b/postgis/postgis.sql.in index 0b8e5fd72..1f7374d10 100644 --- a/postgis/postgis.sql.in +++ b/postgis/postgis.sql.in @@ -3664,6 +3664,28 @@ CREATE OR REPLACE FUNCTION ST_GeoHash(geom geometry, maxchars int4 DEFAULT 0) AS 'MODULE_PATHNAME', 'ST_GeoHash' LANGUAGE 'c' IMMUTABLE STRICT; +----------------------------------------------------------------------- +-- GeoHash input +-- Availability: 2.0.? +----------------------------------------------------------------------- +-- ST_Box2dFromGeoHash(geohash text, precision int4) +CREATE OR REPLACE FUNCTION ST_Box2dFromGeoHash(text, int4 DEFAULT NULL) + RETURNS box2d + AS 'MODULE_PATHNAME','box2d_from_geohash' + LANGUAGE 'c' IMMUTABLE; + +-- ST_PointFromGeoHash(geohash text, precision int4) +CREATE OR REPLACE FUNCTION ST_PointFromGeoHash(text, int4 DEFAULT NULL) + RETURNS geometry + AS 'MODULE_PATHNAME','point_from_geohash' + LANGUAGE 'c' IMMUTABLE; + +-- ST_GeomFromGeoHash(geohash text, precision int4) +CREATE OR REPLACE FUNCTION ST_GeomFromGeoHash(text, int4 DEFAULT NULL) + RETURNS geometry + AS $$ SELECT CAST(ST_Box2dFromGeoHash($1, $2) AS geometry); $$ + LANGUAGE 'sql' IMMUTABLE; + ------------------------------------------------------------------------ -- OGC defined ------------------------------------------------------------------------ diff --git a/regress/Makefile.in b/regress/Makefile.in index 63f861df4..6560bd332 100644 --- a/regress/Makefile.in +++ b/regress/Makefile.in @@ -96,6 +96,7 @@ TESTS = \ geography \ out_geometry \ out_geography \ + in_geohash \ in_gml \ in_kml \ iscollection \ diff --git a/utils/postgis_restore.pl.in b/utils/postgis_restore.pl.in index 4aa8c1eef..c14626b2a 100755 --- a/utils/postgis_restore.pl.in +++ b/utils/postgis_restore.pl.in @@ -777,6 +777,8 @@ COMMENT FUNCTION st_bdmpolyfromtext(text, integer) COMMENT FUNCTION st_bdpolyfromtext(text, integer) COMMENT FUNCTION st_boundary(geometry) COMMENT FUNCTION st_box2d(geometry) +COMMENT FUNCTION st_box2dfromgeohash(text) +COMMENT FUNCTION st_box2dfromgeohash(text, integer) COMMENT FUNCTION st_box3d(geometry) COMMENT FUNCTION st_buffer(geography, double precision) COMMENT FUNCTION st_buffer(geometry, double precision) @@ -880,6 +882,8 @@ COMMENT FUNCTION st_geometrytype(geometry) COMMENT FUNCTION st_geomfromewkb(bytea) COMMENT FUNCTION st_geomfromewkt(text) COMMENT FUNCTION st_geomfromgeojson(text) +COMMENT FUNCTION st_geomfromgeohash(text) +COMMENT FUNCTION st_geomfromgeohash(text, integer) COMMENT FUNCTION st_geomfromgml(text) COMMENT FUNCTION st_geomfromgml(text, integer) COMMENT FUNCTION st_geomfromkml(text) @@ -1050,6 +1054,8 @@ COMMENT FUNCTION st_pixelaspolygon(rast raster, xinteger, yinteger) COMMENT FUNCTION st_pixelheight(raster) COMMENT FUNCTION st_pixelwidth(raster) COMMENT FUNCTION st_point(double precision, double precision) +COMMENT FUNCTION st_pointfromgeohash(text) +COMMENT FUNCTION st_pointfromgeohash(text, integer) COMMENT FUNCTION st_pointfromtext(text) COMMENT FUNCTION st_pointfromtext(text, integer) COMMENT FUNCTION st_point_inside_circle(geometry, double precision, double precision, double precision) -- 2.50.1