A lightweight implementation of shapes drawn across a geo-temporal plane.
Project description
Geostructures
A 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.
Installation
Geostructures is available on PYPI
$ pip install geostructures
Optional Dependencies
Geostructures does not require any of the below dependencies to function, however maintains optional features that use:
- geopandas
- H3
- MGRS
- scipy
- shapely
Overview
Geostructures 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:
- Boxes
- Circles
- Ellipses
- LineStrings
- Points
- Polygons
- Rings/Wedges
All 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 Start
For an interactive introduction, please review our collection of Jupyter notebooks.
Creating GeoShapes
from geostructures import *
box = GeoBox(
Coordinate(-0.154092, 51.539865), # Northwest corner
Coordinate(-0.140592, 51.505665), # Southeast corner
properties={"name": "box"}
)
circle = GeoCircle(
Coordinate(-0.131092, 51.509865), # centerpoint
radius=500,
properties={"name": "circle"}
)
ellipse = GeoEllipse(
Coordinate(-0.093092, 51.529865), # centerpoint
major_axis=1_000, # The distance between the centerpoint and the furthest point along the circumference
minor_axis=250, # The distance between the centerpoint and the closest point along the circumference
rotation=45, # The angle of rotation (between 0 and 360)
properties={"name": "ellipse"}
)
ring = GeoRing(
Coordinate(-0.116092, 51.519865), # centerpoint
inner_radius=800,
outer_radius=1000,
properties={"name": "ring"}
)
# Same as a ring, but with a min/max angle
wedge = GeoRing(
Coordinate(-0.101092, 51.514865), # centerpoint
inner_radius=300,
outer_radius=500,
angle_min=60, # The minimum angle of the wedge
angle_max=190, # The maximum angle of the wedge
properties={"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 Formats
from geostructures import *
from geostructures.collections import FeatureCollection
polygon = 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 formats
polygon.to_geojson()
polygon.from_geojson( { a geojson object } )
polygon.to_wkt()
polygon.from_wkt( '<a wkt polygon string>' )
polygon.to_shapely()
polygon.from_shapely( a shapely polygon )
# Collections of shapes have additional supported formats
collection = FeatureCollection([polygon])
# Creates a geopandas DataFrame
collection.to_geopandas()
collection.from_geopandas( a geopandas DataFrame )
# Creates a GeoJSON FeatureCollection
collection.to_geojson()
collection.from_geojson( { a geojson object } )
# Write a FeatureCollection to an ESRI Shapefile
from zipfile import ZipFile
with ZipFile('shapefile_name.zip', 'w') as zfile:
collection.to_shapefile(zfile)
collection.from_shapefile('shapefile_name.zip')
Plotting Shapes
from geostructures import *
from geostructures.collections import FeatureCollection
from geostructures.visualization.plotly import draw_collection
box = 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 results
fig = draw_collection(collection)
fig
Bounding Shapes by Time
from datetime import datetime
from geostructures import *
from geostructures.collections import Track
from geostructures.time import TimeInterval
track = Track([
# Bound shapes to a specific point in time
GeoPoint(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 time
GeoPoint(
Coordinate(-0.156092, 51.541865),
dt=TimeInterval(
datetime(2020, 5, 1, 14),
datetime(2020, 5, 1, 15)
)
),
])
# Slice by datetime
subset = track[datetime(2020, 5, 1, 12):datetime(2020, 5, 1, 13)]
# Get efficient metrics between shapes
track.centroid_distances # meters
track.speed_diffs # meters per second
track.time_start_diffs # timedeltas
Geohashing
Geostructures supports geohashing using both Uber's H3 and the original Niemeyer geohashing algorithm.
from geostructures import *
from geostructures.collections import FeatureCollection
from geostructures.geohash import H3Hasher, NiemeyerHasher
from geostructures.visualization.plotly import h3_choropleth
box = 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 hasher
hasher = H3Hasher(resolution=10)
hashmap = hasher.hash_collection(collection)
# Display the results
h3_choropleth(hashmap)
# Alternatively, hash using the Niemeyer algorithm
hasher = NiemeyerHasher(length=8, base=16)
hashmap = hasher.hash_collection(collection)
Projections
This library assumes that all geospatial terms and structures conform to the WGS84 standard (CRS 4326).
Reporting Issues / Requesting Features
The Geostructures team uses Github issues to track development goals. Please include as much detail as possible so we can effectively triage your request.
Contributing
We welcome all contributors! Please review CONTRIBUTING.md for more information.
Developers
Carl Best (Sr. Data Scientist/Project Owner)
https://github.com/ccbest/
Eli Talbert (Sr. Data Scientist/PhD)
https://github.com/etalbert102
Jessica Moore (Sr. Data Scientist)
https://github.com/jessica-writes-code
Richard Marshall (Data Scientist/SME)
https://github.com/RichardMarshall13
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
File details
Details for the file geostructures-0.8.1.tar.gz
.
File metadata
- Download URL: geostructures-0.8.1.tar.gz
- Upload date:
- Size: 54.5 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/5.0.0 CPython/3.9.18
File hashes
Algorithm | Hash digest | |
---|---|---|
SHA256 | 797dc84e50567d6bd4f7115668576963b4b4e8dde6df5b3aa8ea843c50f64ab1 |
|
MD5 | a25b6eb5c6be4cfdb8faa3ce07267a2a |
|
BLAKE2b-256 | ed4679f68204bf6e2ff601a4fe91c4c2b936c7b936e99fb0505c9883bd5d1fe5 |
Provenance
File details
Details for the file geostructures-0.8.1-py3-none-any.whl
.
File metadata
- Download URL: geostructures-0.8.1-py3-none-any.whl
- Upload date:
- Size: 41.8 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/5.0.0 CPython/3.9.18
File hashes
Algorithm | Hash digest | |
---|---|---|
SHA256 | b5240917a6f6dab04ce4826b270c56ef7a7fbbb1fe7164e3d350bdc063f65bdb |
|
MD5 | 295569d33849bacd871427b5cf0466ed |
|
BLAKE2b-256 | c44d065d120091795cb2fa87f9f213c88d5ae9b8b812a43f26f664652f1db518 |