Ottenere TopologyException: input geom 1 non è valido a causa di autointersezione in R?


24

L'errore di autointersezione "TopologyException: Input geom 1 is invalid" derivante da geometrie poligonali non valide è stato ampiamente discusso. Tuttavia, non ho trovato una soluzione conveniente sul Web che si basa esclusivamente sulla funzionalità R.

Ad esempio, sono riuscito a creare un oggetto "SpatialPolygons" dall'output di map("state", ...)seguire la bella risposta di Josh O'Brien qui .

library(maps)
library(maptools)

map_states = map("state", fill = TRUE, plot = FALSE)

IDs = sapply(strsplit(map_states$names, ":"), "[[", 1)
spydf_states = map2SpatialPolygons(map_states, IDs = IDs, proj4string = CRS("+init=epsg:4326"))

plot(spydf_states)

stati

Il problema con questo set di dati ampiamente applicato è ora che l'autointersezione si verifica nel punto indicato di seguito.

rgeos::gIsValid(spydf_states)
[1] FALSE
Warning message:
In RGEOSUnaryPredFunc(spgeom, byid, "rgeos_isvalid") :
  Self-intersection at or near point -122.22023214285259 38.060546477866055

Sfortunatamente, questo problema impedisce qualsiasi ulteriore utilizzo di "spydf_states", ad esempio durante la chiamata rgeos::gIntersection. Come posso risolvere questo problema da R?


1
Se ingrandisci quel punto: plot(spydf_states, xlim=c(-122.1,-122.3),ylim=c(38,38.1))vedrai che non c'è "apparentemente", c'è un autointersezione.
Spacedman,

Risposte:


39

L'uso di un buffer di larghezza zero risolve molti problemi di topologia in R.

spydf_states <- gBuffer(spydf_states, byid=TRUE, width=0)

Tuttavia, l'utilizzo di coordinate lat-long non proiettate può causare rgeosavvisi.

Ecco un esempio esteso che si ripropone prima in una proiezione Albers:

library(sp)
library(rgeos)

load("~/Dropbox/spydf_states.RData")

# many geos functions require projections and you're probably going to end
# up plotting this eventually so we convert it to albers before cleaning up
# the polygons since you should use that if you are plotting the US
spydf_states <- spTransform(spydf_states, 
                            CRS("+proj=aea +lat_1=29.5 +lat_2=45.5 +lat_0=37.5 +lon_0=-96"))

# simplify the polgons a tad (tweak 0.00001 to your liking)
spydf_states <- gSimplify(spydf_states, tol = 0.00001)

# this is a well known R / GEOS hack (usually combined with the above) to 
# deal with "bad" polygons
spydf_states <- gBuffer(spydf_states, byid=TRUE, width=0)

# any bad polys?
sum(gIsValid(spydf_states, byid=TRUE)==FALSE)

## [1] 0

plot(spydf_states)

inserisci qui la descrizione dell'immagine


4
eventuali commenti / letture extra sul perché l ' gBuffer"hack" funziona?
MichaelChirico,

vuoi usare gSimplify mentre abbatte il data.frame e converte l'SPDF in oggetto poligonale spaziale?
mercoledì

5
Se stai usando sfpuoi anche usaresf::st_buffer(x, dist = 0)
Phil

funziona anche in alcuni casi quando si usaPostGIS
natsuapo il
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.