Skip to content

Instantly share code, notes, and snippets.

@Pakillo
Forked from johnbaums/polygonizer.R
Last active May 25, 2021 08:32
Show Gist options
  • Save Pakillo/c6b076eceb0ef5a70e3b to your computer and use it in GitHub Desktop.
Save Pakillo/c6b076eceb0ef5a70e3b to your computer and use it in GitHub Desktop.
polygonizer <- function(x, outshape=NULL, gdalformat = 'ESRI Shapefile',
pypath=NULL, readpoly=TRUE, quietish=TRUE) {
# x: an R Raster layer, or the file path to a raster file recognised by GDAL
# outshape: the path to the output shapefile (if NULL, a temporary file will be created)
# gdalformat: the desired OGR vector format
# pypath: the path to gdal_polygonize.py (if NULL, an attempt will be made to determine the location
# readpoly: should the polygon shapefile be read back into R, and returned by this function? (logical)
# quietish: should (some) messages be suppressed? (logical)
if (isTRUE(readpoly)) require(rgdal)
if (is.null(pypath)) {
pypath <- Sys.which('gdal_polygonize.py')
}
## The line below has been commented:
# if (!file.exists(pypath)) stop("Can't find gdal_polygonize.py on your system.")
owd <- getwd()
on.exit(setwd(owd))
setwd(dirname(pypath))
if (!is.null(outshape)) {
outshape <- sub('\\.shp$', '', outshape)
f.exists <- file.exists(paste(outshape, c('shp', 'shx', 'dbf'), sep='.'))
if (any(f.exists))
stop(sprintf('File already exists: %s',
toString(paste(outshape, c('shp', 'shx', 'dbf'),
sep='.')[f.exists])), call.=FALSE)
} else outshape <- tempfile()
if (is(x, 'Raster')) {
require(raster)
writeRaster(x, {f <- tempfile(fileext='.asc')})
rastpath <- normalizePath(f)
} else if (is.character(x)) {
rastpath <- normalizePath(x)
} else stop('x must be a file path (character string), or a Raster object.')
## Now 'python' has to be substituted by OSGeo4W
#system2('python',
system2('C:\\OSGeo4W64\\OSGeo4W.bat',
args=(sprintf('"%1$s" "%2$s" -f "%3$s" "%4$s.shp"',
pypath, rastpath, gdalformat, outshape)))
if (isTRUE(readpoly)) {
shp <- readOGR(dirname(outshape), layer = basename(outshape), verbose=!quietish)
return(shp)
}
return(NULL)
}
@birbritto
Copy link

I'm getting this error despite putting in a formal raster layer as 'x':

"x must be a file path (character string), or a Raster object."

@luisrua
Copy link

luisrua commented May 24, 2021

Hi Francisco,
Thanks for sharing this.
I have tried to run this but I am getting this error.
Error in ogrInfo(dsn = dsn, layer = layer, encoding = encoding, use_iconv = use_iconv, :
Cannot open data source

Any idea of what could be causing this?
I have python and OSGeo4W installed within QGIS 3.16 so I modified the paths to get to both OSGeo4w.bat and the python path.

Muchas gracias de antemano

Luis

@Pakillo
Copy link
Author

Pakillo commented May 24, 2021

Hi Luis,

I haven't used this function for a few years so it may be outdated. Note it was integrated in the APfun package, which probably still works: https://rdrr.io/cran/APfun/man/APpolygonize.html. Check out also further changes in the original function @johnbaums: https://gist.github.com/johnbaums/26e8091f082f2b3dd279

I'd probably try using terra::as.polygons, as shown here: https://stackoverflow.com/a/65335878. It can work with very large rasters and should be fast.

Other alternatives:

Hope this helps

@johnbaums
Copy link

@luisrua
Copy link

luisrua commented May 25, 2021

Dear @johnbaums and @Pakillo.
Thanks so much for your help. I will try the different options proposed.

Regards

Luis

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment