Advanced cleaning based on triangulation / polygonation
lukemac1 opened this issue · comments
Hi Emmanuel,
I am back to cleaning polygons and have come across a different method for cleaning them that seems to address the case of bowtie polygons, which lose a lot of area using either 'gBuffer', 'gSimplify' and 'cleangeo' methods. It's called prepair (https://github.com/tudelft3d/prepair) and is only implemented in C++. I'm trying to implement it to do some cleaning by doing system() calls in R. Thought you may like to take a look at it.
Best,
Luke
Interesting, thanks @lukemac1, i i'll have a look to it, and see if an adapter could be done in cleangeo.
Test case showing a lose of area for bowtie polygons:
sp <- rgeos::readWKT("POLYGON((0 0, 0 10, 10 0, 10 10, 0 0))")
sp.clean <- cleangeo::clgeo_Clean(sp)
plot(sp)
plot(sp.clean, add = TRUE, border = "red")
I found this paper that may be of interest to provided enhanced cleaning function in cleangeo
@lukemac1 By chance would you have a test GIS shapefile (with errors),that i could use for testing new cleaning algorithms? Thanks in advance. So far, i've tested some constrained triangulation technics and it seems to work, although it is really experimental at now.
Hi @eblondel. Here's a dump of info that is as far as I got in this process of using prepair. My apologies for the length, but hopefully it helps you from reinventing the wheel. I'd love to have prepair and pprepair implemented in R, as I'm currently using gBuffer (last I tried it, cleanGeo caused some unexpected enlargement of very complex polygons).
I found out about prepair and pprepair based on this post from @ldemaz on R-sig-geo listserv. In it, he includes a link to some test data with errors including a bowtie polygon and how he tests it and corrects it. That test data is at http://dl.dropbox.com/u/31890709/test_polys.Rdata. I'm including another polygon with a problem below, but have other shapefiles with errors I can share with many more problems if you'd like something large. Let me know.
@ldemaz has developed some R code to call pprepair, most of which can be found in this issue on the pprepair repository but he implemented prepair using python calling into PostGIS. He may be willing to share that code with you as I don't think it's open at this point. I was ultimately not able to make it work well (I'm not a proficient python or PostGIS user yet).
I got pretty far in implementing prepair in R, but had problems with three issues and decided to stop and just use gBuffer(). First, I have a lot of multipart polygons and it seems like prepair doesn't accept shapefiles with "aggregated" multi-part polygons (throws error "first feature ain't a polygon"). If I first disaggregate the polygons prepair will run, but then it only runs on the first polygon of the multiple polygon object only (problem 2), which leaves all the others un-repaired. So I tried then pulling out the part of the multi-polygon that was the problem and got it to run, but then it lost its attribute data (problem 3). I realize that the data could all be stitched back together after all that, but it seems like a complex and long way around the problem, and gBuffer seems to be working well for now as I seem to have few bowtie polygons. Oh, and a final problem that I don't remember if there's a workaround for -- prepair doesn't know how to read spatialpolygondataframes - requiring a conversion to shapefile or WKT -- another layer in the workflow.
Here is some sample data and code that I used to do this based on this single featured mult-polygon with a self-intersection that I was having trouble with, which is attached here:
selfintersection.zip
#read in:
selfinter <- readOGR(dsn = "./tests", layer = "selfintersection")
#Shows ring intersection in the single attribute row, -- but remember it's a multipolygon
gIsValid(selfinter, byid =TRUE, reason = TRUE)
#run through prepair and get an error due to running on the multi-part polygon
system("./functions/prepair/prepair --shpOut --ogr ./tests/selfintersection.shp", intern = TRUE)
[1] "First feature ain't a POLYGON."
#So I disaggregate multi-polygon and try it there, but it only works on the first of the multiple parts
disag <- disaggregate(selfinter)
gIsValid(disag, byid =TRUE, reason = TRUE ) #this shows the polygon, #6, with the problem
#output to a shapefile so prepair can read it, in this case 'multipartSelfIntersect.shp', and run it, but then prepair only works on the first feature of the multi-polygon shapefile...
writeOGR(disag, "./tests", layer = "multipartSelfIntersect", driver = "ESRI Shapefile" )
system("./functions/prepair/prepair_win64/prepair --shpOut --ogr ./tests/multipartSelfIntersect.shp", intern = TRUE)
[1] "Reading only the first feature in the shapefile."
[2] "\tCreating out.shp"
#unfortunately my problem polygon is the 6th polygon, not the first
#So i pull only the problem polygon out and name it 'prob'
plot(disag[6,]) #problem polygon
gIsValid(disag[6,], byid=T, reason=T) #shows that this polygon is messed up
prob<-disag[6,]
#I seem to recall prepair requires shapefiles so I output this single problem polygon into a shapefile
writeOGR(prob, "./tests", layer = "problemMultiPolygon", driver = "ESRI Shapefile" )
inname <- paste(getwd(), "/tests/problemMultiPolygon.shp", sep="")
ppcall <- paste("./functions/prepair/prepair_win64/prepair --shpOut --ogr", inname)
system(ppcall, intern = TRUE) #it can't overwrite, so make sure you don't have object w same name
#also it seems to name the fixed polygon "out" and i'm not sure if it allows you to pick a name for it.
fix.prepair <- readOGR(".", layer = "out")
gIsValid(fix.prepair, byid=TRUE, reason = TRUE) #yay, its fixed!
plot(fix.prepair) #lost all its data and the other polygons...
#oh drats though, it lost all its attribute data...
fix.prepair@data
That's as far as I got with it and I hope it's helpful.
Luke
First tests done with RTriangle package, needs to think more, especially as RTriangle license is incompatible with GPL. Probably needs to find another triangulate
implementation. To investigate function triangulate
from ads
package http://www.rdocumentation.org/packages/ads/functions/triangulate
Moved to a separate branch, given it is unstable. Master reset to a 0.1-2
@lukemac1 these days i worked a lot the package, and i led to some intuitive methodology, alternative to triangulation, with good results. I've tested it on several datasets, all with success. I've also tested different common geometries (like the "bowtie" polygons) and it works also. You are welcome if you want to test it