diff --git a/.github/workflows/README.md b/.github/workflows/README.md index d6edf88d..7076ddd9 100644 --- a/.github/workflows/README.md +++ b/.github/workflows/README.md @@ -2,7 +2,7 @@ This directory contains workflows to be used for Lessons using the {sandpaper} lesson infrastructure. Two of these workflows require R (`sandpaper-main.yaml` -and `pr-recieve.yaml`) and the rest are bots to handle pull request management. +and `pr-receive.yaml`) and the rest are bots to handle pull request management. These workflows will likely change as {sandpaper} evolves, so it is important to keep them up-to-date. To do this in your lesson you can do the following in your @@ -94,7 +94,7 @@ branch called `update/workflows` and a pull request is created. Maintainers are encouraged to review the changes and accept the pull request if the outputs are okay. -This update is run ~~weekly or~~ on demand. +This update is run weekly or on demand. ### 03 Maintain: Update Package Cache (update-cache.yaml) @@ -140,7 +140,7 @@ Once the checks are finished, a comment is issued to the pull request, which will allow maintainers to determine if it is safe to run the "Receive Pull Request" workflow from new contributors. -### Recieve Pull Request (pr-recieve.yaml) +### Receive Pull Request (pr-receive.yaml) **Note of caution:** This workflow runs arbitrary code by anyone who creates a pull request. GitHub has safeguarded the token used in this workflow to have no @@ -171,7 +171,7 @@ The artifacts produced are used by the next workflow. ### Comment on Pull Request (pr-comment.yaml) -This workflow is triggered if the `pr-recieve.yaml` workflow is successful. +This workflow is triggered if the `pr-receive.yaml` workflow is successful. The steps in this workflow are: 1. Test if the workflow is valid and comment the validity of the workflow to the diff --git a/.github/workflows/pr-close-signal.yaml b/.github/workflows/pr-close-signal.yaml index 9b129d5d..d20a2991 100644 --- a/.github/workflows/pr-close-signal.yaml +++ b/.github/workflows/pr-close-signal.yaml @@ -16,7 +16,7 @@ jobs: mkdir -p ./pr printf ${{ github.event.number }} > ./pr/NUM - name: Upload Diff - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: name: pr path: ./pr diff --git a/.github/workflows/pr-comment.yaml b/.github/workflows/pr-comment.yaml index bb2eb03c..8a2bd3ce 100644 --- a/.github/workflows/pr-comment.yaml +++ b/.github/workflows/pr-comment.yaml @@ -82,7 +82,7 @@ jobs: contents: write steps: - name: 'Checkout md outputs' - uses: actions/checkout@v3 + uses: actions/checkout@v4 with: ref: md-outputs path: built diff --git a/.github/workflows/pr-receive.yaml b/.github/workflows/pr-receive.yaml index 371ef542..2d7d5dbf 100644 --- a/.github/workflows/pr-receive.yaml +++ b/.github/workflows/pr-receive.yaml @@ -25,7 +25,7 @@ jobs: - name: "Upload PR number" id: upload if: ${{ always() }} - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: name: pr path: ${{ github.workspace }}/NR @@ -58,10 +58,10 @@ jobs: MD: ${{ github.workspace }}/site/built steps: - name: "Check Out Main Branch" - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: "Check Out Staging Branch" - uses: actions/checkout@v3 + uses: actions/checkout@v4 with: ref: md-outputs path: ${{ env.MD }} @@ -107,20 +107,20 @@ jobs: shell: Rscript {0} - name: "Upload PR" - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: name: pr path: ${{ env.PR }} - name: "Upload Diff" - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: name: diff path: ${{ env.CHIVE }} retention-days: 1 - name: "Upload Build" - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: name: built path: ${{ env.MD }} diff --git a/.github/workflows/sandpaper-main.yaml b/.github/workflows/sandpaper-main.yaml index e17707ac..a4f8dc40 100644 --- a/.github/workflows/sandpaper-main.yaml +++ b/.github/workflows/sandpaper-main.yaml @@ -32,7 +32,7 @@ jobs: steps: - name: "Checkout Lesson" - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: "Set up R" uses: r-lib/actions/setup-r@v2 diff --git a/.github/workflows/sandpaper-version.txt b/.github/workflows/sandpaper-version.txt index 201a22c8..c3f65805 100644 --- a/.github/workflows/sandpaper-version.txt +++ b/.github/workflows/sandpaper-version.txt @@ -1 +1 @@ -0.16.2 +0.16.6 diff --git a/.github/workflows/update-cache.yaml b/.github/workflows/update-cache.yaml index 676d7424..08ea9c97 100644 --- a/.github/workflows/update-cache.yaml +++ b/.github/workflows/update-cache.yaml @@ -43,7 +43,7 @@ jobs: needed: ${{ steps.renv.outputs.exists }} steps: - name: "Checkout Lesson" - uses: actions/checkout@v3 + uses: actions/checkout@v4 - id: renv run: | if [[ -d renv ]]; then @@ -76,7 +76,7 @@ jobs: steps: - name: "Checkout Lesson" - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: "Set up R" uses: r-lib/actions/setup-r@v2 diff --git a/.github/workflows/update-workflows.yaml b/.github/workflows/update-workflows.yaml index 288bcd13..a2d6fee1 100644 --- a/.github/workflows/update-workflows.yaml +++ b/.github/workflows/update-workflows.yaml @@ -36,7 +36,7 @@ jobs: if: ${{ needs.check_token.outputs.workflow == 'true' }} steps: - name: "Checkout Repository" - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: Update Workflows id: update diff --git a/.github/workflows/workshop-setup.yml b/.github/workflows/workshop-setup.yml new file mode 100644 index 00000000..9f681a3e --- /dev/null +++ b/.github/workflows/workshop-setup.yml @@ -0,0 +1,59 @@ +# A workflow for testing the workshop setup in different operating systems + +name: Test Workshop Setup + +# Controls when the action will run. Workflow runs when manually triggered using the UI +on: + workflow_dispatch: + +jobs: + workshop_setup: + runs-on: ${{matrix.os}} + strategy: + matrix: + # list of Os's + R: ['4.4.0'] + os: [ubuntu-latest, macos-latest, windows-latest] + steps: + - uses: actions/checkout@v4 + - name: Setup R + uses: r-lib/actions/setup-r@v2 + with: + r-version: ${{matrix.R}} + rtools-version: '44' + - run: Rscript -e 'print("R was installed successfully")' + - name: Install GDAL, GEOS, and PROJ.4 (macOS) + if: matrix.os == 'macos-latest' + run: | + /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)" + brew update + brew tap osgeo/osgeo4mac && brew tap --repair + brew install proj + brew install geos + brew install gdal + shell: bash + - name: Install GDAL, GEOS, and PROJ.4 (Ubuntu) + if: matrix.os == 'ubuntu-latest' + run: | + sudo add-apt-repository ppa:ubuntugis -y + sudo apt-get update + sudo apt-get install libgdal-dev libgeos-dev libproj-dev -y + shell: bash + # Include Fedora and Arch? + - name: UDUNITS + if: matrix.os == 'ubuntu-latest' + run: | + sudo apt-get install libudunits2-dev -y + shell: bash + - name: Geospatial Packages + uses: r-lib/actions/setup-r-dependencies@v2 + with: + cache-version: 2 + packages: | + any::sessioninfo + any::tidyverse + any::terra + any::sf + - name: Test Lessons + run: | + Rscript -e 'nc <- sf::st_read(system.file("shape/nc.shp", package="sf"), quiet = TRUE); if (sf::st_crs(sf::st_transform(nc, 4326))$epsg == 4326) print("`sf` works as expected"); if (nrow(dplyr::filter(nc, AREA > 0.2)) == 11) print("`tidyverse` works as expected")' diff --git a/episodes/.DS_Store b/episodes/.DS_Store new file mode 100644 index 00000000..bd4890ce Binary files /dev/null and b/episodes/.DS_Store differ diff --git a/episodes/18-import-and-visualise-osm-data.Rmd b/episodes/18-import-and-visualise-osm-data.Rmd index 4c4ebc11..01dbb0a6 100644 --- a/episodes/18-import-and-visualise-osm-data.Rmd +++ b/episodes/18-import-and-visualise-osm-data.Rmd @@ -27,7 +27,7 @@ knitr::opts_chunk$set(warning = FALSE, message = FALSE) ## What is OpenStreetMap? -OpenStreetMap (OSM) is a collaborative project which aims at mapping the world and sharing geospatial data in an open way. Anyone can contribute, by mapping geographical objects they encounter, by adding topical information on existing map objects (their name, function, capacity, etc.), or by mapping buildings and roads from satellite imagery (cf. [HOT: Humanitarian OpenStreetMap Team](https://www.hotosm.org/)). +OpenStreetMap (OSM) is a collaborative project which aims at mapping the world and sharing geospatial data in an open way. Anyone can contribute, by mapping geographical objects they encounter, by adding topical information on existing map objects (their name, function, capacity, etc.), or by mapping buildings and roads from satellite imagery. This information is then validated by other users and eventually added to the common "map" or information system. This ensures that the information is accessible, open, verified, accurate and up-to-date. @@ -48,27 +48,29 @@ assign("has_internet_via_proxy", TRUE, environment(curl::has_internet)) ### Bounding box -The first thing to do is to define the area within which you want to retrieve data, aka the *bounding box*. This can be defined easily using a place name and the package `nominatimlite` to access the free Nominatim API provided by OpenStreetMap. - -We are going to look at *Brielle* together, but you can also work with the small cities of *Naarden*, *Geertruidenberg*, *Gorinchem*, *Enkhuizen* or *Dokkum*. +The first thing to do is to define the area within which you want to retrieve data, aka the *bounding box*. This can be defined easily using a place name and the package `osmdata` to access the free Nominatim API provided by OpenStreetMap. +We are going to look at *Brielle* together. +::::::::::::::::::::::::::::::::::::: callout +Beware that downloading and analysing the data for larger cities might be long, slow and cumbersome on your machine. If you choose another location to work with, please try to choose a city of similar size! +:::::::::::::::::::::::::::::::::::::::::::::::: -We first geocode our spatial text search and extract the corresponding polygon (`geo_lite_sf`) and then extract its bounding box (`st_bbox`). +We first geocode our spatial text search and extract the corresponding bounding box (`getbb`). -```{r} -#install.packages("nominatimlite") -library(nominatimlite) +```{r nominatim} +library(osmdata) -nominatim_polygon <- geo_lite_sf(address = "Brielle", points_only = FALSE) -bb <- st_bbox(nominatim_polygon) +bb <- osmdata::getbb("Brielle") bb ``` ::::::::::::::::::::::::::::::::::::: callout +### Overpass query unavailable without internet + If you encounter an error linked to your internet proxy ("Error: Overpass query unavailable without internet R"), run this line of code. It might not be needed, but ensures that your machine knows it has internet. ```{r} @@ -87,11 +89,10 @@ For example: Brielle (Netherlands) and Brielle (New Jersey) ![Brielle, New Jersey](fig/Brielle_NJ.jpeg "Brielle, New Jersey"){width=40%} -By default, `geo_lite_sf()` from the `nominatimlite` package returns the first item. This means that regardless of the number of returned locations with the given name, the function will return a bounding box and it might be that we are not looking for the first item. We should therefore try to be as unambiguous as possible by adding a country code or district name. +By default, `getbb()` from the `osmdata` package returns the first item. This means that regardless of the number of returned locations with the given name, the function will return a bounding box and it might be that we are not looking for the first item. We should therefore try to be as unambiguous as possible by adding a country code or district name. -```{r} -nominatim_polygon <- geo_lite_sf(address = "Brielle, NL", points_only = FALSE) -bb <- st_bbox(nominatim_polygon) +```{r bbox} +bb <- getbb("Brielle, NL") bb ``` @@ -127,11 +128,7 @@ It appears that there is a function to extract features, using the Overpass API. On this page we can read about the arguments needed for each function: a bounding box for `opq()` and some `key` and `value` for `add_osm_feature()`. Thanks to the examples provided, we can assume that these keys and values correspond to different levels of tags from the OSM classification. In our case, we will keep it at the first level of classification, with "buildings" as `key`, and no value. We also see from the examples that another function is needed when working with the `sf` package: `osmdata_sf()`. This ensures that the type of object is suited for `sf`. With these tips and examples, we can write our feature extraction function as follows: -```{r} -#install.packages("osmdata") -library(osmdata) - - +```{r osm} x <- opq(bbox = bb) %>% add_osm_feature(key = 'building') %>% osmdata_sf() @@ -145,7 +142,7 @@ What is this `x` object made of? It is a data frame of all the buildings contain -```{r} +```{r strbuildings} str(x$osm_polygons) ``` @@ -161,7 +158,7 @@ Let's map the building age of post-1900 Brielle buildings. First, we are going to select the polygons and reproject them with the Amersfoort/RD New projection, suited for maps centred on the Netherlands. This code for this projection is: 28992. -```{r} +```{r transform} buildings <- x$osm_polygons %>% st_transform(.,crs=28992) ``` @@ -180,35 +177,73 @@ Then we create a new variable using the threshold at 1900. Every date before 190 Then we use the `ggplot()` function to visualise the buildings by age. The specific function to represent information as a map is `geom_sf()`. The rest works like other graphs and visualisation, with `aes()` for the aesthetics. -```{r} +```{r map} start_date <- as.numeric(buildings$start_date) buildings$build_date <- if_else(start_date < 1900, 1900, start_date) ggplot(data = buildings) + geom_sf(aes(fill = build_date, colour=build_date)) + scale_fill_viridis_c(option = "viridis")+ - scale_colour_viridis_c(option = "viridis") + scale_colour_viridis_c(option = "viridis") + + coord_sf(datum = st_crs(28992)) ``` So this reveals the historical centre of Brielle (or the city you chose) and the various urban extensions through time. Anything odd? What? Around the centre? Why these limits / isolated points? +## Replicability + +We have produced a proof a concept on Brielle, but can we factorise our work to be replicable with other small fortified cities? You can use any of the following cities: *Naarden*, *Geertruidenberg*, *Gorinchem*, *Enkhuizen* or *Dokkum*. + +We might replace the name in the first line and run everything again. Or we can create a function. +```{r reproducibility} +extract_buildings <- function(cityname, year=1900){ + nominatim_polygon <- geo_lite_sf(address = cityname, points_only = FALSE) + bb <- st_bbox(nominatim_polygon) + + x <- opq(bbox = bb) %>% + add_osm_feature(key = 'building') %>% + osmdata_sf() + + buildings <- x$osm_polygons %>% + st_transform(.,crs=28992) + + start_date <- as.numeric(buildings$start_date) + + buildings$build_date <- if_else(start_date < year, year, start_date) + ggplot(data = buildings) + + geom_sf(aes(fill = build_date, colour=build_date)) + + scale_fill_viridis_c(option = "viridis")+ + scale_colour_viridis_c(option = "viridis") + + ggtitle(paste0("Old buildings in ",cityname)) + + coord_sf(datum = st_crs(28992)) +} + +#test on Brielle +extract_buildings("Brielle, NL") + +#test on Naarden +extract_buildings("Naarden, NL") + +``` ::::::::::::::::::::::::::::::::::::: challenge -## Challenge: import an interactive basemap layer under the buildings with `Leaflet` (20min) +## Challenge: import an interactive basemap layer under the buildings with 'Leaflet' (20min) + +Leaflet is a ["open-source JavaScript library for mobile-friendly interactive maps"](https://leafletjs.com/). Within R, the `leaflet` package allows you to build such interactive maps. As with `ggplot2`, you build a map with a collection of layers. In this case, you will have the leaflet basemap, some tiles, and shapes on top (such as markers, polygons, etc.). -- Check out the [leaflet package documentation](https://rstudio.github.io/leaflet/) +- Check out the [leaflet package documentation](https://rstudio.github.io/leaflet/) and [GDCU cheatsheet](https://github.com/ClementineCttn/r-geospatial-urban/blob/main/instructors/cheatsheet/GDCU_cheatsheet.pdf). - Plot a basemap in Leaflet and try different tiles in the [basemap documentation](https://rstudio.github.io/leaflet/basemaps.html) - Transform the buildings into WGS84 projection and add them to the basemap layer with the `addPolygons()` function. -- Have the `fillColor` of these polygons represent the `build_date` variable. See the [choropleth documentation](https://rstudio.github.io/leaflet/choropleths.html) for use of colors. Tip: use the examples given in the documentation and replace the variable names where needed. +- Have the `fillColor` of these polygons represent the `build_date` variable. See the [choropleth documentation](https://rstudio.github.io/leaflet/choropleths.html) and [GDCU cheatsheet](https://github.com/ClementineCttn/r-geospatial-urban/blob/main/instructors/cheatsheet/GDCU_cheatsheet.pdf) for how use to use fill colors in polygons. Tip: use the examples given in the documentation and replace the variable names where needed. :::::::::::::::::::::::: solution ## One solution -```{r} +```{r leaflet} #install.packages("leaflet") library(leaflet) @@ -216,8 +251,13 @@ library(leaflet) buildings2 <- buildings %>% st_transform(.,crs=4326) +# leaflet(buildings2) %>% +# addTiles() %>% +# addPolygons(fillColor = ~colorQuantile("YlGnBu", -build_date)(-build_date)) + + # For a better visual rendering, try: + leaflet(buildings2) %>% -# addTiles() addProviderTiles(providers$CartoDB.Positron) %>% addPolygons(color = "#444444", weight = 0.1, smoothFactor = 0.5, opacity = 0.2, fillOpacity = 0.8, @@ -226,6 +266,7 @@ leaflet(buildings2) %>% bringToFront = TRUE)) ``` + ::::::::::::::::::::::::::::::::: ::::::::::::::::::::::::::::::::::::: @@ -233,7 +274,7 @@ leaflet(buildings2) %>% ::::::::::::::::::::::::::::::::::::: keypoints - Use the `Nominatim` and `Overpass` APIs within R -- Use the `osmdata` and `nominatimlite` packages to retrieve geospatial data +- Use the `osmdata` package to retrieve geospatial data - Select features and attributes among OSM tags - Use the `ggplot`, `sf` and `leaflet` packages to map data diff --git a/episodes/19-basic-gis-with-r-sf.Rmd b/episodes/19-basic-gis-with-r-sf.Rmd index 669b18c8..d01b1219 100644 --- a/episodes/19-basic-gis-with-r-sf.Rmd +++ b/episodes/19-basic-gis-with-r-sf.Rmd @@ -17,7 +17,7 @@ After completing this episode, participants should be able to… - Perform geoprocessing operations such as unions, joins and intersections with dedicated functions from the `sf` package - Compute the area of spatial polygons - Create buffers and centroids -- Map the results +- Map and save the results :::::::::::::::::::::::::::::::::::::::::::::::: ```{r setup, include=FALSE} @@ -25,12 +25,12 @@ knitr::opts_chunk$set(warning = FALSE, message = FALSE) ``` -```{r message=FALSE} +```{r packages, message=FALSE} library(tidyverse) library(sf) library(osmdata) library(leaflet) -library(nominatimlite) +library(lwgeom) assign("has_internet_via_proxy", TRUE, environment(curl::has_internet)) ``` @@ -49,9 +49,9 @@ Let's focus on old buildings and imagine we're in charge of their conservation. Let's select them and see where they are. -```{r} -nominatim_polygon <- nominatimlite::geo_lite_sf(address = "Brielle, NL", points_only = FALSE) -bb <- sf::st_bbox(nominatim_polygon) +```{r recap} + +bb <- osmdata::getbb("Brielle, NL") x <- opq(bbox = bb) %>% add_osm_feature(key = 'building') %>% osmdata_sf() @@ -69,12 +69,16 @@ buildings$start_date <- as.numeric(buildings$start_date) old_buildings <- buildings %>% filter(start_date <= old) - ggplot(data = old_buildings) + geom_sf(colour="red") + ggplot(data = old_buildings) + + geom_sf(colour="red") + + coord_sf(datum = st_crs(28992)) ``` ::::::::::::::::::::::::::::::::::::: callout +### Overpass query unavailable without internet + If you encounter an error linked to your internet proxy ("Error: Overpass query unavailable without internet R"), run this line of code. It might not be needed, but ensures that your machine knows it has internet. ```{r} @@ -89,7 +93,7 @@ As conservationists, we want to create a zone around historical buildings where Let's say the conservation zone should be 100 meters. In GIS terms, we want to create a _buffer_ around polygons. The corresponding `sf` function is `st_buffer()`, with 2 arguments: the polygons around which to create buffers, and the radius of the buffer. -```{r} +```{r buffer} distance <- 100 # in meters #First, we check that the "old_buildings" layer projection is measured in meters: @@ -99,7 +103,9 @@ st_crs(old_buildings) buffer_old_buildings <- st_buffer(x = old_buildings, dist = distance) -ggplot(data = buffer_old_buildings) + geom_sf() +ggplot(data = buffer_old_buildings) + + geom_sf() + + coord_sf(datum = st_crs(28992)) ``` @@ -107,7 +113,7 @@ ggplot(data = buffer_old_buildings) + geom_sf() Now, we have a lot of overlapping buffers. We would rather create a unique conservation zone rather than overlapping ones in that case. So we have to fuse the overlapping buffers into one polygon. This operation is called _union_ and the corresponding function is `st_union()`. -```{r} +```{r union} single_old_buffer <- st_union(buffer_old_buildings) %>% st_cast(to = "POLYGON") %>% st_as_sf() @@ -126,7 +132,7 @@ We create unique IDs to identify the new polygons. ## Centroids For the sake of visualisation speed, we would like to represent buildings by a single point (for instance: their geometric centre) rather than their actual footprint. This operation means defining their _centroid_ and the corresponding function is `st_centroid()`. -```{r} +```{r centroids} sf::sf_use_s2(FALSE) # s2 works with geographic projections, so to calculate centroids in projected CRS units (meters), we need to disable it. centroids_old <- st_centroid(old_buildings) %>% @@ -134,14 +140,15 @@ centroids_old <- st_centroid(old_buildings) %>% ggplot() + geom_sf(data = single_old_buffer, aes(fill=ID)) + - geom_sf(data = centroids_old) + geom_sf(data = centroids_old) + + coord_sf(datum = st_crs(28992)) ``` ## Intersection Now, we would like to distinguish conservation areas based on the number of historic buildings they contain. In GIS terms, we would like to know how many centroids each fused buffer polygon contains. This operation means _intersecting_ the layer of polygons with the layer of points and the corresponding function is `st_intersection()`. -```{r} +```{r intersection} centroids_buffers <- st_intersection(centroids_old,single_old_buffer) %>% mutate(n = 1) @@ -160,7 +167,8 @@ Now, we would like to distinguish conservation areas based on the number of hist begin = 0.6, end = 1, direction = -1, - option = "B") + option = "B") + + coord_sf(datum = st_crs(28992)) ``` `st_intersection` here adds the attributes of the intersected polygon buffers to the data table of the centroids. This means we will now know about each centroid, the ID of its intersected polygon-buffer, and a variable called "n" which is population with 1 for everyone. This means that all centroids will have the same weight when aggregated. @@ -169,18 +177,24 @@ We aggregate them by ID number (`group_by(ID)`) and sum the variable `n` to know ### Final output: -Let's map this layer over the initial map of individual buildings. +Let's map this layer over the initial map of individual buildings, and save the result. -```{r} -ggplot() + +```{r mapping} +p <- ggplot() + geom_sf(data = buildings) + geom_sf(data = single_buffer, aes(fill=n_buildings), colour = NA) + scale_fill_viridis_c(alpha = 0.6, begin = 0.6, end = 1, direction = -1, - option = "B") + option = "B") + + coord_sf(datum = st_crs(28992)) + p + +ggsave(filename = "fig/ConservationBrielle.png", + plot = p) + ``` ::::::::::::::::::::::::::::::::::::: challenge @@ -192,7 +206,7 @@ The historical threshold now applies to all pre-war buildings, but the distance :::::::::::::::::::::::: solution -```{r} +```{r parameters} old <- 1939 distance <- 10 @@ -227,14 +241,21 @@ centroid_by_buffer <- centroids_buffers %>% single_buffer <- single_old_buffer %>% mutate(n_buildings = centroid_by_buffer$n) - ggplot() + + +pnew <- ggplot() + geom_sf(data = buildings) + geom_sf(data = single_buffer, aes(fill = n_buildings), colour = NA) + scale_fill_viridis_c(alpha = 0.6, begin = 0.6, end = 1, direction = -1, - option = "B") + option = "B") + + coord_sf(datum = st_crs(28992)) + + pnew + +ggsave(filename = "fig/ConservationBrielle_newrules.png", + plot = pnew) ``` :::::::::::::::::::::::: @@ -246,7 +267,7 @@ single_buffer <- single_old_buffer %>% ## Area -```{r} +```{r area} single_buffer$area <- sf::st_area(single_buffer) %>% units::set_units(., km^2) diff --git a/instructors/2-vector-slides.html b/instructors/2-vector-slides.html index e2b96ccc..2ac20db6 100644 --- a/instructors/2-vector-slides.html +++ b/instructors/2-vector-slides.html @@ -27,12 +27,12 @@ ul.task-list{list-style: none;} ul.task-list li input[type="checkbox"] { width: 0.8em; - margin: 0 0.8em 0.2em -1em; /* quarto-specific, see https://github.com/quarto-dev/quarto-cli/issues/4556 */ + margin: 0 0.8em 0.2em -1em; /* quarto-specific, see https://github.com/quarto-dev/quarto-cli/issues/4556 */ vertical-align: middle; } /* CSS for syntax highlighting */ pre > code.sourceCode { white-space: pre; position: relative; } - pre > code.sourceCode > span { line-height: 1.25; } + pre > code.sourceCode > span { display: inline-block; line-height: 1.25; } pre > code.sourceCode > span:empty { height: 1.2em; } .sourceCode { overflow: visible; } code.sourceCode > span { color: inherit; text-decoration: inherit; } @@ -107,11 +107,11 @@ .callout { margin-top: 1em; - margin-bottom: 1em; + margin-bottom: 1em; border-radius: .25rem; } - .callout.callout-style-simple { + .callout.callout-style-simple { padding: 0em 0.5em; border-left: solid #acacac .3rem; border-right: solid 1px silver; @@ -162,7 +162,7 @@ margin-top: 0.5em; margin-bottom: 0.5em; } - + .callout.callout-titled.callout-style-simple .callout-content p { margin-top: 0; } @@ -213,7 +213,7 @@ .callout-title { display: flex } - + .callout-icon::before { margin-top: 1rem; padding-right: .5rem; @@ -224,8 +224,7 @@ } .callout.callout-titled .callout-body > .callout-content > :last-child { - padding-bottom: 0.5rem; - margin-bottom: 0; + margin-bottom: 0.5rem; } .callout.callout-titled .callout-icon::before { @@ -326,12 +325,12 @@ } .reveal .footnotes ol { counter-reset: ol; - list-style-type: none; + list-style-type: none; margin-left: 0; } .reveal .footnotes ol li:before { counter-increment: ol; - content: counter(ol) ". "; + content: counter(ol) ". "; } .reveal .footnotes ol li > p:first-child { display: inline-block; @@ -373,19 +372,19 @@ .reveal .slide > img.r-stretch.quarto-figure-center { display: block; margin-left: auto; - margin-right: auto; + margin-right: auto; } .reveal .slide > img.stretch.quarto-figure-left, .reveal .slide > img.r-stretch.quarto-figure-left { display: block; margin-left: 0; - margin-right: auto; + margin-right: auto; } .reveal .slide > img.stretch.quarto-figure-right, .reveal .slide > img.r-stretch.quarto-figure-right { display: block; margin-left: auto; - margin-right: 0; + margin-right: 0; } @@ -401,12 +400,12 @@

