-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathCity_maps.qmd
More file actions
369 lines (272 loc) · 15.5 KB
/
City_maps.qmd
File metadata and controls
369 lines (272 loc) · 15.5 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
---
title: "City_maps"
title-block-banner: true
title-block-banner-color: cornflowerblue
author: "Pablo Leon"
date: "`r Sys.Date()`"
format:
html:
toc: true
html-math-method: katex
code-fold: true
editor: visual
---
```{r markdown custom style, include=FALSE}
knitr::opts_chunk$set(echo = TRUE, warning = FALSE, message = FALSE,
dpi = 180, fig.width = 8, fig.height = 5)
library(tidyverse)
```
## Creating city maps using **osmdata** package
In this section, I will describe how to build maps for several cities around the world, using global open access mapping data from "osmdata" pacakge in R.
<https://docs.ropensci.org/osmdata/articles/osmdata.html>.
From the package website, they explain how working with open access map data, ensures transparent data provenance and ownership, allowing anyone to contribute, encouraging democratic decision making and citizen science. OSM is a global open access mapping project, which is free and open under the ODbL licence (OpenStreetMap contributors 2017)
## Working with vector data
OpenStreetMap (OSM) project information can be accessed via overpass queries using **osmdata** package in R. This package obtains OSM data from the overpass API, which is a read-only API that serves up custom selected parts of the the OSM map data.
## Installing and loading OSMDATA package from CRAN
To start working with Open OpenStreetMap package, I first install it from CRAN
```{r install OpenStreetMap}
# install.packages("osmdata",dependencies = TRUE)
```
And then load it the usual way using pacman::p_load() function to load several libraries at once, pacman::p_load(here,tidyverse,osmdata,sf,showtext). This is a more efficient way of working with several R libraries.
```{r load osmdata}
#| echo: false
library(osmdata)
```
These are the specific From osmdata package we will use these functions to plot our map:
- getbb(): Get bounding box for a given place name
- available_features(): List recognized features in OpenStreetMap(OSM)
- available_features(): List recognized features in OSM. This function returns a character vector of all known features
- available_tags(): List tags associated with a feature
Once I know which features to include in the map (buildings,roads,rivers,lagoons and bays), then I select the relevant tags that constitute the query we pass to the API to plot them using ggplot2. These are the set of osmdata functions used in this section:
- opq(): Build an Overpass query
- add_osm_feature(): Add a feature to an Overpass query. We specify the feature we want to plot and within that feature, we can also include a set of tags to be plotted in the map. As in the example below, we might want to plot **"highway"** feature in the map, so we include it in the Overpass query, but also we can specify other tags within that feature such as **""motorway","primary","secondary","tertiary","residential","living_street","unclassified"** as we can see in the Valencia city map example.
- osmdata_sf(): Return an OSM Overpass query as an osmdata object in sf format.
These three functions combined provides me with a gggplot2() object I can turn into a map using geom_sf() to handle shape files and polygons.
In a nutshell, a sf object is a collection of simple features that includes attributes and geometries in the form of a data frame. It is a data frame (or tibble) with rows of features, columns of attributes, and a special geometry column that contains the spatial aspects of the features.
For a further explanation about sf objects, please refer to Jesse Sadler website: \[sf objects\]<https://www.jessesadler.com/post/simple-feature-objects/#:~:text=At%20its%20most%20basic%2C%20an,spatial%20aspects%20of%20the%20features.>
Then I load some extra libraries for data wrangling and to create plots
```{r load required libraries}
pacman::p_load(here,tidyverse,osmdata,sf,showtext)
```
The `echo: false` option disables the printing of code (only output is displayed).
## Visualize Valencia city map using OpenStreetMap tutorial
When building maps using OpenStreetMap, we can think about them in similar terms as ggplot2 plots, in the sense we build them step by step, adding one layer at a time to display the required information on top of the initial map of the region we want to create a map from.
Having selected the city we want to plot, then we use getbb() function to obtain a bounding box for a given place name. In this instance I will plot the city of Valencia in Spain.
getbb() provides latitude and longitude coordinates associated with Valencia city in Spain
```{r Bounding box for Valencia city}
getbb("Valencia Spain")
```
## 1. Add first feature to the OpenStreet map
When creating a map of Valencia, it's important to decide which features to include. In OpenStreetMap, each feature is identified by a key, which is then further subdivided into values.
To plot roads or highways on the map, we first need to identify how these features are defined in the osmdata package. We can do this by using the available_features() function to select different types of roads or transportation routes defined in the map.
Once we have chosen the desired features, we can add them to our map along with other layers to create a comprehensive and informative representation of Valencia.
```{r display features}
# Not run as there are more than 250 elements
# available_features()
```
Looking at the list of available features, I can see that "highway" is one of the keys that I can use to plot transportation routes on my map of Valencia. However, I need to determine which specific values are associated with this key.
To do this, I can use the available_tags() function to identify the values that are related to the "highway" key. By selecting the appropriate values for the key, I can customize the map to display the types of transportation routes that are most relevant to my needs."
```{r get values tags for highway key}
available_tags("highway")
```
I plan to begin by mapping the primary roads in Valencia. To do this, I will select a few key tags from the list, such as motorway, primary, secondary, tertiary,residential,living_street, unclassified.
## 2. Choose elements to be included on the first layer of the map
Roads and highways are the first set of elements to be included on my map of Valencia. Displaying transportation routes in the city but also through its metropolitan area. From the previous available_tags() function, I choose "highway" as the appropriate value for this key.
This allows me to display different types of transportation types such as motorways, primary, secondary, and tertiary roads as well as motorways on the map.
```{r Map layer 01 roads}
# MAP LAYER 01: roads
roads <- getbb("Valencia Spain") %>%
opq(timeout = 3500) %>%
add_osm_feature(key = "highway",
value = c("motorway","primary","secondary","tertiary",
"residential","living_street","unclassified")) %>%
osmdata_sf()
roads
```
## 3. Adding natural and urban features to the map
### 3.1 Initial Valencia city map showing roads and highways
In r, I use the sf cartographic object I obtained from our OpenMap API query, mapping several sf objects via ggplot2 and geom_sf() functions.
Also, using getbb("Valencia Spain") function, I ensure the features we display on the map macth the city latitude and longitude I want to plot.
So far I have created just one geom_sf() object, embedded insite the ggplot() function, alongside the lat and long values for the city of Valencia.
Prior to producing the final map, I define the colour palette for each new feature,
```{r map roads color palette}
# Remember to enclose Hexadecimal colors in apostrophes
road_color <- '#000000'
coastline_color <- '#000000'
```
Then I can combine all previous scripts to create the first output map:
- **MAP 01: Create a standard ggplot() object using geom_sf() and osm features defined as roads**
```{r Valencia road map, warning=FALSE}
Valencia_roads_map <- ggplot() +
geom_sf(data = roads$osm_lines,
inherit.aes = FALSE,
color = road_color
) +
# Define city coordinates for maps. Given by getbb("Valencia Spain") function
coord_sf(xlim = c(-0.4325512, -0.2725205),
ylim = c(39.2784496, 39.5666089),
expand = FALSE)
Valencia_roads_map
```
### 3.2 Valencia city displaying roads and streets plus coastline features
Now I have added a new layer to the previous map, including beaches, dunes, bays and coastline natural water features.
```{r natural tag}
available_tags("natural")
```
These are the set of elements I will include in the map enclosed in the concatenate c() function below: "bay","water","beach","wetland","dune", "coastline" all these are coastline and water related map features.
```{r Valencia coastline}
Vlc_coastline <- getbb("Valencia Spain") %>%
opq(timeout = 3500) %>%
add_osm_feature(key = "natural",
value = c("bay","water","beach","wetland","dune","coastline")) %>%
osmdata_sf()
Vlc_coastline
```
- To display the Valencian Bay in blue colour next to the city seafront I define it as a multipolygon object
```{r Valencia coastline multipolygons}
Vlc_coastline_multipolygons <- Vlc_coastline$osm_multipolygons
```
- Roads features are defined as lines whilst coastline and water features are defined as multipolygons
- **MAP 02: Map combining roads and coastline layers**
- Set colour palette for road and coastline features
```{r colour palette road and coastline features}
road_color <- '#1E212B'
coastline_color <- '#D4B483'
```
```{r Valencia coastline map}
# This is the ggplot2() MAP02
Valencia_coastline_map <- ggplot() +
# roads
geom_sf(data = roads$osm_lines,
inherit.aes = FALSE,
color = road_color
) +
# coastline as multipolygons
geom_sf(data = Vlc_coastline_multipolygons,
inherit.aes = FALSE,
color = coastline_color
) +
# Define city coordinates for maps. Given by getbb("Valencia Spain") function
coord_sf(xlim = c(-0.4325512, -0.2725205),
ylim = c(39.2784496, 39.5666089),
expand = FALSE)
Valencia_coastline_map
```
### 3.3 New Water bodies features added to Valencia city map
- I want to include reservoirs and natural lagoons in the map. South of Valencia city there is freshwater lagoon called "La Albufera" I will include them in the map using shades of blue colour.
```{r Valencia sea and river}
Vlc_water <- getbb("Valencia Spain") %>%
opq(timeout = 3500) %>%
add_osm_feature(key = "water") %>%
osmdata_sf()
Vlc_sea <- getbb("Valencia Spain") %>%
opq(timeout = 3500) %>%
add_osm_feature(key = "waterway",
value = "river") %>%
osmdata_sf()
```
- To display these water features in the map, I define them as multipolygon objects
```{r Sea and water as multypolygons}
Vlc_water_multipolygons <- Vlc_water$osm_multipolygons
Vlc_sea_multipolygons <- Vlc_sea$osm_multipolygons
```
- **MAP 03: Map including these new water bodies on top of previous road and highways features**
```{r Valencia sea and river colour palette}
# Set colour palette for water features
road_color <- '#1E212B'
coastline_color <- '#D4B483'
water_color <- '#0066CC'
waterway_color <- '#99CCFF'
```
```{r Valencia city streets and water features}
# This is the ggplot2() MAP03
Valencia_waterways_map <- ggplot() +
# roads
geom_sf(data = roads$osm_lines,
inherit.aes = FALSE,
color = road_color
) +
# coastline as multipolygons
geom_sf(data = Vlc_coastline_multipolygons,
inherit.aes = FALSE,
color = coastline_color
) +
# water colour as multipolygons
geom_sf(data = Vlc_water_multipolygons,
inherit.aes = FALSE,
color = water_color
) +
# waterway colour as multipolygons
geom_sf(data = Vlc_sea_multipolygons,
inherit.aes = FALSE,
color = waterway_color
) +
# Define city coordinates for maps. Given by getbb("Valencia Spain") function
coord_sf(xlim = c(-0.4325512, -0.2725205),
ylim = c(39.2784496, 39.5666089),
expand = FALSE)
Valencia_waterways_map
```
## 4. VALENCIA OPEN STREET MAP
#### 4.1 Combining all features into a final output map
After defining several features to be plotted in the map (roads,coastline,waterways and rivers), I combine them as ggplot2 plot layers. To finally create one single ggplot2 image output as a .png file.
This final step also includes enhancing the map appearance by applying several theme options, adding background colour and Title and Subtitle to the output map.
- Set colour palette for VALENCIA OPEN STREET MAP
```{r Valencia open street map colour palette}
road_color <- '#1E212B'
coastline_color <- '#D4B483'
water_color <- '#0066CC'
waterway_color <- '#99CCFF'
albufera_lagoon <- "#0ACDFF"
font_color <-'#D2691E'
background_color <- "#D4B483"
```
Themed and formatted final output map of Valencia city
- **MAP 04: Valencia city map**
```{r Valencia city map}
Valencia_city_map <- ggplot() +
# roads
geom_sf(data = roads$osm_lines,inherit.aes = FALSE,color = road_color) +
# coastline
geom_sf(data = Vlc_coastline_multipolygons,inherit.aes = FALSE, fill = waterway_color, color = waterway_color) +
# water colour as multipolygons
geom_sf(data = Vlc_water_multipolygons,inherit.aes = FALSE, fill = water_color, color = water_color) +
# waterway colour as multipolygons
geom_sf(data = Vlc_sea_multipolygons,inherit.aes = FALSE, fill = waterway_color, color = waterway_color) +
# Define city coordinates for maps. Given by getbb("Valencia Spain") function
coord_sf(xlim = c(-0.4325512, -0.2725205),ylim = c(39.2784496, 39.5666089),expand = FALSE) +
# Include Map title and subtitle
labs(title = "Valencia ~ l'Albufera", subtitle = '39.4699° N, 0.3763° W') +
# Apply specific theme to map title and sub-title
theme_void() +
theme(
plot.title = element_text(family = "Barlow",color = font_color,size = 9,
hjust = 0, vjust = 1),
plot.title.position = "plot",
plot.subtitle = element_text(family = "Barlow",
color = font_color,
size = 5,
hjust = 0 , vjust = 2.3),
# Setup background color for entire map
panel.border = element_rect(colour = background_color, fill = NA, size = 1),
panel.margin = unit(c(0.6,1.6,1,1.6),"cm"),
plot.background = element_rect(fill = background_color)
)
Valencia_city_map
```
The default image width and height values can be changed to match a standard frame to hang it on the wall as a city map poster.
```{r Output png image parameters}
name <- "Valencia_open_street_map"
width = 20
height = 40
```
The last step is to use ggsave() function to create an output .png file that to be exported and printed.
```{r Save output chart}
ggsave(here::here(paste(name,".png", sep ="_")),
device = "png", width = width, height = height, units = "cm", dpi = "retina", bg = "transparent")
```
In coming weeks new city maps of **The Hague**, Netherlands and **Birmingham**, UK will be added to this section.
## 5. Annex
- Valencia city map output image as .png file <https://github.com/Pablo-source/Maps-in-R/blob/main/City_maps/Valencia_open_street_map_.png>
- Valencia city map R script <https://github.com/Pablo-source/Maps-in-R/blob/main/City_maps/Valencia_open_street_map.R>
- Similar quarto document to the one used to build this website <https://github.com/Pablo-source/Maps-in-R/blob/main/Documentation/Quarto_markdown%20custom%20setup.qmd>