Package: geostructures
GeostructuresA lightweight implementation of shapes drawn across a geo-temporal plane. Geostructures enables you to quickly draw
shapes, convert to/from a variety of other geometric formats, and draw results.InstallationGeostructures is available on PYPI$ pip install geostructuresOptional DependenciesGeostructures does not require any of the below dependencies to function, however maintains optional features that use:geopandasH3MGRSscipyshapelyOverviewGeostructures provides a python interface for functionally defining various shapes drawn on a map. Unlike other
libraries such as Shapely, these shapes retain their mathematical definitions rather than being simplified into N-sided polygons.The shapes currently supported are:BoxesCirclesEllipsesLineStringsPointsPolygonsRings/WedgesAll shapes may optionally be temporally-bound using a specific datetime or a datetime interval.Additionally, geostructures provides convenience objects for representing chronologically-ordered (Track) and unordered (FeatureCollection) collections of the above shapes.Quick StartFor an interactive introduction, please review our collection ofJupyter notebooks.Creating GeoShapesfromgeostructuresimport*box=GeoBox(Coordinate(-0.154092,51.539865),# Northwest cornerCoordinate(-0.140592,51.505665),# Southeast cornerproperties={"name":"box"})circle=GeoCircle(Coordinate(-0.131092,51.509865),# centerpointradius=500,properties={"name":"circle"})ellipse=GeoEllipse(Coordinate(-0.093092,51.529865),# centerpointmajor_axis=1_000,# The distance between the centerpoint and the furthest point along the circumferenceminor_axis=250,# The distance between the centerpoint and the closest point along the circumferencerotation=45,# The angle of rotation (between 0 and 360)properties={"name":"ellipse"})ring=GeoRing(Coordinate(-0.116092,51.519865),# centerpointinner_radius=800,outer_radius=1000,properties={"name":"ring"})# Same as a ring, but with a min/max anglewedge=GeoRing(Coordinate(-0.101092,51.514865),# centerpointinner_radius=300,outer_radius=500,angle_min=60,# The minimum angle of the wedgeangle_max=190,# The maximum angle of the wedgeproperties={"name":"wedge"})linestring=GeoLineString([Coordinate(-0.123092,51.515865),Coordinate(-0.118092,51.514665),Coordinate(-0.116092,51.514865),Coordinate(-0.116092,51.518865),Coordinate(-0.108092,51.512865)],properties={"name":"linestring"})point=GeoPoint(Coordinate(-0.116092,51.519865),properties={"name":"point"})polygon=GeoPolygon([Coordinate(-0.116092,51.509865),Coordinate(-0.111092,51.509865),Coordinate(-0.113092,51.506865),Coordinate(-0.116092,51.509865)# Note that the last coordinate is the same as the first],properties={"name":"polygon"})Converting Between Formatsfromgeostructuresimport*fromgeostructures.collectionsimportFeatureCollectionpolygon=GeoPolygon([Coordinate(-0.116092,51.509865),Coordinate(-0.111092,51.509865),Coordinate(-0.113092,51.506865),Coordinate(-0.116092,51.509865)])# Convert to and from a variety of formatspolygon.to_geojson()polygon.from_geojson({ageojsonobject})polygon.to_wkt()polygon.from_wkt('<a wkt polygon string>')polygon.to_shapely()polygon.from_shapely(ashapelypolygon)# Collections of shapes have additional supported formatscollection=FeatureCollection([polygon])# Creates a geopandas DataFramecollection.to_geopandas()collection.from_geopandas(ageopandasDataFrame)# Creates a GeoJSON FeatureCollectioncollection.to_geojson()collection.from_geojson({ageojsonobject})# Write a FeatureCollection to an ESRI ShapefilefromzipfileimportZipFilewithZipFile('shapefile_name.zip','w')aszfile:collection.to_shapefile(zfile)collection.from_shapefile('shapefile_name.zip')Plotting Shapesfromgeostructuresimport*fromgeostructures.collectionsimportFeatureCollectionfromgeostructures.visualization.plotlyimportdraw_collectionbox=GeoBox(Coordinate(-0.154092,51.539865),Coordinate(-0.140592,51.505665))circle=GeoCircle(Coordinate(-0.131092,51.509865),radius=500)collection=FeatureCollection([box,circle])# Display the resultsfig=draw_collection(collection)figBounding Shapes by Timefromdatetimeimportdatetimefromgeostructuresimport*fromgeostructures.collectionsimportTrackfromgeostructures.timeimportTimeIntervaltrack=Track([# Bound shapes to a specific point in timeGeoPoint(Coordinate(-0.154092,51.539865),dt=datetime(2020,5,1,12)),GeoPoint(Coordinate(-0.155092,51.540865),dt=datetime(2020,5,1,13)),# Or bound them to a span of timeGeoPoint(Coordinate(-0.156092,51.541865),dt=TimeInterval(datetime(2020,5,1,14),datetime(2020,5,1,15))),])# Slice by datetimesubset=track[datetime(2020,5,1,12):datetime(2020,5,1,13)]# Get efficient metrics between shapestrack.centroid_distances# meterstrack.speed_diffs# meters per secondtrack.time_start_diffs# timedeltasGeohashingGeostructures supports geohashing using both Uber's H3 and the original Niemeyer geohashing algorithm.fromgeostructuresimport*fromgeostructures.collectionsimportFeatureCollectionfromgeostructures.geohashimportH3Hasher,NiemeyerHasherfromgeostructures.visualization.plotlyimporth3_choroplethbox=GeoBox(Coordinate(-0.154092,51.539865),Coordinate(-0.140592,51.505665))circle=GeoCircle(Coordinate(-0.131092,51.509865),radius=500)collection=FeatureCollection([box,circle])# Create a hasherhasher=H3Hasher(resolution=10)hashmap=hasher.hash_collection(collection)# Display the resultsh3_choropleth(hashmap)# Alternatively, hash using the Niemeyer algorithmhasher=NiemeyerHasher(length=8,base=16)hashmap=hasher.hash_collection(collection)ProjectionsThis library assumes that all geospatial terms and structures conform to theWGS84 standard(CRS 4326).Reporting Issues / Requesting FeaturesThe Geostructures team uses Github issues to track development goals. Please include as much detail as possible so we can effectively triage your request.ContributingWe welcome all contributors! Please reviewCONTRIBUTING.mdfor more information.DevelopersCarl Best (Sr. Data Scientist/Project Owner)https://github.com/ccbest/Eli Talbert (Sr. Data Scientist/PhD)https://github.com/etalbert102Jessica Moore (Sr. Data Scientist)https://github.com/jessica-writes-codeRichard Marshall (Data Scientist/SME)https://github.com/RichardMarshall13