Introduction to Geospatial Vector Data with R

-Ana Petrović +Ana Petrović
-Claudiu Forgaci +Claudiu Forgaci
@@ -612,7 +611,15 @@

Map scale

- + +
+

Types of geospatial data

+ +
+
+

Raster and vector representations

+ +

Source: Saab, 2003

Geospatial Vector Data in R

@@ -621,7 +628,7 @@

Geospatial Vector Data in R

The sf package

-

Illustration (c) 2018 by Allison Horst

+

Illustration (c) 2018 by Allison Horst

The sf package

-
+ +
+

Geometry in QGIS

+ +
+
+

Geometry in R

+ +

Open and Plot Shapefiles

@@ -655,17 +670,17 @@

Challenge 1: 5 mins

-
lines_Delft <- st_read(here("episodes", "data", "delft-streets.shp"))
-point_Delft <- st_read(here("episodes", "data", "delft-leisure.shp"))
-
-st_geometry_type(lines_Delft)
-st_geometry_type(point_Delft)
-
-st_crs(lines_Delft)
-st_crs(point_Delft)
-
-st_bbox(lines_Delft)
-st_bbox(point_Delft)
+
lines_Delft <- st_read(here("episodes", "data", "delft-streets.shp"))
+point_Delft <- st_read(here("episodes", "data", "delft-leisure.shp"))
+
+st_geometry_type(lines_Delft)
+st_geometry_type(point_Delft)
+
+st_crs(lines_Delft)
+st_crs(point_Delft)
+
+st_bbox(lines_Delft)
+st_bbox(point_Delft)
@@ -696,15 +711,15 @@

