Access and analyze the Building Footprint Datasets.
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.

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.
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.
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.
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./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.docker info.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).
PATH or set as JAVA_HOME, or pass a specific installation via the java argument.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.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.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.
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().
key/opentopo_key argument, e.g. get_bgvi(buildings, key = "YOUR_KEY").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.
Required by get_era5_met(), which fetches ERA5 reanalysis wind/temperature data as boundary conditions for prepare_foam_case().
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").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.
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.
get_era5_met().The symptom if you skip this:
Error: permission denied ... required licences not accepted ... 403
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.
get_era5_met() blocks while polling, so it may appear to hang when it is only waiting.cache_dir (default tempdir()), so repeated calls for the same location and hour are instant.datetime is interpreted as UTC and rounded to the nearest full hour.library(gloBFPr)
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.


| 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) |
The current development workflow writes terrain-aware, canopy-aware wind cases for OpenFOAM and runs them through Docker.

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.
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.

noise <- get_noise_map(
x = buildings_list$poly,
run = FALSE,
out_dir = file.path(tempdir(), "noise_demo"),
receiver_spacing = 10
)
plot_noise_map(noise)


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")
)
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).
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.