Land cover is live
Mapmakers rejoice!
The May release of Overture Maps includes new high-resolution land cover data and new cartographic schema properties.
Our land_cover
layer is vectorized data derived from the European Space Agency’s 2020 WorldCover (10m) rasters. It's similar to the land cover layer in the Daylight map distribution, but Overture Maps added higher-resolution data (zoom level 15) with more detail and land cover classes. You'll find 10 subtypes in the new data: snow, forest, urban, grass, crop, barren, wetland, moss, mangrove, and shrub.
Our May release also includes schema properties that offer cartographic "hints" for optimal use of Overture Maps data in mapmaking. We added min_zoom
and max_zoom
to define the recommended zooms for each resolution of land cover, using the common “slippy maps” zoom level specification. This is a first step toward improving the user experience for mapmakers. We plan to expand these properties in future releases of Overture Maps data.
Exploring land cover
In the example below, we'll show you how to extract, process, and visualize land cover data for an area of interest using lonboard and the Overture Maps Python command-line tool. We recommend that you consult the Overture Maps buildings example in the lonboard docs to better understand the methods used here.
You'll need to install lonboard and overturemaps-py before you get started.
#pip install overturemaps
pip install -e . #clone repo and install pre-release version in directory
import pandas as pd
import geopandas as gpd
import overturemaps #dev branch, pre-release
from shapely import wkb
from lonboard import Map, PolygonLayer
from lonboard.colormap import apply_categorical_cmap
# specify bounding box
bbox = -78.6429, 39.463, -73.7806, 41.6242
# read in Overture Maps land_cover data type
table = overturemaps.record_batch_reader("land_cover", bbox).read_all()
table = table.combine_chunks()
# convert to dataframe
df = table.to_pandas()
# filter for higher resolution land_cover features
df_h = df[df.cartography.apply(lambda x: x['min_zoom'] == 8)]
# create color map for land_cover subtypes, loosely based on natural-color palette: https://www.shadedrelief.com/shelton/c.html
color_map = {
"urban": [167, 162, 186],
"forest": [134, 178, 137],
"barren": [245, 237, 213],
"shrub": [239, 218, 182],
"grass": [254, 239, 173],
"crop": [222, 223, 154],
"wetland": [158, 207, 195],
"mangrove": [83, 171, 128],
"moss": [250, 230, 160],
"snow": [255, 255, 255],
#"none": [108, 159, 184],
}
# apply color map to land_cover subtypes
colors = apply_categorical_cmap(df_h.subtype, color_map)
# dataframe to geodataframe, set crs
gdf = gpd.GeoDataFrame(
df_h,
geometry=df_h['geometry'].apply(wkb.loads),
crs="EPSG:4326"
)
# reproject to Pennsylvania State Plane (https://epsg.io/2272)
# gdf = gdf.to_crs(2272)
# create map layer
layer = PolygonLayer.from_geopandas(
gdf= gdf[['id','subtype', 'cartography', 'geometry']].reset_index(drop=True),
get_fill_color=colors,
get_line_color=colors,
)
#render map
view_state = {
"longitude": -76.2,
"latitude": 39.6,
"zoom": 8,
"pitch": 65,
"bearing": 5,
}
m = Map(layer, view_state=view_state)
m