library(vicspatial)
#> In May 2025 (version 0.3.0) `VicmapR` was renamed to `vicspatial`. Unfortunately this change has been requested by the trademark holders of `VICMAP` (Department of Transport and Planning). While redirections should be in place for GitHub and CRAN websites, please check existing code for explicit mentions of `VicmapR`.
#> 
#> Attaching package: 'vicspatial'
#> The following object is masked from 'package:stats':
#> 
#>     filter
library(sf)
#> Linking to GEOS 3.13.0, GDAL 3.8.5, PROJ 9.5.1; sf_use_s2() is TRUE
library(leaflet)


#check sf installation
sf::sf_extSoftVersion()
#>           GEOS           GDAL         proj.4 GDAL_with_GEOS     USE_PROJ_H 
#>       "3.13.0"        "3.8.5"        "9.5.1"         "true"         "true" 
#>           PROJ 
#>        "9.5.1"

How to query data

Searching for data

In order to begin a query of the WFS server a spatial layer must be selected. To know which layers are available use the listLayers() function, which will return ~ 690 layers to choose from.

available_layers <- listLayers()

head(available_layers, 10)
#>                                           Name                    Title
#> 1           open-data-platform:ad_deeca_region          ad_deeca_region
#> 2       open-data-platform:ad_lga_area_polygon      ad_lga_area_polygon
#> 3  open-data-platform:ad_locality_area_polygon ad_locality_area_polygon
#> 4          open-data-platform:ad_vicgov_region         ad_vicgov_region
#> 5                   open-data-platform:address                  address
#> 6              open-data-platform:address_main             address_main
#> 7               open-data-platform:address_sup              address_sup
#> 8         open-data-platform:altern100_polygon        altern100_polygon
#> 9                   open-data-platform:anasurv                  anasurv
#> 10          open-data-platform:annotation_text          annotation_text
#>                                                                                                                                                                                                                                                                                                                                                                                                                                   Abstract
#> 1  Part of the Vicmap Admin dataset series.  This dataset contains the Department of Energy, Environment and Climate Action (DEECA) Regional Boundaries as defined by DEECA. \nThe regions are based on the Victorian Government Regional Boundaries. The main difference is that the three metropolitan regions have been aggregated to form the Port Phillip region, there are six regions.\nAligned to Road Network - Vicmap Transport.
#> 2                                                                                                                                                                                                               Part of the Vicmap Admin dataset series.  This dataset contains Local Government Boundaries (LGA's) polygons.  LGA's are as defined by Dept. for Victorian Communities (DVC).\nAligned to Road Network - Vicmap Transport.
#> 3                                                                                                                                                                                                                    Part of the Vicmap Admin dataset series.  Locality  Boundaries Boundary polygons for Victoria.  Locality Boundaries are as defined by The Registrar of Geographic Names.\nAligned to Road Network - Vicmap Transport.
#> 4                                                                                                                                         Part of the Vicmap Admin dataset series.  \n\nThis dataset contains the Victorian Government Regional Departmental Boundaries as defined by Local Government Victoria, Dept. of Planning & Community Development (DPCD). There are eight regions.\n\nAligned to Road Network - Vicmap Transport.
#> 5                                                                                                                                              See the product metadata record VICMAP_ADDRESS (Vicmap Address) ANZVI0803002578 \nTo access the data:- \nhttps://datashare.maps.vic.gov.au/search?q=uuid%3Db9e9146d-8378-5c37-b6cd-63e3a8d05d02\n\nVicmap Address is Victoria's authoritative geocoded database of property address points.
#> 6                                                                                                                                                                                                                                                                                                                                                                                                                                     <NA>
#> 7                                                                                                                                                                                                                                                                                                                                                                                                                                     <NA>
#> 8                                                                                                                                                                                                                                                                                                                                                                           Changes in the chemical or mineralogical composition of a rock
#> 9                                                                                                                                                     The analog airborne survey index was originally compiled in MapInfo. It contains survey boundary polygons and associated survey metadata that include acquisition parameters. All open file airborne geophysical surveys are included where data were acquired using analog systems.
#> 10                                                                                       Annotation Text  is a point layer belonging to Vicmap Property and consists of point data representing the location of Annotation and Text for Vicmap Property.  The points have been attributed with the appropropriate text.\n\nThis layer should be used in conjuction with the other layers and aspatial tables that make up Vicmap Property.
#>                              metadataID
#> 1  4b6be7f5-01a8-431f-90f8-91e45011dcd0
#> 2  bc822a9c-3766-57ac-a034-bcad3fb66d86
#> 3  6ed3b98f-b277-564a-997e-962be72c5ae8
#> 4  45394ea3-d758-59e2-8937-d8390cc90d7e
#> 5  8f3e3caa-e4bd-5e43-afc4-59b71c1f27f2
#> 6  4ff2aee8-ff0c-55db-b677-efc97b40a50d
#> 7  8323c048-5474-5313-b381-d771b807765c
#> 8  e7a18b45-ea9c-5172-acbd-70aca36cbabe
#> 9  23d0cc28-f727-5b1c-aa54-876fe1590926
#> 10 9128adcc-f8fd-5295-bcac-cc45a7247e8b

