ArcGIS REST API’s may be spatially queried using the get_layer_by_*
family of functions. These functions require a spatial object of class
sf
(i.e. of the R package sf: Simple Features for R)
and a Spatial
Relationship to be passed to the geometry and sp_rel
arguments respectively.
The package contains five functions that can be used to perform spatial queries:
get_layer_by_line
get_layer_by_point
get_layer_by_polygon
get_layer_by_multipoint
get_layer_by_envelope
#WDNR Server
server <- "https://dnrmaps.wi.gov/arcgis/rest/services/"
server2 <- "https://dnrmaps.wi.gov/arcgis2/rest/services/"
#River URL
layer <- "TS_AGOL_STAGING_SERVICES/EN_AGOL_STAGING_SurfaceWater_WTM/MapServer/2"
river_url <- paste0(server2,layer)
#Country URL
layer <- "DW_Map_Dynamic/EN_Basic_Basemap_WTM_Ext_Dynamic_L16/MapServer/3"
county_url <- paste0(server,layer)
#Trout URL
layer <- "FM_Trout/FM_TROUT_HAB_SITES_WTM_Ext/MapServer/0"
trout_url <- paste0(server,layer)
#Watershed URL
layer <- "WT_SWDV/WT_Federal_Hydrologic_Units_WTM_Ext/MapServer/0"
watershed_url <- paste0(server,layer)
#get layers for queries
mke_river <- get_spatial_layer(
river_url,
where = "RIVER_SYS_NAME = 'Milwaukee River'"
)
trout_hab_project_pts <- get_spatial_layer(
trout_url,
where = "WATERBODYNAMECOMBINED = 'Sugar Creek' and FISCALYEAR = 2017"
)
trout_hab_project_pt <- trout_hab_project_pts[1, ]
# get watershed layer for Cook Creek
cook_creek_ws <- get_spatial_layer(
watershed_url,
where = "HUC12_NAME = 'Cook Creek'"
)
The get_layer_by_line
function uses A LINSESTRING or
MULTILINESTRING sf object to query an ArcGIS REST API. The below example
uses a MULTILINESTRING sf object of the Milwaukee River to query the
Wisconsin County polygon layer.
mke_river_counties <- get_layer_by_line(url = county_url, geometry = mke_river)
plot_layer(mke_river, outline_poly = mke_river_counties)
The get_layer_by_line
function uses a POINT sf object to
query an ArcGIS REST API. The below example shows how this can be used
to return which rivers intersect with a trout habitat project on Sugar
Creek in southeast Wisconsin.
trout_stream <- get_layer_by_point(url = river_url, geometry = trout_hab_project_pt)
plot_layer(trout_stream) +
ggplot2::geom_sf(data = trout_hab_project_pt, color = "red", size = 2)
get_layer_by_point
can also handle multipoint objects.
This example shows the same stream as above with a single point, but now
with multiple restoration points.
restored_streams <- get_layer_by_point(url = river_url, geometry = trout_hab_project_pts)
plot_layer(restored_streams) +
ggplot2::geom_sf(data = trout_hab_project_pts, color = "blue")
The get_layer_by_line
function uses a POLYGON sf object
to query an ArcGIS REST API. The below examples shows how this can be
used to find what rivers are within a particular watershed.
cook_creek_streams <- `get_layer_by_poly(river_url, cook_creek_ws)
plot_layer(cook_creek_streams, cook_creek_ws)
The get_layer_by_envelope
function accepts any sf object
to query an ArcGIS REST API using the sf objects bounding box. The below
example shows how this is used to query WI’s Rivers ArcGIS REST API
using a sf POLYGON object of a watershed for a small stream. Note how
the results compare to when this same object is queried using the
get_layer_by_poly
function.
cook_creek_env <- get_layer_by_envelope(river_url, cook_creek_ws)
# example of the envelope to visualize how it spatially queries
example_env <- sf::st_as_sfc(sf::st_bbox(cook_creek_ws))
plot_layer(cook_creek_env, cook_creek_ws) +
ggplot2::geom_sf(data = example_env, fill = NA)
Spatial queries can be combined with SQL statements to further refine queries.
The sp_rel
argument can be used to define the spatial
relationship between the two feature classes involved within a spatial
query. The default spatial relationships for the
get_layer_by_poly
function is “contains”. All other
functions default to “intersects”.
example_poly <- sf_polygon(
c(-90.62, 43.76),
c(-90.62, 43.77),
c(-90.61, 43.77),
c(-90.61, 43.76),
c(-90.62, 43.76)
)
poly_streams_contains <- get_layer_by_poly(river_url, example_poly)
plot_layer(poly_streams_contains, outline_poly = example_poly)
Using “crosses” returns different records compared to the above example (i.e. this returns records when they cross the polygon border).
poly_streams_crosses <- get_layer_by_poly(river_url, example_poly, sp_rel = "crosses")
plot_layer(poly_streams_crosses, outline_poly = example_poly)
The sp_rel_lookup
data.frame explains the various types
of spatial relationships available through ArcGIS REST APIs.
The sp_rel_valid
data.frame shows which spatial
relationships are valid with different geometry types being queried and
used to do spatial queries.
The valid_sp_rel
function can be used to to see which
spatial relation types are applicable to different geometries.
valid_sp_rel("line","line")
#> [1] "esriSpatialRelCrosses" "esriSpatialRelEnvelopeIntersects"
#> [3] "esriSpatialRelIndexIntersects" "esriSpatialRelIntersects"
#> [5] "esriSpatialRelRelation"