Abrufen der TopologieAusnahme: Eingabe-Geom 1 ist ungültig. Dies liegt an der Selbstüberschneidung in R?

24

Der "TopologyException: Input Geom 1 is invalid" -Selbstschnittfehler, der sich aus ungültigen Polygongeometrien ergibt, wurde ausführlich erörtert. Im Internet habe ich jedoch keine bequeme Lösung gefunden, die sich ausschließlich auf die R-Funktionalität stützt.

Zum Beispiel habe ich es geschafft, ein 'SpatialPolygons'-Objekt aus der Ausgabe von map("state", ...)Josh O'Briens netter Antwort hier zu erstellen .

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)

Zustände

Das Problem mit diesem weit verbreiteten Datensatz besteht nun darin, dass die Selbstüberschneidung an dem unten angegebenen Punkt auftritt.

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

Leider verhindert dieses Problem die weitere Verwendung von 'spydf_states', zB beim Aufruf rgeos::gIntersection. Wie kann ich dieses Problem in R lösen?

fdetsch
quelle
1
Wenn Sie um diesen Punkt herum zoomen, werden plot(spydf_states, xlim=c(-122.1,-122.3),ylim=c(38,38.1))Sie feststellen, dass es keinen "scheinbaren" Umstand gibt - es gibt eine Selbstüberschneidung.
Spacedman

Antworten:

39

Die Verwendung eines Puffers mit der Breite Null beseitigt viele Topologieprobleme in R.

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

Das Arbeiten mit nicht projizierten Längenkoordinaten kann jedoch rgeoszu Warnungen führen.

Hier ist ein erweitertes Beispiel, das zuerst auf eine Albers-Projektion projiziert:

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)

Bildbeschreibung hier eingeben

hrbrmstr
quelle
4
Irgendwelche zusätzlichen Kommentare / Lesungen darüber, warum der gBuffer"Hack" funktioniert?
MichaelChirico
Möchten Sie gSimplify verwenden, um die Datei data.frame zu entfernen und die SPDF in ein räumliches Polygonobjekt zu konvertieren?
wnursal
5
Wenn Sie verwenden sf, können Sie auchsf::st_buffer(x, dist = 0)
Phil
funktioniert auch in einigen Fällen bei Verwendung vonPostGIS
Natsuapo