Vicmap promise

vicspatial introduces a new class called vicmap_promise, which is an extension to the httr::url class. Essentially this object is how the vicmap query is stored before data is collected. That is to say vicmap_promise is essentially a promise of what data will be retrieved.

In order to generate a new promise the vicmap_query function can be used to select the layer. The promise prints a sample of the data (max = 6 rows) as well as the dimensions (nrow and ncol).

# query the watercourse layer
vicmap_query(layer = "open-data-platform:hy_watercourse")
#> • Using collect() on this object will return 1832869
#> • features and 21 fields
#> • At most six rows of the record are printed here
#> ────────────────────────────────────────────────────────────────────────────────
#> Simple feature collection with 6 features and 20 fields
#> Geometry type: LINESTRING
#> Dimension:     XY
#> Bounding box:  xmin: 141.8898 ymin: -39.01699 xmax: 146.3676 ymax: -34.36471
#> Geodetic CRS:  GDA94
#> # A tibble: 6 × 21
#>   id                  ufi    pfi feature_type_code name  named_feature_id origin
#>   <chr>             <int>  <int> <chr>             <chr> <chr>            <chr> 
#> 1 hy_watercourse.1 3.63e6 9.63e6 watercourse_stre… NA    NA               1     
#> 2 hy_watercourse.2 3.63e6 9.63e6 watercourse_stre… NA    NA               1     
#> 3 hy_watercourse.3 3.63e6 9.63e6 watercourse_stre… NA    NA               1     
#> 4 hy_watercourse.4 2.55e6 8.55e6 watercourse_chan… NA    NA               2     
#> 5 hy_watercourse.5 2.55e6 8.55e6 watercourse_chan… NA    NA               2     
#> 6 hy_watercourse.6 2.55e6 8.55e6 watercourse_chan… NA    NA               2     
#> # ℹ 14 more variables: construction <chr>, usage <chr>, hierarchy <chr>,
#> #   auth_org_code <chr>, auth_org_id <chr>, auth_org_verified <chr>,
#> #   feature_quality_id <int>, task_id <chr>, create_date_pfi <dttm>,
#> #   superceded_pfi <chr>, feature_ufi <int>, feature_create_date_ufi <dttm>,
#> #   create_date_ufi <dttm>, geometry <LINESTRING [°]>

Adding arguments to the query

The vicmap_promise object can be easily added to through piping in of additional functions (e.g. head(), filter() and select()).

The resulting query can be displayed using the show_query() function, which will list the WFS parameters.

vicmap_query(layer = "open-data-platform:hy_watercourse") %>%
  head(50) %>% #return only 50 rows
  filter(hierarchy == "L") %>% # filter the column 'HIERACHY' to values of 'L'
  select(hierarchy, pfi) %>% # select columns 'HIERARCHY' and 'PFI'
  show_query()
#> <base url>
#> https://opendata.maps.vic.gov.au/geoserver/ows
#> 
#> <body>
#> service: wfs 
#> version: 2.0.0 
#> request: GetFeature 
#> typeNames: open-data-platform:hy_watercourse 
#> outputFormat: application/json 
#> count: 50 
#> srsName: EPSG:4283 
#> CQL_FILTER: ("hierarchy" = 'L') 
#> propertyName: geom,hierarchy,pfi 
#> 
#> <full query url>
#> https://opendata.maps.vic.gov.au/geoserver/ows?service=wfs&version=2.0.0&request=GetFeature&typeNames=open-data-platform%3Ahy_watercourse&outputFormat=application%2Fjson&count=50&srsName=EPSG%3A4283&CQL_FILTER=%28%22hierarchy%22%20%3D%20%27L%27%29&propertyName=geom%2Chierarchy%2Cpfi