Challenge 2: 3 mins

-
ncol(point_Delft)
-ncol(boundary_Delft)
-
-head(point_Delft)
-head(point_Delft, 10)
-
-point_Delft
-
-names(point_Delft)
+
ncol(point_Delft)
+ncol(boundary_Delft)
+
+head(point_Delft)
+head(point_Delft, 10)
+
+point_Delft
+
+names(point_Delft)
@@ -727,22 +742,22 @@

Challenge 3: 5 mins

-
levels(factor(lines_Delft$highway))
-
-motorway_Delft <- lines_Delft %>% 
-  filter(highway == "motorway")
-
-motorway_Delft %>% 
-  mutate(length = st_length(.)) %>% 
-  select(everything(), geometry) %>%
-  summarise(total_length = sum(length))
-
-nrow(motorway_Delft)
-
-ggplot(data = motorway_Delft) +
-  geom_sf(size = 1.5) +
-  ggtitle("Mobility network of Delft", subtitle = "Motorways") +
-  coord_sf()
+
levels(factor(lines_Delft$highway))
+
+motorway_Delft <- lines_Delft %>% 
+  filter(highway == "motorway")
+
+motorway_Delft %>% 
+  mutate(length = st_length(.)) %>% 
+  select(everything(), geometry) %>%
+  summarise(total_length = sum(length))
+
+nrow(motorway_Delft)
+
+ggplot(data = motorway_Delft) +
+  geom_sf(size = 1.5) +
+  ggtitle("Mobility network of Delft", subtitle = "Motorways") +
+  coord_sf()
@@ -766,16 +781,16 @@

Challenge 4: 3 mins

-
levels(factor(lines_Delft$highway))
-
-line_widths <- c(0.25, 0.75, 0.5, 1)
-
-ggplot(data = lines_Delft_selection) +
-  geom_sf(aes(size = highway)) +
-  scale_size_manual(values = line_widths) +
-  labs(size = "Road Size") +
-  ggtitle("Mobility network of Delft", subtitle = "Roads & Cycleways - Line width varies") +
-  coord_sf()
+
levels(factor(lines_Delft$highway))
+
+line_widths <- c(0.25, 0.75, 0.5, 1)
+
+ggplot(data = lines_Delft_selection) +
+  geom_sf(aes(size = highway)) +
+  scale_size_manual(values = line_widths) +
+  labs(size = "Road Size") +
+  ggtitle("Mobility network of Delft", subtitle = "Roads & Cycleways - Line width varies") +
+  coord_sf()
@@ -797,16 +812,16 @@

Challenge 5: 5 mins

-
levels(factor(lines_Delft_selection$highway))
-
-lines_Delft_bicycle <- lines_Delft %>% 
-  filter(highway == "cycleway")
-
-ggplot() +
-  geom_sf(data = lines_Delft) +
-  geom_sf(data = lines_Delft_bicycle, color = "magenta", size = 2) +
-  ggtitle("Mobility network of Delft", subtitle = "Roads dedicated to bikes") +
-  coord_sf()
+
levels(factor(lines_Delft_selection$highway))
+
+lines_Delft_bicycle <- lines_Delft %>% 
+  filter(highway == "cycleway")
+
+ggplot() +
+  geom_sf(data = lines_Delft) +
+  geom_sf(data = lines_Delft_bicycle, color = "magenta", size = 2) +
+  ggtitle("Mobility network of Delft", subtitle = "Roads dedicated to bikes") +
+  coord_sf()
@@ -828,14 +843,14 @@

Challenge 6: 3 mins

-
municipal_boundaries_NL <- st_read(here("episodes", "data", "nl-gemeenten.shp"))
-str(municipal_boundaries_NL)
-levels(factor(municipal_boundaries_NL$ligtInPr_1))
-
-ggplot(data = municipal_boundaries_NL) +
-  geom_sf(aes(color = ligtInPr_1), size = 1) +
-  ggtitle("Contiguous NL Municipal Boundaries") +
-  coord_sf()
+
municipal_boundaries_NL <- st_read(here("episodes", "data", "nl-gemeenten.shp"))
+str(municipal_boundaries_NL)
+levels(factor(municipal_boundaries_NL$ligtInPr_1))
+
+ggplot(data = municipal_boundaries_NL) +
+  geom_sf(aes(color = ligtInPr_1), size = 1) +
+  ggtitle("Contiguous NL Municipal Boundaries") +
+  coord_sf()
@@ -863,24 +878,24 @@

Challenge 7: 5 mins

-
leisure_locations_selection <- st_read(here("episodes", "data", "delft-leisure.shp")) %>% 
-  filter(leisure %in% c("playground", "picnic_table"))
-
-blue_orange <- c("cornflowerblue", "darkorange")
-
-p <- ggplot() + 
-  geom_sf(data = lines_Delft_selection, aes(color = highway)) + 
-  scale_color_manual(name = "Line Type", values = road_colors) +
-  ggtitle("Road network and leisure")
-
-p +
-  geom_sf(data = leisure_locations_selection, aes(fill = leisure), shape = 21) +
-  scale_fill_manual(name = "Leisure Type", values = blue_orange)
-
-p + 
-  geom_sf(data = leisure_locations_selection, aes(fill = leisure, shape = leisure), size = 3) +
-  scale_fill_manual(name = "Leisure Type", values = blue_orange) +
-  scale_shape_manual(name = "Leisure Type", values = c(21, 22))
+
leisure_locations_selection <- st_read(here("episodes", "data", "delft-leisure.shp")) %>% 
+  filter(leisure %in% c("playground", "picnic_table"))
+
+blue_orange <- c("cornflowerblue", "darkorange")
+
+p <- ggplot() + 
+  geom_sf(data = lines_Delft_selection, aes(color = highway)) + 
+  scale_color_manual(name = "Line Type", values = road_colors) +
+  ggtitle("Road network and leisure")
+
+p +
+  geom_sf(data = leisure_locations_selection, aes(fill = leisure), shape = 21) +
+  scale_fill_manual(name = "Leisure Type", values = blue_orange)
+
+p + 
+  geom_sf(data = leisure_locations_selection, aes(fill = leisure, shape = leisure), size = 3) +
+  scale_fill_manual(name = "Leisure Type", values = blue_orange) +
+  scale_shape_manual(name = "Leisure Type", values = c(21, 22))
@@ -909,22 +924,20 @@

Challenge 8: 3 mins

-
boundary_ZH <- municipal_boundary_NL %>% 
-  filter(ligtInPr_1 == "Zuid-Holland")
-
-ggplot() +
-  geom_sf(data = boundary_ZH, aes(color ="color"), show.legend = "line") +
-  scale_color_manual(name = "", labels = "Municipal Boundaries", values = c("color" = "gray18")) +
-  geom_sf(data = boundary_Delft, aes(shape = "shape"), color = "purple", fill = "purple") +
-  scale_shape_manual(name = "", labels = "Municipality of Delft", values = c("shape" = 19)) +
-  ggtitle("Delft location in South Holland") +
-  theme(legend.background = element_rect(color = NA)) +
-  coord_sf()
-
-
+
boundary_ZH <- municipal_boundary_NL %>% 
+  filter(ligtInPr_1 == "Zuid-Holland")
+
+ggplot() +
+  geom_sf(data = boundary_ZH, aes(color ="color"), show.legend = "line") +
+  scale_color_manual(name = "", labels = "Municipal Boundaries", values = c("color" = "gray18")) +
+  geom_sf(data = boundary_Delft, aes(shape = "shape"), color = "purple", fill = "purple") +
+  scale_shape_manual(name = "", labels = "Municipality of Delft", values = c("shape" = 19)) +
+  ggtitle("Delft location in South Holland") +
+  theme(legend.background = element_rect(color = NA)) +
+  coord_sf()
+
@@ -940,7 +953,7 @@

Challenge 8: 3 mins

- + @@ -955,6 +968,7 @@

Challenge 8: 3 mins

