---
title: "Geospatial Data<br>Geocoding"
author: "Keith VanderLinden<br>Calvin University"
output:
  xaringan::moon_reader:
    nature:
      titleSlideClass: ["left", "top"]
      highlightLines: true
      ratio: "16:9"     
---

```{r child = "../../resources/scripts/slide-setup.Rmd"}
```

```{r packages, echo = FALSE, warning = FALSE, message = FALSE}
knitr::opts_chunk$set(eval = TRUE)
options(dplyr.print_max = 12)
library(tidyverse)
```

# Geocoding

*Geocoding* converts between descriptions of locations and their geographic coordinates.

We will use the [tidygeocoder](https://jessecambon.github.io/tidygeocoder/) to do our geocoding.

```{r}
library(sf)
library(ggspatial)
library(tidygeocoder)
```

.footnote[All examples from the TidyGeocoder: https://jessecambon.github.io/tidygeocoder/]

???
Geocoding translates between:
- machine-readable coordinates
- human-readable street addresses.

---
# Locations

```{r}
addresses <- tibble(address = c(
  "3201 Burton Street SE, Grand Rapids, MI, 49546", # Calvin University
  "303 Monroe Ave NW, Grand Rapids, MI, 49503"      # DeVos Performance Hall
  )) %>%
  geocode(address, method = "osm") %>%
  st_as_sf(coords = c("long", "lat")) %>%
  st_set_crs(4326)  
addresses
```

???
- This code uses tidygeocoder to geocode the given street addresses.
  - It uses the API from OSM, the [open-street map](https://nominatim.org/).
  - It translates from the older `st` encoding to the newer `sf`.
      - Be careful, these systems tend to put longitude first.
  - It chooses the WGS84/EPSG4326 CRS for encoding the coordinates.
  - It returns a POINT geom specification (vector data).

---
# Mapping the Locations

.pull-left[
```{r geocoding-points, error = FALSE, message = FALSE, warning = FALSE, results = "hide", fig.show = "hide"}
addresses %>% 
  ggplot() +
  annotation_map_tile(
    type = "osm", 
    zoomin = 0
  ) +
  geom_sf()
```
]
.pull-right[
```{r ref.label = "geocoding-points", echo = FALSE, message = FALSE, warning = FALSE, output.lines = 10, out.width = "100%"}
```
]

???
- This code plots the locations on a (vector) map.
  - It pulls a (vector) map tile from open-street-maps.
  - It then plots the points (on the top right and bottom left of the map).

---
# Reverse Geocoding

```{r echo = FALSE}
mystery_addresses <- tibble::tribble(
~name,                  ~address,
"White House",          "1600 Pennsylvania Ave NW, Washington, DC",
"Willis Tower",         "233 S Wacker Dr, Chicago, IL 60606",
"Transamerica Pyramid", "600 Montgomery St, San Francisco, CA 94111",
)

# Geocode the addresses.
mystery_lat_longs <- mystery_addresses %>%
  geocode(address, method = 'osm', lat = latitude , long = longitude) %>%
  select(latitude, longitude)
```

.pull-left[
`tidygeocoder` can also reverse-geocode geospatial coordinates into location names and street addresses.

We start with these latitude-longitude coordinates.
```{r}
mystery_lat_longs
```

]
--
.pull-right[
```{r}
reverse <- mystery_lat_longs %>% 
  reverse_geocode(
    lat = latitude, long = longitude, 
    method = 'osm', address = address, 
    full_results = TRUE) %>%
  select(address)
reverse
```
]

???
- This example starts with a (hidden) specification of three known locations.
- It uses OSM again.
- `full_results` requests all the data, not just the lat-lon.
- One wonders how close the lat-long has to be...

---
# Computing Distances

.pull-left[
We can compute *geodesic* distances between geo-coded locations.

We return to the local sites of interest and use the [openroute service](https://www.openrouteservice.org) to do the computations.

```{r}
# Defined earlier
addresses
```
]
--
.pull-right[
```{r}
addresses %>%
  st_distance() %>%
  units::set_units("miles")
```
]

???
- This code computes the distance between the GR addresses (used above).
- Distances:
  - *Geodesic* is "great circle" distance.
  - "Driving distance" is a more practical value.

---
# Computing Routes

```{r echo = FALSE}
MY_API_KEY <- "5b3ce3597851110001cf6248190ba6cccbe044818956b053f99c534a"
```

```{r}
library(openrouteservice)
ors_api_key(MY_API_KEY)

calvin_devos <- addresses %>%
  st_coordinates() %>%
  as_tibble()
```

.pull-left[
Driving
```{r}
route_driving <- calvin_devos %>%
  ors_directions(profile = "driving-car",  #<<
                 output = "sf")

route_driving %>%
  st_length() %>%
  units::set_units("miles")
```
]
.pull-right[
Cycling
```{r}
route_cycling <- calvin_devos %>%
  ors_directions(profile = "cycling-regular", #<<
                 output = "sf")

route_cycling %>%
  st_length() %>%
  units::set_units("miles")
```
]

???
- This computation requires an ORS API key, generated at the OpenRouteService API website.
- We can set a `preference = "fastest" / "recommended"`.
- ORS clearly has a detailed (vector) representation of streets, distances, times, etc.
- Is there some way to get times? Clearly the system knows that the car can handle longer distances in return for much higher speeds.

---
# Mapping the Routes

.pull-left[
The computed routes can easily be mapped.

```{r geocoding-routes, error = FALSE, message = FALSE, warning = FALSE, results = "hide", fig.show = "hide"}
library(leaflet)
leaflet(height = "400px") %>%
  addTiles() %>%
  addPolylines(data = route_driving, 
               weight = 7) %>%
  addPolylines(data = route_cycling, 
               color = "green", 
               weight = 7)
```
]
.pull-right[
```{r ref.label = "geocoding-routes", echo = FALSE, message = FALSE, warning = FALSE}
```
]

???
