Household surveys, agricultural censuses, and ground-truth campaigns rely on high-resolution satellite imagery to delineate Enumeration Areas (EAs), verify building footprints, and guide field enumerators to sampled structures.
vantorr provides a dedicated suite of fieldwork functions that turn Vantor / Maxar satellite basemaps and seamline metadata into ready-to-use survey resources:
vantor_survey_grid(): Partition an Area of Interest (AOI) into square or hexagonal survey index cells labeled "A1", "A2", "B1", etc.vantor_vintage_report(): Audit the acquisition dates (acq_time), resolution (gsd), and sensor quality of Vantor basemap strips across each Enumeration Area to flag outdated imagery before deploying field teams.vantor_plus_code() & vantor_export_capi(): Enrich sample points with offline-capable Open Location Codes (Google Plus Codes), grid cell assignments (cell_id), and imagery acquisition dates (imagery_acq_date), and export platform-specific preload files:
.csv) & GeoJSON (.geojson) with odk_geopoint ("lat lon 0 0") for ODK Collect, KoboToolbox, and ArcGIS Survey123..tab) assignment preload tables (output_suso_tab) with <gps_var>__Latitude, <gps_var>__Longitude, and _target_area for World Bank Survey Solutions (or direct programmatic assignment creation via the SurveySolutionsAPIv2 R package).vantor_field_atlas(): Generate a multi-page printable PDF Field Atlas (Map Book) featuring an Overview Index sheet and zoomed-in Enumeration Area detail sheets with Vantor satellite imagery, scale bars, north arrows, and enumerator sign-off footers.vantor_offline_package() & vantor_write_tpk(): Bundle vector layers (.gpkg, zipped .shp), CAPI preload tables (.csv and Survey Solutions .tab), georeferenced Web Mercator basemaps (.tif), and multi-zoom Esri Tile Packages (.tpk / .tpkx and clean _tpk.zip upload archives) into a portable directory for offline tablet apps (World Bank Survey Solutions, QField, Mergin Maps, ArcGIS Field Maps). See vignette("survey-solutions-workflow", package = "vantorr") for the dedicated Survey Solutions & SurveySolutionsAPIv2 guide.Start by defining your survey Area of Interest (using any sf, terra, or stars object, or a WGS84 bounding box) and partitioning it into a metric enumeration grid with vantor_survey_grid():
library(vantorr)
library(sf)
#> Warning: package 'sf' was built under R version 4.3.3
#> Linking to GEOS 3.13.0, GDAL 3.8.5, PROJ 9.5.1; sf_use_s2() is TRUE
# Define a 1.5 km x 1.5 km survey Area of Interest in WGS84 (EPSG:4326)
aoi <- st_bbox(
c(xmin = -105.010, ymin = 39.730, xmax = -104.995, ymax = 39.742),
crs = st_crs(4326)
)
# Generate a 500 m square survey grid with alphanumeric labels (A1, A2, B1, ...)
survey_grid <- vantor_survey_grid(
aoi = aoi,
cell_size = 500,
shape = "square",
verbose = FALSE
)
survey_grid[, c("cell_id", "row_idx", "col_idx", "centroid_lon", "centroid_lat", "area_m2")]
#> Simple feature collection with 16 features and 6 fields
#> Geometry type: POLYGON
#> Dimension: XY
#> Bounding box: xmin: -105.01 ymin: 39.73 xmax: -104.992 ymax: 39.74382
#> Geodetic CRS: WGS 84
#> First 10 features:
#> cell_id row_idx col_idx centroid_lon centroid_lat area_m2
#> 1 A1 1 1 -105.0078 39.74209 250000
#> 2 A2 1 2 -105.0033 39.74209 250000
#> 3 A3 1 3 -104.9988 39.74209 250000
#> 4 A4 1 4 -104.9943 39.74209 250000
#> 5 B1 2 1 -105.0078 39.73864 250000
#> 6 B2 2 2 -105.0033 39.73864 250000
#> 7 B3 2 3 -104.9988 39.73864 250000
#> 8 B4 2 4 -104.9943 39.73864 250000
#> 9 C1 3 1 -105.0078 39.73518 250000
#> 10 C2 3 2 -105.0033 39.73518 250000
#> geometry
#> 1 POLYGON ((-105.01 39.74036,...
#> 2 POLYGON ((-105.0055 39.7403...
#> 3 POLYGON ((-105.001 39.74036...
#> 4 POLYGON ((-104.9965 39.7403...
#> 5 POLYGON ((-105.01 39.73691,...
#> 6 POLYGON ((-105.0055 39.7369...
#> 7 POLYGON ((-105.001 39.73691...
#> 8 POLYGON ((-104.9965 39.7369...
#> 9 POLYGON ((-105.01 39.73345,...
#> 10 POLYGON ((-105.0055 39.7334...
You can also generate hexagonal tessellations for spatial cluster sampling by setting shape = "hexagonal":
hex_grid <- vantor_survey_grid(
aoi = aoi,
cell_size = 500,
shape = "hexagonal",
verbose = FALSE
)
When using satellite imagery to list households or sample structures, survey managers need to know whether the mosaic over each Enumeration Area is recent or several years old.
vantor_vintage_report() intersects your survey_grid (or Enumeration Area polygons) with Vantor’s OGC WFS Seamlines metadata (vantor_get_seamlines()) and calculates per-cell vintage metrics, flagging any cells where the imagery is older than max_age_days (default 730 days / 2 years):
# In an online session with Vantor credentials, seamlines are fetched automatically:
# vintage_grid <- vantor_vintage_report(survey_grid, product = "VIVID_STANDARD_30")
# Offline demonstration using synthetic seamline polygons:
bb_mid <- -105.0025
strip_west <- st_bbox(c(xmin = -105.012, ymin = 39.728, xmax = bb_mid, ymax = 39.745), crs = st_crs(4326))
strip_east <- st_bbox(c(xmin = bb_mid, ymin = 39.728, xmax = -104.990, ymax = 39.745), crs = st_crs(4326))
mock_seamlines <- st_sf(
acq_time = c("2025-08-14T17:45:00Z", "2021-03-20T18:10:00Z"),
gsd = c(0.30, 0.31),
ona = c(10.2, 18.5),
sensor = c("WV03", "WV02"),
catid = c("10400100AA11", "10300100BB22"),
geometry = c(st_as_sfc(strip_west), st_as_sfc(strip_east))
)
vintage_grid <- vantor_vintage_report(
aoi = survey_grid,
seamlines = mock_seamlines,
max_age_days = 730,
reference_date = as.Date("2026-10-15"),
verbose = FALSE
)
st_drop_geometry(vintage_grid)[, c(
"cell_id", "n_strips", "earliest_acq_date", "latest_acq_date",
"max_age_days", "sensors", "vintage_warning"
)]
#> cell_id n_strips earliest_acq_date latest_acq_date max_age_days sensors
#> 1 A1 1 2025-08-14 2025-08-14 427 WV03
#> 2 A2 2 2021-03-20 2025-08-14 2035 WV03, WV02
#> 3 A3 1 2021-03-20 2021-03-20 2035 WV02
#> 4 A4 1 2021-03-20 2021-03-20 2035 WV02
#> 5 B1 1 2025-08-14 2025-08-14 427 WV03
#> 6 B2 2 2021-03-20 2025-08-14 2035 WV03, WV02
#> 7 B3 1 2021-03-20 2021-03-20 2035 WV02
#> 8 B4 1 2021-03-20 2021-03-20 2035 WV02
#> 9 C1 1 2025-08-14 2025-08-14 427 WV03
#> 10 C2 2 2021-03-20 2025-08-14 2035 WV03, WV02
#> 11 C3 1 2021-03-20 2021-03-20 2035 WV02
#> 12 C4 1 2021-03-20 2021-03-20 2035 WV02
#> 13 D1 1 2025-08-14 2025-08-14 427 WV03
#> 14 D2 2 2021-03-20 2025-08-14 2035 WV03, WV02
#> 15 D3 1 2021-03-20 2021-03-20 2035 WV02
#> 16 D4 1 2021-03-20 2021-03-20 2035 WV02
#> vintage_warning
#> 1 FALSE
#> 2 TRUE
#> 3 TRUE
#> 4 TRUE
#> 5 FALSE
#> 6 TRUE
#> 7 TRUE
#> 8 TRUE
#> 9 FALSE
#> 10 TRUE
#> 11 TRUE
#> 12 TRUE
#> 13 FALSE
#> 14 TRUE
#> 15 TRUE
#> 16 TRUE
Once household or cluster sample points are selected within your Enumeration Areas, vantor_export_capi() enriches them with coordinates, ODK / Kobo geopoint strings, offline Google Plus Codes (vantor_plus_code()), one-click Google Maps navigation links, grid cell assignments (cell_id), and imagery acquisition dates (imagery_acq_date).
Because different CAPI platforms expect different preload schemas, vantor_export_capi() supports three simultaneous export targets:
output_csv & output_geojson: Standard CSV and GeoJSON files containing odk_geopoint ("lat lon 0 0") for pulldata() in ODK Collect, KoboToolbox, and ArcGIS Survey123.output_suso_tab (suso_gps_var = "hh_gps"): A tab-delimited (.tab) assignment preload file formatted specifically for World Bank Survey Solutions Headquarters (Survey Setup -> Questionnaires -> Upload Assignments). It automatically splits coordinates into <suso_gps_var>__Latitude and <suso_gps_var>__Longitude so preloaded households appear as interactive pins on the Interviewer tablet’s Map Dashboard, sets _target_area from cell_id, and includes plus_code and imagery_acq_date for cover-page display.# Create sample household locations across the AOI
sample_pts <- st_as_sf(
data.frame(
hh_id = c("HH-101", "HH-102", "HH-103", "HH-104"),
head_name = c("Household A", "Household B", "Household C", "Household D"),
lon = c(-105.008, -105.004, -105.001, -104.997),
lat = c(39.739, 39.738, 39.734, 39.733)
),
coords = c("lon", "lat"),
crs = 4326
)
# Enrich samples and export to ODK CSV, GeoJSON, and Survey Solutions .tab
csv_file <- tempfile(pattern = "odk_preload_", fileext = ".csv")
geojson_file <- tempfile(pattern = "field_samples_", fileext = ".geojson")
suso_tab_file <- tempfile(pattern = "suso_preload_", fileext = ".tab")
capi_samples <- vantor_export_capi(
samples = sample_pts,
id_col = "hh_id",
grid = vintage_grid,
seamlines = mock_seamlines,
output_csv = csv_file,
output_geojson = geojson_file,
output_suso_tab = suso_tab_file,
suso_gps_var = "hh_gps",
verbose = FALSE
)
st_drop_geometry(capi_samples)[, c(
"sample_id", "cell_id", "plus_code",
"hh_gps__Latitude", "hh_gps__Longitude",
"imagery_acq_date", "imagery_sensor"
)]
#> sample_id cell_id plus_code hh_gps__Latitude hh_gps__Longitude
#> 1 HH-101 B1 85FPPXQR+JR 39.739 -105.008
#> 2 HH-102 B2 85FPPXQW+6C 39.738 -105.004
#> 3 HH-103 C3 85FPPXMX+JJ 39.734 -105.001
#> 4 HH-104 D3 85FQP2M3+66 39.733 -104.997
#> imagery_acq_date imagery_sensor
#> 1 2025-08-14 WV03
#> 2 2025-08-14 WV03
#> 3 2021-03-20 WV02
#> 4 2021-03-20 WV02
Inspecting the generated Survey Solutions .tab file confirms that it contains the exact <gps_var>__Latitude, <gps_var>__Longitude, and _target_area columns required by Survey Solutions Headquarters:
read.delim(suso_tab_file, check.names = FALSE)[, c(
"sample_id", "cell_id", "plus_code",
"hh_gps__Latitude", "hh_gps__Longitude",
"_target_area"
)]
#> sample_id cell_id plus_code hh_gps__Latitude hh_gps__Longitude _target_area
#> 1 HH-101 B1 85FPPXQR+JR 39.739 -105.008 B1
#> 2 HH-102 B2 85FPPXQW+6C 39.738 -105.004 B2
#> 3 HH-103 C3 85FPPXMX+JJ 39.734 -105.001 C3
#> 4 HH-104 D3 85FQP2M3+66 39.733 -104.997 D3
Enumerators can type the preloaded plus_code (e.g., 85FPPXQR+JR) from the interview cover page directly into Google Maps or OSM on a mobile tablet to get turn-by-turn routing to the sampled structure completely offline, then switch to the offline Vantor .tpk basemap for the final 100 meters.
For paper back-up maps and field supervisor binders, vantor_field_atlas() generates a multi-page PDF Map Book containing:
A1, A2, …), and all sample locations.buffer_m = 50), metric scale bar, north arrow, sample point labels, imagery vintage date, and a field notes sign-off line.atlas_pdf <- tempfile(pattern = "vantor_atlas_", fileext = ".pdf")
vantor_field_atlas(
grid = vintage_grid,
points = capi_samples,
output_file = atlas_pdf,
title = "Denver Survey Enumeration Atlas",
buffer_m = 50,
fetch_basemap = FALSE, # Set fetch_basemap = TRUE when authenticated to embed Vantor RGB imagery
verbose = FALSE
)
file.exists(atlas_pdf)
#> [1] TRUE
When authenticated with Vantor (vantor_has_auth()), simply set fetch_basemap = TRUE (or pass a pre-downloaded SpatRaster via raster = ...) to render the 30 cm or 15 cm Vantor Vivid RGB satellite basemap underneath every page of the PDF atlas:
vantor_field_atlas(
grid = vintage_grid,
points = capi_samples,
output_file = "denver_field_atlas.pdf",
fetch_basemap = TRUE,
resolution = 0.3,
product = "VIVID_STANDARD_30"
)
vantor_offline_package() & vantor_write_tpk())To deploy your survey grid, CAPI sample points, seamline vintage polygons, and georeferenced Vantor satellite imagery to mobile CAPI and GIS apps—including World Bank Survey Solutions (v24.09+ built on the ArcGIS Maps SDK for .NET v200.x), QField, Mergin Maps, and ArcGIS Field Maps—use vantor_offline_package() and vantor_write_tpk():
.tpk / .tpkx) and Clean Upload Archives (_tpk.zip): vantor_write_tpk() builds multi-zoom Web Mercator (EPSG:3857 / Esri WKID: 102100) tile pyramids in pure R without requiring proprietary ArcGIS software or ArcGIS Online credits. Setting zip_for_suso = TRUE also creates a <stem>_tpk.zip archive stripped of macOS __MACOSX/._* resource forks for direct upload to Survey Solutions Headquarters (Survey Setup -> Maps)._shapes.zip): Setting create_shapefiles = TRUE exports Enumeration Area grid cells and sample points as EPSG:4326 Shapefiles (including a label attribute column for automatic feature labeling in Survey Solutions) zipped at the archive root..tab Preload (_suso_preload.tab) & ODK .csv (_samples.csv): Automatically generated whenever samples is supplied..tif): Any included raster basemap is automatically reprojected to EPSG:3857 so Survey Solutions’ Esri RasterLayer engine renders it accurately.bundle <- vantor_offline_package(
grid = vintage_grid,
samples = capi_samples,
seamlines = mock_seamlines,
create_shapefiles = TRUE, # Zipped Shapefiles for Survey Solutions HQ
fetch_basemap = FALSE, # Set TRUE to download and include the GeoTIFF basemap
package_name = "denver_survey_ea",
verbose = FALSE
)
# Inspect the generated multi-layer GeoPackage, ODK CSV, Survey Solutions .tab, and Shapefile ZIP
bundle$layers
#> [1] "survey_grid" "survey_samples" "imagery_seamlines"
basename(c(bundle$gpkg_path, bundle$csv_path, bundle$suso_tab_path, bundle$shapefile_zip_path))
#> [1] "denver_survey_ea.gpkg" "denver_survey_ea_samples.csv"
#> [3] "denver_survey_ea_suso_preload.tab" "denver_survey_ea_shapes.zip"
st_layers(bundle$gpkg_path)
#> Driver: GPKG
#> Available layers:
#> layer_name geometry_type features fields crs_name
#> 1 survey_grid Polygon 16 15 WGS 84
#> 2 survey_samples Point 4 11 WGS 84
#> 3 imagery_seamlines Polygon 2 5 WGS 84
To generate a standalone multi-zoom .tpk (and clean _tpk.zip upload archive) directly from Vantor WMS imagery or an existing terra::SpatRaster:
# Online: fetch zoom levels 15-17 directly from Vantor WMS into a .tpk + _tpk.zip
vantor_write_tpk(
x = vintage_grid,
output_file = "denver_ea_basemap.tpk",
zoom = 15:17,
product = "VIVID_STANDARD_30",
zip_for_suso = TRUE
)
For a step-by-step guide covering Survey Solutions Headquarters upload requirements, WKID: 102100 coordinate conventions, .tab preloading, and automated server upload & assignment creation using the SurveySolutionsAPIv2 R package, see vignette("survey-solutions-workflow", package = "vantorr").