Skip to content

Commit

Permalink
Merge pull request #1094 from geocompx/1092-review-edition-2-rl-ii
Browse files Browse the repository at this point in the history
1092 review edition 2 rl ii
  • Loading branch information
Robinlovelace committed May 8, 2024
2 parents b526413 + 1d33502 commit fb366cf
Show file tree
Hide file tree
Showing 113 changed files with 274 additions and 251 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -16,3 +16,4 @@ libs/

geocompr2.rds
*.gpkg
figures/
191 changes: 97 additions & 94 deletions 01-introduction.Rmd

Large diffs are not rendered by default.

12 changes: 6 additions & 6 deletions 02-spatial-data.Rmd
Original file line number Diff line number Diff line change
Expand Up @@ -126,7 +126,7 @@ source("https://github.com/geocompx/geocompr/raw/main/code/02-vectorplots.R") #
```

```{r vectorplots, fig.cap="Illustration of vector (point) data in which the location of London (the red X) is represented with reference to an origin (the blue circle). The left plot represents a geographic CRS with an origin at 0° longitude and latitude. The right plot represents a projected CRS with an origin located in the sea west of the South West Peninsula.", out.width="49%", fig.show='hold', echo=FALSE, fig.scap="Illustration of vector (point) data."}
knitr::include_graphics(c("figures/vector_lonlat.png", "figures/vector_projected.png"))
knitr::include_graphics(c("images/vector_lonlat.png", "images/vector_projected.png"))
```

The **sf** package provides classes for geographic vector data and a consistent command-line interface to important low level libraries for geocomputation:
Expand Down Expand Up @@ -158,7 +158,7 @@ All 18 types can be represented with the **sf** package, although at the time of
]

```{r sf-ogc, fig.cap="Simple feature types fully supported by sf.", out.width="60%", echo=FALSE}
knitr::include_graphics("figures/sf-classes.png")
knitr::include_graphics("images/sf-classes.png")
```

**sf** can represent all common vector geometry types (raster data classes are not supported by **sf**): points, lines, polygons and their respective 'multi' versions (which group together features of the same type into a single feature).
Expand Down Expand Up @@ -473,7 +473,7 @@ Figure \@ref(fig:02-sfdiagram) shows how an sf object is created -- geometries c

```{r 02-sfdiagram, fig.cap="Building blocks of sf objects.", echo=FALSE}
# source("code/02-sfdiagram.R")
knitr::include_graphics("figures/02-sfdiagram.png")
knitr::include_graphics("images/02-sfdiagram.png")
```

Non-geographic attributes represent the name of the feature or other attributes such as measured values, groups, and other things.
Expand Down Expand Up @@ -811,7 +811,7 @@ By default the S2 geometry engine is turned on, as can be verified with the foll
sf_use_s2()
```

An example of the consequences of turning the geometry engine off is shown below, by creating buffers around the `india` object created earlier in the chapter (note the warnings emitted when S2 is turned off) (Figure \ref(fig:s2example)):
An example of the consequences of turning the geometry engine off is shown below, by creating buffers around the `india` object created earlier in the chapter (note the warnings emitted when S2 is turned off) (Figure \@ref(fig:s2example)):

