Routes

Overview

Boy Swallows Universe cover

Boy Swallows Universe is a crime fiction novel by Trent Dalton based in the suburbs around Brisbane, Queensland, Australia. The story takes readers for a detailed guided tour of Brisbane’s suburbs including Darra, Bracken Ridge, The Gap and beyond.

The routes and address data below present suggested ways of exploring the locations detailed throughout Boy Swallows Universe. Some addresses are a best-effort guess at the main fictional addresses in the book.

Routes have been generated using a trial account with Routific. Full details of the mapping process can be found in the Technical section.

Source code and data are available on GitHub.



Single Route

Overview

The Single Route was generated by optimising all Brisbane-based locations as one continuous itinerary. The purpose is to provide an ordered trip across all locations spanning multiple days.

Map

single_map <- google_map() %>%
  add_polylines(data = pls_df, polyline = "polylines")
htmltools::tagList(single_map)

Data

datatable(df, options = list(
  pageLength = 5,
  columnDefs = list(list(visible = FALSE, targets = c(4, 5, 6, 7, 8, 9)))
))

Single Route CSV data file

Multi-Day Routes

Overview

The Multi-Day Routes were generated by reorganising all Brisbane-based locations into a series of routes that could be completed within one day. The purpose is to provide a 7-day itinerary across all locations.

All Multi-Day Routes start and finish at the Brisbane General Post Office.

Data

Multi-Day Route CSV data file

day_map_counter <- 0
day_maps <- lapply(day_polylines, function(x) {
  day_map_counter <<- day_map_counter + 1
  day_pls_df <- data.frame(polylines = unlist(x), stringsAsFactors = F)
  day_map <- google_map() %>%
      add_polylines(data = day_pls_df, polyline = "polylines")
  day_map <- htmlwidgets::prependContent(
    day_map, htmltools::tags$h3(sprintf('Day %s Route', day_map_counter)))
  day_map <- htmlwidgets::appendContent(day_map, htmltools::tags$h3('Data'))
  day_map <- htmlwidgets::appendContent(
    day_map, datatable(day_routes[[day_map_counter]], options = list(
      pageLength = 5,
      columnDefs = list(list(visible = FALSE, targets = c(1, 5, 6, 7, 8, 9, 10)))
    )))
  day_map
})
htmltools::tagList(day_maps)

Day 1 Route

Data

Day 2 Route

Data

Day 3 Route

Data

Day 4 Route

Data

Day 5 Route

Data

Day 6 Route

Data

Day 7 Route

Data

Surrounds Route

Overview

The Surrounds Route was generated by optimising all non-Brisbane-based locations as one continuous itinerary. The purpose is to provide an ordered trip across all locations spanning multiple days.

Map

surrounds_map <- google_map() %>%
  add_polylines(data = surrounds_pls_df, polyline = "polylines")
htmltools::tagList(surrounds_map)

Data

datatable(surrounds_df, options = list(
  pageLength = 5,
  columnDefs = list(list(visible = FALSE, targets = c(4, 5, 6, 7, 8, 9)))
))

Brisbane Surrounds Route CSV data file

Technical

Source Data

All addresses were compiled, in reading order, into BSU - Locations.csv and BSU - Locations - Surrounds.csv. South East Queensland locations outside the Brisbane/Ipswich/Moreton Bay/Logan localities were separated out into the separate Surrounds CSV file.

Routific Routes

Routes were generated by uploading the Source Data CSV files to Routific. Routific generated routes processed hundreds of locations to provide optimised routes starting from the Brisbane General Post Office.

The routes were exported into CSV files (available after each map above) containing latitude and longitude pairs.

Route Maps

The latitude and longitude pairs were processed using R data frames and displayed using the googleway package. The tables are displayed with the DT package and rendered using R Markdown.

Single Route / Surrounds Route

library(googleway)
library(knitr)
library(rmarkdown)
library(DT)
load(".RData")

