Elevation Maps#
Elevation maps describe the height of the Earth’s surface above sea level. They can be stored as vector data (contour lines) or raster data (height grids).
Data Structure#
Vector Format (geopandas.GeoDataFrame)
Columns:
elev - elevation value (meters above sea level)
geometry - LINESTRING (contour lines) or POLYGON
Raster Format (xarray.DataArray)
DataArray:
name: elevation
dims: (south_north, west_east)
dtype: float (meters above sea level)
I/O#
Reading:
windkit.read_elevation_map() reads elevation from raster or vector files:
elev_vector = wk.read_elevation_map("elev.map", crs="EPSG:32629")
elev_raster = wk.read_elevation_map("elev.tif")
See I/O for the supported formats and for reading maps from zip archives.
Writing:
windkit.elevation_map_to_file() writes elevation maps:
wk.elevation_map_to_file(elev_raster, "output.tif")
Working with Raster Elevation#
Raster data can be reprojected using windkit.spatial.warp():
warped = wk.spatial.warp(raster_in_latlon, to_crs="EPSG:32632")
Clip raster to smaller area using windkit.spatial.clip()
# Clip raster to a smaller area
bbox = wk.spatial.BBox.from_cornerpts(
minx=502000, miny=4602000,
maxx=508000, maxy=4608000,
crs="EPSG:32629"
)
clipped = wk.spatial.clip(raster, bbox)
Filling No-Data Cells#
Raster elevation data often has missing cells, for example over water or at
the edge of a tile, stored as NaN or infinite values. The flow models
cannot use such cells, so windkit.fill_elevation_nodata() replaces
them explicitly:
Cells connected to the edge of the raster take the value of the nearest valid cell.
Interior holes are interpolated linearly from the valid cells around them.
elev = xr.DataArray(
[[10.0, 12.0, 14.0, 16.0],
[11.0, np.nan, 15.0, 17.0],
[12.0, 14.0, 16.0, 18.0],
[np.nan, 15.0, 17.0, 19.0]],
dims=["south_north", "west_east"],
coords={"south_north": [0.0, 100.0, 200.0, 300.0],
"west_east": [0.0, 100.0, 200.0, 300.0]},
name="elevation",
)
with warnings.catch_warnings(record=True) as caught:
warnings.simplefilter("always")
filled = wk.fill_elevation_nodata(elev, max_fill_fraction=0.2)
for warning in caught:
print(warning.message)
print(filled.values)
Filling 1 boundary no-data cell(s) in elevation raster 'elevation' using nearest-neighbour interpolation.
Filling 1 interior no-data cell(s) in elevation raster 'elevation' using piecewise-linear interpolation.
[[10. 12. 14. 16.]
[11. 13. 15. 17.]
[12. 14. 16. 18.]
[12. 15. 17. 19.]]
A warning reports how many cells were filled each way. Filling invents
terrain, so by default it is refused when more than 5 % of the cells are
missing (max_fill_fraction=0.05); for large gaps it is usually better to
clip the raster to its valid extent. Pass a larger fraction, or None, to
fill anyway.