In order to return a spatial data.frame object (sf) collect() must be used.

watercourse_data <- vicmap_query(layer = "open-data-platform:hy_watercourse") %>%
  head(50) %>% #return only 50 rows
  filter(hierarchy == "L") %>% # filter the column 'HIERACHY' to values of 'L'
  select(hierarchy, pfi) %>% # select columns 'HIERARCHY' and 'PFI'
  collect()

str(watercourse_data)
#> sf [50 × 4] (S3: sf/tbl_df/tbl/data.frame)
#>  $ id       : chr [1:50] "hy_watercourse.1" "hy_watercourse.2" "hy_watercourse.3" "hy_watercourse.4" ...
#>  $ pfi      : int [1:50] 9627981 9628133 9628125 8547189 8547359 8547370 8547394 8547461 8547592 8547635 ...
#>  $ hierarchy: chr [1:50] "L" "L" "L" "L" ...
#>  $ geometry :sfc_LINESTRING of length 50; first list element:  'XY' num [1:21, 1:2] 146 146 146 146 146 ...
#>  - attr(*, "sf_column")= chr "geometry"
#>  - attr(*, "agr")= Factor w/ 3 levels "constant","aggregate",..: NA NA NA
#>   ..- attr(*, "names")= chr [1:3] "id" "pfi" "hierarchy"

Geometric filters

vicspatial translates numerous geometric filter functions available in the Victorian Government’s WFS Geoserver supports numerous geometric filters:

  • EQUALS
  • DISJOINT
  • INTERSECTS
  • TOUCHES
  • CROSSES
  • WITHIN
  • CONTAINS
  • OVERLAPS
  • DWITHIN
  • BEYOND
  • BBOX

These filters can be used within the filter() function by providing them an object of class sf/sfc/sfg/bbox. Below is a leaflet map with the melbourne rail network being read in with the use of three different types of filter functions: INTERSECTS(), BBOX() and DWITHIN().

#### Return objects that intersect melbourne ####
# Read in an example shape to restrict our query to using geometric filtering
melbourne <- sf::st_read(system.file("shapes/melbourne.geojson", package="vicspatial"), quiet = F) %>% 
  sf::st_transform(4283)
#> Reading layer `melbourne' from data source 
#>   `/Users/runner/work/_temp/Library/vicspatial/shapes/melbourne.geojson' 
#>   using driver `GeoJSON'
#> Simple feature collection with 1 feature and 8 fields
#> Geometry type: MULTIPOLYGON
#> Dimension:     XY
#> Bounding box:  xmin: 144.897 ymin: -37.85066 xmax: 144.9913 ymax: -37.77545
#> Geodetic CRS:  WGS 84

# Return data that intersects melbourne
rail_intersects <- vicmap_query(layer = "open-data-platform:tr_rail") %>% # layer to query
  filter(INTERSECTS(melbourne)) %>% # more advanced geometric filter
  collect()

melbourne_bbox <- sf::st_bbox(melbourne)

rail_bbox <- vicmap_query(layer = "open-data-platform:tr_rail") %>%
  filter(BBOX(melbourne_bbox)) %>%
  collect()

melbourne_centroid <- sf::st_centroid(melbourne)

rail_dwithin <- vicmap_query(layer = "open-data-platform:tr_rail") %>%
  filter(DWITHIN(melbourne_centroid, distance = 10000, units = "meters")) %>%
  collect()

leaflet(width = "100%") %>%
  addProviderTiles("CartoDB.Positron") %>%
  addPolygons(data = melbourne, color = "grey", group = "Melbourne polygon") %>%
  addPolygons(data = sf::st_bbox(melbourne) %>% st_as_sfc(), color = "black", group = "Melbourne bbox") %>%
  addPolylines(data = rail_intersects, color = "Red", group = "INTERSECTS") %>% 
  addPolylines(data = rail_bbox, color = "Blue", group = "BBOX") %>%
  addPolylines(data = rail_dwithin, color = "Green", group = "DWITHIN") %>%
  addLayersControl(baseGroups = c("Melbourne polygon", "Melbourne bbox"), 
                   overlayGroups = c("INTERSECTS", "BBOX", "DWITHIN")) %>%
  hideGroup(c("BBOX", "DWITHIN"))