Reveal.initialize({ 'controlsAuto': true, 'previewLinksAuto': false, +'smaller': false, 'pdfSeparateFragments': false, 'autoAnimateEasing': "ease", 'autoAnimateDuration': 1, @@ -962,7 +976,7 @@

Challenge 8: 3 mins

'menu': {"side":"left","useTextContentForMissingTitles":true,"markers":false,"loadIcons":false,"custom":[{"title":"Tools","icon":"","content":""}],"openButton":true}, 'chalkboard': {"buttons":true}, 'smaller': false, - + // Display controls in the bottom right corner controls: false, @@ -1140,7 +1154,7 @@

Challenge 8: 3 mins

] }); - + - - \ No newline at end of file + + diff --git a/instructors/2-vector-slides.qmd b/instructors/2-vector-slides.qmd index 2594ec74..036f74a4 100644 --- a/instructors/2-vector-slides.qmd +++ b/instructors/2-vector-slides.qmd @@ -202,6 +202,14 @@ It can be expressed as: ::: +## Types of geospatial data + +![](fig/raster-vector.jpg) + +## Raster and vector representations + +![Source: Saab, 2003](fig/raster-vector-data-types.png) + # Geospatial Vector Data in R ## The `sf` package @@ -214,6 +222,14 @@ It can be expressed as: - represents simple features as records in a data frame with a `geometry` column - function names start with a prefix `st_` ("st" stands for spatial type), which is also handy for auto-completion in RStudio +## Geometry in QGIS + +![](fig/geometry-qgis.png) + +## Geometry in R + +![](fig/geometry-r.png) + # Open and Plot Shapefiles ## Challenge 1: **5 mins** diff --git a/instructors/2-vector-slides_files/libs/quarto-html/quarto-html.min.css b/instructors/2-vector-slides_files/libs/quarto-html/quarto-html.min.css index 8b137891..c2857c39 100644 --- a/instructors/2-vector-slides_files/libs/quarto-html/quarto-html.min.css +++ b/instructors/2-vector-slides_files/libs/quarto-html/quarto-html.min.css @@ -1 +1 @@ - +/*# sourceMappingURL=0a6b880beb84f9b6f36107a76f82c5b1.css.map */ diff --git a/instructors/2-vector-slides_files/libs/revealjs/dist/theme/quarto.css b/instructors/2-vector-slides_files/libs/revealjs/dist/theme/quarto.css index 02915705..5e282dc4 100644 --- a/instructors/2-vector-slides_files/libs/revealjs/dist/theme/quarto.css +++ b/instructors/2-vector-slides_files/libs/revealjs/dist/theme/quarto.css @@ -1,8 +1,5 @@ -@import"./fonts/source-sans-pro/source-sans-pro.css";:root{--r-background-color: #fff;--r-main-font: Source Sans Pro, Helvetica, sans-serif;--r-main-font-size: 40px;--r-main-color: #000000;--r-block-margin: 12px;--r-heading-margin: 0 0 12px 0;--r-heading-font: Source Sans Pro, Helvetica, sans-serif;--r-heading-color: #000000;--r-heading-line-height: 1.2;--r-heading-letter-spacing: normal;--r-heading-text-transform: none;--r-heading-text-shadow: none;--r-heading-font-weight: 600;--r-heading1-text-shadow: none;--r-heading1-size: 2.5em;--r-heading2-size: 1.6em;--r-heading3-size: 1.3em;--r-heading4-size: 1em;--r-code-font: SFMono-Regular, Menlo, Monaco, Consolas, Liberation Mono, Courier New, monospace;--r-link-color: #00A6D6;--r-link-color-dark: #006b8a;--r-link-color-hover: #0ac8ff;--r-selection-background-color: #57d9ff;--r-selection-color: #fff}.reveal-viewport{background:#fff;background-color:var(--r-background-color)}.reveal{font-family:var(--r-main-font);font-size:var(--r-main-font-size);font-weight:normal;color:var(--r-main-color)}.reveal ::selection{color:var(--r-selection-color);background:var(--r-selection-background-color);text-shadow:none}.reveal ::-moz-selection{color:var(--r-selection-color);background:var(--r-selection-background-color);text-shadow:none}.reveal .slides section,.reveal .slides section>section{line-height:1.3;font-weight:inherit}.reveal h1,.reveal h2,.reveal h3,.reveal h4,.reveal h5,.reveal h6{margin:var(--r-heading-margin);color:var(--r-heading-color);font-family:var(--r-heading-font);font-weight:var(--r-heading-font-weight);line-height:var(--r-heading-line-height);letter-spacing:var(--r-heading-letter-spacing);text-transform:var(--r-heading-text-transform);text-shadow:var(--r-heading-text-shadow);word-wrap:break-word}.reveal h1{font-size:var(--r-heading1-size)}.reveal h2{font-size:var(--r-heading2-size)}.reveal h3{font-size:var(--r-heading3-size)}.reveal h4{font-size:var(--r-heading4-size)}.reveal h1{text-shadow:var(--r-heading1-text-shadow)}.reveal p{margin:var(--r-block-margin) 0;line-height:1.3}.reveal h1:last-child,.reveal h2:last-child,.reveal h3:last-child,.reveal h4:last-child,.reveal h5:last-child,.reveal h6:last-child{margin-bottom:0}.reveal img,.reveal video,.reveal iframe{max-width:95%;max-height:95%}.reveal strong,.reveal b{font-weight:bold}.reveal em{font-style:italic}.reveal ol,.reveal dl,.reveal ul{display:inline-block;text-align:left;margin:0 0 0 1em}.reveal ol{list-style-type:decimal}.reveal ul{list-style-type:disc}.reveal ul ul{list-style-type:square}.reveal ul ul ul{list-style-type:circle}.reveal ul ul,.reveal ul ol,.reveal ol ol,.reveal ol ul{display:block;margin-left:40px}.reveal dt{font-weight:bold}.reveal dd{margin-left:40px}.reveal blockquote{display:block;position:relative;width:70%;margin:var(--r-block-margin) auto;padding:5px;font-style:italic;background:rgba(255,255,255,.05);box-shadow:0px 0px 2px rgba(0,0,0,.2)}.reveal blockquote p:first-child,.reveal blockquote p:last-child{display:inline-block}.reveal q{font-style:italic}.reveal pre{display:block;position:relative;width:90%;margin:var(--r-block-margin) auto;text-align:left;font-size:.55em;font-family:var(--r-code-font);line-height:1.2em;word-wrap:break-word;box-shadow:0px 5px 15px rgba(0,0,0,.15)}.reveal code{font-family:var(--r-code-font);text-transform:none;tab-size:2}.reveal pre code{display:block;padding:5px;overflow:auto;max-height:400px;word-wrap:normal}.reveal .code-wrapper{white-space:normal}.reveal .code-wrapper code{white-space:pre}.reveal table{margin:auto;border-collapse:collapse;border-spacing:0}.reveal table th{font-weight:bold}.reveal table th,.reveal table td{text-align:left;padding:.2em .5em .2em .5em;border-bottom:1px solid}.reveal table th[align=center],.reveal table td[align=center]{text-align:center}.reveal table th[align=right],.reveal table td[align=right]{text-align:right}.reveal table tbody tr:last-child th,.reveal table tbody tr:last-child td{border-bottom:none}.reveal sup{vertical-align:super;font-size:smaller}.reveal sub{vertical-align:sub;font-size:smaller}.reveal small{display:inline-block;font-size:.6em;line-height:1.2em;vertical-align:top}.reveal small *{vertical-align:top}.reveal img{margin:var(--r-block-margin) 0}.reveal a{color:var(--r-link-color);text-decoration:none;transition:color .15s ease}.reveal a:hover{color:var(--r-link-color-hover);text-shadow:none;border:none}.reveal .roll span:after{color:#fff;background:var(--r-link-color-dark)}.reveal .r-frame{border:4px solid var(--r-main-color);box-shadow:0 0 10px rgba(0,0,0,.15)}.reveal a .r-frame{transition:all .15s linear}.reveal a:hover .r-frame{border-color:var(--r-link-color);box-shadow:0 0 20px rgba(0,0,0,.55)}.reveal .controls{color:var(--r-link-color)}.reveal .progress{background:rgba(0,0,0,.2);color:var(--r-link-color)}@media print{.backgrounds{background-color:var(--r-background-color)}}.top-right{position:absolute;top:1em;right:1em}.visually-hidden{border:0;clip:rect(0 0 0 0);height:auto;margin:0;overflow:hidden;padding:0;position:absolute;width:1px;white-space:nowrap}.hidden{display:none !important}.zindex-bottom{z-index:-1 !important}figure.figure{display:block}.quarto-layout-panel{margin-bottom:1em}.quarto-layout-panel>figure{width:100%}.quarto-layout-panel>figure>figcaption,.quarto-layout-panel>.panel-caption{margin-top:10pt}.quarto-layout-panel>.table-caption{margin-top:0px}.table-caption p{margin-bottom:.5em}.quarto-layout-row{display:flex;flex-direction:row;align-items:flex-start}.quarto-layout-valign-top{align-items:flex-start}.quarto-layout-valign-bottom{align-items:flex-end}.quarto-layout-valign-center{align-items:center}.quarto-layout-cell{position:relative;margin-right:20px}.quarto-layout-cell:last-child{margin-right:0}.quarto-layout-cell figure,.quarto-layout-cell>p{margin:.2em}.quarto-layout-cell img{max-width:100%}.quarto-layout-cell .html-widget{width:100% !important}.quarto-layout-cell div figure p{margin:0}.quarto-layout-cell figure{display:block;margin-inline-start:0;margin-inline-end:0}.quarto-layout-cell table{display:inline-table}.quarto-layout-cell-subref figcaption,figure .quarto-layout-row figure figcaption{text-align:center;font-style:italic}.quarto-figure{position:relative;margin-bottom:1em}.quarto-figure>figure{width:100%;margin-bottom:0}.quarto-figure-left>figure>p,.quarto-figure-left>figure>div{text-align:left}.quarto-figure-center>figure>p,.quarto-figure-center>figure>div{text-align:center}.quarto-figure-right>figure>p,.quarto-figure-right>figure>div{text-align:right}.quarto-figure>figure>div.cell-annotation,.quarto-figure>figure>div code{text-align:left}figure>p:empty{display:none}figure>p:first-child{margin-top:0;margin-bottom:0}figure>figcaption.quarto-float-caption-bottom{margin-bottom:.5em}figure>figcaption.quarto-float-caption-top{margin-top:.5em}div[id^=tbl-]{position:relative}.quarto-figure>.anchorjs-link{position:absolute;top:.6em;right:.5em}div[id^=tbl-]>.anchorjs-link{position:absolute;top:.7em;right:.3em}.quarto-figure:hover>.anchorjs-link,div[id^=tbl-]:hover>.anchorjs-link,h2:hover>.anchorjs-link,h3:hover>.anchorjs-link,h4:hover>.anchorjs-link,h5:hover>.anchorjs-link,h6:hover>.anchorjs-link,.reveal-anchorjs-link>.anchorjs-link{opacity:1}#title-block-header{margin-block-end:1rem;position:relative;margin-top:-1px}#title-block-header .abstract{margin-block-start:1rem}#title-block-header .abstract .abstract-title{font-weight:600}#title-block-header a{text-decoration:none}#title-block-header .author,#title-block-header .date,#title-block-header .doi{margin-block-end:.2rem}#title-block-header .quarto-title-block>div{display:flex}#title-block-header .quarto-title-block>div>h1{flex-grow:1}#title-block-header .quarto-title-block>div>button{flex-shrink:0;height:2.25rem;margin-top:0}tr.header>th>p:last-of-type{margin-bottom:0px}table,table.table{margin-top:.5rem;margin-bottom:.5rem}caption,.table-caption{padding-top:.5rem;padding-bottom:.5rem;text-align:center}figure.quarto-float-tbl figcaption.quarto-float-caption-top{margin-top:.5rem;margin-bottom:.25rem;text-align:center}figure.quarto-float-tbl figcaption.quarto-float-caption-bottom{padding-top:.25rem;margin-bottom:.5rem;text-align:center}.utterances{max-width:none;margin-left:-8px}iframe{margin-bottom:1em}details{margin-bottom:1em}details[show]{margin-bottom:0}details>summary{color:#4d4d4d}details>summary>p:only-child{display:inline}pre.sourceCode,code.sourceCode{position:relative}p code:not(.sourceCode){white-space:pre-wrap}code{white-space:pre}@media print{code{white-space:pre-wrap}}pre>code{display:block}pre>code.sourceCode{white-space:pre}pre>code.sourceCode>span>a:first-child::before{text-decoration:none}pre.code-overflow-wrap>code.sourceCode{white-space:pre-wrap}pre.code-overflow-scroll>code.sourceCode{white-space:pre}code a:any-link{color:inherit;text-decoration:none}code a:hover{color:inherit;text-decoration:underline}ul.task-list{padding-left:1em}[data-tippy-root]{display:inline-block}.tippy-content .footnote-back{display:none}.footnote-back{margin-left:.2em}.tippy-content{overflow-x:auto}.quarto-embedded-source-code{display:none}.quarto-unresolved-ref{font-weight:600}.quarto-cover-image{max-width:35%;float:right;margin-left:30px}.cell-output-display .widget-subarea{margin-bottom:1em}.cell-output-display:not(.no-overflow-x),.knitsql-table:not(.no-overflow-x){overflow-x:auto}.panel-input{margin-bottom:1em}.panel-input>div,.panel-input>div>div{display:inline-block;vertical-align:top;padding-right:12px}.panel-input>p:last-child{margin-bottom:0}.layout-sidebar{margin-bottom:1em}.layout-sidebar .tab-content{border:none}.tab-content>.page-columns.active{display:grid}div.sourceCode>iframe{width:100%;height:300px;margin-bottom:-0.5em}a{text-underline-offset:3px}div.ansi-escaped-output{font-family:monospace;display:block}/*! +@import"./fonts/source-sans-pro/source-sans-pro.css";:root{--r-background-color: #fff;--r-main-font: Source Sans Pro, Helvetica, sans-serif;--r-main-font-size: 40px;--r-main-color: #000000;--r-block-margin: 12px;--r-heading-margin: 0 0 12px 0;--r-heading-font: Source Sans Pro, Helvetica, sans-serif;--r-heading-color: #000000;--r-heading-line-height: 1.2;--r-heading-letter-spacing: normal;--r-heading-text-transform: none;--r-heading-text-shadow: none;--r-heading-font-weight: 600;--r-heading1-text-shadow: none;--r-heading1-size: 2.5em;--r-heading2-size: 1.6em;--r-heading3-size: 1.3em;--r-heading4-size: 1em;--r-code-font: SFMono-Regular, Menlo, Monaco, Consolas, Liberation Mono, Courier New, monospace;--r-link-color: #00A6D6;--r-link-color-dark: #006b8a;--r-link-color-hover: #0ac8ff;--r-selection-background-color: #57d9ff;--r-selection-color: #fff}.reveal-viewport{background:#fff;background-color:var(--r-background-color)}.reveal{font-family:var(--r-main-font);font-size:var(--r-main-font-size);font-weight:normal;color:var(--r-main-color)}.reveal ::selection{color:var(--r-selection-color);background:var(--r-selection-background-color);text-shadow:none}.reveal ::-moz-selection{color:var(--r-selection-color);background:var(--r-selection-background-color);text-shadow:none}.reveal .slides section,.reveal .slides section>section{line-height:1.3;font-weight:inherit}.reveal h1,.reveal h2,.reveal h3,.reveal h4,.reveal h5,.reveal h6{margin:var(--r-heading-margin);color:var(--r-heading-color);font-family:var(--r-heading-font);font-weight:var(--r-heading-font-weight);line-height:var(--r-heading-line-height);letter-spacing:var(--r-heading-letter-spacing);text-transform:var(--r-heading-text-transform);text-shadow:var(--r-heading-text-shadow);word-wrap:break-word}.reveal h1{font-size:var(--r-heading1-size)}.reveal h2{font-size:var(--r-heading2-size)}.reveal h3{font-size:var(--r-heading3-size)}.reveal h4{font-size:var(--r-heading4-size)}.reveal h1{text-shadow:var(--r-heading1-text-shadow)}.reveal p{margin:var(--r-block-margin) 0;line-height:1.3}.reveal h1:last-child,.reveal h2:last-child,.reveal h3:last-child,.reveal h4:last-child,.reveal h5:last-child,.reveal h6:last-child{margin-bottom:0}.reveal img,.reveal video,.reveal iframe{max-width:95%;max-height:95%}.reveal strong,.reveal b{font-weight:bold}.reveal em{font-style:italic}.reveal ol,.reveal dl,.reveal ul{display:inline-block;text-align:left;margin:0 0 0 1em}.reveal ol{list-style-type:decimal}.reveal ul{list-style-type:disc}.reveal ul ul{list-style-type:square}.reveal ul ul ul{list-style-type:circle}.reveal ul ul,.reveal ul ol,.reveal ol ol,.reveal ol ul{display:block;margin-left:40px}.reveal dt{font-weight:bold}.reveal dd{margin-left:40px}.reveal blockquote{display:block;position:relative;width:70%;margin:var(--r-block-margin) auto;padding:5px;font-style:italic;background:rgba(255,255,255,.05);box-shadow:0px 0px 2px rgba(0,0,0,.2)}.reveal blockquote p:first-child,.reveal blockquote p:last-child{display:inline-block}.reveal q{font-style:italic}.reveal pre{display:block;position:relative;width:90%;margin:var(--r-block-margin) auto;text-align:left;font-size:.55em;font-family:var(--r-code-font);line-height:1.2em;word-wrap:break-word;box-shadow:0px 5px 15px rgba(0,0,0,.15)}.reveal code{font-family:var(--r-code-font);text-transform:none;tab-size:2}.reveal pre code{display:block;padding:5px;overflow:auto;max-height:400px;word-wrap:normal}.reveal .code-wrapper{white-space:normal}.reveal .code-wrapper code{white-space:pre}.reveal table{margin:auto;border-collapse:collapse;border-spacing:0}.reveal table th{font-weight:bold}.reveal table th,.reveal table td{text-align:left;padding:.2em .5em .2em .5em;border-bottom:1px solid}.reveal table th[align=center],.reveal table td[align=center]{text-align:center}.reveal table th[align=right],.reveal table td[align=right]{text-align:right}.reveal table tbody tr:last-child th,.reveal table tbody tr:last-child td{border-bottom:none}.reveal sup{vertical-align:super;font-size:smaller}.reveal sub{vertical-align:sub;font-size:smaller}.reveal small{display:inline-block;font-size:.6em;line-height:1.2em;vertical-align:top}.reveal small *{vertical-align:top}.reveal img{margin:var(--r-block-margin) 0}.reveal a{color:var(--r-link-color);text-decoration:none;transition:color .15s ease}.reveal a:hover{color:var(--r-link-color-hover);text-shadow:none;border:none}.reveal .roll span:after{color:#fff;background:var(--r-link-color-dark)}.reveal .r-frame{border:4px solid var(--r-main-color);box-shadow:0 0 10px rgba(0,0,0,.15)}.reveal a .r-frame{transition:all .15s linear}.reveal a:hover .r-frame{border-color:var(--r-link-color);box-shadow:0 0 20px rgba(0,0,0,.55)}.reveal .controls{color:var(--r-link-color)}.reveal .progress{background:rgba(0,0,0,.2);color:var(--r-link-color)}@media print{.backgrounds{background-color:var(--r-background-color)}}.top-right{position:absolute;top:1em;right:1em}.hidden{display:none !important}.zindex-bottom{z-index:-1 !important}.quarto-layout-panel{margin-bottom:1em}.quarto-layout-panel>figure{width:100%}.quarto-layout-panel>figure>figcaption,.quarto-layout-panel>.panel-caption{margin-top:10pt}.quarto-layout-panel>.table-caption{margin-top:0px}.table-caption p{margin-bottom:.5em}.quarto-layout-row{display:flex;flex-direction:row;align-items:flex-start}.quarto-layout-valign-top{align-items:flex-start}.quarto-layout-valign-bottom{align-items:flex-end}.quarto-layout-valign-center{align-items:center}.quarto-layout-cell{position:relative;margin-right:20px}.quarto-layout-cell:last-child{margin-right:0}.quarto-layout-cell figure,.quarto-layout-cell>p{margin:.2em}.quarto-layout-cell img{max-width:100%}.quarto-layout-cell .html-widget{width:100% !important}.quarto-layout-cell div figure p{margin:0}.quarto-layout-cell figure{display:inline-block;margin-inline-start:0;margin-inline-end:0}.quarto-layout-cell table{display:inline-table}.quarto-layout-cell-subref figcaption,figure .quarto-layout-row figure figcaption{text-align:center;font-style:italic}.quarto-figure{position:relative;margin-bottom:1em}.quarto-figure>figure{width:100%;margin-bottom:0}.quarto-figure-left>figure>p,.quarto-figure-left>figure>div{text-align:left}.quarto-figure-center>figure>p,.quarto-figure-center>figure>div{text-align:center}.quarto-figure-right>figure>p,.quarto-figure-right>figure>div{text-align:right}figure>p:empty{display:none}figure>p:first-child{margin-top:0;margin-bottom:0}figure>figcaption{margin-top:.5em}div[id^=tbl-]{position:relative}.quarto-figure>.anchorjs-link{position:absolute;top:.6em;right:.5em}div[id^=tbl-]>.anchorjs-link{position:absolute;top:.7em;right:.3em}.quarto-figure:hover>.anchorjs-link,div[id^=tbl-]:hover>.anchorjs-link,h2:hover>.anchorjs-link,h3:hover>.anchorjs-link,h4:hover>.anchorjs-link,h5:hover>.anchorjs-link,h6:hover>.anchorjs-link,.reveal-anchorjs-link>.anchorjs-link{opacity:1}#title-block-header{margin-block-end:1rem;position:relative;margin-top:-1px}#title-block-header .abstract{margin-block-start:1rem}#title-block-header .abstract .abstract-title{font-weight:600}#title-block-header a{text-decoration:none}#title-block-header .author,#title-block-header .date,#title-block-header .doi{margin-block-end:.2rem}#title-block-header .quarto-title-block>div{display:flex}#title-block-header .quarto-title-block>div>h1{flex-grow:1}#title-block-header .quarto-title-block>div>button{flex-shrink:0;height:2.25rem;margin-top:0}tr.header>th>p:last-of-type{margin-bottom:0px}table,.table{caption-side:top;margin-bottom:1.5rem}caption,.table-caption{padding-top:.5rem;padding-bottom:.5rem;text-align:center}.utterances{max-width:none;margin-left:-8px}iframe{margin-bottom:1em}details{margin-bottom:1em}details[show]{margin-bottom:0}details>summary{color:#4d4d4d}details>summary>p:only-child{display:inline}pre.sourceCode,code.sourceCode{position:relative}p code:not(.sourceCode){white-space:pre-wrap}code{white-space:pre}@media print{code{white-space:pre-wrap}}pre>code{display:block}pre>code.sourceCode{white-space:pre}pre>code.sourceCode>span>a:first-child::before{text-decoration:none}pre.code-overflow-wrap>code.sourceCode{white-space:pre-wrap}pre.code-overflow-scroll>code.sourceCode{white-space:pre}code a:any-link{color:inherit;text-decoration:none}code a:hover{color:inherit;text-decoration:underline}ul.task-list{padding-left:1em}[data-tippy-root]{display:inline-block}.tippy-content .footnote-back{display:none}.quarto-embedded-source-code{display:none}.quarto-unresolved-ref{font-weight:600}.quarto-cover-image{max-width:35%;float:right;margin-left:30px}.cell-output-display .widget-subarea{margin-bottom:1em}.cell-output-display:not(.no-overflow-x),.knitsql-table:not(.no-overflow-x){overflow-x:auto}.panel-input{margin-bottom:1em}.panel-input>div,.panel-input>div>div{display:inline-block;vertical-align:top;padding-right:12px}.panel-input>p:last-child{margin-bottom:0}.layout-sidebar{margin-bottom:1em}.layout-sidebar .tab-content{border:none}.tab-content>.page-columns.active{display:grid}div.sourceCode>iframe{width:100%;height:300px;margin-bottom:-0.5em}div.ansi-escaped-output{font-family:monospace;display:block}/*! * * ansi colors from IPython notebook's * -* we also add `bright-[color]-` synonyms for the `-[color]-intense` classes since -* that seems to be what ansi_up emits -* -*/.ansi-black-fg{color:#3e424d}.ansi-black-bg{background-color:#3e424d}.ansi-black-intense-black,.ansi-bright-black-fg{color:#282c36}.ansi-black-intense-black,.ansi-bright-black-bg{background-color:#282c36}.ansi-red-fg{color:#e75c58}.ansi-red-bg{background-color:#e75c58}.ansi-red-intense-red,.ansi-bright-red-fg{color:#b22b31}.ansi-red-intense-red,.ansi-bright-red-bg{background-color:#b22b31}.ansi-green-fg{color:#00a250}.ansi-green-bg{background-color:#00a250}.ansi-green-intense-green,.ansi-bright-green-fg{color:#007427}.ansi-green-intense-green,.ansi-bright-green-bg{background-color:#007427}.ansi-yellow-fg{color:#ddb62b}.ansi-yellow-bg{background-color:#ddb62b}.ansi-yellow-intense-yellow,.ansi-bright-yellow-fg{color:#b27d12}.ansi-yellow-intense-yellow,.ansi-bright-yellow-bg{background-color:#b27d12}.ansi-blue-fg{color:#208ffb}.ansi-blue-bg{background-color:#208ffb}.ansi-blue-intense-blue,.ansi-bright-blue-fg{color:#0065ca}.ansi-blue-intense-blue,.ansi-bright-blue-bg{background-color:#0065ca}.ansi-magenta-fg{color:#d160c4}.ansi-magenta-bg{background-color:#d160c4}.ansi-magenta-intense-magenta,.ansi-bright-magenta-fg{color:#a03196}.ansi-magenta-intense-magenta,.ansi-bright-magenta-bg{background-color:#a03196}.ansi-cyan-fg{color:#60c6c8}.ansi-cyan-bg{background-color:#60c6c8}.ansi-cyan-intense-cyan,.ansi-bright-cyan-fg{color:#258f8f}.ansi-cyan-intense-cyan,.ansi-bright-cyan-bg{background-color:#258f8f}.ansi-white-fg{color:#c5c1b4}.ansi-white-bg{background-color:#c5c1b4}.ansi-white-intense-white,.ansi-bright-white-fg{color:#a1a6b2}.ansi-white-intense-white,.ansi-bright-white-bg{background-color:#a1a6b2}.ansi-default-inverse-fg{color:#fff}.ansi-default-inverse-bg{background-color:#000}.ansi-bold{font-weight:bold}.ansi-underline{text-decoration:underline}:root{--quarto-body-bg: #fff;--quarto-body-color: #000000;--quarto-text-muted: #4d4d4d;--quarto-border-color: #999999;--quarto-border-width: 1px;--quarto-border-radius: 4px}table.gt_table{color:var(--quarto-body-color);font-size:1em;width:100%;background-color:rgba(0,0,0,0);border-top-width:inherit;border-bottom-width:inherit;border-color:var(--quarto-border-color)}table.gt_table th.gt_column_spanner_outer{color:var(--quarto-body-color);background-color:rgba(0,0,0,0);border-top-width:inherit;border-bottom-width:inherit;border-color:var(--quarto-border-color)}table.gt_table th.gt_col_heading{color:var(--quarto-body-color);font-weight:bold;background-color:rgba(0,0,0,0)}table.gt_table thead.gt_col_headings{border-bottom:1px solid currentColor;border-top-width:inherit;border-top-color:var(--quarto-border-color)}table.gt_table thead.gt_col_headings:not(:first-child){border-top-width:1px;border-top-color:var(--quarto-border-color)}table.gt_table td.gt_row{border-bottom-width:1px;border-bottom-color:var(--quarto-border-color);border-top-width:0px}table.gt_table tbody.gt_table_body{border-top-width:1px;border-bottom-width:1px;border-bottom-color:var(--quarto-border-color);border-top-color:currentColor}div.columns{display:initial;gap:initial}div.column{display:inline-block;overflow-x:initial;vertical-align:top;width:50%}.code-annotation-tip-content{word-wrap:break-word}.code-annotation-container-hidden{display:none !important}dl.code-annotation-container-grid{display:grid;grid-template-columns:min-content auto}dl.code-annotation-container-grid dt{grid-column:1}dl.code-annotation-container-grid dd{grid-column:2}pre.sourceCode.code-annotation-code{padding-right:0}code.sourceCode .code-annotation-anchor{z-index:100;position:relative;float:right;background-color:rgba(0,0,0,0)}input[type=checkbox]{margin-right:.5ch}:root{--mermaid-bg-color: #fff;--mermaid-edge-color: #999;--mermaid-node-fg-color: #000000;--mermaid-fg-color: #000000;--mermaid-fg-color--lighter: #1a1a1a;--mermaid-fg-color--lightest: #333333;--mermaid-font-family: Source Sans Pro, Helvetica, sans-serif;--mermaid-label-bg-color: #fff;--mermaid-label-fg-color: #468;--mermaid-node-bg-color: rgba(68, 102, 136, 0.1);--mermaid-node-fg-color: #000000}@media print{:root{font-size:11pt}#quarto-sidebar,#TOC,.nav-page{display:none}.page-columns .content{grid-column-start:page-start}.fixed-top{position:relative}.panel-caption,.figure-caption,figcaption{color:#666}}.code-copy-button{position:absolute;top:0;right:0;border:0;margin-top:5px;margin-right:5px;background-color:rgba(0,0,0,0);z-index:3}.code-copy-button:focus{outline:none}.code-copy-button-tooltip{font-size:.75em}pre.sourceCode:hover>.code-copy-button>.bi::before{display:inline-block;height:1rem;width:1rem;content:"";vertical-align:-0.125em;background-image:url('data:image/svg+xml,');background-repeat:no-repeat;background-size:1rem 1rem}pre.sourceCode:hover>.code-copy-button-checked>.bi::before{background-image:url('data:image/svg+xml,')}pre.sourceCode:hover>.code-copy-button:hover>.bi::before{background-image:url('data:image/svg+xml,')}pre.sourceCode:hover>.code-copy-button-checked:hover>.bi::before{background-image:url('data:image/svg+xml,')}.panel-tabset [role=tablist]{border-bottom:1px solid #999;list-style:none;margin:0;padding:0;width:100%}.panel-tabset [role=tablist] *{-webkit-box-sizing:border-box;box-sizing:border-box}@media(min-width: 30em){.panel-tabset [role=tablist] li{display:inline-block}}.panel-tabset [role=tab]{border:1px solid rgba(0,0,0,0);border-top-color:#999;display:block;padding:.5em 1em;text-decoration:none}@media(min-width: 30em){.panel-tabset [role=tab]{border-top-color:rgba(0,0,0,0);display:inline-block;margin-bottom:-1px}}.panel-tabset [role=tab][aria-selected=true]{background-color:#999}@media(min-width: 30em){.panel-tabset [role=tab][aria-selected=true]{background-color:rgba(0,0,0,0);border:1px solid #999;border-bottom-color:#fff}}@media(min-width: 30em){.panel-tabset [role=tab]:hover:not([aria-selected=true]){border:1px solid #999}}.code-with-filename .code-with-filename-file{margin-bottom:0;padding-bottom:2px;padding-top:2px;padding-left:.7em;border:var(--quarto-border-width) solid var(--quarto-border-color);border-radius:var(--quarto-border-radius);border-bottom:0;border-bottom-left-radius:0%;border-bottom-right-radius:0%}.code-with-filename div.sourceCode,.reveal .code-with-filename div.sourceCode{margin-top:0;border-top-left-radius:0%;border-top-right-radius:0%}.code-with-filename .code-with-filename-file pre{margin-bottom:0}.code-with-filename .code-with-filename-file{background-color:rgba(219,219,219,.8)}.quarto-dark .code-with-filename .code-with-filename-file{background-color:#555}.code-with-filename .code-with-filename-file strong{font-weight:400}.reveal.center .slide aside,.reveal.center .slide div.aside{position:initial}section.has-light-background,section.has-light-background h1,section.has-light-background h2,section.has-light-background h3,section.has-light-background h4,section.has-light-background h5,section.has-light-background h6{color:#222}section.has-light-background a,section.has-light-background a:hover{color:#2a76dd}section.has-light-background code{color:#4758ab}section.has-dark-background,section.has-dark-background h1,section.has-dark-background h2,section.has-dark-background h3,section.has-dark-background h4,section.has-dark-background h5,section.has-dark-background h6{color:#fff}section.has-dark-background a,section.has-dark-background a:hover{color:#42affa}section.has-dark-background code{color:#ffa07a}#title-slide,div.reveal div.slides section.quarto-title-block{text-align:center}#title-slide .subtitle,div.reveal div.slides section.quarto-title-block .subtitle{margin-bottom:2.5rem}.reveal .slides{text-align:left}.reveal .title-slide h1{font-size:1.6em}.reveal[data-navigation-mode=linear] .title-slide h1{font-size:2.5em}.reveal div.sourceCode{border:1px solid #999;border-radius:4px}.reveal pre{width:100%;box-shadow:none;background-color:#fff;border:none;margin:0;font-size:.55em}.reveal code{color:var(--quarto-hl-fu-color);background-color:rgba(0,0,0,0);white-space:pre-wrap}.reveal pre.sourceCode code{background-color:#fff;padding:6px 9px;max-height:500px;white-space:pre}.reveal pre code{background-color:#fff;color:#000}.reveal .column-output-location{display:flex;align-items:stretch}.reveal .column-output-location .column:first-of-type div.sourceCode{height:100%;background-color:#fff}.reveal blockquote{display:block;position:relative;color:#4d4d4d;width:unset;margin:var(--r-block-margin) auto;padding:.625rem 1.75rem;border-left:.25rem solid #4d4d4d;font-style:normal;background:none;box-shadow:none}.reveal blockquote p:first-child,.reveal blockquote p:last-child{display:block}.reveal .slide aside,.reveal .slide div.aside{position:absolute;bottom:20px;font-size:0.7em;color:#4d4d4d}.reveal .slide sup{font-size:0.7em}.reveal .slide.scrollable aside,.reveal .slide.scrollable div.aside{position:relative;margin-top:1em}.reveal .slide aside .aside-footnotes{margin-bottom:0}.reveal .slide aside .aside-footnotes li:first-of-type{margin-top:0}.reveal .layout-sidebar{display:flex;width:100%;margin-top:.8em}.reveal .layout-sidebar .panel-sidebar{width:270px}.reveal .layout-sidebar-left .panel-sidebar{margin-right:calc(0.5em*2)}.reveal .layout-sidebar-right .panel-sidebar{margin-left:calc(0.5em*2)}.reveal .layout-sidebar .panel-fill,.reveal .layout-sidebar .panel-center,.reveal .layout-sidebar .panel-tabset{flex:1}.reveal .panel-input,.reveal .panel-sidebar{font-size:.5em;padding:.5em;border-style:solid;border-color:#999;border-width:1px;border-radius:4px;background-color:#f8f9fa}.reveal .panel-sidebar :first-child,.reveal .panel-fill :first-child{margin-top:0}.reveal .panel-sidebar :last-child,.reveal .panel-fill :last-child{margin-bottom:0}.panel-input>div,.panel-input>div>div{vertical-align:middle;padding-right:1em}.reveal p,.reveal .slides section,.reveal .slides section>section{line-height:1.3}.reveal.smaller .slides section,.reveal .slides section.smaller,.reveal .slides section .callout{font-size:0.7em}.reveal.smaller .slides section section{font-size:inherit}.reveal.smaller .slides h1,.reveal .slides section.smaller h1{font-size:calc(2.5em/0.7)}.reveal.smaller .slides h2,.reveal .slides section.smaller h2{font-size:calc(1.6em/0.7)}.reveal.smaller .slides h3,.reveal .slides section.smaller h3{font-size:calc(1.3em/0.7)}.reveal .columns>.column>:not(ul,ol){margin-left:.25em;margin-right:.25em}.reveal .columns>.column:first-child>:not(ul,ol){margin-right:.5em;margin-left:0}.reveal .columns>.column:last-child>:not(ul,ol){margin-right:0;margin-left:.5em}.reveal .slide-number{color:#0ac8ff;background-color:#fff}.reveal .footer{color:#4d4d4d}.reveal .footer a{color:#00a6d6}.reveal .footer.has-dark-background{color:#fff}.reveal .footer.has-dark-background a{color:#7bc6fa}.reveal .footer.has-light-background{color:#505050}.reveal .footer.has-light-background a{color:#6a9bdd}.reveal .slide-number{color:#4d4d4d}.reveal .slide-number.has-dark-background{color:#fff}.reveal .slide-number.has-light-background{color:#505050}.reveal .slide figure>figcaption,.reveal .slide img.stretch+p.caption,.reveal .slide img.r-stretch+p.caption{font-size:0.7em}@media screen and (min-width: 500px){.reveal .controls[data-controls-layout=edges] .navigate-left{left:.2em}.reveal .controls[data-controls-layout=edges] .navigate-right{right:.2em}.reveal .controls[data-controls-layout=edges] .navigate-up{top:.4em}.reveal .controls[data-controls-layout=edges] .navigate-down{bottom:2.3em}}.tippy-box[data-theme~=light-border]{background-color:#fff;color:#000;border-radius:4px;border:solid 1px #4d4d4d;font-size:.6em}.tippy-box[data-theme~=light-border] .tippy-arrow{color:#4d4d4d}.tippy-box[data-placement^=bottom]>.tippy-content{padding:7px 10px;z-index:1}.reveal .callout.callout-style-simple .callout-body,.reveal .callout.callout-style-default .callout-body,.reveal .callout.callout-style-simple div.callout-title,.reveal .callout.callout-style-default div.callout-title{font-size:inherit}.reveal .callout.callout-style-default .callout-icon::before,.reveal .callout.callout-style-simple .callout-icon::before{height:2rem;width:2rem;background-size:2rem 2rem}.reveal .callout.callout-titled .callout-title p{margin-top:.5em}.reveal .callout.callout-titled .callout-icon::before{margin-top:1rem}.reveal .callout.callout-titled .callout-body>.callout-content>:last-child{margin-bottom:1rem}.reveal .panel-tabset [role=tab]{padding:.25em .7em}.reveal .slide-menu-button .fa-bars::before{background-image:url('data:image/svg+xml,')}.reveal .slide-chalkboard-buttons .fa-easel2::before{background-image:url('data:image/svg+xml,')}.reveal .slide-chalkboard-buttons .fa-brush::before{background-image:url('data:image/svg+xml,')}/*! light */.reveal ol[type=a]{list-style-type:lower-alpha}.reveal ol[type=a s]{list-style-type:lower-alpha}.reveal ol[type=A s]{list-style-type:upper-alpha}.reveal ol[type=i]{list-style-type:lower-roman}.reveal ol[type=i s]{list-style-type:lower-roman}.reveal ol[type=I s]{list-style-type:upper-roman}.reveal ol[type="1"]{list-style-type:decimal}.reveal ul.task-list{list-style:none}.reveal ul.task-list li input[type=checkbox]{width:2em;height:2em;margin:0 1em .5em -1.6em;vertical-align:middle}div.cell-output-display div.pagedtable-wrapper table.table{font-size:.6em}.reveal .code-annotation-container-hidden{display:none}.reveal code.sourceCode button.code-annotation-anchor,.reveal code.sourceCode .code-annotation-anchor{font-family:SFMono-Regular,Menlo,Monaco,Consolas,"Liberation Mono","Courier New",monospace;color:var(--quarto-hl-co-color);border:solid var(--quarto-hl-co-color) 1px;border-radius:50%;font-size:.7em;line-height:1.2em;margin-top:2px;user-select:none;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;-o-user-select:none}.reveal code.sourceCode button.code-annotation-anchor{cursor:pointer}.reveal code.sourceCode a.code-annotation-anchor{text-align:center;vertical-align:middle;text-decoration:none;cursor:default;height:1.2em;width:1.2em}.reveal code.sourceCode.fragment a.code-annotation-anchor{left:auto}.reveal #code-annotation-line-highlight-gutter{width:100%;border-top:solid var(--quarto-hl-co-color) 1px;border-bottom:solid var(--quarto-hl-co-color) 1px;z-index:2}.reveal #code-annotation-line-highlight{margin-left:-8em;width:calc(100% + 4em);border-top:solid var(--quarto-hl-co-color) 1px;border-bottom:solid var(--quarto-hl-co-color) 1px;z-index:2;margin-bottom:-2px}.reveal code.sourceCode .code-annotation-anchor.code-annotation-active{background-color:var(--quarto-hl-normal-color, #aaaaaa);border:solid var(--quarto-hl-normal-color, #aaaaaa) 1px;color:#fff;font-weight:bolder}.reveal pre.code-annotation-code{padding-top:0;padding-bottom:0}.reveal pre.code-annotation-code code{z-index:3;padding-left:0px}.reveal dl.code-annotation-container-grid{margin-left:.1em}.reveal dl.code-annotation-container-grid dt{margin-top:.65rem;font-family:SFMono-Regular,Menlo,Monaco,Consolas,"Liberation Mono","Courier New",monospace;border:solid #000 1px;border-radius:50%;height:1.3em;width:1.3em;line-height:1.3em;font-size:.5em;text-align:center;vertical-align:middle;text-decoration:none}.reveal dl.code-annotation-container-grid dd{margin-left:.25em}.reveal .scrollable ol li:first-child:nth-last-child(n+10),.reveal .scrollable ol li:first-child:nth-last-child(n+10)~li{margin-left:1em}html.print-pdf .reveal .slides .pdf-page:last-child{page-break-after:avoid}.reveal .quarto-title-block .quarto-title-authors{display:flex;justify-content:center}.reveal .quarto-title-block .quarto-title-authors .quarto-title-author{padding-left:.5em;padding-right:.5em}.reveal .quarto-title-block .quarto-title-authors .quarto-title-author a,.reveal .quarto-title-block .quarto-title-authors .quarto-title-author a:hover,.reveal .quarto-title-block .quarto-title-authors .quarto-title-author a:visited,.reveal .quarto-title-block .quarto-title-authors .quarto-title-author a:active{color:inherit;text-decoration:none}.reveal .quarto-title-block .quarto-title-authors .quarto-title-author .quarto-title-author-name{margin-bottom:.1rem}.reveal .quarto-title-block .quarto-title-authors .quarto-title-author .quarto-title-author-email{margin-top:0px;margin-bottom:.4em;font-size:.6em}.reveal .quarto-title-block .quarto-title-authors .quarto-title-author .quarto-title-author-orcid img{margin-bottom:4px}.reveal .quarto-title-block .quarto-title-authors .quarto-title-author .quarto-title-affiliation{font-size:.7em;margin-top:0px;margin-bottom:8px}.reveal .quarto-title-block .quarto-title-authors .quarto-title-author .quarto-title-affiliation:first{margin-top:12px}.reveal .slide blockquote{border-left:3px solid #4d4d4d;padding-left:.5em}.fragment{font-size:1.6rem}p{font-size:2.4rem}.psmaller{font-size:2rem}.caption{text-align:center}/*# sourceMappingURL=f95d2bded9c28492b788fe14c3e9f347.css.map */ +*/.ansi-black-fg{color:#3e424d}.ansi-black-bg{background-color:#3e424d}.ansi-black-intense-fg{color:#282c36}.ansi-black-intense-bg{background-color:#282c36}.ansi-red-fg{color:#e75c58}.ansi-red-bg{background-color:#e75c58}.ansi-red-intense-fg{color:#b22b31}.ansi-red-intense-bg{background-color:#b22b31}.ansi-green-fg{color:#00a250}.ansi-green-bg{background-color:#00a250}.ansi-green-intense-fg{color:#007427}.ansi-green-intense-bg{background-color:#007427}.ansi-yellow-fg{color:#ddb62b}.ansi-yellow-bg{background-color:#ddb62b}.ansi-yellow-intense-fg{color:#b27d12}.ansi-yellow-intense-bg{background-color:#b27d12}.ansi-blue-fg{color:#208ffb}.ansi-blue-bg{background-color:#208ffb}.ansi-blue-intense-fg{color:#0065ca}.ansi-blue-intense-bg{background-color:#0065ca}.ansi-magenta-fg{color:#d160c4}.ansi-magenta-bg{background-color:#d160c4}.ansi-magenta-intense-fg{color:#a03196}.ansi-magenta-intense-bg{background-color:#a03196}.ansi-cyan-fg{color:#60c6c8}.ansi-cyan-bg{background-color:#60c6c8}.ansi-cyan-intense-fg{color:#258f8f}.ansi-cyan-intense-bg{background-color:#258f8f}.ansi-white-fg{color:#c5c1b4}.ansi-white-bg{background-color:#c5c1b4}.ansi-white-intense-fg{color:#a1a6b2}.ansi-white-intense-bg{background-color:#a1a6b2}.ansi-default-inverse-fg{color:#fff}.ansi-default-inverse-bg{background-color:#000}.ansi-bold{font-weight:bold}.ansi-underline{text-decoration:underline}:root{--quarto-body-bg: #fff;--quarto-body-color: #000000;--quarto-text-muted: #4d4d4d;--quarto-border-color: #999999;--quarto-border-width: 1px;--quarto-border-radius: 4px}table.gt_table{color:var(--quarto-body-color);font-size:1em;width:100%;background-color:rgba(0,0,0,0);border-top-width:inherit;border-bottom-width:inherit;border-color:var(--quarto-border-color)}table.gt_table th.gt_column_spanner_outer{color:var(--quarto-body-color);background-color:rgba(0,0,0,0);border-top-width:inherit;border-bottom-width:inherit;border-color:var(--quarto-border-color)}table.gt_table th.gt_col_heading{color:var(--quarto-body-color);font-weight:bold;background-color:rgba(0,0,0,0)}table.gt_table thead.gt_col_headings{border-bottom:1px solid currentColor;border-top-width:inherit;border-top-color:var(--quarto-border-color)}table.gt_table thead.gt_col_headings:not(:first-child){border-top-width:1px;border-top-color:var(--quarto-border-color)}table.gt_table td.gt_row{border-bottom-width:1px;border-bottom-color:var(--quarto-border-color);border-top-width:0px}table.gt_table tbody.gt_table_body{border-top-width:1px;border-bottom-width:1px;border-bottom-color:var(--quarto-border-color);border-top-color:currentColor}div.columns{display:initial;gap:initial}div.column{display:inline-block;overflow-x:initial;vertical-align:top;width:50%}.code-annotation-tip-content{word-wrap:break-word}.code-annotation-container-hidden{display:none !important}dl.code-annotation-container-grid{display:grid;grid-template-columns:min-content auto}dl.code-annotation-container-grid dt{grid-column:1}dl.code-annotation-container-grid dd{grid-column:2}pre.sourceCode.code-annotation-code{padding-right:0}code.sourceCode .code-annotation-anchor{z-index:100;position:absolute;right:.5em;left:inherit;background-color:rgba(0,0,0,0)}:root{--mermaid-bg-color: #fff;--mermaid-edge-color: #999;--mermaid-node-fg-color: #000000;--mermaid-fg-color: #000000;--mermaid-fg-color--lighter: #1a1a1a;--mermaid-fg-color--lightest: #333333;--mermaid-font-family: Source Sans Pro, Helvetica, sans-serif;--mermaid-label-bg-color: #fff;--mermaid-label-fg-color: #468;--mermaid-node-bg-color: rgba(68, 102, 136, 0.1);--mermaid-node-fg-color: #000000}@media print{:root{font-size:11pt}#quarto-sidebar,#TOC,.nav-page{display:none}.page-columns .content{grid-column-start:page-start}.fixed-top{position:relative}.panel-caption,.figure-caption,figcaption{color:#666}}.code-copy-button{position:absolute;top:0;right:0;border:0;margin-top:5px;margin-right:5px;background-color:rgba(0,0,0,0);z-index:3}.code-copy-button:focus{outline:none}.code-copy-button-tooltip{font-size:.75em}pre.sourceCode:hover>.code-copy-button>.bi::before{display:inline-block;height:1rem;width:1rem;content:"";vertical-align:-0.125em;background-image:url('data:image/svg+xml,');background-repeat:no-repeat;background-size:1rem 1rem}pre.sourceCode:hover>.code-copy-button-checked>.bi::before{background-image:url('data:image/svg+xml,')}pre.sourceCode:hover>.code-copy-button:hover>.bi::before{background-image:url('data:image/svg+xml,')}pre.sourceCode:hover>.code-copy-button-checked:hover>.bi::before{background-image:url('data:image/svg+xml,')}.panel-tabset [role=tablist]{border-bottom:1px solid #999;list-style:none;margin:0;padding:0;width:100%}.panel-tabset [role=tablist] *{-webkit-box-sizing:border-box;box-sizing:border-box}@media(min-width: 30em){.panel-tabset [role=tablist] li{display:inline-block}}.panel-tabset [role=tab]{border:1px solid rgba(0,0,0,0);border-top-color:#999;display:block;padding:.5em 1em;text-decoration:none}@media(min-width: 30em){.panel-tabset [role=tab]{border-top-color:rgba(0,0,0,0);display:inline-block;margin-bottom:-1px}}.panel-tabset [role=tab][aria-selected=true]{background-color:#999}@media(min-width: 30em){.panel-tabset [role=tab][aria-selected=true]{background-color:rgba(0,0,0,0);border:1px solid #999;border-bottom-color:#fff}}@media(min-width: 30em){.panel-tabset [role=tab]:hover:not([aria-selected=true]){border:1px solid #999}}.code-with-filename .code-with-filename-file{margin-bottom:0;padding-bottom:2px;padding-top:2px;padding-left:.7em;border:var(--quarto-border-width) solid var(--quarto-border-color);border-radius:var(--quarto-border-radius);border-bottom:0;border-bottom-left-radius:0%;border-bottom-right-radius:0%}.code-with-filename div.sourceCode,.reveal .code-with-filename div.sourceCode{margin-top:0;border-top-left-radius:0%;border-top-right-radius:0%}.code-with-filename .code-with-filename-file pre{margin-bottom:0}.code-with-filename .code-with-filename-file,.code-with-filename .code-with-filename-file pre{background-color:rgba(219,219,219,.8)}.quarto-dark .code-with-filename .code-with-filename-file,.quarto-dark .code-with-filename .code-with-filename-file pre{background-color:#555}.code-with-filename .code-with-filename-file strong{font-weight:400}.reveal.center .slide aside,.reveal.center .slide div.aside{position:initial}section.has-light-background,section.has-light-background h1,section.has-light-background h2,section.has-light-background h3,section.has-light-background h4,section.has-light-background h5,section.has-light-background h6{color:#222}section.has-light-background a,section.has-light-background a:hover{color:#2a76dd}section.has-light-background code{color:#4758ab}section.has-dark-background,section.has-dark-background h1,section.has-dark-background h2,section.has-dark-background h3,section.has-dark-background h4,section.has-dark-background h5,section.has-dark-background h6{color:#fff}section.has-dark-background a,section.has-dark-background a:hover{color:#42affa}section.has-dark-background code{color:#ffa07a}#title-slide,div.reveal div.slides section.quarto-title-block{text-align:center}#title-slide .subtitle,div.reveal div.slides section.quarto-title-block .subtitle{margin-bottom:2.5rem}.reveal .slides{text-align:left}.reveal .title-slide h1{font-size:1.6em}.reveal[data-navigation-mode=linear] .title-slide h1{font-size:2.5em}.reveal div.sourceCode{border:1px solid #999;border-radius:4px}.reveal pre{width:100%;box-shadow:none;background-color:#fff;border:none;margin:0;font-size:.55em}.reveal code{color:var(--quarto-hl-fu-color);background-color:rgba(0,0,0,0);white-space:pre-wrap}.reveal pre.sourceCode code{background-color:#fff;padding:6px 9px;max-height:500px;white-space:pre}.reveal pre code{background-color:#fff;color:#000}.reveal .column-output-location{display:flex;align-items:stretch}.reveal .column-output-location .column:first-of-type div.sourceCode{height:100%;background-color:#fff}.reveal blockquote{display:block;position:relative;color:#4d4d4d;width:unset;margin:var(--r-block-margin) auto;padding:.625rem 1.75rem;border-left:.25rem solid #4d4d4d;font-style:normal;background:none;box-shadow:none}.reveal blockquote p:first-child,.reveal blockquote p:last-child{display:block}.reveal .slide aside,.reveal .slide div.aside{position:absolute;bottom:20px;font-size:0.7em;color:#4d4d4d}.reveal .slide sup{font-size:0.7em}.reveal .slide.scrollable aside,.reveal .slide.scrollable div.aside{position:relative;margin-top:1em}.reveal .slide aside .aside-footnotes{margin-bottom:0}.reveal .slide aside .aside-footnotes li:first-of-type{margin-top:0}.reveal .layout-sidebar{display:flex;width:100%;margin-top:.8em}.reveal .layout-sidebar .panel-sidebar{width:270px}.reveal .layout-sidebar-left .panel-sidebar{margin-right:calc(0.5em * 2)}.reveal .layout-sidebar-right .panel-sidebar{margin-left:calc(0.5em * 2)}.reveal .layout-sidebar .panel-fill,.reveal .layout-sidebar .panel-center,.reveal .layout-sidebar .panel-tabset{flex:1}.reveal .panel-input,.reveal .panel-sidebar{font-size:.5em;padding:.5em;border-style:solid;border-color:#999;border-width:1px;border-radius:4px;background-color:#f8f9fa}.reveal .panel-sidebar :first-child,.reveal .panel-fill :first-child{margin-top:0}.reveal .panel-sidebar :last-child,.reveal .panel-fill :last-child{margin-bottom:0}.panel-input>div,.panel-input>div>div{vertical-align:middle;padding-right:1em}.reveal p,.reveal .slides section,.reveal .slides section>section{line-height:1.3}.reveal.smaller .slides section,.reveal .slides section.smaller,.reveal .slides section .callout{font-size:0.7em}.reveal.smaller .slides h1,.reveal .slides section.smaller h1{font-size:calc(2.5em / 0.7)}.reveal.smaller .slides h2,.reveal .slides section.smaller h2{font-size:calc(1.6em / 0.7)}.reveal.smaller .slides h3,.reveal .slides section.smaller h3{font-size:calc(1.3em / 0.7)}.reveal .columns>.column>:not(ul,ol){margin-left:.25em;margin-right:.25em}.reveal .columns>.column:first-child>:not(ul,ol){margin-right:.5em;margin-left:0}.reveal .columns>.column:last-child>:not(ul,ol){margin-right:0;margin-left:.5em}.reveal .slide-number{color:#0ac8ff;background-color:#fff}.reveal .footer{color:#4d4d4d}.reveal .footer a{color:#00a6d6}.reveal .slide-number{color:#4d4d4d}.reveal .slide figure>figcaption,.reveal .slide img.stretch+p.caption,.reveal .slide img.r-stretch+p.caption{font-size:0.7em}@media screen and (min-width: 500px){.reveal .controls[data-controls-layout=edges] .navigate-left{left:.2em}.reveal .controls[data-controls-layout=edges] .navigate-right{right:.2em}.reveal .controls[data-controls-layout=edges] .navigate-up{top:.4em}.reveal .controls[data-controls-layout=edges] .navigate-down{bottom:2.3em}}.tippy-box[data-theme~=light-border]{background-color:#fff;color:#000;border-radius:4px;border:solid 1px #4d4d4d;font-size:.6em}.tippy-box[data-theme~=light-border] .tippy-arrow{color:#4d4d4d}.tippy-box[data-placement^=bottom]>.tippy-content{padding:7px 10px;z-index:1}.reveal .callout.callout-style-simple .callout-body,.reveal .callout.callout-style-default .callout-body,.reveal .callout.callout-style-simple div.callout-title,.reveal .callout.callout-style-default div.callout-title{font-size:inherit}.reveal .callout.callout-style-default .callout-icon::before,.reveal .callout.callout-style-simple .callout-icon::before{height:2rem;width:2rem;background-size:2rem 2rem}.reveal .callout.callout-titled .callout-title p{margin-top:.5em}.reveal .callout.callout-titled .callout-icon::before{margin-top:1rem}.reveal .callout.callout-titled .callout-body>.callout-content>:last-child{margin-bottom:1rem}.reveal .panel-tabset [role=tab]{padding:.25em .7em}.reveal .slide-menu-button .fa-bars::before{background-image:url('data:image/svg+xml,')}.reveal .slide-chalkboard-buttons .fa-easel2::before{background-image:url('data:image/svg+xml,')}.reveal .slide-chalkboard-buttons .fa-brush::before{background-image:url('data:image/svg+xml,')}/*! light */.reveal ol[type=a]{list-style-type:lower-alpha}.reveal ol[type=a s]{list-style-type:lower-alpha}.reveal ol[type=A s]{list-style-type:upper-alpha}.reveal ol[type=i]{list-style-type:lower-roman}.reveal ol[type=i s]{list-style-type:lower-roman}.reveal ol[type=I s]{list-style-type:upper-roman}.reveal ol[type="1"]{list-style-type:decimal}.reveal ul.task-list{list-style:none}.reveal ul.task-list li input[type=checkbox]{width:2em;height:2em;margin:0 1em .5em -1.6em;vertical-align:middle}div.cell-output-display div.pagedtable-wrapper table.table{font-size:.6em}.reveal .code-annotation-container-hidden{display:none}.reveal code.sourceCode button.code-annotation-anchor,.reveal code.sourceCode .code-annotation-anchor{font-family:SFMono-Regular,Menlo,Monaco,Consolas,"Liberation Mono","Courier New",monospace;color:var(--quarto-hl-co-color);border:solid var(--quarto-hl-co-color) 1px;border-radius:50%;font-size:.7em;line-height:1.2em;margin-top:2px}.reveal code.sourceCode button.code-annotation-anchor{cursor:pointer}.reveal code.sourceCode a.code-annotation-anchor{text-align:center;vertical-align:middle;text-decoration:none;cursor:default;height:1.2em;width:1.2em}.reveal #code-annotation-line-highlight-gutter{width:100%;border-top:solid var(--quarto-hl-co-color) 1px;border-bottom:solid var(--quarto-hl-co-color) 1px;z-index:2}.reveal #code-annotation-line-highlight{margin-left:-8em;width:calc(100% + 4em);border-top:solid var(--quarto-hl-co-color) 1px;border-bottom:solid var(--quarto-hl-co-color) 1px;z-index:2;margin-bottom:-2px}.reveal code.sourceCode .code-annotation-anchor.code-annotation-active{background-color:var(--quarto-hl-normal-color, #aaaaaa);border:solid var(--quarto-hl-normal-color, #aaaaaa) 1px;color:#fff;font-weight:bolder}.reveal pre.code-annotation-code{padding-top:0;padding-bottom:0}.reveal pre.code-annotation-code code{z-index:3;padding-left:0px}.reveal dl.code-annotation-container-grid{margin-left:.1em}.reveal dl.code-annotation-container-grid dt{margin-top:.65rem;font-family:SFMono-Regular,Menlo,Monaco,Consolas,"Liberation Mono","Courier New",monospace;border:solid #000 1px;border-radius:50%;height:1.3em;width:1.3em;line-height:1.3em;font-size:.5em;text-align:center;vertical-align:middle;text-decoration:none}.reveal dl.code-annotation-container-grid dd{margin-left:.25em}.reveal .scrollable ol li:first-child:nth-last-child(n+10),.reveal .scrollable ol li:first-child:nth-last-child(n+10)~li{margin-left:1em}.reveal .quarto-title-block .quarto-title-authors{display:flex;justify-content:center}.reveal .quarto-title-block .quarto-title-authors .quarto-title-author{padding-left:.5em;padding-right:.5em}.reveal .quarto-title-block .quarto-title-authors .quarto-title-author a,.reveal .quarto-title-block .quarto-title-authors .quarto-title-author a:hover,.reveal .quarto-title-block .quarto-title-authors .quarto-title-author a:visited,.reveal .quarto-title-block .quarto-title-authors .quarto-title-author a:active{color:inherit;text-decoration:none}.reveal .quarto-title-block .quarto-title-authors .quarto-title-author .quarto-title-author-name{margin-bottom:.1rem}.reveal .quarto-title-block .quarto-title-authors .quarto-title-author .quarto-title-author-email{margin-top:0px;margin-bottom:.4em;font-size:.6em}.reveal .quarto-title-block .quarto-title-authors .quarto-title-author .quarto-title-author-orcid img{margin-bottom:4px}.reveal .quarto-title-block .quarto-title-authors .quarto-title-author .quarto-title-affiliation{font-size:.7em;margin-top:0px;margin-bottom:8px}.reveal .quarto-title-block .quarto-title-authors .quarto-title-author .quarto-title-affiliation:first{margin-top:12px}.reveal .slide blockquote{border-left:3px solid #4d4d4d;padding-left:.5em}.fragment{font-size:1.6rem}p{font-size:2.4rem}.psmaller{font-size:2rem}.caption{text-align:center}/*# sourceMappingURL=f95d2bded9c28492b788fe14c3e9f347.css.map */ diff --git a/instructors/4-gis-slides.html b/instructors/4-gis-slides.html index cd154305..778dabc3 100644 --- a/instructors/4-gis-slides.html +++ b/instructors/4-gis-slides.html @@ -445,7 +445,7 @@