locations <- read.csv('C:\\Users\\Naaman\\Documents\\Code\\BSU\\data\\BSU - Routific - Single Route.csv')
df <- data.frame(locations)

polylines <- lapply(2:nrow(df)-1, function(x) {
  route <- google_directions(origin = unlist(df[x, 8:9]),
                             destination = unlist(df[x+1, 8:9]),
                             mode = "driving",
                             simplify = TRUE)
  
  route$routes$overview_polyline$points
})

pls_df <- data.frame(polylines = unlist(polylines), stringsAsFactors = F)
single_map <- google_map() %>%
  add_polylines(data = pls_df, polyline = "polylines")
htmltools::tagList(single_map)

Data Import

The Routific-generated CSV file was imported and loaded as an R Data Frame.

Polylines

Polylines determining the route outlines are drawn using the google_directions function from the Googleway R package. The lapply function iterates through the route data frame and returns a polyline between the current row and the next row. Columns 8 & 9 represent the Latitude and Longitude columns.

Generate Map with Route

The list of polylines is converted into a data frame and passed to the google_map/add_polylines Googleway functions. The map is then displayed using the htmltools::tagList function to match the same formatting used for the Multi-Day Routes.

Multi-Day Routes

library(googleway)
library(knitr)
library(rmarkdown)
library(DT)
load(".RData")

locations_7days <- read.csv('C:\\Users\\Naaman\\Documents\\Code\\BSU\\data\\BSU - Routific - 7 Days.csv')
day_routes <- split(
  locations_7days, 
  cumsum(locations_7days[,"Stop.Number"] == "0" & !is.na(locations_7days[,"Stop.Number"]))
)

day_polylines <- sapply(day_routes, function(y) {
  y <- subset(y, Visit.Name != "Break")
  lapply(2:nrow(y)-1, function(x) {
    day_route <- google_directions(origin = unlist(y[x, 9:10]),
                                   destination = unlist(y[x+1, 9:10]),
                                   mode = "driving",
                                   simplify = TRUE)
    day_route$routes$overview_polyline$points
  })
})

day_pls_df <- data.frame(polylines = unlist(day_polylines[[1]]), stringsAsFactors = F)

day_map_counter <- 0
day_maps <- lapply(day_polylines, function(x) {
  day_map_counter <<- day_map_counter + 1
  day_pls_df <- data.frame(polylines = unlist(x), stringsAsFactors = F)
  day_map <- google_map() %>%
      add_polylines(data = day_pls_df, polyline = "polylines")
  day_map <- htmlwidgets::prependContent(
    day_map, htmltools::tags$h3(sprintf('Day %s Route', day_map_counter)))
  day_map <- htmlwidgets::appendContent(day_map, htmltools::tags$h3('Data'))
  day_map <- htmlwidgets::appendContent(
    day_map, datatable(day_routes[[day_map_counter]], options = list(
      pageLength = 5,
      columnDefs = list(list(visible = FALSE, targets = c(1, 5, 6, 7, 8, 9, 10)))
    )))
  day_map
})

htmltools::tagList(day_maps)

Data Import

The Routific-generated CSV file was imported and split into multiple data frames based on zeroes in the Stop.Number column. The cumsum() splitting technique is credited to the following Stack Overflow post: https://stackoverflow.com/a/11402170/8751739.

Polylines

Each day’s list of routes have “Break” lines removed before building polylines similar to the Single Route maps. Columns 9 & 10 represent the Latitude and Longitude columns in the Multi-Day data frames.

Generate Map with Route

The list of polylines is converted into a data frame and passed to the google_map/add_polylines Googleway functions. The Multi-Day maps are generated as a continuous block of R HTMLWidgets with accompanying DT data tables. To assist with formatting, prependContent and appendContent from htmlwidgets are used for placing titles and data tables before and after maps. The collection of maps and tables are then displayed using the htmltools::tagList.