Mendapatkan TopologyException: Input geom 1 tidak valid yang disebabkan oleh persimpangan-sendiri di R?

24

'TopologyException: Input geom 1 tidak valid' kesalahan persimpangan sendiri yang timbul dari geometri poligon tidak valid telah banyak dibahas. Namun, saya belum menemukan solusi yang mudah di web yang hanya mengandalkan fungsionalitas R.

Sebagai contoh, saya telah berhasil membuat objek 'SpatialPolygons' dari hasil map("state", ...)mengikuti jawaban bagus Josh O'Brien di sini .

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)

menyatakan

Masalah dengan dataset yang diterapkan secara luas ini sekarang adalah persimpangan-sendiri terjadi pada titik yang diberikan di bawah ini.

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

Sayangnya, masalah ini mencegah penggunaan lebih lanjut dari 'spydf_states', misalnya saat menelepon rgeos::gIntersection. Bagaimana saya bisa mengatasi masalah ini dari dalam R?

fdetsch
sumber
1
Jika Anda memperbesar sekitar titik itu: plot(spydf_states, xlim=c(-122.1,-122.3),ylim=c(38,38.1))Anda akan melihat tidak ada "tampaknya" tentang hal itu - ada persimpangan diri.
Spacedman

Jawaban:

39

Menggunakan buffer nol lebar membersihkan banyak masalah topologi di R.

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

Namun bekerja dengan koordinat lat-panjang yang tidak diproyeksikan dapat menyebabkan Anda rgeosmembuang peringatan.

Berikut adalah contoh lanjutan yang memproyeksikan proyeksi Albers terlebih dahulu:

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)

masukkan deskripsi gambar di sini

hrbrmstr
sumber
4
ada komentar / bacaan tambahan tentang mengapa gBuffer"peretasan" bekerja?
MichaelChirico
Anda ingin menggunakan gSimplify karena meruntuhkan data.frame dan mengubah SPDF menjadi objek poligon spasial?
wnursal
5
Jika Anda menggunakan sfAnda juga dapat menggunakansf::st_buffer(x, dist = 0)
Phil
juga berfungsi dalam beberapa kasus saat menggunakanPostGIS
natsuapo