10. Working with Vector Tiles and PMTiles#

10.1. Introduction#

10.2. Learning Objectives#

10.3. Sample Datasets#

10.4. Installation and Setup#

# %pip install -U "leafmap[pmtiles]"
import duckdb
import leafmap.maplibregl as leafmap

10.5. Visualizing Vector Tiles Directly from Files#

10.5.1. Configuring JupyterHub Access (Optional)#

# leafmap.configure_jupyterhub("https://your-jupyterhub-domain.com")

10.5.2. Visualizing Data from Vector Files#

url = "https://data.source.coop/giswqs/nwi/wetlands/RI_Wetlands.parquet"
filepath = leafmap.download_file(url)
m = leafmap.Map(style="liberty", height="600px")
m.add_basemap("Esri.WorldImagery")
m.add_duckdb_layer(
    data=filepath,
    layer_name="wetlands",
    layer_type="fill",
    paint={"fill-color": "#3388ff"},
    opacity=0.5,
    fit_bounds=True,
    use_view=False,
    min_zoom=None,
    quiet=False,
)
m

10.5.3. Visualizing Data from Existing DuckDB Databases#

url = "https://data.gishub.org/duckdb/nyc_data.db.zip"
leafmap.download_file(url, unzip=True)
db_path = "nyc_data.db"
con = duckdb.connect(db_path)
con.install_extension("spatial")
con.load_extension("spatial")
con.sql("SHOW TABLES;")
con.close()
m = leafmap.Map(
    center=[-73.9031255, 40.7127753], zoom=9, style="positron", height="600px"
)
m.add_basemap("Esri.WorldImagery")
m.add_duckdb_layer(
    database_path=db_path,
    table_name="nyc_census_blocks",
    layer_name="Census Blocks",
    layer_type="fill",
    paint={"fill-color": "#3388ff", "fill-outline-color": "#ffffff"},
    opacity=0.5,
    fit_bounds=False,
    src_crs="EPSG:26918",
    quiet=True,
)
m

10.6. Converting Vector Data to PMTiles#

10.6.1. Understanding Coordinate Transformations for PMTiles#

10.6.2. Exporting a Global Cities Dataset to PMTiles#

con = duckdb.connect()
con.install_extension("spatial")
con.load_extension("spatial")
con.sql(
    """
COPY (
    SELECT * EXCLUDE (geometry),
           ST_Transform(geometry, 'EPSG:4326', 'EPSG:3857', true) AS geometry
    FROM 'https://data.gishub.org/duckdb/cities.parquet'
)
TO 'cities.pmtiles'
WITH (
    FORMAT GDAL,
    DRIVER 'PMTiles',
    LAYER_CREATION_OPTIONS ('MINZOOM=0', 'MAXZOOM=14')
)
"""
)

10.7. Visualizing PMTiles#

10.7.1. Visualizing Local PMTiles with Martin Tile Server#

process = leafmap.start_martin(pmtiles=["cities.pmtiles"])
m = leafmap.Map(style="positron")
url = "http://localhost:3000/cities"
paint = {
    "circle-color": "#3388ff",
    "circle-radius": 4,
    "circle-opacity": 0.5,
    "circle-stroke-color": "#ffffff",
    "circle-stroke-width": 1,
}
m.add_vector_tile(
    url, layer_id="cities", layer_type="circle", name="World Cities", paint=paint
)
m
leafmap.stop_martin(process)

10.7.2. Visualizing Cloud-Hosted PMTiles#

release = "2025-10-22"
url = f"https://overturemaps-tiles-us-west-2-beta.s3.amazonaws.com/{release}/buildings.pmtiles"
print(url)

10.7.3. Creating 3D Building Visualizations#

m = leafmap.Map(
    center=[-74.0095, 40.7046], zoom=15, pitch=60, bearing=-17, style="positron"
)
m.add_basemap("OpenStreetMap.Mapnik")
m.add_basemap("Esri.WorldImagery", visible=False)

value_color_pairs = [0, "lightgray", 200, "royalblue", 400, "lightblue"]
style = {
    "layers": [
        {
            "id": "Building",
            "source": "buildings",
            "source-layer": "building",
            "type": "fill-extrusion",
            "filter": [
                ">",
                ["get", "height"],
                0,
            ],
            "paint": {
                "fill-extrusion-color": [
                    "interpolate",
                    ["linear"],
                    ["get", "height"],
                ]
                + value_color_pairs,
                "fill-extrusion-height": ["*", ["get", "height"], 1],
            },
        },
        {
            "id": "Building-part",
            "source": "buildings",
            "source-layer": "building_part",
            "type": "fill-extrusion",
            "filter": [
                ">",
                ["get", "height"],
                0,
            ],
            "paint": {
                "fill-extrusion-color": [
                    "interpolate",
                    ["linear"],
                    ["get", "height"],
                ]
                + value_color_pairs,
                "fill-extrusion-height": ["*", ["get", "height"], 1],
            },
        },
    ],
}

m.add_pmtiles(
    url,
    style=style,
    visible=True,
    opacity=1.0,
    tooltip=True,
    fit_bounds=False,
)
m

10.7.4. Simplified 3D Building Visualization#

m = leafmap.Map(
    center=[-74.0095, 40.7046], zoom=15, pitch=60, bearing=-17, style="positron"
)
m.add_basemap("OpenStreetMap.Mapnik")
m.add_basemap("Esri.WorldImagery", visible=False)
m.add_overture_3d_buildings(
    values=[0, 200, 400], colors=["lightgray", "royalblue", "lightblue"]
)
m

10.7.5. Visualizing 2D Building Footprints#

m = leafmap.Map(center=[-74.0095, 40.7046], zoom=15)
m.add_basemap("OpenStreetMap.Mapnik")
m.add_basemap("Esri.WorldImagery", visible=True)
m.add_overture_data(theme="buildings", opacity=0.8)
m
m = leafmap.Map(center=[-74.0095, 40.7046], zoom=16)
m.add_basemap("OpenStreetMap.Mapnik")
m.add_basemap("Esri.WorldImagery", visible=True)
m.add_overture_buildings(type="line", line_color="#ff0000", line_width=2, opacity=0.7)
m

10.7.6. Visualizing Overture Transportation Networks#

m = leafmap.Map(center=[-74.0095, 40.7046], zoom=16)
m.add_basemap("Esri.WorldImagery", visible=True)
m.add_overture_data(theme="transportation", opacity=0.8)
m

10.7.7. Visualizing Overture Places#

m = leafmap.Map(center=[-74.0095, 40.7046], zoom=16)
m.add_basemap("Esri.WorldImagery", visible=True)
m.add_overture_data(theme="places", opacity=0.8)
m

10.8. Key Takeaways#

10.9. Exercises#

10.9.1. Exercise 1: Visualizing Local Vector Files with On-the-Fly Tiling#

10.9.2. Exercise 2: Visualizing Data from DuckDB Database#

10.9.3. Exercise 3: Converting Spatial Data to PMTiles#

10.9.4. Exercise 4: Serving and Visualizing Local PMTiles#

10.9.5. Exercise 5: Exporting NYC Data to PMTiles#

10.9.6. Exercise 6: Multi-Layer PMTiles Visualization#

10.9.7. Exercise 7: Visualizing Cloud-Hosted Overture Data#

10.9.8. Exercise 8: Custom 3D Building Visualization#

10.9.9. Exercise 9: Overture Transportation Network Analysis#

10.9.10. Exercise 10: Complete Spatial Analysis to PMTiles Workflow#