Learning objectives

-

What is OpenStreetMap? 🗺

+

What is OpenStreetMap?

@@ -463,7 +463,7 @@

What is OpenStreetMap? 🗺

-

What is OpenStreetMap? 🗾

+

What is OpenStreetMap?

Anyone can contribute, by:

-

OSM 🗾

+

OSM

The OSM information system relies on :

-

The Bounding Box ⬛

+

The Bounding Box

We first geocode our spatial text search and extract the corresponding polygon (geo_lite_sf) and then extract its bounding box (st_bbox).

nominatim_polygon <- nominatimlite::geo_lite_sf(address = "Brielle", points_only = FALSE)
@@ -501,7 +501,7 @@ 

The Bounding Box ⬛

-

The Bounding Box 🔳

+

The Bounding Box

A Problem with download? Try:

assign("has_internet_via_proxy", TRUE, environment(curl::has_internet))
@@ -735,11 +735,11 @@ 

Mapping urbanisation in Brielle

-

⏰ Challenge

+

Challenge

Import an interactive basemap layer under the buildings with Leaflet

-
+
20:00
@@ -754,11 +754,11 @@

⏰ Challenge

-

⏰ To submit your work in Zoom:

+

To submit your work in Zoom:

-

⏰ One solution

+

One solution

buildings2 <- buildings %>%
   st_transform(.,crs=4326)
