Do you need to know what Geohashes make up a Polygon, or run along a LineString fast? Generate a Geohash Signature from any shape using the geohash_signature
module!
Supports Python 2.7 and 3.5+ (but please use 3, come on now people)
- Python >=2.7 (including Python 3.x) (>=3.5 recommended)
- Shapely >= 1.6
- python-geohash >= 0.8.5
- geojson >= 2.3.0
python setup.py install
within
performances slightly slower then intersects
because intersects
uses the fishnet algorithm to chop up the shape so it can be calculated in parallel.
The larger the shape and/or smaller the Geohash Level will result in dramatic performance decreases. The sweet spot tends to be around a signature with a Geohash Level of 10.
Generating a Geohash Signature using the intersects
method against a Polygon with dimensions of 152.9m x 152.4m
on an 8 core machine
-
intersects(POLYGON, 10)
- 0m1.806s
- results in 33,540 geohashes
-
intersects(POLYGON, 11)
- 0m26.470s
- results in 1,052,676 geohashes
-
intersects(POLYGON, 12)
- 19m55.589s
- results in 33,579,012 geohashes
- shape: Shapely Shape or GeoJSON dictionary
- geohash_level: 1-12 [Default: 10]
- compress: True|False [Default: False]
Takes a Shapely Shape or GeoJSON dictionary, and returns a set of Geohashes that intersect or are within. Defaults to Geohash level of 10. You can also optionally compress the response to its common prefix and components.
- geohashes: A <List> or <Set> of Geohashes
- save_to: Optionally write the FeatureCollection to a file.
Helper function to generate a Feature Collection. Takes a <List> or <Set> of Geohashes and returns them as a Feature Collection of Polygons or optionally you can save that Feature Collection as a GeoJSON file.
- geohashes: A <List> or <Set> of Geohashes
Helper function to compress hashes after the fact. Takes a <List> or <Set> of Geohashes and returns a tuple (common_prefix, set(parts)).
import geohash_signature
from shapely.geometry import Polygon
# Create a shapely shape
COORDINATES = [[-73.99603330, 40.73283237],
[-73.99610310, 40.73287904],
[-73.99604151, 40.73295838],
[-73.99596555, 40.73293815],
[-73.99578489, 40.73290082],
[-73.99578489, 40.73290082],
[-73.99576436, 40.73283704],
[-73.99582184, 40.73275458],
[-73.99591423, 40.73275147]]
SHAPE = Polygon(COORDINATES)
# OR pass GeoJSON dictionary
# SHAPE = {
# "type": "Polygon",
# "coordinates": [COORDINATES]
# }
# Returns a set() of Geohashes
GEOHASHES = geohash_signature.intersects(SHAPE, geohash_level=10)
GEOHASHES_WITHIN = geohash_signature.within(SHAPE, geohash_level=10)
Optionally you can compress the Geohash response. intersects
and within
have an optional compress
property, or you can manually compress using compress_geohashes
method.
This will return the Geohashes in a tuple (common_prefix, {"part", "part", "part"})
i.e. ("dr5rspj", {"tzg", "tzp", "tzq", "tzr"})
import geohash_signature
from shapely.geometry import Polygon
# Create a shapely shape
COORDINATES = [[-73.99603330, 40.73283237],
[-73.99610310, 40.73287904],
[-73.99604151, 40.73295838],
[-73.99596555, 40.73293815],
[-73.99578489, 40.73290082],
[-73.99578489, 40.73290082],
[-73.99576436, 40.73283704],
[-73.99582184, 40.73275458],
[-73.99591423, 40.73275147]]
SHAPE = Polygon(COORDINATES)
# intersects & within accept an optional compress attribute
PREFIX, COMPONENTS = geohash_signature.intersects(SHAPE,
geohash_level=10,
compress=True)
# Or manually compress the results
PREFIX, COMPONENTS = geohash_signature.compress_geohashes(GEOHASHES)
You can pass GeoJSON as a string or a file path.
Usage:
geohash-signature <geojson>
[--geohash_level=<level>]
[--filter=<filter>]
[--compress]
Options:
geojson Path to GeoJSON file or String. (required)
--geohash_level=<1-12> The resolution of the signature. (default: 9)
--filter=<intersects|within> Which signature filter to use. (default: intersects)
--compress Compress the results (optional)
$ geohash-signature /path/to/poly.geojson \
--geohash_level=10 \
--filter=intersects \
--compress
This General Public License does not permit incorporating your program into proprietary programs.
In simple words, if you are using this NOT FOR PROFIT, skies the limit. If you plan to use this in a commerical application, please reach out to me for licensing. Think how MySQL works.