--- title: "prepr: Automatic Repair of Spatial Polygons" output: rmarkdown::html_vignette: toc: true fig_caption: true fontsize: 11pt documentclass: article vignette: > %\VignetteIndexEntry{prepr: Automatic Repair of Spatial Polygons} %\VignetteEngine{knitr::rmarkdown_notangle} --- ```{r, include = FALSE} # define variables for vignette figures and code execution h <- 4.0 w <- 7.0 is_check <- ("CheckExEnv" %in% search()) || any(c("_R_CHECK_TIMINGS_", "_R_CHECK_LICENSE_") %in% names(Sys.getenv())) || !identical(Sys.getenv("MY_UNIVERSE"), "") knitr::opts_chunk$set( fig.align = "center", eval = !is_check, purl = !is_check, R.options = list(width = 80) ) ``` ## Introduction The _prepr R_ R package is used to repair broken spatial polygons. To achieve this, the package uses the constrained triangulation approach implemented in the [`prepair`](https://github.com/tudelft3d/prepair) C++ library ([Ledoux et al. 2014](https://doi.org/10.1016/j.cageo.2014.01.009)). Specifically, the main `st_prepair()` function is used to repair polygons. ## Tutorial Here we provide a short tutorial showing how the _prepr_ package can be used to repair broken polygon geometries. To start with, we will load the package. We will also load the _sf_ package for working with spatial data. ```{r, message = FALSE} # load packages library(sf) # package for working with spatial data library(prepr) # package for repairing spatial geometries ``` We will now show how the _prepr_ package can be used to repair broken geometries. To achieve this, we will examine a range of different mechanisms by which polygons can be broken. For each of these mechanisms, we will manually create a broken polygon geometry based on the mechanism, repair the geometry (using `st_prepair()`), and then compare the repaired geometry with the original broken geometry. We will also confirm that the broken geometries have indeed been repaired (using `sf::st_is_valid()`). ### A 'bowtie' polygon ```{r example1} # create broken polygon x <- st_as_sfc("POLYGON((0 0, 0 10, 10 0, 10 10, 0 0))") # verify that polygon is broken, and display reason why it's broken st_is_valid(x, reason = TRUE) # repair the polygon y <- st_prepair(x) # verify that repaired polygon is NOT broken st_is_valid(y) # visualize the polygons par(mfrow = c(1, 2), mar = c(0, 0, 2.5, 0)) plot(x, main = "original", col = "#999999") points(st_coordinates(st_cast(x, "POINT")), col = "#e41a1c", pch = 16, cex = 2) plot(y, main = "repaired", col = "#999999") points(st_coordinates(st_cast(y, "POINT")), col = "#e41a1c", pch = 16, cex = 2) ``` ### Square with wrong orientation ```{r example2} # create broken polygon x <- st_as_sfc("POLYGON((0 0, 0 10, 10 10, 10 0, 0 0))") # verify that polygon is broken, and display reason why it's broken st_is_valid(x, reason = TRUE) # repair the polygon y <- st_prepair(x) # verify that repaired polygon is NOT broken st_is_valid(y) # visualize the polygons par(mfrow = c(1, 2), mar = c(0, 0, 2.5, 0)) plot(x, main = "original", col = "#999999") points(st_coordinates(st_cast(x, "POINT")), col = "#e41a1c", pch = 16, cex = 2) plot(y, main = "repaired", col = "#999999") points(st_coordinates(st_cast(y, "POINT")), col = "#e41a1c", pch = 16, cex = 2) ``` ### Inner ring with one edge sharing part of an edge of the outer ring ```{r example3} # create broken polygon x <- st_as_sfc( "POLYGON((0 0, 10 0, 10 10, 0 10, 0 0),(5 2, 5 7, 10 7, 10 2, 5 2))" ) # verify that polygon is broken, and display reason why it's broken st_is_valid(x, reason = TRUE) # repair the polygon y <- st_prepair(x) # verify that repaired polygon is NOT broken st_is_valid(y) # visualize the polygons par(mfrow = c(1, 2), mar = c(0, 0, 2.5, 0)) plot(x, main = "original", col = "#999999") points(st_coordinates(st_cast(x, "POINT")), col = "#e41a1c", pch = 16, cex = 2) plot(y, main = "repaired", col = "#999999") points(st_coordinates(st_cast(y, "POINT")), col = "#e41a1c", pch = 16, cex = 2) ``` ### Dangling edge ```{r example4} # create broken polygon x <- st_as_sfc("POLYGON((0 0, 10 0, 15 5, 10 0, 10 10, 0 10, 0 0))") # verify that polygon is broken, and display reason why it's broken st_is_valid(x, reason = TRUE) # repair the polygon y <- st_prepair(x) # verify that repaired polygon is NOT broken st_is_valid(y) # visualize the polygons par(mfrow = c(1, 2), mar = c(0, 0, 2.5, 0)) plot(x, main = "original", col = "#999999") points(st_coordinates(st_cast(x, "POINT")), col = "#e41a1c", pch = 16, cex = 2) plot(y, main = "repaired", col = "#999999") points(st_coordinates(st_cast(y, "POINT")), col = "#e41a1c", pch = 16, cex = 2) ``` ### Two adjacent inner rings ```{r example5} # create broken polygon x <- st_as_sfc( paste( "POLYGON((0 0, 10 0, 10 10, 0 10, 0 0),", "(1 1, 1 8, 3 8, 3 1, 1 1), (3 1, 3 8, 5 8, 5 1, 3 1))" ) ) # verify that polygon is broken, and display reason why it's broken st_is_valid(x, reason = TRUE) # repair the polygon y <- st_prepair(x) # verify that repaired polygon is NOT broken st_is_valid(y) # visualize the polygons par(mfrow = c(1, 2), mar = c(0, 0, 2.5, 0)) plot(x, main = "original", col = "#999999") points(st_coordinates(st_cast(x, "POINT")), col = "#e41a1c", pch = 16, cex = 2) plot(y, main = "repaired", col = "#999999") points(st_coordinates(st_cast(y, "POINT")), col = "#e41a1c", pch = 16, cex = 2) ``` ### Polygon with an inner ring inside another inner ring ```{r example6} # create broken polygon x <- st_as_sfc( paste( "POLYGON((0 0, 10 0, 10 10, 0 10, 0 0),", "(2 8, 5 8, 5 2, 2 2, 2 8), (3 3, 4 3, 3 4, 3 3))" ) ) # verify that polygon is broken, and display reason why it's broken st_is_valid(x, reason = TRUE) # repair the polygon y <- st_prepair(x) # verify that repaired polygon is NOT broken st_is_valid(y) # visualize the polygons par(mfrow = c(1, 2), mar = c(0, 0, 2.5, 0)) plot(x, main = "original", col = "#999999") points(st_coordinates(st_cast(x, "POINT")), col = "#e41a1c", pch = 16, cex = 2) plot(y, main = "repaired", col = "#999999") points(st_coordinates(st_cast(y, "POINT")), col = "#e41a1c", pch = 16, cex = 2) ``` ## Citation We recommend citing the methodology that underpins the _prepr R_ package. To cite this work, please use: > Ledoux H, Arroyo Ohori K, and Meijers M (2014) A triangulation-based approach to automatically repair GIS polygons. *Computers & Geosciences* 66:121--131. ## Getting help If you have any questions about using the _prepr R_ package or suggestions for improving it, please [file an issue at the package's online code repository](https://github.com/prioritizr/prepr/issues/new).