---
title: "Introduction to package `mapsapi`"
author: "Michael Dorman"
date: "`r Sys.Date()`"
output:
  html_document:
    toc: true
    toc_float:
      collapsed: false
      smooth_scroll: false
    toc_depth: 3
    theme: united
vignette: >
  %\VignetteIndexEntry{Introduction to package `mapsapi`}
  %\VignetteEngine{knitr::rmarkdown}
  %\VignetteEncoding{UTF-8}
---

<style>
/* resize the widget container */
.leaflet { 
  width: 100% !important;
}

/* center the widget */
div.svg-container {
  margin: auto !important;
}
</style>

## Introduction

The `mapsapi` package provides an interface to the Google Maps APIs, currently four of them:

* <a href="https://developers.google.com/maps/documentation/directions/overview" target="_blank">Google Maps Direction API</a>
* <a href="https://developers.google.com/maps/documentation/distance-matrix/overview" target="_blank">Google Maps Distance Matrix API</a>
* <a href="https://developers.google.com/maps/documentation/geocoding/overview" target="_blank">Google Maps Geocode API</a>
* <a href="https://developers.google.com/maps/documentation/maps-static/overview" target="_blank">Maps Static API</a>

Functions `mp_directions`, `mp_matrix` and `mp_geocode` are used to access the Directions, Matrix and Geocode APIs, respectively. They return an `xml_document` object (package `xml2`) with the response contents.  

* Given a *directions* response, functions `mp_get_routes` and `mp_get_segments` can be used to process the response document into a spatial layer. Function `mp_get_routes` gives each alternative as a separate line, while function `mp_get_segments` gives each segment (that is, a portion of the route associated with specific driving instructions) as a separate line. 

* Given a *distance matrix* response, function `mp_get_matrix` can be used to obtain distance/duration matrices.

* Given a *geocode* response, functions `mp_get_points` and `mp_get_bounds` can be used to obtain geocoded locations as a point or polygon (bounds) layer. 

The fourth function `mp_map` is used to access the Maps Static API. It returns a `stars` raster RGB image, which can be used as background in maps.

## Installation

The CRAN version can be installed with:

```{r, eval=FALSE}
install.packages("mapsapi")
```

The development version can be installed using `remotes`:

```{r, eval=FALSE}
install.packages("remotes")
remotes::install_github("michaeldorman/mapsapi")
```

Once installed, the package can be loaded with `library`:

```{r}
library(mapsapi)
```

A Google Maps APIs key is required to use the package:

```{r, eval=FALSE}
key = "AIz....."
```


## Directions

The following expression queries the Directions API for driving directions from Tel-Aviv and Haifa. Note that locations can be specified as a coordinate pair, a textual address or an `sf` spatial object. For example:

```{r, eval=FALSE}
doc = mp_directions(
  origin = c(34.81127, 31.89277),
  destination = "Haifa",
  alternatives = TRUE,
  key = key,
  quiet = TRUE
)
```

Alternatively, we can use the sample response data included in the packages:

```{r}
library(xml2)
doc = as_xml_document(response_directions_driving)
```

Given the response object, we can use `mp_get_routes` to create a spatial layer of route lines:

```{r}
r = mp_get_routes(doc)
```

Here is the resulting object:

```{r}
r
```

and a visualization using `leaflet`:

```{r}
library(leaflet)
pal = colorFactor(palette = "Dark2", domain = r$alternative_id)
leaflet() %>% 
  addProviderTiles("CartoDB.DarkMatter") %>%
  addPolylines(data = r, opacity = 1, weight = 7, color = ~pal(alternative_id))
```

Separate segments can be extracted from the same response using `mp_get_segments`:

```{r}
seg = mp_get_segments(doc)
```

Here are the first six features of the resulting object:

```{r}
head(seg)
```

and a visualization:

```{r}
pal = colorFactor(
  palette = sample(colors(), length(unique(seg$segment_id))), 
  domain = seg$segment_id
  )
leaflet(seg) %>% 
  addProviderTiles("CartoDB.DarkMatter") %>%
  addPolylines(opacity = 1, weight = 7, color = ~pal(segment_id), popup = ~instructions)
```

## Distance Matrix

The following expression queries the Distance Matrix API to obtain a matrix of driving distance and duration between all combinations of three locations: Tel-Aviv, Jerusalem and Beer-Sheva. 

```{r}
locations = c("Tel-Aviv", "Jerusalem", "Beer-Sheva")
```

```{r, eval=FALSE}
doc = mp_matrix(
  origins = locations,
  destinations = locations,
  key = key,
  quiet = TRUE
)
```

Alternatively, we can use the sample response data included in the packages:

```{r}
doc = as_xml_document(response_matrix)
```

The `mp_get_matrix` function can then be used to process the XML response into a `matrix`. Possible values of the matrix include:

* `distance_m`---Distance, in meters
* `distance_text`---Distance, textual description
* `duration_s`---Duration, in seconds
* `duration_text`---Duration, textual description

```{r}
m = mp_get_matrix(doc, value = "distance_m")
colnames(m) = locations
rownames(m) = locations
m
```

## Geocode

The following expression queries the Directions API for geocoding a single address:

```{r, eval=FALSE}
doc = mp_geocode(
  addresses = "Tel-Aviv",
  key = key,
  quiet = TRUE
)
```

Alternatively, we can use the sample response data included with the package:

```{r}
doc = list("Tel-Aviv" = as_xml_document(response_geocode))
```

Given the response object, we can use `mp_get_points` to create a spatial layer of geocoded point locations:

```{r}
pnt = mp_get_points(doc)
pnt
```

Here is a visualization using `leaflet`:

```{r}
leaflet() %>% 
  addProviderTiles("CartoDB.DarkMatter") %>%
  addCircleMarkers(data = pnt)
```

Or the bounds:

```{r}
bounds = mp_get_bounds(doc)
bounds
```

And a visualization using `leaflet`:

```{r}
leaflet() %>% 
  addProviderTiles("CartoDB.DarkMatter") %>%  
  addPolygons(data = bounds)
```

## Static maps

The `mp_map` function can be used to access the Maps Static API to download an RGB image with a map.

Here is an example:

```{r, eval=FALSE}
r = mp_map(center = "31.253205,34.791914", zoom = 14, key = key, quiet = TRUE)
```

Alternatively, we can use the sample response data included with the package:

```{r}
r = response_map
```

The result is a `stars` raster, which can be plotted with `plot`:

```{r, eval=FALSE}
library(stars)
plot(r)
```

```{r, echo=FALSE}
library(stars)
plot(r, useRaster = TRUE)
```

or with `ggplot2`:

```{r}
library(ggplot2)
cols = attr(r[[1]], "colors")
ggplot() +
  geom_stars(data = r, aes(x = x, y = y, fill = color)) +
  scale_fill_manual(values = cols, guide = FALSE) +
  coord_sf()
```
