{ "cells": [ { "cell_type": "markdown", "id": "0", "metadata": {}, "source": [ "[![image](https://jupyterlite.rtfd.io/en/latest/_static/badge.svg)](https://demo.leafmap.org/lab/index.html?path=notebooks/102_fused.ipynb)\n", "[![image](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/opengeos/leafmap/blob/master/docs/notebooks/102_fused.ipynb)\n", "[![image](https://mybinder.org/badge_logo.svg)](https://mybinder.org/v2/gh/opengeos/leafmap/HEAD)\n", "\n", "**Mapping Overture Buildings and Foursquare Places with Leafmap + Fused**\n", "\n", "Fetch data by calling [Fused UDFs](https://docs.fused.io/core-concepts/write/) and render it on a [Leafmap](https://leafmap.org/) map.\n", "\n", "This notebook shows how you can:\n", "\n", "1. Load [Overture Buildings](https://docs.overturemaps.org/getting-data/fused) for a drawn area\n", "2. Load [Foursquare (FSQ) Place](https://docs.foursquare.com/data-products/docs/access-fsq-os-places) POIs for a drawn area" ] }, { "cell_type": "code", "execution_count": null, "id": "1", "metadata": {}, "outputs": [], "source": [ "# %pip install fused>=1.11.1 \"leafmap[maplibre]\" -q" ] }, { "cell_type": "code", "execution_count": null, "id": "2", "metadata": {}, "outputs": [], "source": [ "import os\n", "import pandas as pd\n", "import geopandas as gpd\n", "from shapely.geometry import shape\n", "import fused\n", "import leafmap\n", "import leafmap.maplibregl as maplibre" ] }, { "cell_type": "markdown", "id": "3", "metadata": {}, "source": [ "## 1. Load Overture Buildings for drawn area\n", "\n", "First draw a bounding box over an area of interest (AOI) and create a GeoDataFrame with it. Then, [run the Overture UDF](https://docs.fused.io/core-concepts/run/) to fetch data for that AOI.\n", "\n", "### 1.1 First, draw an AOI" ] }, { "cell_type": "code", "execution_count": null, "id": "4", "metadata": {}, "outputs": [], "source": [ "m = leafmap.Map(center=[40.713370, -73.996181], zoom=14)\n", "m" ] }, { "cell_type": "code", "execution_count": null, "id": "5", "metadata": {}, "outputs": [], "source": [ "# If no AOI is drawn, use the default AOI\n", "\n", "if m.user_roi is None:\n", " m.user_roi = {\n", " \"type\": \"Feature\",\n", " \"properties\": {},\n", " \"geometry\": {\n", " \"type\": \"Polygon\",\n", " \"coordinates\": [\n", " [\n", " [-74.025621, 40.699967],\n", " [-74.025621, 40.730283],\n", " [-73.966055, 40.730283],\n", " [-73.966055, 40.699967],\n", " [-74.025621, 40.699967],\n", " ]\n", " ],\n", " },\n", " }" ] }, { "cell_type": "markdown", "id": "6", "metadata": {}, "source": [ "### 1.2 Then, convert it to a GeoDataFrame." ] }, { "cell_type": "code", "execution_count": null, "id": "7", "metadata": {}, "outputs": [], "source": [ "import geopandas as gpd\n", "\n", "# Convert drawing to GeoDataFrame\n", "gdf_drawing = gpd.GeoDataFrame(\n", " [m.user_roi[\"properties\"]], geometry=[shape(m.user_roi[\"geometry\"])]\n", ")\n", "\n", "gdf_drawing" ] }, { "cell_type": "markdown", "id": "8", "metadata": {}, "source": [ "### 1.3 Fetch Overture Buildings for the AOI and render them on the map\n", "\n", "The data comes from calling the \"[Overture Maps Example](https://www.fused.io/workbench/catalog/Overture_Maps_Example-64071fb8-2c96-4015-adb9-596c3bac6787)\" public UDF with `fused.run`." ] }, { "cell_type": "code", "execution_count": null, "id": "9", "metadata": {}, "outputs": [], "source": [ "# Fetch Overture Buildings GDF with Fused UDF\n", "gdf = fused.run(\"UDF_Overture_Maps_Example\", bbox=gdf_drawing)" ] }, { "cell_type": "code", "execution_count": null, "id": "10", "metadata": {}, "outputs": [], "source": [ "gdf.head()" ] }, { "cell_type": "code", "execution_count": null, "id": "11", "metadata": {}, "outputs": [], "source": [ "print(f\"The number of buildings within the AOI: {len(gdf)}\")" ] }, { "cell_type": "code", "execution_count": null, "id": "12", "metadata": {}, "outputs": [], "source": [ "# Add GDF to map\n", "m.add_gdf(\n", " gdf[[\"id\", \"geometry\", \"height\", \"class\"]],\n", " layer_type=\"fill\",\n", " name=\"Buildings\",\n", " fill_colors=[\"red\"],\n", ")" ] }, { "cell_type": "markdown", "id": "13", "metadata": {}, "source": [ "### 1.4 Visualize buildings in 3D." ] }, { "cell_type": "code", "execution_count": null, "id": "14", "metadata": {}, "outputs": [], "source": [ "m = maplibre.Map(pitch=60)\n", "m.add_basemap(\"USGS.USImagery\")\n", "gdf_filter = gdf[gdf.height > 0][[\"id\", \"geometry\", \"height\", \"class\"]]\n", "m.add_data(gdf_filter, column=\"height\", cmap=\"Blues\", extrude=True, name=\"Buildings\")\n", "m" ] }, { "cell_type": "code", "execution_count": null, "id": "15", "metadata": {}, "outputs": [], "source": [ "m.layer_interact()" ] }, { "cell_type": "markdown", "id": "16", "metadata": {}, "source": [ "## 2. Load FSQ Places POIs for drawn area\n", "\n", "### 2.1 Fetch FSQ Places for the AOI (defined above) and render them on the map\n", "\n", "The data comes from calling the \"[Foursquare Open Source Places](https://www.fused.io/workbench/catalog/Foursquare_Open_Source_Places-5cd75ead-e319-4279-8efc-04276de145bc)\" public UDF with `fused.run`." ] }, { "cell_type": "code", "execution_count": null, "id": "17", "metadata": {}, "outputs": [], "source": [ "# Fetch FSQ GDF with Fused UDF\n", "gdf = fused.run(\"UDF_Foursquare_Open_Source_Places\", bbox=gdf_drawing)\n", "\n", "# `add_points_from_xy` requires latitude and longitude columns\n", "gdf[\"latitude\"] = gdf.geometry.y\n", "gdf[\"longitude\"] = gdf.geometry.x\n", "\n", "# Show place categories\n", "set(gdf.level1_category_name.values)" ] }, { "cell_type": "code", "execution_count": null, "id": "18", "metadata": {}, "outputs": [], "source": [ "# Subsample the gdf\n", "gdf_sample = (\n", " gdf[[\"name\", \"latitude\", \"longitude\", \"geometry\"]].head(200).reset_index(drop=True)\n", ")\n", "# gdf_sample = gdf[gdf.level1_category_name == 'Dining and Drinking'][['name', 'latitude', 'longitude']].head(1000).reset_index(drop=True)\n", "gdf_sample" ] }, { "cell_type": "markdown", "id": "19", "metadata": {}, "source": [ "### 2.2 Visualize the POIs on a 2d map" ] }, { "cell_type": "code", "execution_count": null, "id": "20", "metadata": {}, "outputs": [], "source": [ "m = leafmap.Map(center=[40.713370, -73.996181], zoom=14)\n", "# Add as marker cluster\n", "m.add_points_from_xy(\n", " gdf_sample,\n", " x=\"longitude\",\n", " y=\"latitude\",\n", " spin=False,\n", " add_legend=True,\n", ")\n", "m" ] }, { "cell_type": "markdown", "id": "21", "metadata": {}, "source": [ "### 2.3 Visualize POIs with OpenStreetMap vector tiles" ] }, { "cell_type": "code", "execution_count": null, "id": "22", "metadata": {}, "outputs": [], "source": [ "m = maplibre.Map(pitch=60, style=\"https://maps.gishub.org/styles/openstreetmap.json\")\n", "m.add_gdf(gdf_sample, name=\"Places\")\n", "m" ] }, { "cell_type": "markdown", "id": "23", "metadata": {}, "source": [ "### 2.4 Visualize the POIs on a 3D map with Overture buildings" ] }, { "cell_type": "code", "execution_count": null, "id": "24", "metadata": {}, "outputs": [], "source": [ "m = maplibre.Map(zoom=18, pitch=60, style=\"positron\")\n", "m.add_overture_3d_buildings()\n", "m.add_gdf(gdf_sample, name=\"Places\")\n", "m" ] }, { "cell_type": "markdown", "id": "25", "metadata": {}, "source": [ "### 2.5 Visualize the POIs on a 3D map with [OpenFreeMap](https://openfreemap.org/) vector tiles" ] }, { "cell_type": "code", "execution_count": null, "id": "26", "metadata": {}, "outputs": [], "source": [ "m = maplibre.Map(pitch=60, style=\"liberty\")\n", "m.add_gdf(gdf_sample, name=\"Places\")\n", "m" ] } ], "metadata": { "kernelspec": { "display_name": "Python 3 (ipykernel)", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.11.8" } }, "nbformat": 4, "nbformat_minor": 5 }