Skip to main content

A lightweight implementation of shapes drawn across a geo-temporal plane.

Project description

Geostructures

Unit Tests

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.

plotting

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


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

geostructures-0.8.1.tar.gz (54.5 kB view details)

Uploaded Source

Built Distribution

geostructures-0.8.1-py3-none-any.whl (41.8 kB view details)

Uploaded Python 3

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

Hashes for geostructures-0.8.1.tar.gz
Algorithm Hash digest
SHA256 797dc84e50567d6bd4f7115668576963b4b4e8dde6df5b3aa8ea843c50f64ab1
MD5 a25b6eb5c6be4cfdb8faa3ce07267a2a
BLAKE2b-256 ed4679f68204bf6e2ff601a4fe91c4c2b936c7b936e99fb0505c9883bd5d1fe5

See more details on using hashes here.

Provenance

File details

Details for the file geostructures-0.8.1-py3-none-any.whl.

File metadata

File hashes

Hashes for geostructures-0.8.1-py3-none-any.whl
Algorithm Hash digest
SHA256 b5240917a6f6dab04ce4826b270c56ef7a7fbbb1fe7164e3d350bdc063f65bdb
MD5 295569d33849bacd871427b5cf0466ed
BLAKE2b-256 c44d065d120091795cb2fa87f9f213c88d5ae9b8b812a43f26f664652f1db518

See more details on using hashes here.

Provenance

Supported by

AWS AWS Cloud computing and Security Sponsor Datadog Datadog Monitoring Fastly Fastly CDN Google Google Download Analytics Microsoft Microsoft PSF Sponsor Pingdom Pingdom Monitoring Sentry Sentry Error logging StatusPage StatusPage Status page