Error with NULL polygons during cleaning
tdmcarthur opened this issue · comments
Travis McArthur commented
I used R to convert a publicly-available .kml file to .shp. Then I imported it into R with readOGR(). I ran clgeo_Clean() with verbose = TRUE and after a time it threw:
Error in slot(x, "coords") :
cannot get a slot ("coords") from an object of type "NULL"
with traceback() output:
12: slot(x, "coords")
11: FUN(X[[i]], ...)
10: lapply(po, function(x) {
outpo <- x
coords <- slot(x, "coords")
coords[, 1] <- as.character(coords[, 1])
coords[, 2] <- as.character(coords[, 2])
if (nrow(unique(slot(x, "coords"))) < 3)
outpo <- NULL
return(outpo)
})
9: FUN(X[[i]], ...)
8: lapply(1:length(holes), function(i) {
hole <- holes[[i]]
temphole <- SpatialPolygons(Srl = list(Polygons(srl = list(hole),
ID = "1")))
po <- hole
isValid <- clgeo_IsValid(temphole, verbose)
if (!isValid) {
po <- clgeo_CleanByPolygonation.Polygon(hole, verbose)
}
if (!is.list(po))
po <- list(po)
po <- lapply(po, function(x) {
outpo <- x
coords <- slot(x, "coords")
coords[, 1] <- as.character(coords[, 1])
coords[, 2] <- as.character(coords[, 2])
if (nrow(unique(slot(x, "coords"))) < 3)
outpo <- NULL
return(outpo)
})
po <- po[!sapply(po, is.null)]
out <- NULL
if (!is.null(po) && length(po) > 0) {
if (!is.list(po))
po <- list(po)
polyholes <- Polygons(srl = po, ID = as.character(ID))
if (slot(polyholes, "area") > 0)
out <- polyholes
if (!is.null(out)) {
if (slot(polyholes, "area") >= (1/rgeos::getScale())) {
ID <<- ID + 1
}
else {
out <- NULL
}
}
}
return(out)
})
7: FUN(X[[i]], ...)
6: lapply(sp@polygons, clgeo_CleanByPolygonation.Polygons, verbose)
5: unlist(lapply(sp@polygons, clgeo_CleanByPolygonation.Polygons,
verbose))
4: clgeo_CleanByPolygonation.SpatialPolygons(polygon, verbose)
3: FUN(X[[i]], ...)
2: lapply(1:length(sp), function(x) {
polygon <- slot(sp, "polygons")[[x]]
ID <- slot(polygon, "ID")
if (!all(is.na(nv))) {
if (x %in% nv) {
polygons <- slot(polygon, "Polygons")
poly.nb <- length(polygons)
removedHoles <- vector()
if (poly.nb > 0) {
newpolygons <- list()
for (i in 1:poly.nb) {
if (slot(polygons[[i]], "hole")) {
if (dim(unique(slot(polygons[[i]], "coords")))[1] <
3) {
if (length(removedHoles) == 0 & verbose) {
logger.info(sprintf("Cleaning orphaned holes at index %s",
x))
}
removedHoles <- c(removedHoles, i)
}
else {
newpolygon <- polygons[[i]]
slot(newpolygon, "hole") <- TRUE
newpolygons <- c(newpolygons, newpolygon)
}
}
else {
newpolygon <- polygons[[i]]
slot(newpolygon, "hole") <- FALSE
newpolygons <- c(newpolygons, newpolygon)
}
}
slot(polygon, "Polygons") <- newpolygons
}
polygon <- SpatialPolygons(Srl = list(polygon))
isValid <- report[x, ]$valid
if (length(removedHoles) > 0) {
if (verbose) {
logger.info(sprintf("Checking geometry validity at index %s",
x))
}
tryCatch({
slot(polygon, "polygons") <<- lapply(slot(polygon,
"polygons"), checkPolygonsHoles)
}, warning = function(msg) {
if (verbose)
logger.info(sprintf("Catched MAPTOOLS warning '%s'",
msg))
}, error = function(err) {
if (verbose)
logger.info(sprintf("Catched MAPTOOLS error '%s'",
err))
})
isValid <<- clgeo_IsValid(polygon, verbose)
}
if (is.null(errors.only) & !isValid) {
if (verbose) {
report.msg <- NULL
if (!is.na(report[x, "error_msg"])) {
report.msg <- report[x, "error_msg"]
}
else if (!is.na(report[x, "warning_msg"])) {
report.msg <- report[x, "warning_msg"]
}
logger.info(sprintf("Cleaning geometry at index %s (%s)",
x, report.msg))
}
if (strategy == "POLYGONATION") {
polygon <- clgeo_CleanByPolygonation.SpatialPolygons(polygon,
verbose)
}
else if (strategy == "BUFFER") {
attempt <- 1
polygon <- gBuffer(polygon, id = ID, width = 0)
while (attempt < 3) {
if (!clgeo_IsValid(polygon, verbose)) {
attempt <- attempt + 1
polygon <- gBuffer(polygon, id = ID, width = 0)
}
else {
break
}
}
}
}
if (!is.null(polygon)) {
polygon <- polygon@polygons[[1]]
slot(polygon, "ID") <- ID
}
else {
if (verbose) {
logger.info(sprintf("Removing false polygon at index %s",
x))
}
}
}
}
return(polygon)
})
1: clgeo_Clean(asentamiento.shp.orig, verbose = TRUE)
I will email @eblondel the file.
Emmanuel Blondel commented
@tdmcarthur I've made a minor fix in the code. I've tried to run it on the complete shapefile without exception raised. Let me know if it works for you
sp.clean <- clgeo_Clean(sp, verbose = TRUE)
ok <- all(sapply(1:nrow(sp.clean),function(x){return(gIsValid(sp.clean[x,]))}))
Deleted user commented
Thanks for making the fix so quickly! I tried it again with the new build of the package and I had no problems.