Data Types

Geotypes adds some high-level wrappers around geopandas and shapely to allow for easier use. They allow easy conversion between georeference schemes, better tracking of what coordinate system the variables are in and easy conversion between types. These include:

import geotypes

GeoPoint

The GeoPoint is an x,y coordinate with an associated Coordinate Reference System (CRS). It allows easy conversion to LL and XY data types.

p = geotypes.geometry.GeoPoint(x=151.28826000, y=-33.79798000, crs="epsg:4326") # initialise a lat, lon centred in Manly.
print("GeoPoint", p)
ll = p.to_ll() # Converts to lat,lon data type
print("In LL", ll)
p_utm = p.to_crs("EPSG:32756")  # converts to utm zone 56S
print("In UTM Zone 56S", p_utm)
GeoPoint GeoPoint(x=151.28826,y=-33.79798,crs=epsg:4326)
In LL LL(lat=-33.79798, lon=151.28826)
In UTM Zone 56S GeoPoint(x=341542.2378026622,y=6258926.312196327,crs=EPSG:32756)

LL

The lat,lon data type is there for convience and to make it explicit about what is latitude, what is longitude.

ll = geotypes.geometry.LL(-33.79798000,151.28826000)
print(ll)
# Convert to geopoint
p = ll.to_geopoint()
print(p)
LL(lat=-33.79798, lon=151.28826)
GeoPoint(x=151.28826,y=-33.79798,crs=EPSG:4326)

GeoPath

A path in geographic space, effectively a geopandas geoseries / shapely linestring with an associated CRS. It is commonly used to represent sampling transects (such as AUV transects). It has some convient functions to collect samples at set distances along the path - which can be done no-matter what

# Define a set of points. This is a simple broad grid in CRS "EPSG:32756"
points = [(342041.99358729343, 6259392.849573873),
 (342495.27623430215, 6259603.771833958),
 (342579.64503957686, 6259422.458960008),
 (342126.36269032373, 6259211.536449324),
 (342210.73189359176, 6259030.223443877),
 (342664.01394509675, 6259241.146205157)]

# create the geopath object
geopath = geotypes.geometry.GeoPath(points, crs="EPSG:32756")
print(geopath)

# Iterating over it returns a geopoint.
print("Geopoints:")
for p in geopath:
    print(p)
print("\n")

# Easily convert to other crs
geopath4326 = geopath.to_crs("EPSG:4326")
print(geopath4326)

# Sample points along the geopath
geopath_subsampled = geopath.sample_points_along_path(d=20) # sample a point every 20 meters.
print("Number of points in original {}, in subsampled {}".format(len(geopath), len(geopath_subsampled)))
GeoPath (crs= EPSG:32756): 
    (342041.99358729343, 6259392.849573873)
    (342495.27623430215, 6259603.771833958)
    (342579.64503957686, 6259422.458960008)
    (342126.36269032373, 6259211.536449324)
    (342210.73189359176, 6259030.223443877)
    (342664.01394509675, 6259241.146205157)

Geopoints:
GeoPoint(x=342041.99358729343,y=6259392.849573873,crs=EPSG:32756)
GeoPoint(x=342495.27623430215,y=6259603.771833958,crs=EPSG:32756)
GeoPoint(x=342579.64503957686,y=6259422.458960008,crs=EPSG:32756)
GeoPoint(x=342126.36269032373,y=6259211.536449324,crs=EPSG:32756)
GeoPoint(x=342210.73189359176,y=6259030.223443877,crs=EPSG:32756)
GeoPoint(x=342664.01394509675,y=6259241.146205157,crs=EPSG:32756)


GeoPath (crs= EPSG:4326): 
    (151.2937399882331, -33.79384884712429)
    (151.29867207410172, -33.79201494327435)
    (151.2995507283774, -33.793662084087515)
    (151.2946185667885, -33.795496022572)
    (151.29549717899934, -33.797143191322725)
    (151.30042941631163, -33.7953092181998)

Number of points in original 6, in subsampled 95

GeoArea

A GeoArea is a wrapper around a geopandas GeoSeries with just one element, a polygon or multipolygon. They are used within the situ framework to represent sampling bounds or focal areas. As such, they have easy access to random sampling.

# Define a geoarea
geoarea = geotypes.geometry.GeoArea([(151.28412747953516, -33.78781691040293),
 (151.30572252046485, -33.78781691040293),
 (151.30572478467255, -33.805848131225765),
 (151.28412521532746, -33.805848131225765),
 (151.28412747953516, -33.78781691040293)], crs='EPSG:4326')

# get some samples from within it - these are GeoPoints:
for n in range(5):
    print(geoarea.random_point_geo())
# you can get also get points directly as LLs, regardless of the CRS.
for n in range(5):
    print(geoarea.random_point_ll())
GeoPoint(x=151.30020242178347,y=-33.78922404592678,crs=EPSG:4326)
GeoPoint(x=151.28622164423567,y=-33.80260967226125,crs=EPSG:4326)
GeoPoint(x=151.3051581370423,y=-33.79769333597564,crs=EPSG:4326)
GeoPoint(x=151.2907319212945,y=-33.80119453539296,crs=EPSG:4326)
GeoPoint(x=151.3014452881778,y=-33.80002746268745,crs=EPSG:4326)
LL(lat=-33.79903137500317, lon=151.3032352521167)
LL(lat=-33.79032258219548, lon=151.2971890468687)
LL(lat=-33.802069867335, lon=151.28755613264838)
LL(lat=-33.79611942282693, lon=151.29250630774257)
LL(lat=-33.80493653206971, lon=151.2946950074714)
# Plot the overall area on the map
import folium
# Plot the area
m = geoarea.explore(style_kwds={'fill': False, 'color':'green'})
# Plot the geopath
geopath.explore(m=m)
# Plot the samples along the geopath
geotypes.geometry.GeoPoints(geopath.sample_points_along_path(50).to_geopoints()).explore(m=m)
# Plot some random samples from the geoarea
geotypes.geometry.GeoPoints([geoarea.random_point_ll() for _ in range(10)]).explore(m=m, style_kwds={'color':'red'})
folium.LayerControl().add_to(m)
display(m)
Make this Notebook Trusted to load map: File -> Trust Notebook

Local Equivalents

There are local equivalents to the classes presented above. These include: - XY: Equivalent of GeoPoint - LocalPoints: Equivalent of GeoPoints - LocalPath: Equivalent of GeoPath - LocalArea: Equivalent of GeoArea These are just wrappers around the shapely geometry classes, but offer some extra functionality, including being able to convert to and from the Geo equivalents.

origin_ll = geoarea.centroid_ll()
# Convert the position to local
xy = p.to_local(origin_ll)
# Now go back to GeoPoint, this time with a different CRS.
pll = xy.to_geo(origin_ll, "epsg:4326")
# Print all to compare
print(p, xy, pll)


# Convert a GeoPath to a LocalPath
localpath = geopath.to_local(origin_ll)
# And go back again
geopath2 = localpath.to_geo(origin_ll, geopath.crs)
GeoPoint(x=342664.01394509675,y=6259241.146205157,crs=EPSG:32756) XY(x=509.7408123251043, y=168.9840842232932) GeoPoint(x=151.30042941631163,y=-33.7953092181998,crs=epsg:4326)
/home/jhs/environments/general/lib/python3.10/site-packages/geotypes/geometry.py:1409: UserWarning:

Geometry is in a geographic CRS. Results from 'centroid' are likely incorrect. Use 'GeoSeries.to_crs()' to re-project geometries to a projected CRS before this operation.