@@ -772,8 +772,8 @@ 

⏰ One solution

highlightOptions = highlightOptions(color = "white", weight = 2, bringToFront = TRUE))
-
- +
+
@@ -812,7 +812,7 @@

Objectives:

-

the ‘sf’ package 📦

+

the ‘sf’ package

-

the ‘sf’ cheatsheet 🗾

+

the ‘sf’ cheatsheet

-

the ‘sf’ cheatsheet 🗾

+

the ‘sf’ cheatsheet

-

Conservation in Brielle, NL 🏭

+

Conservation in Brielle, NL

Let’s focus on old buildings and imagine we’re in charge of their conservation. We want to know how much of the city would be affected by a non-construction zone of 100m around pre-1800 buildings.

Let’s select them and see where they are.

-

Conservation in Brielle, NL 🏫

+

Conservation in Brielle, NL

old <- 1800 # year prior to which you consider a building old
 
@@ -851,12 +851,12 @@ 

Conservation in Brielle, NL 🏫

summary(buildings$start_date)
   Length     Class      Mode 
-    10604 character character 
+ 10601 character character
-

Conservation in Brielle, NL 🏨

+

Conservation in Brielle, NL

buildings$start_date <- as.numeric(as.character(buildings$start_date))
 
@@ -966,13 +966,14 @@ 

