Summarising geometry#
With a data cube containing variable geometry, you can use xvec to generate a summary geometry that can be used as an additional GeometryIndex.
import geopandas as gpd
import xproj
import xvec
Use the example dataset of Svalbard glaciers over time.
glaciers_df = gpd.read_file("https://github.com/loreabad6/post/raw/refs/heads/main/inst/extdata/svalbard.gpkg")
glaciers = (
glaciers_df.set_index(["name", "year"])
.to_xarray()
.proj.assign_crs(spatial_ref=glaciers_df.crs) # use xproj to store the CRS information
)
glaciers
<xarray.Dataset> Size: 432B
Dimensions: (name: 5, year: 3)
Coordinates:
* name (name) object 40B 'Austre Brøggerbreen' ... 'Steenbreen'
* year (year) float64 24B 1.936e+03 1.99e+03 2.007e+03
* spatial_ref int64 8B 0
Data variables:
length (name, year) float64 120B 5.808e+03 5.265e+03 ... 1.819e+03
fwidth (name, year) float64 120B 1.254e+03 470.1 888.4 ... 279.4 202.6
geometry (name, year) object 120B POLYGON ((432375.11039999966 876165...
Indexes:
spatial_ref CRSIndex (crs=EPSG:32633)Visualised, the changing variable geometry looks like this:
f, axs = glaciers.xvec.plot(col='year', geometry='geometry')
Generate summary geometry along ‘name’ dimension.
glaciers = glaciers.xvec.summarize_geometry(
dim="name", geom_array="geometry"
)
glaciers
<xarray.Dataset> Size: 472B
Dimensions: (name: 5, year: 3)
Coordinates:
* name (name) object 40B 'Austre Brøggerbreen' ... 'Steenbreen'
* year (year) float64 24B 1.936e+03 1.99e+03 2.007e+03
* spatial_ref int64 8B 0
* summary_geometry (name) object 40B POLYGON ((428910.11039999966 8757044....
Data variables:
length (name, year) float64 120B 5.808e+03 ... 1.819e+03
fwidth (name, year) float64 120B 1.254e+03 470.1 ... 279.4 202.6
geometry (name, year) object 120B POLYGON ((432375.11039999966 8...
Indexes:
spatial_ref CRSIndex (crs=EPSG:32633)
summary_geometry GeometryIndex (crs=EPSG:32633)This has added new coordinates backed by the GeometryIndex to the dimension name. It optionally tries to retrieve CRS of the variable geometry using xproj.
f, ax = glaciers.xvec.plot(geometry="summary_geometry", alpha=.5)
The default summary is using the total envelope (bounding box) of all geometries at the same coordinate of the set dimension. However, you can do any of the:
"envelope"- envelope (bounding box) of combined geometries"oriented_envelope"- oriented envelope (minimum rotated recatngle) of combined geometries"centroid"- centroid of combined geometries (derived from a GeometryCollection combining all)"convex_hull"- convex hull of combined geometries"concave_hull"- concave hull of combined geometries"collection"- collection combining all geometries"union"- union of all geometries
or a callable.
glaciers = glaciers.xvec.summarize_geometry(
dim="name", geom_array="geometry", aggfunc='convex_hull'
)
f, ax = glaciers.xvec.plot(geometry="summary_geometry", alpha=.5)
You can also pass additional args to the aggregation function.
glaciers = glaciers.xvec.summarize_geometry(
dim="name", geom_array="geometry", aggfunc='concave_hull', ratio=.5
)
f, ax = glaciers.xvec.plot(geometry="summary_geometry", alpha=.5)