gloBFPr logo

Access and analyze the Building Footprint Datasets.

Overview

The gloBFPr package allows R users to search, download, and process global building footprint tiles with associated height information, derived from the 3D-GloBFP dataset published by Che et al. (2024, 2025) and GlobalBuildingAtlas dataset by Zhu et al. (2025). With the building data, users can compute complex metrics of urban morphology and simulate urban environments about thermal and acoustic conditions. The package will look to include more global Building Dataset in the future.

Map and 3D visualization examples from gloBFPr

Features

Installation

Install the development version:

# Install devtools if needed
install.packages("devtools")

# Install from GitHub
devtools::install_github("billbillbilly/gloBFPr@dev")

The package will be on CRAN soon.

External software

Two gloBFPr workflows call out to external command-line software rather than bundling it as an R dependency. Both are optional — only install what you need.

OpenFOAM (via Docker)

prepare_foam_case() + run_openfoam_docker() run pedestrian-level wind simulations with OpenFOAM inside a Docker container, so no local OpenFOAM install is required. The current development workflow uses buoyantBoussinesqPimpleFoam with URANS kOmegaSST for wind cases.

  1. Install Docker Desktop (macOS/Windows) or Docker Engine (Linux), and make sure it is running.
  2. No image pull step is needed — run_openfoam_docker() pulls the default image (opencfd/openfoam-run:2506) automatically on first use. To pre-pull it yourself: docker pull opencfd/openfoam-run:2506.
  3. macOS only: Docker Desktop shares /Users, /Volumes, and /tmp by default. Put your case directory somewhere under your home folder (e.g. prepare_foam_case(case_dir = "~/openfoam_demo", ...)) rather than tempdir()//var/folders, which Docker cannot see. If you get a "No such file or directory" or empty-mount error, add the case directory under Docker Desktop → Settings → Resources → File Sharing, then Apply & Restart.
  4. Verify Docker is reachable before running a case: docker info.

NoiseModelling

get_noise_map(x = buildings, run = TRUE) (and prepare_noisemodelling_inputs() with run = TRUE) runs the official NoiseModelling headless WPS scripts, a separate GPL-3-licensed Java application (gloBFPr itself remains MIT-licensed; NoiseModelling is only invoked, not bundled).

  1. Install Java 11–21 (Java 17 recommended) and make sure it is on PATH or set as JAVA_HOME, or pass a specific installation via the java argument.
  2. You do not need to install NoiseModelling yourself: if no local copy is found, get_noise_map() downloads the official headless runner (default version 5.0.1) into an R user cache directory the first time it is needed.
  3. To install it ahead of time, or reuse an existing install, call install_noisemodelling() directly, or point gloBFPr at an existing copy with options(gloBFPr.noisemodelling.path = "/path/to/NoiseModelling_without_gui-5.0.1") or the NOISEMODELLING_HOME environment variable.

API keys

Two functions groups require a free API key from a third-party data provider. Everything else in the package (footprint search/download, morphology, block analysis, NoiseModelling, OpenFOAM) works without any key.

OpenTopography (elevation data)

Required by any function that downloads a digital elevation model: get_bgvi(), svf(), get_shadow_footprint(), get_shadow_height(), get_radiation(), get_fused_dsm(), get_3d_world(terrain = TRUE), and the opentopo_key argument of prepare_openfoam_inputs(), get_noise_map(), and prepare_noisemodelling_inputs().

  1. Register for a free account and request an API key at https://portal.opentopography.org/requestService?service=api.
  2. Pass the key directly via each function's key/opentopo_key argument, e.g. get_bgvi(buildings, key = "YOUR_KEY").
  3. The USGS 3DEP 1 m/10 m dataset is currently restricted to academic accounts. Non-academic users can request an enterprise key by emailing info@opentopography.org. See OpenTopography's Terms of Use for appropriate use of the API.

You can avoid needing a key for get_3d_world() by setting terrain = FALSE (flat ground), or by supplying a pre-loaded dem/canopy_height raster (e.g. the bundled globfp_example_dem) instead of downloading one.

Copernicus Climate Data Store (ERA5 weather data)

Required by get_era5_met(), which fetches ERA5 reanalysis wind/temperature data as boundary conditions for prepare_foam_case().

  1. Register for a free account at https://cds.climate.copernicus.eu.
  2. Copy your personal access token from your CDS user profile page.
  3. Set it once per session with Sys.setenv(CDS_API_KEY = "your-token-here"), or store it in ~/.Renviron so it loads automatically, or pass it directly via get_era5_met(cds_key = "your-token-here").
  4. Accept the ERA5 dataset licence (one time, in a browser) — see below. Without this, requests fail with a 403 permission denied even though the token is valid.