Centroids

Centroids

-
sf::sf_use_s2(FALSE) # s2 works with geographic projections, so to calculate centroids in projected CRS units (meters), we need to disable it.
-centroids_old <- st_centroid(old_buildings) %>%
-  st_transform(.,crs=28992)  
-
-ggplot() + 
-    geom_sf(data = single_old_buffer, aes(fill=ID)) +
-    geom_sf(data = centroids_old)
+
sf::sf_use_s2(FALSE)  # s2 works with geographic projections, so to calculate centroids in projected CRS units (meters), we need to disable it
+
+centroids_old <- st_centroid(old_buildings) %>%
+  st_transform(.,crs=28992)  
+
+ggplot() + 
+    geom_sf(data = single_old_buffer, aes(fill=ID)) +
+    geom_sf(data = centroids_old)
@@ -1031,12 +1032,12 @@

Final Output

-

⏰Challenge: Conservation rules have changed!

+

Challenge: Conservation rules have changed!

The historical threshold now applies to all pre-WWII buildings, but the distance to these building is reduced to 10m.

Can you map the number of all buildings per 10m fused buffer?

-
+
10:00
@@ -1106,10 +1107,10 @@

Problem

-

⏰ Challenge: visualise the density of old buildings

+

Challenge: visualise the density of old buildings

-
+
10:00
@@ -1160,7 +1161,7 @@

What’s next?

-

🦜 A few words of caution

+

A few words of caution

We have taught you to think, type, try, test, read the documentation. This is not only the old fashion way, but the foundation.

When you encounter a bug, a challenge, a question that we have not covered, you could always make use of:

    @@ -1170,12 +1171,12 @@

    🦜 A few words of caution

-

🦜 A few words of caution

+

A few words of caution

Be careful to keep it as a help, tool and support whose quality you can still assess.

They can provide fixes that you do not understand, answers that don’t make sense, and even wrong answers! So build yourself some foundations before you get into them.

-

🐰The end… wait!

+

The end… wait!

Any questions?

@@ -1225,7 +1226,7 @@

Call for helpers!

This strengthens the community… and it can bring you GS Credits.

-

🐰The end… for real!

+

The end… for real!