```{r}
india_buffer_with_s2 = st_buffer(india, 1) # 1 meter
Expand Down Expand Up @@ -1086,7 +1086,7 @@ Both datums in Figure \@ref(fig:datum-fig) are put on top of a geoid - a model o
(ref:datum-fig) Geocentric and local geodetic datums shown on top of a geoid (in false color and the vertical exaggeration by 10,000 scale factor). Image of the geoid is adapted from the work of @essd-11-647-2019.

```{r datum-fig, echo=FALSE, message=FALSE, fig.cap="(ref:datum-fig)", fig.scap="Geocentric and local geodetic datums on a geoid."}
knitr::include_graphics("figures/02_datum_fig.png")
knitr::include_graphics("images/02_datum_fig.png")
```

### Projected coordinate reference systems
Expand Down Expand Up @@ -1122,7 +1122,7 @@ For now, it is sufficient to know:

```{r vector-crs, echo=FALSE, fig.cap="Examples of geographic (WGS 84; left) and projected (NAD83 / UTM zone 12N; right) coordinate systems for a vector data type.", message=FALSE, fig.asp=0.56, fig.scap="Examples of geographic and projected CRSs (vector data)."}
# source("https://github.com/geocompx/geocompr/raw/main/code/02-vector-crs.R")
knitr::include_graphics("figures/02_vector_crs.png")
knitr::include_graphics("images/02_vector_crs.png")
```

## Units
Expand Down
10 changes: 5 additions & 5 deletions 04-spatial-operations.Rmd
Original file line number Diff line number Diff line change
Expand Up @@ -686,7 +686,7 @@ sum(st_coordinates(cycle_hire)[, 1] %in% st_coordinates(cycle_hire_osm)[, 1])

```{r cycle-hire, fig.cap="The spatial distribution of cycle hire points in London based on official data (blue) and OpenStreetMap data (red).", echo=FALSE, warning=FALSE, fig.scap="The spatial distribution of cycle hire points in London."}
if (knitr::is_latex_output()){
knitr::include_graphics("figures/cycle-hire-1.png")
knitr::include_graphics("images/cycle-hire-1.png")
} else if (knitr::is_html_output()){
# library(tmap)
# osm_tiles = tmaptools::read_osm(tmaptools::bb(cycle_hire, ext = 1.3), type = "https://korona.geog.uni-heidelberg.de/tiles/roadsg/x={x}&y={y}&z={z}")
Expand Down Expand Up @@ -862,7 +862,7 @@ elev[clip]
This amounts to retrieving the values of the first raster object (in this case `elev`) that fall within the extent of a second raster (here: `clip`), as illustrated in Figure \@ref(fig:raster-subset).

```{r raster-subset, echo = FALSE, fig.cap = "Original raster (left). Raster mask (middle). Output of masking a raster (right).", fig.scap="Subsetting raster values."}
knitr::include_graphics("figures/04_raster_subset.png")
knitr::include_graphics("images/04_raster_subset.png")
```

The example above returned the values of specific cells, but in many cases spatial outputs from subsetting operations on raster datasets are needed.
Expand Down Expand Up @@ -956,7 +956,7 @@ elev > 5
```

```{r 04-local-operations, echo=FALSE, fig.cap="Examples of different local operations of the elev raster object: adding two rasters, squaring, applying logarithmic transformation, and performing a logical operation."}
knitr::include_graphics("figures/04-local-operations.png")
knitr::include_graphics("images/04-local-operations.png")
```

Another good example of local operations is the classification of intervals of numeric values into groups such as grouping a digital elevation model into low (class 1), middle (class 2) and high elevations (class 3).
Expand Down Expand Up @@ -1038,7 +1038,7 @@ The result, shown on the right panel in Figure \@ref(fig:04-ndvi), can be compar
It allows us to see that the largest NDVI values are connected to northern areas of dense forest, while the lowest values are related to the lake in the north and snowy mountain ridges.

```{r 04-ndvi, echo=FALSE, fig.cap="RGB image (left) and NDVI values (right) calculated for the example satellite file of the Zion National Park"}
knitr::include_graphics("figures/04-ndvi.png")
knitr::include_graphics("images/04-ndvi.png")
```

Predictive mapping is another interesting application of local raster operations.
Expand Down Expand Up @@ -1067,7 +1067,7 @@ r_focal = focal(elev, w = matrix(1, nrow = 3, ncol = 3), fun = min)
This function also accepts additional arguments, for example, should it remove NAs in the process (`na.rm = TRUE`) or not (`na.rm = FALSE`).

```{r focal-example, echo = FALSE, fig.cap = "Input raster (left) and resulting output raster (right) due to a focal operation - finding the minimum value in 3-by-3 moving windows.", fig.scap="Illustration of a focal operation."}
knitr::include_graphics("figures/04_focal_example.png")
knitr::include_graphics("images/04_focal_example.png")
```

We can quickly check if the output meets our expectations.
Expand Down
4 changes: 2 additions & 2 deletions 06-raster-vector.Rmd
Original file line number Diff line number Diff line change
Expand Up @@ -468,7 +468,7 @@ As illustrated in Figure \@ref(fig:contour-tmap), isolines can be labelled.
# plot(dem, col = terrain.colors(25), alpha = 0.5, legend = FALSE, add = TRUE)
# # add contour lines
# contour(dem, col = "white", add = TRUE)
knitr::include_graphics("figures/06-contour-tmap.png")
knitr::include_graphics("images/06-contour-tmap.png")
```

\index{spatial vectorization!polygons}
Expand All @@ -483,7 +483,7 @@ grain_poly = as.polygons(grain) |>
st_as_sf()
```

```{r 06-raster-vector-40, echo=FALSE, fig.cap="Illustration of vectorization of raster (left) into polygons (dissolve = FALSE; center) and aggregated polygons (dissolve = TRUE; right).", warning=FALSE, fig.asp=0.4, fig.scap="Illustration of vectorization."}
```{r 06-raster-vector-40, echo=FALSE, fig.cap="Illustration of vectorization of raster (left) into polygons (dissolve = FALSE; center) and aggregated polygons (dissolve = TRUE; right).", warning=FALSE, message=FALSE, fig.asp=0.4, fig.scap="Illustration of vectorization."}
source("code/06-raster-vectorization2.R", print.eval = TRUE)
```

Expand Down
12 changes: 6 additions & 6 deletions 07-reproj.Rmd
Original file line number Diff line number Diff line change
Expand Up @@ -238,20 +238,20 @@ GEOS is always used for projected data and data with no CRS; for geographic data
}' -> s2geos
# # exported manually; the code below returns a low res version of png
# tmp = DiagrammeR::grViz(s2geos)
# htmlwidgets::saveWidget(widget = tmp, file = "figures/07-s2geos.html")
# htmlwidgets::saveWidget(widget = tmp, file = "images/07-s2geos.html")
# # tmp
# tmp = DiagrammeRsvg::export_svg(tmp)
# library(htmltools)
# html_print(HTML(tmp))
# tmp = charToRaw(tmp)
# # rsvg::rsvg_png(tmp, "figures/07-s2geos.png")
# webshot::webshot(url = "figures/07-s2geos.html", file = "figures/07-s2geos.png", vwidth = 800, vheight = 600)
# # rsvg::rsvg_png(tmp, "images/07-s2geos.png")
# webshot::webshot(url = "images/07-s2geos.html", file = "images/07-s2geos.png", vwidth = 800, vheight = 600)
# download.file(
# "https://user-images.githubusercontent.com/1825120/188572856-7946ae32-98de-444c-9f48-b1d7afcf9345.png",
# destfile = "figures/07-s2geos.png"
# destfile = "images/07-s2geos.png"
# )
# browseURL("figures/07-s2geos.png")
knitr::include_graphics("figures/07-s2geos.png")
# browseURL("images/07-s2geos.png")
knitr::include_graphics("images/07-s2geos.png")
```

To demonstrate the importance of CRSs, we will create buffer of 100 km around the `london` object from the previous section.
Expand Down
22 changes: 11 additions & 11 deletions 09-mapping.Rmd
Original file line number Diff line number Diff line change
Expand Up @@ -695,9 +695,9 @@ Unlike the faceted plot, it does not squeeze multiple maps into a single screen

```{r urban-animated, message=FALSE, fig.cap="Animated map showing the top 30 largest urban agglomerations from 1950 to 2030 based on population projects by the United Nations. Animated version available online at: r.geocompx.org.", fig.scap="Animated map showing the top 30 largest 'urban agglomerations'.", echo=FALSE, fig.height=3.3}
if (knitr::is_latex_output()){
knitr::include_graphics("figures/urban-animated.png")
knitr::include_graphics("images/urban-animated.png")
} else if (knitr::is_html_output()){
knitr::include_graphics("figures/urban-animated.gif")
knitr::include_graphics("images/urban-animated.gif")
}
```

Expand Down Expand Up @@ -737,7 +737,7 @@ source("https://github.com/geocompx/geocompr/raw/main/code/09-usboundaries.R")

```{r animus, echo=FALSE, message=FALSE, fig.cap="Animated map showing population growth, state formation and boundary changes in the United States, 1790-2010. Animated version available online at r.geocompx.org.", fig.scap="Animated map showing boundary changes in the United States."}
u_animus_html = "https://user-images.githubusercontent.com/1825120/38543030-5794b6f0-3c9b-11e8-9da9-10ec1f3ea726.gif"
u_animus_pdf = "figures/animus.png"
u_animus_pdf = "images/animus.png"
if (knitr::is_latex_output()){
knitr::include_graphics(u_animus_pdf)
} else if (knitr::is_html_output()){
Expand Down Expand Up @@ -770,7 +770,7 @@ map_nz

```{r tmview, message=FALSE, fig.cap="Interactive map of New Zealand created with tmap in view mode. Interactive version available online at: r.geocompx.org.", fig.scap="Interactive map of New Zealand.", echo=FALSE}
if (knitr::is_latex_output()){
knitr::include_graphics("figures/tmview-1.png")
knitr::include_graphics("images/tmview-1.png")
} else if (knitr::is_html_output()){
# tmap_mode("view")
# m_tmview = map_nz
Expand Down Expand Up @@ -798,7 +798,7 @@ tm_shape(world_coffee) + tm_polygons(facets) +
```

```{r sync, message=FALSE, fig.cap="Faceted interactive maps of global coffee production in 2016 and 2017 in sync, demonstrating tmap's view mode in action.", fig.scap="Faceted interactive maps of global coffee production.", echo=FALSE}
knitr::include_graphics("figures/interactive-facets.png")
knitr::include_graphics("images/interactive-facets.png")
```

Switch **tmap** back to plotting mode with the same function:
Expand All @@ -815,7 +815,7 @@ mapview::mapview(nz)
```

```{r mapview, message=FALSE, fig.cap="Illustration of mapview in action.", echo=FALSE}
knitr::include_graphics("figures/mapview.png")
knitr::include_graphics("images/mapview.png")
# knitr::include_graphics("https://user-images.githubusercontent.com/1825120/39979522-e8277398-573e-11e8-8c55-d72c6bcc58a4.png")
# mv = mapview::mapview(nz)
# mv@map
Expand All @@ -842,7 +842,7 @@ trails |>
```

```{r mapview2, message=FALSE, fig.cap="Using mapview at the end of a sf-based pipe expression.", echo=FALSE, warning=FALSE}
knitr::include_graphics("figures/mapview-example.png")
knitr::include_graphics("images/mapview-example.png")
# knitr::include_graphics("https://user-images.githubusercontent.com/1825120/39979271-5f515256-573d-11e8-9ede-e472ca007d73.png")
```

Expand Down Expand Up @@ -886,7 +886,7 @@ mapdeck(style = ms, pitch = 45, location = c(0, 52), zoom = 4) |>
```

```{r mapdeck, echo=FALSE, fig.cap="Map generated by mapdeck, representing road traffic casualties across the UK. Height of 1 km cells represents number of crashes.", fig.scap="Map generated by mapdeck."}
knitr::include_graphics("figures/mapdeck-mini.png")
knitr::include_graphics("images/mapdeck-mini.png")
```

You can zoom and drag the map in the browser, in addition to rotating and tilting it when pressing `Cmd`/`Ctrl`.
Expand Down Expand Up @@ -921,7 +921,7 @@ leaflet(data = cycle_hire) |>

```{r leaflet, message=FALSE, fig.cap="The leaflet package in action, showing cycle hire points in London. See interactive version [online](https://geocompr.github.io/img/leaflet.html).", fig.scap="The leaflet package in action.", echo=FALSE}
if (knitr::is_latex_output() || knitr::is_html_output()){
knitr::include_graphics("figures/leaflet-1.png")
knitr::include_graphics("images/leaflet-1.png")
} else {
# pre-generated for https://github.com/ropensci/stplanr/issues/385
# pal = colorNumeric("RdYlBu", domain = cycle_hire$nbikes)
Expand Down Expand Up @@ -995,7 +995,7 @@ shinyApp(ui, server)

```{r lifeApp, echo=FALSE, message=FALSE, fig.cap="Screenshot showing minimal example of a web mapping application created with shiny.", fig.scap="Minimal example of a web mapping application."}
# knitr::include_graphics("https://user-images.githubusercontent.com/1825120/39690606-8f9400c8-51d2-11e8-84d7-f4a66a477d2a.png")
knitr::include_graphics("figures/shiny-app.png")
knitr::include_graphics("images/shiny-app.png")
```

The **user interface** (`ui`) of lifeApp is created by `fluidPage()`.
Expand Down Expand Up @@ -1044,7 +1044,7 @@ knitr::include_app("https://shiny.robinlovelace.net/CycleHireApp/")
```

```{r CycleHireApp-latex, echo=FALSE, message=FALSE, fig.cap="CycleHireApp, a simple web mapping application for finding the closest cycle hiring station based on your location and requirement of cycles. Interactive version available online at r.geocompx.org.", fig.scap="coffeeApp, a simple web mapping application.", eval=knitr::is_latex_output()}
knitr::include_graphics("figures/09_cycle_hire_app.png")
knitr::include_graphics("images/09_cycle_hire_app.png")
```

## Other mapping packages
Expand Down
22 changes: 11 additions & 11 deletions 10-gis.Rmd
Original file line number Diff line number Diff line change
Expand Up @@ -88,9 +88,9 @@ Furthermore, R outperforms GISs in some areas of geocomputation\index{geocomputa

This chapter focuses on 'bridges' to three mature open source GIS products, summarized in Table \@ref(tab:gis-comp):

- QGIS\index{QGIS}, via the package **qgisprocess**\index{qgisprocess (package)} (Section \@ref(rqgis))
- SAGA\index{SAGA}, via **Rsagacmd**\index{Rsagacmd (package)} (Section \@ref(saga))
- GRASS GIS\index{GRASS GIS}, via **rgrass**\index{rgrass (package)} (Section \@ref(grass))
- QGIS\index{QGIS}, via the package **qgisprocess**\index{qgisprocess (package)} [@R-qgisprocess; Section \@ref(rqgis)]
- SAGA\index{SAGA}, via **Rsagacmd**\index{Rsagacmd (package)} [@R-Rsagacmd; Section \@ref(saga)]
- GRASS GIS\index{GRASS GIS}, via **rgrass**\index{rgrass (package)} [@R-rgrass; Section \@ref(grass)]

There have also been major developments in enabling open source GIS software to write and execute R scripts inside QGIS\index{QGIS} (see [docs.qgis.org](https://docs.qgis.org/3.28/en/docs/training_manual/processing/r_intro.html)) and GRASS GIS (see [grasswiki.osgeo.org](https://grasswiki.osgeo.org/wiki/R_statistics/rgrass#R_within_GRASS)).

Expand Down Expand Up @@ -358,7 +358,7 @@ Note that the threshold must be specified in square meters regardless of the coo

Let's run this algorithm and convert its output into a new `sf` object `clean_sf`.

```{r 09-gis-7c, eval=has_qgis_plugins, message=FALSE}
```{r 09-gis-7c, eval=FALSE, message=FALSE}
clean = qgis_run_algorithm("grass:v.clean",
input = union_sf,
tool = "rmarea", threshold = 25000
Expand All @@ -369,7 +369,7 @@ clean_sf = st_as_sf(clean)
The result, the right panel of \@ref(fig:sliver), looks as expected -- sliver polygons are now removed.

```{r sliver, echo=FALSE, fig.cap="Sliver polygons colored in red (left panel). Cleaned polygons (right panel)."}
knitr::include_graphics("figures/10-sliver.png")
knitr::include_graphics("images/10-sliver.png")
```

### Raster data {#qgis-raster}
Expand Down Expand Up @@ -458,7 +458,7 @@ Calculation of geomorphons requires an input DEM (`elevation`), and can be custo
It includes, `search` -- a length for which the line-of-sight is calculated, and ``-m`` -- a flag specifying that the search value will be provided in meters (and not the number of cells).
More information about additional arguments can be found in the original paper and the [GRASS GIS documentation](https://grass.osgeo.org/grass-stable/manuals/r.geomorphon.html).

```{r, eval=has_qgis_plugins}
```{r, eval=FALSE}
dem_geomorph = qgis_run_algorithm("grass:r.geomorphon",
elevation = dem,
`-m` = TRUE, search = 120
Expand All @@ -468,15 +468,15 @@ dem_geomorph = qgis_run_algorithm("grass:r.geomorphon",
Our output, `dem_geomorph$forms`, contains a raster file with 10 categories -- each one representing a terrain form.
We can read it into R with `qgis_as_terra()`, and then visualize it (Figure \@ref(fig:qgis-raster-map), right panel) or use it in our subsequent calculations.

```{r, eval=has_qgis_plugins}
```{r, eval=FALSE}
dem_geomorph_terra = qgis_as_terra(dem_geomorph$forms)
```

Interestingly, there are connections between some geomorphons and the TWI values, as shown in Figure \@ref(fig:qgis-raster-map).
The largest TWI values mostly occur in valleys and hollows, while the lowest values are seen, as expected, on ridges.

```{r qgis-raster-map, echo=FALSE, fig.cap="Topographic wetness index (TWI, left panel) and geomorphons (right panel) derived for the Mongón study area."}
knitr::include_graphics("figures/10-qgis-raster-map.png")
knitr::include_graphics("images/10-qgis-raster-map.png")
```

## SAGA {#saga}
Expand Down Expand Up @@ -553,7 +553,7 @@ ndvi_segments = ndvi_srg$segments |>
```

```{r sagasegments, echo=FALSE, fig.cap="Normalized difference vegetation index (NDVI, left panel) and NDVI-based segments derived using the seeded region growing algorithm for the Mongón study area."}
knitr::include_graphics("figures/10-saga-segments.png")
knitr::include_graphics("images/10-saga-segments.png")
```

The resulting polygons (segments) represent areas with similar values.
Expand Down Expand Up @@ -697,14 +697,14 @@ mapview::mapview(route) + points
```

```{r grass-mapview, fig.cap="Shortest route (blue line) between 24 cycle hire stations (blue dots) on the OSM street network of London.", fig.scap="Shortest route between 24 cycle hire stations.", echo=FALSE, out.width="80%"}
knitr::include_graphics("figures/10_shortest_route.png")
knitr::include_graphics("images/10_shortest_route.png")
```

```{r 09-gis-35, eval=FALSE, echo=FALSE}
library(mapview)
m_1 = mapview(route) + points
mapview::mapshot(m_1,
file = file.path(getwd(), "figures/09_shortest_route.png"),
file = file.path(getwd(), "images/09_shortest_route.png"),
remove_controls = c(
"homeButton", "layersControl",
"zoomControl"
Expand Down
2 changes: 1 addition & 1 deletion 11-algorithms.Rmd
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ It is hard to enforce reproducibility in R scripts, but there are tools that can
By default, RStudio \index{RStudio} 'code-checks' R scripts and underlines faulty code with a red wavy line, as illustrated below:

```{r codecheck, echo=FALSE, fig.cap="Code checking in RStudio. This example, from the script 11-centroid-alg.R, highlights an unclosed curly bracket on line 19.", fig.scap="Illustration of 'code checking' in RStudio."}
knitr::include_graphics("figures/codecheck.png")
knitr::include_graphics("images/codecheck.png")
```

```{block2 spellcheck, type='rmdnote'}
Expand Down

0 comments on commit fb366cf

Please sign in to comment.