This requires the ecmwfr package (install.packages("ecmwfr")), which get_era5_met() uses to submit the CDS request. Version 2.0.0 or later is needed: the legacy CDS was retired in 2024 and older ecmwfr versions cannot authenticate with current tokens.

Accepting the ERA5 licence

CDS gates every dataset behind a per-account licence acceptance that the API cannot perform for you. This is the single most common setup failure.

  1. Open https://cds.climate.copernicus.eu/datasets/reanalysis-era5-single-levels?tab=download#manage-licences
  2. Scroll to the bottom of the page, past the variable and date selectors, to "Terms of use".
  3. Accept the listed licences (typically the Copernicus licence and an ERA5-specific one).
  4. Re-run get_era5_met().

The symptom if you skip this:

Error: permission denied ... required licences not accepted ... 403

Which variables are requested

You do not need to tick any checkboxes on the CDS download form — those only build a manual download, and the web UI selection is ignored by the API. get_era5_met() specifies its own variables in the request:

CDS field Value Used for
Product type Reanalysis —
Variable 10m_u_component_of_wind inlet_velocity[1] (eastward, m/s)
Variable 10m_v_component_of_wind inlet_velocity[2] (northward, m/s)
Variable 2m_temperature T_ref (ambient air temperature, K)
Variable skin_temperature optional T_skin ground-temperature estimate (K)

Note that skin_temperature is not in the form's "Popular" block; it appears under "Temperature and pressure". Again, this matters only if you are downloading manually.

Notes on ERA5 data

Usage

  1. Load
library(gloBFPr)
  1. Search and download data by bounding box
bbox <- c(-83.065644,42.333792,-83.045217,42.346988)
buildings_list <- search_3dglobdf(bbox = bbox, 
                                  out_type = "all", 
                                  # mask = TRUE,
                                  cell_size = 1)

This will return a list containing: - poly: an sf object of 3D building footprints - binary: a binary raster of building presence - graduated: a raster representing building height in meters

Specify cell_size = 1 to generate raster layers with 1-meter resolution, ensuring detailed spatial representation of building geometries within the defined area of interest.

Setting mask = TRUE ensures the height raster is masked by the building footprints.

Output examples:

Building footprint polygons         Building height polygons

Binary building footprint raster         Building height raster         Cropped building height raster

  1. Calculate metrics
Categories Metrics Code Concept
Morphology Ground area g_area Horizontal footprint area of the building
Perimeter pmeter Total boundary length of the footprint
Vertical surface v_surf Estimated surface area of building walls
Total surface t_surf Sum of vertical surface and ground area
Volume vol Approximate building volume (area × height)
Object-oriented bounding box volume obb_vol Volume of the smallest rotated bounding box containing the building
Perimeter-area ratio pa_ratio Indicator of compactness and shape irregularity
Rectangularity rec Ratio of area to its minimum bounding rectangle
Fractality fra Complexity of surface based on volume-to-surface ratio
Hemisphericality hem Deviation from ideal hemisphere volume
Convexity cnv Ratio of footprint area to its convex hull area
Cuboidness cbn Degree to which the object resembles a cuboid
Mean Euclidean distance to centroid me_dist Average distance from footprint vertices to centroid
Mean pairwise distance mp_dist Average distance between all footprint vertex pairs
Volume exchange ratio vol_exch Volume-to-surface ratio indicating massiveness
Elongation ratio on X direction elo_x Shortest horizontal extent divided by height
Elongation ratio on Y direction elo_y Longest horizontal extent divided by height
Elongation ratio on Z direction elo_z Height relative to the maximum horizontal extent
Neighbor Number of adjacent buildings n_count Count of nearby buildings based on proximity and Voronoi adjacency
Mean distance from the building m_ndist Average distance to neighboring buildings
Minimum distance from the building min_ndist Closest neighboring building distance
Maximum distance from the building max_ndist Farthest neighboring building distance
Standard deviation of distances sd_ndist Variation in distances to neighboring buildings
Greenery Distance to the nearest green space dng Distance from building centroid to closest vegetation pixel, in a straight line or along the real street network (network = "osm")
Distance measure used dng_method Whether dng was measured along the street network or fell back to a straight line
Mean Green View Index (GVI) mean_gvi Average proportion of visible greenery in viewshed
Bottom Green View Index (GVI) bottom_gvi GVI from the bottom viewpoint, 1.7 m above ground
Top Green View Index (GVI) top_gvi GVI from the top viewpoint; equals bottom GVI for short buildings
Minimum of Green View Index (GVI) min_gvi Lowest GVI across all floor viewpoints (if floor = TRUE)
Maximum of GVI max_gvi Highest GVI across all floor viewpoints (if floor = TRUE)
Standard deviation of GVI sd_gvi Variation in greenery visibility across building height (if floor = TRUE)
Estimated floors estimated_floors Estimated number of floors based on building height (if floor = TRUE)
  1. Simulate urban environments

