`vignettes/linevia.Rmd`

`linevia.Rmd`

This vignette builds on the transport chapter of the Geocomputation with R book by showing how to create multi-stage desire lines, from the ground-up. It depends on these packages and datasets:

```
library(sf)
library(stplanr)
library(tidyverse)
library(spDataLarge)
desire_lines = od2line(bristol_od, bristol_zones)
```

```
## Warning in st_centroid.sf(zones): st_centroid assumes attributes are
## constant over geometries of x
```

```
## Warning in st_centroid.sfc(st_geometry(x), of_largest_polygon =
## of_largest_polygon): st_centroid does not give correct centroids for
## longitude/latitude data
```

The first stage is to create matrices of coordinates that will subsequently be used to create matrices representing each leg:

```
mat_orig = as.matrix(line2df(desire_rail)[c("fx", "fy")])
mat_dest = as.matrix(line2df(desire_rail)[c("tx", "ty")])
mat_rail = st_coordinates(bristol_stations)
```

The outputs are three matrices representing the starting points of the trips, their destinations and possible intermediary points at public transport nodes (named `orig`

, `dest`

and `rail`

respectively). But how to identify *which* intermediary points to use for each desire line? The `knn()`

function from the **nabor** package (which is used internally by **stplanr** so it should already be installed) solves this problem by finding *k nearest neighbors* between two sets of coordinates. By setting the `k`

parameter, one can define how many nearest neighbors should be returned. Of course, `k`

cannot exceed the number of observations in the input (here: `mat_rail`

). We are interested in just one nearest neighbor, namely, the closest railway station:

```
knn_orig = nabor::knn(mat_rail, query = mat_orig, k = 1)$nn.idx
knn_dest = nabor::knn(mat_rail, query = mat_dest, k = 1)$nn.idx
```

This results not in matrices of coordinates, but row indices that can subsequently be used to subset the `mat_rail`

. It is worth taking a look at the results to ensure that the process has worked properly, and to explain what has happened:

`as.numeric(knn_orig)`

`## [1] 25 3 2`

`as.numeric(knn_dest)`

`## [1] 27 27 27`

The output demonstrates that each object contains three whole numbers (the number of rows in `desire_rail`

) representing the rail station closest to the origin and destination of each desire line. Note that while each ‘origin station’ is different, the destination (station `30`

) is the same for all desire lines. This is to be expected because rail travel in cities tends to converge on a single large station (in this case Bristol Temple Meads). The indices can now be used to create matrices representing the rail station of origin and destination:

The final stage is to convert these matrices into meaningful geographic objects, in this case simple feature ‘multilinestrings’ that capture the fact that each stage is a separate line, but part of the same overall trip:

```
mats2line = function(mat1, mat2) {
lapply(1:nrow(mat1), function(i) {
rbind(mat1[i, ], mat2[i, ]) %>%
st_linestring()
}) %>% st_sfc()
}
desire_rail$leg_orig = mats2line(mat_orig, mat_rail_o)
desire_rail$leg_rail = mats2line(mat_rail_o, mat_rail_d)
desire_rail$leg_dest = mats2line(mat_rail_d, mat_dest)
```

The results are visualised below: