name: 1 class: center middle main-title section-title-4 # Vector Data Models for Geographic Information .class-info[ **Session 5** .light[HES597: Introduction to Spatial Data in R<br> Boise State University Human-Environment Systems<br> Fall 2021] ] --- name: outline class: title title-inv-5 # Plan for today -- What do we mean by vector data? -- Types of vector data -- Creating vector data in `R` -- Operations on vector data --- class: title title-inv-3 # Defining the vector data model ## __Vector data__ provide a way to represent real-world features in a GIS .pull-left[ * Useful for locations with discrete, well-defined boundaries * Very precise (not necessarily accurate) * Not the same as the `vector` data class ] --- class: center middle section-title section-title-2 animated fadeIn <figure> <img src="img/03/landscape_geometry.jpeg" alt="ZZZ" title="ZZZ" width="100%"> <figcaption>Image Source: QGIS User's manual </figcaption> </figure> --- layout: false name: types # Vector as a data model .pull-left[ * __Vertices__ (i.e., discrete x-y locations) define the shape of the vector * The organization of those vertices define the _shape_ of the vector * General types: points, lines, polygons ] .pull-right[ <figure> <img src="img/03/points-lines-polygons-vector-data-types.png" alt="ZZZ" title="ZZZ" width="100%"> <figcaption>Image Source: Colin Williams (NEON)</figcaption> </figure> ] --- # Representing vector data in R .pull-left[ * `sf` hierarchy reflects increasing complexity of geometry * `st_point`, `st_linestring`, `st_polygon` for single features * `st_multi*` for multiple features of the same type * `st_geometrycollection` for multiple feature types * `st_as_sfc` creates the geometry list column for many `sf` operations ] .pull-right[ <figure> <img src="img/03/sf-classes.png" alt="ZZZ" title="ZZZ" width="100%"> <figcaption>Simple feature types suppored in R (from Lovelace et al. 2020)</figcaption> </figure> ] --- layout: false name: types # Representing vector data in R * `sp` is more general, reflects increasing complexity of attributes: * Points, SpatialPoints, SpatialPointsDataframe * Lines, SpatialLines, SpatialLiinesDataframe * Polygon, SpatialPolygons, SpatialPolygonsDataframe --- layout: false name: create # Points ## `Spatial*` objects ```r library(sp) library(raster) #loaded to improve printing of Spatil objects proj <- CRS('+proj=longlat +datum=WGS84') long <- c(-116.7, -120.4, -116.7, -113.5, -115.5, -120.8, -119.5, -113.7, -113.7, -110.7) lat <- c(45.3, 42.6, 38.9, 42.1, 35.7, 38.9, 36.2, 39, 41.6, 36.9) pts <- SpatialPoints(cbind(long, lat), proj4string = proj) pts ``` ``` ## class : SpatialPoints ## features : 10 ## extent : -120.8, -110.7, 35.7, 45.3 (xmin, xmax, ymin, ymax) ## crs : +proj=longlat +datum=WGS84 +no_defs ``` --- # Points ## `sf` objects ```r library(sf) pts <- st_multipoint(cbind(long, lat)) str(pts) ``` ``` ## 'XY' num [1:10, 1:2] -117 -120 -117 -114 -116 ... ## - attr(*, "dimnames")=List of 2 ## ..$ : NULL ## ..$ : chr [1:2] "long" "lat" ``` ```r pts2 <- pts %>% st_sfc(., crs = st_crs(proj)) str(pts2) ``` ``` ## sfc_MULTIPOINT of length 1; first list element: 'XY' num [1:10, 1:2] -117 -120 -117 -114 -116 ... ## - attr(*, "dimnames")=List of 2 ## ..$ : NULL ## ..$ : chr [1:2] "long" "lat" ``` --- # Lines ## `Spatial*` objects .pull-left[ ```r lon <- c(-116.8, -114.2, -112.9, -111.9, -114.2, -115.4, -117.7) lat <- c(41.3, 42.9, 42.4, 39.8, 37.6, 38.3, 37.6) lonlat <- cbind(lon, lat) line1 <- Line(lonlat[1:3,]) line2 <- Line(lonlat[4:7,]) linelst <- Lines(list(line1), ID="a") linelst2 <- Lines(list(line2), ID="b") slines <- SpatialLines(list(linelst, linelst2), proj4string = proj) ``` ] .pull-right[ ```r plot(slines, col="blue") ``` <img src="03-slides_files/figure-html/splineplot-1.png" width="216" style="display: block; margin: auto;" /> ] --- # Lines ## `sf` objects .pull-left[ ```r lon <- c(-116.8, -114.2, -112.9, -111.9, -114.2, -115.4, -117.7) lat <- c(41.3, 42.9, 42.4, 39.8, 37.6, 38.3, 37.6) lonlat <- cbind(lon, lat) pts <- st_multipoint(lonlat) sfline <- st_multilinestring(list(pts[1:3,], pts[4:7,])) ``` ] .pull-right[ ```r plot(sfline, col="green") ``` <img src="03-slides_files/figure-html/sglineplot-1.png" width="216" style="display: block; margin: auto;" /> ] --- # Polygons ## `Spatial*` objects .pull-left[ ```r lon <- c(-116.8, -114.2, -112.9, -111.9, -114.2, -115.4, -117.7) lat <- c(41.3, 42.9, 42.4, 39.8, 37.6, 38.3, 37.6) lonlat <- cbind(lon, lat) poly <- Polygon(lonlat, hole=FALSE) polylst <- Polygons(list(poly), 's1') spP <- SpatialPolygons(list(polylst)) ``` ] .pull-right[ <img src="03-slides_files/figure-html/sppolyplot-1.png" width="216" style="display: block; margin: auto;" /> ] --- # Polygons ## `sf` objects .pull-left[ ```r outer = matrix(c(0,0,10,0,10,10,0,10,0,0),ncol=2, byrow=TRUE) hole1 = matrix(c(1,1,1,2,2,2,2,1,1,1),ncol=2, byrow=TRUE) hole2 = matrix(c(5,5,5,6,6,6,6,5,5,5),ncol=2, byrow=TRUE) pts = list(outer, hole1, hole2) pl1 = st_polygon(pts) ``` ] .pull-right[ ```r plot(pl1) ``` <img src="03-slides_files/figure-html/sfpolyplot-1.png" width="216" style="display: block; margin: auto;" /> ] --- # Common problems with vector data * Vectors and scale * Slivers and overlaps * Undershoots and overshoots * Self-intersections and rings ### _It can be very difficult to deal with topological errors in `R`_ --- layout: false name: types # Common operations on vector data > Moving forward we will rely primarily on the `sf` package for vector manipulation. I'll demonstrate a few common operations on vector data here. We'll explore more during the sections on database operations. If you need to `Spatial*` objects for particular functions (e.g., anything in `raster`), you can use `as(your.object, "Spatial")`. Both packages provide access to many of the 'spatial' backbones of `R` (like `geos` and `gdal`), they just differ in how the "verbs" are specified. For `sf` operations the `st_` prefix is typical. For `rgeos` operations, the `g` prefix is common. --- # Convert a data frame to `sf` object * Useful for situations where point locations given as columns in spreadsheet * Requires that you the projection used when the data were collected * Using the `meuse` dataset (use `?sp::meuse` to learn more about it) ```r data(meuse) head(meuse, n=3) ``` ``` ## x y cadmium copper lead zinc elev dist om ffreq soil lime ## 1 181072 333611 11.7 85 299 1022 7.909 0.00135803 13.6 1 1 1 ## 2 181025 333558 8.6 81 277 1141 6.983 0.01222430 14.0 1 1 1 ## 3 181165 333537 6.5 68 199 640 7.800 0.10302900 13.0 1 1 1 ## landuse dist.m ## 1 Ah 50 ## 2 Ah 30 ## 3 Ah 150 ``` --- # Convert a data frame to `sf` object * Using the `x` and `y` columns in the data .pull-left[ ```r meuse_sf = st_as_sf(meuse, coords = c("x", "y"), crs = 28992, agr = "constant") meuse_sf[1:3,] ``` ``` ## Simple feature collection with 3 features and 12 fields ## Attribute-geometry relationship: 12 constant, 0 aggregate, 0 identity ## Geometry type: POINT ## Dimension: XY ## Bounding box: xmin: 181025 ymin: 333537 xmax: 181165 ymax: 333611 ## Projected CRS: Amersfoort / RD New ## cadmium copper lead zinc elev dist om ffreq soil lime landuse dist.m ## 1 11.7 85 299 1022 7.909 0.00135803 13.6 1 1 1 Ah 50 ## 2 8.6 81 277 1141 6.983 0.01222430 14.0 1 1 1 Ah 30 ## 3 6.5 68 199 640 7.800 0.10302900 13.0 1 1 1 Ah 150 ## geometry ## 1 POINT (181072 333611) ## 2 POINT (181025 333558) ## 3 POINT (181165 333537) ``` ] .pull-right[ <img src="03-slides_files/figure-html/meuseplot-1.png" width="504" style="display: block; margin: auto;" /> ] --- # Buffer vectors * When we want our analysis to extend beyond the 'edges' of our study area * When we are trying to develop samples * Distance is in units of the CRS +proj=sterea +lat_0=52.1561605555556 +lon_0=5.38763888888889 +k=0.9999079 +x_0=155000 +y_0=463000 +ellps=bessel +units=m +no_defs .pull-left[ ```r meuse.buf <- st_buffer(meuse_sf, dist = 500) ``` ] .pull-right[ ```r plot(st_geometry(meuse.buf)) ``` <img src="03-slides_files/figure-html/plotmbuf-1.png" width="216" style="display: block; margin: auto;" /> ] --- # Estimate area, distance, (or length) ```r st_area(meuse.buf)[1:5] ``` ``` ## Units: [m^2] ## [1] 785039.3 785039.3 785039.3 785039.3 785039.3 ``` --- # Estimate area, distance, (or length) ```r st_distance(meuse_sf)[1:5, 1:5] ``` ``` ## Units: [m] ## [,1] [,2] [,3] [,4] [,5] ## [1,] 0.00000 70.83784 118.8486 259.2393 366.3141 ## [2,] 70.83784 0.00000 141.5662 282.8516 362.6403 ## [3,] 118.84864 141.56624 0.0000 143.1712 251.0239 ## [4,] 259.23927 282.85155 143.1712 0.0000 154.2628 ## [5,] 366.31407 362.64032 251.0239 154.2628 0.0000 ``` ```r st_distance(meuse.buf)[1:5,1:5] ``` ``` ## Units: [m] ## [,1] [,2] [,3] [,4] [,5] ## [1,] 0 0 0 0 0 ## [2,] 0 0 0 0 0 ## [3,] 0 0 0 0 0 ## [4,] 0 0 0 0 0 ## [5,] 0 0 0 0 0 ```