Wind flow with OpenFOAM

The current development workflow writes terrain-aware, canopy-aware wind cases for OpenFOAM and runs them through Docker.

Textured mesh 3D export from gloBFPr
data(globfp_example)
buildings_list <- list(poly = globfp_example, binary = NULL, graduated = NULL)

foam_inputs <- prepare_openfoam_inputs(
  case_dir          = file.path(path.expand("~"), "openfoam_demo"),
  buildings_list    = buildings_list,
  height_col        = "Height",
  include_buildings = TRUE,
  overwrite         = TRUE
)

case_files <- prepare_foam_case(
  case_dir       = foam_inputs$case_dir,
  stl_file       = foam_inputs$files$building_stl,
  domain         = foam_inputs$domain,
  inlet_velocity = c(5, 0, 0),
  z_ref          = 10,
  base_cell_size = 5,
  sim_hours      = 0.5,
  overwrite      = TRUE
)

run_openfoam_docker(foam_inputs$case_dir, wait = TRUE)
wind_map <- read_foam_pedestrian_slice(foam_inputs$case_dir, resolution = 2)
plot_foam_map(wind_map, layer = "U_mag", legend_title = "Speed (m/s)")

Use get_era5_met() when you want ERA5 wind and temperature boundary conditions, and prepare_foam_geometry() when you want DEM-derived terrain and canopy drag included in the case geometry.

Road-noise mapping

get_noise_map() prepares building, road, ground-effect, receiver, and optional barrier layers for NoiseModelling. With run = TRUE, it can also launch the headless NoiseModelling workflow.

Textured mesh 3D export from gloBFPr
noise <- get_noise_map(
  x        = buildings_list$poly,
  run      = FALSE,
  out_dir  = file.path(tempdir(), "noise_demo"),
  receiver_spacing = 10
)

plot_noise_map(noise)
  1. 3D reconstruction
Textured mesh 3D export from gloBFPrVoxel 3D export from gloBFPr
library(gloBFPr)

data(globfp_example)
buildings <- globfp_example

data(globfp_example_dem)
data(globfp_example_canopy_height)

world <- get_3d_world(
  x              = buildings,
  terrain        = TRUE,
  dem            = rast(globfp_example_dem),
  canopy_height  = rast(globfp_example_canopy_height),
  canopy         = NULL,
  roads          = "overture",
  water          = "overture",
  greenspace     = TRUE,
  basemap        = TRUE,
  facade_palette = TRUE,
  out_dir        = file.path(tempdir(), "world_textured"),
  quiet          = FALSE
)

world_vox <- get_3d_world(
  x              = buildings,
  terrain        = TRUE,
  dem            = rast(globfp_example_dem),
  canopy_height  = rast(globfp_example_canopy_height),
  canopy         = NULL,
  roads          = "overture",
  water          = "overture",
  greenspace     = TRUE,
  facade_palette = TRUE,
  all_vox        = TRUE,
  vox_size       = 1,
  out_dir        = file.path(tempdir(), "world_vox")
)

Note

The downloading process may take some time, depending on the number and size of building footprint tiles.

This implementation relies on the current structure of the dataset as hosted on Figshare. It may break if the dataset owner changes the file organization or metadata format.

Please read the function documentation carefully. The dataset may require proper citation when used.

Noise preparation functions use OSM road class to infer default traffic speeds and vehicle volumes when observed traffic counts are unavailable. These defaults are intended for screening-level or scenario-based analysis and should be replaced with local traffic observations for calibrated noise maps.

To run the integrated NoiseModelling workflow, call get_noise_map(x = buildings, run = TRUE). Roads are downloaded from OSM using the building extent unless a road layer is supplied, and greenspace can be retrieved with datasource_greenspace. See External software for how to set up Java and NoiseModelling (and OpenFOAM, for the wind workflow).

Other similar approaches

Issues and bugs

If you discover a bug not associated with connection to the API that is not already a reported issue, please open a new issue providing a reproducible example.