Reputation: 7329
PostGIS has this function ST_GeomFromGeoHash
to get the bounding box geometry of the geohash area (https://postgis.net/docs/ST_GeomFromGeoHash.html), but it has not been ported to BigQuery yet. Is there any workaround?
Upvotes: 1
Views: 1303
Reputation: 7329
I've implemented the following BigQuery UDF that converts a geohash of arbitrary precision to a bounding box geometry:
CREATE OR REPLACE FUNCTION dataset.geohash_to_bbox(geohash STRING)
RETURNS STRING
LANGUAGE js AS """
var BASE32_CODES = "0123456789bcdefghjkmnpqrstuvwxyz";
var BASE32_CODES_DICT = {};
for (var i = 0; i < BASE32_CODES.length; i++) {
BASE32_CODES_DICT[BASE32_CODES.charAt(i)] = i;
}
var ENCODE_AUTO = 'auto';
var MIN_LAT = -90;
var MAX_LAT = 90;
var MIN_LON = -180;
var MAX_LON = 180;
var decode_bbox = function (hash_string) {
var isLon = true,
maxLat = MAX_LAT,
minLat = MIN_LAT,
maxLon = MAX_LON,
minLon = MIN_LON,
mid;
var hashValue = 0;
for (var i = 0, l = hash_string.length; i < l; i++) {
var code = hash_string[i].toLowerCase();
hashValue = BASE32_CODES_DICT[code];
for (var bits = 4; bits >= 0; bits--) {
var bit = (hashValue >> bits) & 1;
if (isLon) {
mid = (maxLon + minLon) / 2;
if (bit === 1) {
minLon = mid;
} else {
maxLon = mid;
}
} else {
mid = (maxLat + minLat) / 2;
if (bit === 1) {
minLat = mid;
} else {
maxLat = mid;
}
}
isLon = !isLon;
}
}
return "POLYGON (( " + minLon + " " + minLat + ", " + maxLon + " " + minLat + ", " + maxLon + " " + maxLat + ", " + minLon + " " + maxLat + ", " + minLon + " " + minLat + "))";
};
return decode_bbox(geohash);
""";
Example usage:
select <dataset>.geohash_to_geom("ttnfv2u");
>> POLYGON((77.2119140625 28.6083984375, 77.2119140625 28.65234375, 77.255859375 28.65234375, 77.255859375 28.6083984375, 77.2119140625 28.6083984375))
Upvotes: 2
Reputation: 7744
BigQuery has ST_GEOGPOINTFROMGEOHASH
which returns the central point. There is currently no function that returns the box though. The UDF in another answer is often a reasonable workaround, but you should be aware of its usage limitation.
GeoHash normally represents a rectangle on a flat 2D map. BigQuery works with Geography, with geodesic edges, so an edge between two points with same latitude does not follow the parallel, but being geodesic line is a shorter route closer to the pole. So the BigQuery polygon is a bit different from 2D box. You can often ignore the differences, but it might give you wrong results depending on how you use this polygon.
Upvotes: 0