class: inverse, left, nonum, clear background-image: url("figs/oleron.jpg") background-size: cover .titlestyle1[GIS and mapping] <br> .titlestyle[A lecture on] <br> .titlestyle[on the GIS] <br> .titlestyle[and] <br> .titlestyle[mapping ecosystem of R] <link rel="stylesheet" type="text/css" href="//fonts.googleapis.com/css?family=Lora" /> <br><br><br><br> .captionstyle[Robin Lovelace & Jakub Nowosad] .captionstyle[2021-06-29, SIGR2021, Oleron] --- class: inverse, left, bottom # Hello! --- # Hi, I'm Robin .pull-left[ Website: https://www.robinlovelace.net/ Twitter: [robinlovelace](https://twitter.com/robinlovelace) 1. [I'm Associate Professor of Transport Data Science, University of Leeds](https://environment.leeds.ac.uk/transport/staff/953/dr-robin-lovelace) 2. [I am a co-author of Geocomputation with R book](https://geocompr.github.io/) 3. [I create R packages](https://github.com/robinlovelace) and publicly available web applications for evidence-based policies (see the Propensity to Cycle Tool at [www.pct.bike](https://www.pct.bike/) and the [ActDev](https://actdev.cyipt.bike/) project for recent examples) ] -- .pull-right[ ![](https://user-images.githubusercontent.com/1825120/110671502-79afbc80-81c6-11eb-9dc5-52046b1d04c8.gif) ] --- # Hi, I'm Jakub .pull-left[ Website: https://nowosad.github.io/ Twitter: [jakub_nowosad](https://twitter.com/jakub_nowosad) 1. [I am an assistant professor in the Department of Geoinformation at the Adam Mickiewicz University in Poznań](https://nowosad.github.io/publications/) 2. [I am a co-author of the Geocomputation with R book](https://geocompr.github.io/) 3. [I create R packages](https://nowosad.github.io/projects/) ] .pull-right[ <img src="figs/sa-changes.png" width="40%" /><img src="figs/cover.png" width="40%" /><img src="figs/logo-landscapemetrics.png" width="40%" /><img src="figs/logo-sabre.png" width="40%" /> ] --- # Where to ask questions: .pull-left[ ## During the course - GitHub for any technical questions + sharing code https://github.com/Nowosad/SIGR2021 - In the chat on [Slack](https://join.slack.com/t/geocomprworkspace/shared_invite/zt-sc7tqriq-9Q2rkveZwqCAQoBS3yqZNQ) (sign-in) - Feel free to post code here: https://rustpad.io/#uFuBVH (no sign-in) - In person ] .pull-right[ ## After the course - StackOverflow, general questions, quick answers - RStudio Community (R questions) - GIS StackExchange (for geographic data/software) - R-SIG-Geo email list (R-spatial questions) ] -- .pull-left[ Creating a reproducible example with reprex: 1. Find or write some code to test (e.g. `plot(spData::world)`) 2. Copy it (`Clt+C`) 3. Create a reproducible example with `reprex::reprex()` ``` r library(spData) plot(world) #> Error in data.matrix(x): 'list' object cannot be coerced to type 'double' ``` <sup>Created on 2021-06-29 by the [reprex package](https://reprex.tidyverse.org) (v2.0.0)</sup> ] .pull-right[ ``` r library(sf) library(spData) plot(world) ``` ![](https://geocompr.robinlovelace.net/02-spatial-data_files/figure-html/world-all-1.png) <sup>Created on 2021-06-29 by the [reprex package](https://reprex.tidyverse.org) (v2.0.0)</sup> ] --- class: inverse, left, bottom # GIS ecosystem of R --- # R spatial .left-column[ - Ecology - Earth-Observation - Economics - Demography - Politics - Journalism - Archeology - Transport - Climatology - Meteorology - Geomorphometry - Hydrology - Urban-Planning - Mining - Marine-Studies - Soil-Science - Tourism - and many more... ] .rc[ <a href="https://www.tylermw.com/3d-maps-with-rayshader/"> <img src="figs/montbayabove.gif" width="85%" style="display: block; margin: auto;" /> </a> <a href="https://www.mdpi.com/2306-5729/4/3/92"> <img src="figs/water-detection.png" width="85%" style="display: block; margin: auto;" /> </a> ] --- # R spatial .pull-left[ - Spatial aspect can be important in any part of data analysis - data preparation, vizualization, modeling, or communicating the results - It does not need to be the most important part - R is great to integrate various aspects of analysis <a href=" https://ikashnitsky.github.io/2018/the-lancet-paper/"> <img src="figs/demography-map.png" width="90%" style="display: block; margin: auto;" /> </a> ] .pull-right[ <a href="https://riatelab.github.io/MDM/"> <img src="figs/cartography-map.png" width="1600" style="display: block; margin: auto;" /> </a> <br> <a href="https://www.pct.bike/"> <img src="figs/pct-example2.png" width="1404" style="display: block; margin: auto;" /> </a> ] --- # R spatial .pull-left[ <a href="https://github.com/mtennekes/tmap/tree/master/demo/ClassicMap"> <img src="figs/tmap-map.png" width="2449" style="display: block; margin: auto;" /> </a> <a href="https://github.com/Z3tt/30DayMapChallenge"> <img src="figs/Zones_TimezonesEarth.png" width="8400" style="display: block; margin: auto;" /> </a> ] .pull-right[ - https://geocompr.github.io/ - https://www.rspatial.org/ - https://www.r-spatial.org/ - `#rspatial` and `#geocompr` on Twitter <a href="https://nowosad.github.io/post/maps-distortion/"> <img src="figs/worlds_animate_without_antarctica2.gif" style="display: block; margin: auto;" /> </a> ] --- # What can you do with geographic data + R? .lc[ - Exploratory data analysis ([EDA](https://r4ds.had.co.nz/exploratory-data-analysis.html)) - Output data in different formats (e.g. creating a .GeoTIFF or .shp file to share with others) - Data processing (e.g. adding new variables, 'adding value') - Data transformation (e.g. [changing CRS](https://geocompr.robinlovelace.net/reproj-geo-data.html), reducing size via simplification/aggregation) - Data [visualisation](https://geocompr.robinlovelace.net/adv-map.html#mapping-applications) - Web application development - Software development e.g. to share new methdods ] -- .rc[ <img src="https://user-images.githubusercontent.com/1825120/38543030-5794b6f0-3c9b-11e8-9da9-10ec1f3ea726.gif" width="100%" style="display: block; margin: auto;" /> ] --- # R is a (geo)computational power tool! .left-column[ #### R's flexibility enables 100s of people to create new tools #### R can be seen as the 'engine' that enables functionality provided in packages ![](https://openclipart.org/image/800px/98191) #### That provides flexibility but has some consequences... ] -- .right-column[ ### It's important to use the right tool for the job ![](https://user-images.githubusercontent.com/1825120/123144850-0f104d00-d454-11eb-80c1-5fb860d10482.gif) ] --- background-image: url("https://camo.githubusercontent.com/f032cac4c2273236d3d70f384b34f76a5cf70f9d00d4c868bed0ac3f5c3b52d4/68747470733a2f2f692e696d6775722e636f6d2f415478487764462e706e67") ### Which type of data is best? ??? Raster data tends to be more appropriate for physical sciences --- # Sharing your ideas with R ## R's ecosystem makes it easy to communicate your results <img src="https://user-images.githubusercontent.com/1825120/123699833-9a744e80-d857-11eb-9fde-3847970a04dc.png" style="display: block; margin: auto;" /> --- # Tips for sharing maps .pull-left[ - Copy paste into emails - Set width and resolution carefully for publication - Use vector graphics (e.g. svg/pdf) when appropriate - Save `tmap` maps with `tmap_save(map, "map.html")` and send the html - One click publishing with RStudio ## See rpubs.com/robinlovelace ] .pull-right[ ![](https://user-images.githubusercontent.com/1825120/123700406-56ce1480-d858-11eb-8d6b-961c61d94390.png) ] --- # Sharing your computational workflow See [excalidraw.com/](https://excalidraw.com/) for collaborative drawing app ![](https://user-images.githubusercontent.com/1825120/123762809-0e940e00-d8bb-11eb-8dab-0e881299bbef.png) --- # Building your own packages and distributing code .lc2[ **Great way to share code is on GitHub** Register at [github.com](https://github.com) <img src="https://github.githubassets.com/images/modules/logos_page/Octocat.png" width="20%" style="display: block; margin: auto;" /> Next step: reproducible README ```r usethis::use_readme_rmd() ``` **Example packages** - [stats19](https://docs.ropensci.org/stats19): data - [sabre](https://github.com/Nowosad/sabre): methods - [supercells](https://github.com/Nowosad/supercells): methods - [noise-phenomena](https://github.com/cboettig/noise-phenomena) academic paper ] .rc2[ <img src="https://raw.githubusercontent.com/hadley/r-pkgs/master/images/cover.png" width="80%" style="display: block; margin: auto;" /> ] --- # R packages - [**sf**](https://github.com/r-spatial/sf), [**sp**](https://github.com/edzer/sp), [**terra**](https://github.com/rspatial/terra), [**raster**](https://github.com/rspatial/raster), [**stars**](https://github.com/r-spatial/stars) - spatial classes - [**dplyr**](https://github.com/tidyverse/dplyr), [**rmapshaper**](https://github.com/ateucher/rmapshaper) - processing of attribute tables/geometries - [**rnaturalearth**](https://github.com/ropensci/rnaturalearth), [**osmdata**](https://github.com/ropensci/osmdata), [**getlandsat**](https://github.com/ropensci/getlandsat) - spatial data download - [**rgrass7**](https://github.com/rsbivand/rgrass7), [**qgisprocess**](https://github.com/paleolimbot/qgisprocess), [**RSAGA**](https://github.com/r-spatial/RSAGA), [**link2GI**](https://github.com/r-spatial/link2GI) - connecting with GIS software - [**gstat**](https://github.com/r-spatial/gstat), [**mlr3**](https://github.com/mlr-org/mlr3), [**CAST**](https://github.com/HannaMeyer/CAST) - spatial data modeling - [**rasterVis**](https://github.com/oscarperpinan/rastervis), [**tmap**](https://github.com/mtennekes/tmap), [**ggplot2**](https://github.com/tidyverse/ggplot2) - static visualizations - [**leaflet**](https://github.com/rstudio/leaflet), [**mapview**](https://github.com/r-spatial/mapview), [**mapdeck**](https://github.com/SymbolixAU/mapdeck) - interactive visualizations - many more... Learn more at https://cran.r-project.org/web/views/Spatial.html. --- # R packages - specialized packages - [**spatstat**](http://spatstat.org/) - [**spdep**](https://github.com/r-spatial/spdep) - [**spatialreg**](https://github.com/r-spatial/spatialreg) - [**dismo**](https://github.com/rspatial/dismo) - [**landscapemetrics**](https://github.com/r-spatialecology/landscapemetrics) - part of https://github.com/r-spatialecology - [**RStoolbox**](http://bleutner.github.io/RStoolbox/rstbx-docu/RStoolbox.html) - [**rayshader**](https://github.com/tylermorganwall/rayshader) - [**gdalcubes**](https://github.com/appelmar/gdalcubes_R) - many more... Learn more at https://cran.r-project.org/web/views/Spatial.html, https://cran.r-project.org/web/views/Environmetrics.html, and https://cran.r-project.org/web/views/SpatioTemporal.html. --- # R packages - [How to cite R packages?](https://neuropsychology.github.io/psycho.R//2018/08/31/cite_packages.html) ```r # citation() citation("tmap") ``` ``` ## ## To cite tmap/tmaptools in publications use: ## ## Tennekes M (2018). "tmap: Thematic Maps in R." _Journal of Statistical ## Software_, *84*(6), 1-39. doi: 10.18637/jss.v084.i06 (URL: ## https://doi.org/10.18637/jss.v084.i06). ## ## A BibTeX entry for LaTeX users is ## ## @Article{, ## title = {{tmap}: Thematic Maps in {R}}, ## author = {Martijn Tennekes}, ## journal = {Journal of Statistical Software}, ## year = {2018}, ## volume = {84}, ## number = {6}, ## pages = {1--39}, ## doi = {10.18637/jss.v084.i06}, ## } ``` --- # R spatial infrastructure <a href="https://www.r-spatial.org/r/2020/03/17/wkt.html"> <img src="figs/sf-infrastructure.png" width="75%" style="display: block; margin: auto;" /> </a> --- # OSGeo libraries .left-column[ **[PROJ](https://www.osgeo.org/projects/proj/)** - "conversion of coordinates" - First versions in [1970s](https://en.wikipedia.org/wiki/PROJ#cite_note-Kresse_Danko_2011_p._948-3) **[GDAL](https://www.osgeo.org/projects/gdal/)** - Geospatial Data Abstraction Library, first release 2000 - "200+ geospatial data formats" **[GEOS](https://www.osgeo.org/projects/gdal/)** - Geometry Engine – Open Source - "spatial predicate functions and spatial operators" ] .right-column[ <a href="https://www.osgeo.org/"> <img src="https://www.osgeo.org/wp-content/themes/roots/assets/img/logo-osgeo.svg" width="60%" style="display: block; margin: auto;" /> </a> <div class="figure" style="text-align: center"> <img src="figs/GEOS.png" alt="GEOS build matrix" width="90%" /> <p class="caption">GEOS build matrix</p> </div> .caption[Source: https://trac.osgeo.org/geos] - Access to these three libraries used to require **sp**, **rgdal** and **rgeos** - Now **sf** provides a unified access to all three 🎉 ] --- # R-GIS bridges You can call GIS algorithms directly from R using **qgisprocess**, **rgrass7**, **RSAGA**, or **arcgisbinding**. <img src="figs/gis-logos.png" width="80%" style="display: block; margin: auto;" /> --- class: inverse, left, bottom # Vector data model --- # Vector data model ecosystem of R .pull-left[ - The **sf** package is the successor of the **sp** package based on the OGC standard Simple Features - Combines the functionality of three previous packages: **sp**, **rgeos** and **rgdal** - Most of the functions in this package start with a prefix `st_` - This package handles additional vector data types (e.g. polygon and multipolygon are two separate classes), allows for easier data processing, and support for spatial databases such as PostGIS - https://r-spatial.github.io/sf/ and https://github.com/rstudio/cheatsheets/blob/master/sf.pdf ] .pull-right[ - The **terra** package has its own vector data classes. ] --- # sf reading ```r file_path = system.file("shapes/world.gpkg", package = "spData") file_path ``` ``` ## [1] "/home/jn/R/x86_64-redhat-linux-gnu-library/4.0/spData/shapes/world.gpkg" ``` ```r # world = read_sf(file_path) ``` ```r # Bad: not reproducible library(sf) world = read_sf("/home/jn/R/x86_64-redhat-linux-gnu-library/4.0/spData/shapes/world.gpkg") world ``` --- # sf reading ```r library(sf) file_path_txt = system.file("misc/cycle_hire_xy.csv", package = "spData") cycle_hire_xy = read.csv(file_path_txt) cycle_hire_sf = st_as_sf(cycle_hire_xy, coords = c("X", "Y")) cycle_hire_sf ``` ``` ## Simple feature collection with 742 features and 5 fields ## Geometry type: POINT ## Dimension: XY ## Bounding box: xmin: -0.2367699 ymin: 51.45475 xmax: -0.002275 ymax: 51.54214 ## CRS: NA ## First 10 features: ## id name area nbikes nempty ## 1 1 River Street Clerkenwell 4 14 ## 2 2 Phillimore Gardens Kensington 2 34 ## 3 3 Christopher Street Liverpool Street 0 32 ## 4 4 St. Chad's Street King's Cross 4 19 ## 5 5 Sedding Street Sloane Square 15 12 ## 6 6 Broadcasting House Marylebone 0 18 ## 7 7 Charlbert Street St. John's Wood 15 0 ## 8 8 Lodge Road St. John's Wood 5 13 ## 9 9 New Globe Walk Bankside 3 16 ## 10 10 Park Street Bankside 1 17 ## geometry ## 1 POINT (-0.1099705 51.52916) ## 2 POINT (-0.1975742 51.49961) ## 3 POINT (-0.08460569 51.52128) ## 4 POINT (-0.1209737 51.53006) ## 5 POINT (-0.156876 51.49313) ## 6 POINT (-0.1442289 51.51812) ## 7 POINT (-0.1680743 51.5343) ## 8 POINT (-0.1701345 51.52834) ## 9 POINT (-0.09644075 51.50739) ## 10 POINT (-0.09275416 51.50597) ``` --- # sf - Combines the functionality of three previous packages: **sp**, **rgeos** and **rgdal** - https://github.com/r-spatial/sf/wiki/Migrating - Conversion from `sf` to `sp`: ```r library(spData) library(sp) library(sf) world_sp = as(world, Class = "Spatial") # sp functions ... ``` - Conversion from `sp` to `sf`: ```r world_sf = st_as_sf(world_sp) ``` --- # sf - Most of the functions in this package start with a prefix `st_` ```r # lsf.str("package:sf") ls("package:sf") ``` ``` ## [1] "%>%" "as_Spatial" "dbDataType" ## [4] "dbWriteTable" "gdal_crs" "gdal_extract" ## [7] "gdal_inv_geotransform" "gdal_metadata" "gdal_polygonize" ## [10] "gdal_rasterize" "gdal_read" "gdal_read_mdim" ## [13] "gdal_subdatasets" "gdal_utils" "gdal_write" ## [16] "gdal_write_mdim" "get_key_pos" "NA_agr_" ## [19] "NA_bbox_" "NA_crs_" "NA_m_range_" ## [22] "NA_z_range_" "plot_sf" "rawToHex" ## [25] "read_sf" "sf_add_proj_units" "sf_extSoftVersion" ## [28] "sf_proj_info" "sf_proj_network" "sf_proj_pipelines" ## [31] "sf_proj_search_paths" "sf_project" "sf_use_s2" ## [34] "sf.colors" "st_agr" "st_agr<-" ## [37] "st_area" "st_as_binary" "st_as_grob" ## [40] "st_as_s2" "st_as_sf" "st_as_sfc" ## [43] "st_as_text" "st_axis_order" "st_bbox" ## [46] "st_bind_cols" "st_boundary" "st_buffer" ## [49] "st_cast" "st_centroid" "st_collection_extract" ## [52] "st_combine" "st_contains" "st_contains_properly" ## [55] "st_convex_hull" "st_coordinates" "st_covered_by" ## [58] "st_covers" "st_crop" "st_crosses" ## [61] "st_crs" "st_crs<-" "st_difference" ## [64] "st_dimension" "st_disjoint" "st_distance" ## [67] "st_drivers" "st_drop_geometry" "st_equals" ## [70] "st_equals_exact" "st_filter" "st_geometry" ## [73] "st_geometry_type" "st_geometry<-" "st_geometrycollection" ## [76] "st_graticule" "st_inscribed_circle" "st_interpolate_aw" ## [79] "st_intersection" "st_intersects" "st_is" ## [82] "st_is_empty" "st_is_longlat" "st_is_simple" ## [85] "st_is_valid" "st_is_within_distance" "st_jitter" ## [88] "st_join" "st_layers" "st_length" ## [91] "st_line_merge" "st_line_sample" "st_linestring" ## [94] "st_m_range" "st_make_grid" "st_make_valid" ## [97] "st_multilinestring" "st_multipoint" "st_multipolygon" ## [100] "st_nearest_feature" "st_nearest_points" "st_node" ## [103] "st_normalize" "st_overlaps" "st_point" ## [106] "st_point_on_surface" "st_polygon" "st_polygonize" ## [109] "st_precision" "st_precision<-" "st_read" ## [112] "st_read_db" "st_relate" "st_reverse" ## [115] "st_sample" "st_segmentize" "st_set_agr" ## [118] "st_set_crs" "st_set_geometry" "st_set_precision" ## [121] "st_sf" "st_sfc" "st_shift_longitude" ## [124] "st_simplify" "st_snap" "st_sym_difference" ## [127] "st_touches" "st_transform" "st_triangulate" ## [130] "st_union" "st_viewport" "st_voronoi" ## [133] "st_within" "st_wrap_dateline" "st_write" ## [136] "st_write_db" "st_z_range" "st_zm" ## [139] "vec_cast.sfc" "vec_ptype2.sfc" "write_sf" ``` - TAB --- # sf ```r library(spData) library(sf) world ``` ``` ## Simple feature collection with 177 features and 10 fields ## Geometry type: MULTIPOLYGON ## Dimension: XY ## Bounding box: xmin: -180 ymin: -89.9 xmax: 180 ymax: 83.64513 ## Geodetic CRS: WGS 84 ## # A tibble: 177 x 11 ## iso_a2 name_long continent region_un subregion type area_km2 pop lifeExp ## * <chr> <chr> <chr> <chr> <chr> <chr> <dbl> <dbl> <dbl> ## 1 FJ Fiji Oceania Oceania Melanesia Sove… 1.93e4 8.86e5 70.0 ## 2 TZ Tanzania Africa Africa Eastern … Sove… 9.33e5 5.22e7 64.2 ## 3 EH Western … Africa Africa Northern… Inde… 9.63e4 NA NA ## 4 CA Canada North Am… Americas Northern… Sove… 1.00e7 3.55e7 82.0 ## 5 US United S… North Am… Americas Northern… Coun… 9.51e6 3.19e8 78.8 ## 6 KZ Kazakhst… Asia Asia Central … Sove… 2.73e6 1.73e7 71.6 ## 7 UZ Uzbekist… Asia Asia Central … Sove… 4.61e5 3.08e7 71.0 ## 8 PG Papua Ne… Oceania Oceania Melanesia Sove… 4.65e5 7.76e6 65.2 ## 9 ID Indonesia Asia Asia South-Ea… Sove… 1.82e6 2.55e8 68.9 ## 10 AR Argentina South Am… Americas South Am… Sove… 2.78e6 4.30e7 76.3 ## # … with 167 more rows, and 2 more variables: gdpPercap <dbl>, ## # geom <MULTIPOLYGON [°]> ``` --- # sf ```r plot(world) ``` <img src="lecture_files/figure-html/05-rspatial-classes-7-1.png" style="display: block; margin: auto;" /> --- class: inverse, left, bottom # Raster data model --- # Raster data model ecosystem of R .pull-left[ **raster** and its successor **terra** <img src="figs/terra.png" width="40%" style="display: block; margin: auto;" /> - The **terra** package contains classes and methods representing raster objects - It allows raster data to be loaded and saved - It allows raster algebra and raster processing - It includes a number of additional functions, e.g., for analysis of terrain characteristics - It allows you to work on large sets of data - ?`terra-package`, https://rspatial.github.io/terra/reference/terra-package.html - It is a successor of the **raster** package - http://www.rpubs.com/etiennebr/visualraster ] -- .pull-right[ **stars** <img src="figs/cube2.png" width="80%" style="display: block; margin: auto;" /> - The **stars** package contains classes and methods representing spatiotemporal data (raster and vector data cubes) - It allows raster data to be loaded and saved - It allows raster processing - It allows you to work on large sets of data - It supports regular, rotated, sheared, rectilinear and curvilinear rasters - https://r-spatial.github.io/stars/ ] --- # terra The **terra** package contains classes and methods representing raster objects ```r library(spData) library(terra) rast(elev) ``` ``` ## class : SpatRaster ## dimensions : 6, 6, 1 (nrow, ncol, nlyr) ## resolution : 0.5, 0.5 (x, y) ## extent : -1.5, 1.5, -1.5, 1.5 (xmin, xmax, ymin, ymax) ## coord. ref. : +proj=longlat +ellps=WGS84 +towgs84=0,0,0,0,0,0,0 +no_defs ## source : memory ## name : layer ## min value : 1 ## max value : 36 ``` --- # terra ```r # plot(elev) ``` --- # terra ```r elev[] ``` ``` ## [1] 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 ## [26] 26 27 28 29 30 31 32 33 34 35 36 ``` --- # terra ```r raster_filepath = system.file("raster/srtm.tif", package = "spDataLarge") new_raster = rast(raster_filepath) new_raster ``` ``` ## class : SpatRaster ## dimensions : 457, 465, 1 (nrow, ncol, nlyr) ## resolution : 0.0008333333, 0.0008333333 (x, y) ## extent : -113.2396, -112.8521, 37.13208, 37.51292 (xmin, xmax, ymin, ymax) ## coord. ref. : +proj=longlat +datum=WGS84 +no_defs ## source : srtm.tif ## name : srtm ## min value : 1024 ## max value : 2892 ``` --- # terra ```r raster_filepath2 = system.file("raster/landsat.tif", package = "spDataLarge") new_raster2 = rast(raster_filepath2) plot(new_raster2) ``` <img src="lecture_files/figure-html/05-rspatial-classes-14-1.png" style="display: block; margin: auto;" /> --- # terra ```r plotRGB(new_raster2, r = 3, g = 2, b = 1, stretch = "lin") ``` <img src="lecture_files/figure-html/unnamed-chunk-24-1.png" style="display: block; margin: auto;" /> --- # terra .lc2[ ```r my_raster = rast(nrows = 10, ncols = 20, xmin = 0, xmax = 20, ymin = -10, ymax = 0, crs = "EPSG:4326", vals = 1:200) my_raster ``` ``` ## class : SpatRaster ## dimensions : 10, 20, 1 (nrow, ncol, nlyr) ## resolution : 1, 1 (x, y) ## extent : 0, 20, -10, 0 (xmin, xmax, ymin, ymax) ## coord. ref. : +proj=longlat +datum=WGS84 +no_defs ## source : memory ## name : lyr.1 ## min value : 1 ## max value : 200 ``` ] .rc2[ ```r plot(my_raster) ``` <img src="lecture_files/figure-html/unnamed-chunk-25-1.png" style="display: block; margin: auto;" /> ] --- # terra .lc2[ ```r my_raster2 = rast(res = c(1, 1), xmin = 0, xmax = 20, ymin = -10, ymax = 0, crs = "EPSG:4326", vals = 1:200) my_raster2 ``` ``` ## class : SpatRaster ## dimensions : 10, 20, 1 (nrow, ncol, nlyr) ## resolution : 1, 1 (x, y) ## extent : 0, 20, -10, 0 (xmin, xmax, ymin, ymax) ## coord. ref. : +proj=longlat +datum=WGS84 +no_defs ## source : memory ## name : lyr.1 ## min value : 1 ## max value : 200 ``` ] .rc2[ ```r plot(my_raster2) ``` <img src="lecture_files/figure-html/unnamed-chunk-26-1.png" style="display: block; margin: auto;" /> ] -- More about **terra** on Friday! --- class: inverse, left, bottom # Mapping ecosystem of R --- # Mapping ecosystem of R .pull-left[ Static maps: - **graphics** <!-- - **rasterVis** --> - **ggplot2** - **ggspatial** - **mapsf** - **cartography** - ... Interactive maps: - **leaflet** - **mapview** - **mapdeck** - ... ] .pull-right[ Both: - **tmap** Specific-purpose mapping: - **cartogram** - **geofacet** - **geogrid** - **rayshader** - ... ] --- # Mapping ecosystem of R .pull-left[ **tmap** - tmap is an R package for drawing thematic maps Its API is based on A Layered Grammar of Graphics https://www.jstatsoft.org/article/view/v090c01 ```r library(sf) library(tmap) nz = read_sf("data/new_zealand.gpkg") nz_ports = read_sf("data/nz_ports.gpkg") *tm_shape(nz) + tm_graticules() + * tm_polygons(col = "Median_income") + * tm_shape(nz_ports) + * tm_dots(size = 0.75) + tm_scale_bar(breaks = c(0, 100, 200)) + tm_compass(position = c("right", "top")) + tm_layout(bg.color = "lightblue") ``` **Shapes and layers** ] .pull-right[ <img src="lecture_files/figure-html/plot-label-out1-1.png" style="display: block; margin: auto;" /> ] --- # Mapping ecosystem of R .pull-left[ ```r library(sf) library(tmap) nz = read_sf("data/new_zealand.gpkg") nz_ports = read_sf("data/nz_ports.gpkg") tm_shape(nz) + tm_graticules() + tm_polygons(col = "Median_income") + tm_shape(nz_ports) + tm_dots(size = 0.75) + * tm_scale_bar(breaks = c(0, 100, 200)) + * tm_compass(position = c("right", "top")) + tm_layout(bg.color = "lightblue") ``` **Attributes layers** ] .pull-right[ <img src="lecture_files/figure-html/plot-label-out1b-1.png" style="display: block; margin: auto;" /> ] --- # Mapping ecosystem of R .pull-left[ ```r library(sf) library(tmap) nz = read_sf("data/new_zealand.gpkg") nz_ports = read_sf("data/nz_ports.gpkg") tm_shape(nz) + * tm_graticules() + tm_polygons(col = "Median_income") + tm_shape(nz_ports) + tm_dots(size = 0.75) + tm_scale_bar(breaks = c(0, 100, 200)) + tm_compass(position = c("right", "top")) + * tm_layout(bg.color = "lightblue") ``` **Other** More about **tmap** during the workshop. ] .pull-right[ <img src="lecture_files/figure-html/plot-label-out1c-1.png" style="display: block; margin: auto;" /> ] --- # graphics .pull-left[ ```r plot(nz) ``` ] .pull-right[ <img src="lecture_files/figure-html/plot-label-out2-1.png" style="display: block; margin: auto;" /> ] --- # graphics .pull-left[ ```r plot(st_geometry(nz)) ``` ] .pull-right[ <img src="lecture_files/figure-html/plot-label-out3-1.png" style="display: block; margin: auto;" /> ] --- # graphics .pull-left[ ```r library(RColorBrewer) par(bg = "lightblue") g = st_graticule(nz, lon = c(170, 175), lat = c(-45, -40, -35)) plot(nz["Median_income"], graticule = g, axes = TRUE, reset = FALSE, main = "Median income", breaks = c(22000, 24000, 26000, 28000, 30000, 32000, 34000), pal = brewer.pal(6, "YlOrRd")) plot(st_geometry(nz_ports), add = TRUE) ``` ] .pull-right[ <img src="lecture_files/figure-html/plot-label-out4-1.png" style="display: block; margin: auto;" /> ] --- # ggplot2 .pull-left[ ```r library(ggplot2) ggplot() + geom_sf(data = nz, aes(fill = Median_income)) + geom_sf(data = nz_ports, size = 3) + scale_fill_distiller(palette = "YlOrRd", direction = 1, name = "Median Income") + theme(panel.background = element_rect(fill = "lightblue")) ``` ] .pull-right[ <img src="lecture_files/figure-html/plot-label-out5-1.png" style="display: block; margin: auto;" /> ] --- # ggplot2 .pull-left[ ```r library(ggplot2) ggplot() + geom_sf(data = nz, aes(fill = Median_income)) + geom_sf(data = nz_ports, size = 3) + scale_fill_distiller(palette = "YlOrRd", direction = 1, name = "Median Income") + scale_x_continuous(breaks = c(170, 175, 180)) + theme(panel.background = element_rect(fill = "lightblue")) ``` ] .pull-right[ <img src="lecture_files/figure-html/plot-label-out6-1.png" style="display: block; margin: auto;" /> ] --- # ggspatial .pull-left[ ```r library(ggspatial) ggplot() + geom_sf(data = nz, aes(fill = Median_income)) + geom_sf(data = nz_ports, size = 3) + scale_fill_distiller(palette = "YlOrRd", direction = 1, name = "Median Income") + scale_x_continuous(breaks = c(170, 175, 180)) + annotation_scale(location = "br") + annotation_north_arrow(location = "tr", which_north = "true") + theme(panel.background = element_rect(fill = "lightblue")) ``` ] .pull-right[ <img src="lecture_files/figure-html/plot-label-out8-1.png" style="display: block; margin: auto;" /> ] --- # mapsf .pull-left[ ```r library(mapsf) g = st_graticule(nz, lon = c(170, 175), lat = c(-45, -40, -35)) mf_map(g, bg = "lightblue") mf_map(x = nz, var = "Median_income", type = "choro", breaks = "pretty", leg_title = "Median income", pal = "YlOrRd", add = TRUE) mf_arrow(pos = "topright") mf_scale() ``` ] .pull-right[ <img src="lecture_files/figure-html/plot-label-out9-1.png" style="display: block; margin: auto;" /> ] --- # leaflet .pull-left[ ```r library(leaflet) leaflet(nz) %>% addTiles() %>% addPolygons() ``` ] .pull-right[
] --- # leaflet .pull-left[ ```r library(leaflet) nz4326 = st_transform(nz, 4326) nz_ports4326 = st_transform(nz_ports, 4326) pal = colorBin("YlOrRd", domain = nz4326$Median_income) leaflet(nz4326) %>% addTiles() %>% addPolygons(fillOpacity = 1, weight = 1, fillColor = ~pal(Median_income)) %>% addLegend(pal = pal, values = ~Median_income, opacity = 1, title = "Median income") %>% addCircleMarkers(data = nz_ports4326) ``` ] .pull-right[
] --- # mapview .pull-left[ ```r library(mapview) mapview(nz["Median_income"]) + st_geometry(nz_ports) ``` ] .pull-right[
] --- # mapview .pull-left[ ```r library(mapview) library(RColorBrewer) mapview(nz, zcol = "Median_income", layer.name = "Median income", col.regions = brewer.pal(7, "YlOrRd")) + st_geometry(nz_ports) ``` ] .pull-right[
] --- # mapdeck .pull-left[ ```r library(mapdeck) nz4326 = st_transform(nz, 4326) nz4326$elev = (nz4326$Median_income/1000)^3.5 # Sys.setenv(MAPBOX_API_KEY = "xxxxxxxxxx") mapdeck(style = mapdeck_style("dark")) %>% add_polygon(data = nz4326, layer = "polygon_layer", fill_colour = "Median_income", elevation = "elev" ) ``` ] .pull-right[
] --- # ggplot2 (+ gganimate) .pull-left[ ```r library(ggplot2) library(sf) pzn_districts = read_sf("data/pzn_districts.gpkg") pzn_air = read_sf("data/pzn_pm10.gpkg") gp1 = ggplot() + geom_sf(data = pzn_districts) + geom_sf(data = pzn_air, aes(size = PM10_avg)) gp1 ``` ] .pull-right[ <img src="lecture_files/figure-html/plot-label-out15-1.png" style="display: block; margin: auto;" /> ] --- # ggplot2 (+ gganimate) .pull-left[ ```r library(gganimate) gp2 = gp1 + transition_time(Date) + labs(title = "Date: {frame_time}") + ease_aes("linear") + shadow_wake(wake_length = 0.1, alpha = FALSE) gp2 ``` ] .pull-right[ ![](figs/gp2.gif) ] --- # Other mapping packages .pull-left[ https://github.com/sjewo/cartogram <img src="figs/cartogram.png" width="672" style="display: block; margin: auto;" /> ] .pull-right[ https://hafen.github.io/geofacet/ <img src="figs/geogrid.png" width="672" style="display: block; margin: auto;" /> ] --- # Other mapping packages .pull-left[ https://github.com/schochastics/edgebundle <img src="figs/edgebundle.png" width="672" style="display: block; margin: auto;" /> ] .pull-right[ https://www.rayshader.com/ <img src="figs/rayshader.png" width="672" style="display: block; margin: auto;" /> ] --- class: inverse, left, bottom # Coordinate reference systems --- # Coordinates - numbers describing positions in space .pull-left[ **Geographic coordinates**: angles (degrees; longitude and latitude) pointing out locations on a spherical or ellipsoidal surface (*ellipsoid - a mathematical approximation of the size and shape of the earth*) <img src="lecture_files/figure-html/unnamed-chunk-34-1.png" style="display: block; margin: auto;" /> ] .pull-right[ **Projected coordinates**: measured on a two-dimensional flat space (e.g. in meters; x and y), related to an ellipsoid by projection <img src="lecture_files/figure-html/unnamed-chunk-35-1.png" style="display: block; margin: auto;" /> ] --- # Coordinate reference system (CRS) **Coordinate reference system: a set of information describing the system used to locate objects in space.** **It includes:** - a set of mathematical rules for specifying how coordinates are to be assigned to points - a set of parameters that define the position of the origin, the scale, and the orientation of a coordinate system (a datum) ---- **Two main groups of CRS:** - Geographic coordinate reference systems, GCRS - composed of an ellipsoid and a datum; units in degrees - Projected coordinate reference systems, PCRS - based on a GCRS and a projection --- # How to describe CRS? .pull-left[ **Two main current methods (see on the right):** - CRS codes, e.g., EPSG:4326 - `WKT2` **One (currently discouraged in most cases) method:** - `proj4string` - +proj=longlat +datum=WGS84 +no_defs ---- *More information:* - https://proj.org/usage/projections.html - https://spatialreference.org/ref/epsg/ - https://www.youtube.com/watch?v=Va0STgco7-4 (especially 10:47-27:48) - https://www.gaia-gis.it/fossil/libspatialite/wiki?name=PROJ.6 - https://ihatecoordinatesystems.com/ ] .pull-right[ .tiny[ ``` ## Coordinate Reference System: ## User input: EPSG:4326 ## wkt: ## GEOGCRS["WGS 84", ## DATUM["World Geodetic System 1984", ## ELLIPSOID["WGS 84",6378137,298.257223563, ## LENGTHUNIT["metre",1]]], ## PRIMEM["Greenwich",0, ## ANGLEUNIT["degree",0.0174532925199433]], ## CS[ellipsoidal,2], ## AXIS["geodetic latitude (Lat)",north, ## ORDER[1], ## ANGLEUNIT["degree",0.0174532925199433]], ## AXIS["geodetic longitude (Lon)",east, ## ORDER[2], ## ANGLEUNIT["degree",0.0174532925199433]], ## USAGE[ ## SCOPE["Horizontal component of 3D system."], ## AREA["World."], ## BBOX[-90,-180,90,180]], ## ID["EPSG",4326]] ``` ] ] <!-- A coordinate reference sytem (CRS) describes how coordinates are to be interpreted: which location on Earth do they refer to. In case of projected coordinates the CRS contains the projection type and parameters, in all cases which reference ellipsoid the original geographic coordinates are associated with (e.g., WGS84, or NAD27). --> --- # Getting CRS - vector data ```r library(spData) library(sf) ``` .pull-left[ .tiny[ ```r st_crs(world) ``` ``` ## Coordinate Reference System: ## User input: EPSG:4326 ## wkt: ## GEOGCRS["WGS 84", ## DATUM["World Geodetic System 1984", ## ELLIPSOID["WGS 84",6378137,298.257223563, ## LENGTHUNIT["metre",1]]], ## PRIMEM["Greenwich",0, ## ANGLEUNIT["degree",0.0174532925199433]], ## CS[ellipsoidal,2], ## AXIS["geodetic latitude (Lat)",north, ## ORDER[1], ## ANGLEUNIT["degree",0.0174532925199433]], ## AXIS["geodetic longitude (Lon)",east, ## ORDER[2], ## ANGLEUNIT["degree",0.0174532925199433]], ## USAGE[ ## SCOPE["Horizontal component of 3D system."], ## AREA["World."], ## BBOX[-90,-180,90,180]], ## ID["EPSG",4326]] ``` ] ] .pull-right[ .tiny[ ```r st_crs(world)$proj4string ``` ``` ## [1] "+proj=longlat +datum=WGS84 +no_defs" ``` ```r st_crs(world)$epsg ``` ``` ## [1] 4326 ``` ```r st_crs(world)$wkt ``` ``` ## [1] "GEOGCRS[\"WGS 84\",\n DATUM[\"World Geodetic System 1984\",\n ELLIPSOID[\"WGS 84\",6378137,298.257223563,\n LENGTHUNIT[\"metre\",1]]],\n PRIMEM[\"Greenwich\",0,\n ANGLEUNIT[\"degree\",0.0174532925199433]],\n CS[ellipsoidal,2],\n AXIS[\"geodetic latitude (Lat)\",north,\n ORDER[1],\n ANGLEUNIT[\"degree\",0.0174532925199433]],\n AXIS[\"geodetic longitude (Lon)\",east,\n ORDER[2],\n ANGLEUNIT[\"degree\",0.0174532925199433]],\n USAGE[\n SCOPE[\"Horizontal component of 3D system.\"],\n AREA[\"World.\"],\n BBOX[-90,-180,90,180]],\n ID[\"EPSG\",4326]]" ``` ] ] --- # Getting CRS - raster data ```r library(spData) library(terra) elev = rast(elev) ``` .pull-left[ .tiny[ ```r crs(elev, describe = TRUE) ``` ``` ## name EPSG area extent ## 1 unknown <NA> <NA> NA, NA, NA, NA ``` ```r crs(elev) ``` ``` ## [1] "BOUNDCRS[\n SOURCECRS[\n GEOGCRS[\"unknown\",\n DATUM[\"World Geodetic System 1984\",\n ELLIPSOID[\"WGS 84\",6378137,298.257223563,\n LENGTHUNIT[\"metre\",1]],\n ID[\"EPSG\",6326]],\n PRIMEM[\"Greenwich\",0,\n ANGLEUNIT[\"degree\",0.0174532925199433],\n ID[\"EPSG\",8901]],\n CS[ellipsoidal,2],\n AXIS[\"longitude\",east,\n ORDER[1],\n ANGLEUNIT[\"degree\",0.0174532925199433,\n ID[\"EPSG\",9122]]],\n AXIS[\"latitude\",north,\n ORDER[2],\n ANGLEUNIT[\"degree\",0.0174532925199433,\n ID[\"EPSG\",9122]]]]],\n TARGETCRS[\n GEOGCRS[\"WGS 84\",\n DATUM[\"World Geodetic System 1984\",\n ELLIPSOID[\"WGS 84\",6378137,298.257223563,\n LENGTHUNIT[\"metre\",1]]],\n PRIMEM[\"Greenwich\",0,\n ANGLEUNIT[\"degree\",0.0174532925199433]],\n CS[ellipsoidal,2],\n AXIS[\"latitude\",north,\n ORDER[1],\n ANGLEUNIT[\"degree\",0.0174532925199433]],\n AXIS[\"longitude\",east,\n ORDER[2],\n ANGLEUNIT[\"degree\",0.0174532925199433]],\n ID[\"EPSG\",4326]]],\n ABRIDGEDTRANSFORMATION[\"Transformation from unknown to WGS84\",\n METHOD[\"Geocentric translations (geog2D domain)\",\n ID[\"EPSG\",9603]],\n PARAMETER[\"X-axis translation\",0,\n ID[\"EPSG\",8605]],\n PARAMETER[\"Y-axis translation\",0,\n ID[\"EPSG\",8606]],\n PARAMETER[\"Z-axis translation\",0,\n ID[\"EPSG\",8607]]]]" ``` ] ] .pull-right[ .tiny[ ```r st_crs(elev) ``` ``` ## Coordinate Reference System: ## User input: BOUNDCRS[ ## SOURCECRS[ ## GEOGCRS["unknown", ## DATUM["World Geodetic System 1984", ## ELLIPSOID["WGS 84",6378137,298.257223563, ## LENGTHUNIT["metre",1]], ## ID["EPSG",6326]], ## PRIMEM["Greenwich",0, ## ANGLEUNIT["degree",0.0174532925199433], ## ID["EPSG",8901]], ## CS[ellipsoidal,2], ## AXIS["longitude",east, ## ORDER[1], ## ANGLEUNIT["degree",0.0174532925199433, ## ID["EPSG",9122]]], ## AXIS["latitude",north, ## ORDER[2], ## ANGLEUNIT["degree",0.0174532925199433, ## ID["EPSG",9122]]]]], ## TARGETCRS[ ## GEOGCRS["WGS 84", ## DATUM["World Geodetic System 1984", ## ELLIPSOID["WGS 84",6378137,298.257223563, ## LENGTHUNIT["metre",1]]], ## PRIMEM["Greenwich",0, ## ANGLEUNIT["degree",0.0174532925199433]], ## CS[ellipsoidal,2], ## AXIS["latitude",north, ## ORDER[1], ## ANGLEUNIT["degree",0.0174532925199433]], ## AXIS["longitude",east, ## ORDER[2], ## ANGLEUNIT["degree",0.0174532925199433]], ## ID["EPSG",4326]]], ## ABRIDGEDTRANSFORMATION["Transformation from unknown to WGS84", ## METHOD["Geocentric translations (geog2D domain)", ## ID["EPSG",9603]], ## PARAMETER["X-axis translation",0, ## ID["EPSG",8605]], ## PARAMETER["Y-axis translation",0, ## ID["EPSG",8606]], ## PARAMETER["Z-axis translation",0, ## ID["EPSG",8607]]]] ## wkt: ## BOUNDCRS[ ## SOURCECRS[ ## GEOGCRS["unknown", ## DATUM["World Geodetic System 1984", ## ELLIPSOID["WGS 84",6378137,298.257223563, ## LENGTHUNIT["metre",1]], ## ID["EPSG",6326]], ## PRIMEM["Greenwich",0, ## ANGLEUNIT["degree",0.0174532925199433], ## ID["EPSG",8901]], ## CS[ellipsoidal,2], ## AXIS["longitude",east, ## ORDER[1], ## ANGLEUNIT["degree",0.0174532925199433, ## ID["EPSG",9122]]], ## AXIS["latitude",north, ## ORDER[2], ## ANGLEUNIT["degree",0.0174532925199433, ## ID["EPSG",9122]]]]], ## TARGETCRS[ ## GEOGCRS["WGS 84", ## DATUM["World Geodetic System 1984", ## ELLIPSOID["WGS 84",6378137,298.257223563, ## LENGTHUNIT["metre",1]]], ## PRIMEM["Greenwich",0, ## ANGLEUNIT["degree",0.0174532925199433]], ## CS[ellipsoidal,2], ## AXIS["geodetic latitude (Lat)",north, ## ORDER[1], ## ANGLEUNIT["degree",0.0174532925199433]], ## AXIS["geodetic longitude (Lon)",east, ## ORDER[2], ## ANGLEUNIT["degree",0.0174532925199433]], ## ID["EPSG",4326]]], ## ABRIDGEDTRANSFORMATION["Transformation from unknown to WGS84", ## METHOD["Geocentric translations (geog2D domain)", ## ID["EPSG",9603]], ## PARAMETER["X-axis translation",0, ## ID["EPSG",8605]], ## PARAMETER["Y-axis translation",0, ## ID["EPSG",8606]], ## PARAMETER["Z-axis translation",0, ## ID["EPSG",8607]]]] ``` ] ] --- class: inverse, left, bottom # Geocomputation --- # What is Geocomputation? .pull-left[ > GeoComputation is about using the various different types of geodata and about developing relevant geo-tools within the overall context of a 'scientific' approach (Openshaw 2000). ] .pull-right[ <img src="figs/s.openshaw.png" width="309" style="display: block; margin: auto;" /> ] -- - But we do differ from early definitions in one important way: > At the turn of the 21st Century it was unrealistic to expect readers to be able to reproduce code examples, due to barriers preventing access to the necessary hardware, software and data --- # What's in the geocompr box? .pull-left[ - Chapter 1: History + 'philosophy' = important Foundations - Starting from nothing - Class definitions - Spatial/attribute operations - Projections - Data IO Extensions - Advanced methods - How to build your own functions Applications - A taster of what you can do ] .pull-right[ <img src="https://raw.githubusercontent.com/Robinlovelace/geocompr/master/images/frontcover.png" width="100%" style="display: block; margin: auto;" /> ] --- class: inverse, left, bottom # Summary --- # Summary .pull-left[ ## Resources: https://geocompr.github.io/ https://nowosad.github.io https://www.robinlovelace.net/ ] .pull-right[ ## Contact: <svg viewBox="0 0 512 512" style="height:1em;position:relative;display:inline-block;top:.1em;" xmlns="http://www.w3.org/2000/svg"> <path d="M459.37 151.716c.325 4.548.325 9.097.325 13.645 0 138.72-105.583 298.558-298.558 298.558-59.452 0-114.68-17.219-161.137-47.106 8.447.974 16.568 1.299 25.34 1.299 49.055 0 94.213-16.568 130.274-44.832-46.132-.975-84.792-31.188-98.112-72.772 6.498.974 12.995 1.624 19.818 1.624 9.421 0 18.843-1.3 27.614-3.573-48.081-9.747-84.143-51.98-84.143-102.985v-1.299c13.969 7.797 30.214 12.67 47.431 13.319-28.264-18.843-46.781-51.005-46.781-87.391 0-19.492 5.197-37.36 14.294-52.954 51.655 63.675 129.3 105.258 216.365 109.807-1.624-7.797-2.599-15.918-2.599-24.04 0-57.828 46.782-104.934 104.934-104.934 30.213 0 57.502 12.67 76.67 33.137 23.715-4.548 46.456-13.32 66.599-25.34-7.798 24.366-24.366 44.833-46.132 57.827 21.117-2.273 41.584-8.122 60.426-16.243-14.292 20.791-32.161 39.308-52.628 54.253z"></path></svg> #rspatial <svg viewBox="0 0 512 512" style="height:1em;position:relative;display:inline-block;top:.1em;" xmlns="http://www.w3.org/2000/svg"> <path d="M459.37 151.716c.325 4.548.325 9.097.325 13.645 0 138.72-105.583 298.558-298.558 298.558-59.452 0-114.68-17.219-161.137-47.106 8.447.974 16.568 1.299 25.34 1.299 49.055 0 94.213-16.568 130.274-44.832-46.132-.975-84.792-31.188-98.112-72.772 6.498.974 12.995 1.624 19.818 1.624 9.421 0 18.843-1.3 27.614-3.573-48.081-9.747-84.143-51.98-84.143-102.985v-1.299c13.969 7.797 30.214 12.67 47.431 13.319-28.264-18.843-46.781-51.005-46.781-87.391 0-19.492 5.197-37.36 14.294-52.954 51.655 63.675 129.3 105.258 216.365 109.807-1.624-7.797-2.599-15.918-2.599-24.04 0-57.828 46.782-104.934 104.934-104.934 30.213 0 57.502 12.67 76.67 33.137 23.715-4.548 46.456-13.32 66.599-25.34-7.798 24.366-24.366 44.833-46.132 57.827 21.117-2.273 41.584-8.122 60.426-16.243-14.292 20.791-32.161 39.308-52.628 54.253z"></path></svg> #geocompr <svg viewBox="0 0 512 512" style="height:1em;position:relative;display:inline-block;top:.1em;" xmlns="http://www.w3.org/2000/svg"> <path d="M459.37 151.716c.325 4.548.325 9.097.325 13.645 0 138.72-105.583 298.558-298.558 298.558-59.452 0-114.68-17.219-161.137-47.106 8.447.974 16.568 1.299 25.34 1.299 49.055 0 94.213-16.568 130.274-44.832-46.132-.975-84.792-31.188-98.112-72.772 6.498.974 12.995 1.624 19.818 1.624 9.421 0 18.843-1.3 27.614-3.573-48.081-9.747-84.143-51.98-84.143-102.985v-1.299c13.969 7.797 30.214 12.67 47.431 13.319-28.264-18.843-46.781-51.005-46.781-87.391 0-19.492 5.197-37.36 14.294-52.954 51.655 63.675 129.3 105.258 216.365 109.807-1.624-7.797-2.599-15.918-2.599-24.04 0-57.828 46.782-104.934 104.934-104.934 30.213 0 57.502 12.67 76.67 33.137 23.715-4.548 46.456-13.32 66.599-25.34-7.798 24.366-24.366 44.833-46.132 57.827 21.117-2.273 41.584-8.122 60.426-16.243-14.292 20.791-32.161 39.308-52.628 54.253z"></path></svg> jakub_nowosad <svg viewBox="0 0 512 512" style="height:1em;position:relative;display:inline-block;top:.1em;" xmlns="http://www.w3.org/2000/svg"> <path d="M459.37 151.716c.325 4.548.325 9.097.325 13.645 0 138.72-105.583 298.558-298.558 298.558-59.452 0-114.68-17.219-161.137-47.106 8.447.974 16.568 1.299 25.34 1.299 49.055 0 94.213-16.568 130.274-44.832-46.132-.975-84.792-31.188-98.112-72.772 6.498.974 12.995 1.624 19.818 1.624 9.421 0 18.843-1.3 27.614-3.573-48.081-9.747-84.143-51.98-84.143-102.985v-1.299c13.969 7.797 30.214 12.67 47.431 13.319-28.264-18.843-46.781-51.005-46.781-87.391 0-19.492 5.197-37.36 14.294-52.954 51.655 63.675 129.3 105.258 216.365 109.807-1.624-7.797-2.599-15.918-2.599-24.04 0-57.828 46.782-104.934 104.934-104.934 30.213 0 57.502 12.67 76.67 33.137 23.715-4.548 46.456-13.32 66.599-25.34-7.798 24.366-24.366 44.833-46.132 57.827 21.117-2.273 41.584-8.122 60.426-16.243-14.292 20.791-32.161 39.308-52.628 54.253z"></path></svg> robinlovelace ]