Point (dari linestring) dalam Polygon menggunakan ogr dan Python

10

Saat ini saya sedang mengerjakan sebuah proyek di mana saya perlu membangun jaringan topologi dari fitur geometri yang saya temukan di shapefile. Sejauh ini menggunakan proyek open source Ben Reilly, saya telah berhasil mengubah linestrings menjadi edge networkx, serta mendeteksi fitur dekat (linestrings lainnya mengatakan) dan menambahkannya ke titik terdekat sehingga saya dapat menjalankan algoritma jalur terpendek.

Tapi itu bagus untuk satu shapefile. Namun, saya sekarang perlu menghubungkan fitur-fitur dari berbagai shapefile ke dalam grafik networkx besar. Jadi misalnya, jika suatu titik berada dalam poligon saya akan menghubungkannya (dengan menghubungkannya maksud saya tambahkan tepi networkx - add_edge (g.GetPoint (1), g.GetPoint (2)) dengan titik di shapefile berikutnya yang juga berada dalam poligon yang memiliki atribut yang sama (katakanlah, ID). Perhatikan bahwa poligon dalam shps yang berbeda hanya berbagi ID yang sama dan bukan koordinat. Poin yang termasuk dalam poligon juga tidak memiliki koordinat yang sama.

Solusi saya untuk masalah ini adalah mengidentifikasi titik yang berada dalam poligon, menyimpannya, menemukan titik di shapefile berikutnya yang berada di poligon dengan id yang sama dan kemudian menambahkan tepi networkx di antara mereka.

Bagaimana menemukan jika suatu titik berada di dalam poligon? Nah, ada algoritma yang terkenal: Algoritma RayCasting yang melakukan itu. Di sinilah sebenarnya saya terjebak, karena untuk mengimplementasikan algoritma saya memerlukan koordinat poligon, dan tidak tahu cara mengaksesnya sekarang, bahkan setelah membaca sekilas melalui dokumentasi Geometri OGR. Jadi, pertanyaan yang saya tanyakan adalah bagaimana cara mengakses titik poligon, atau koordinat ATAU adakah cara yang lebih mudah untuk mendeteksi apakah suatu titik berada dalam poligon? Menggunakan python dengan perpustakaan osgeo.ogr saya memberi kode berikut:

 if g.GetGeometryType() == 3: #polygon
                c = g.GetDimension()
                x = g.GetPointCount()
                y = g.GetY()
                z = g.GetZ()

lihat gambar untuk pemahaman yang lebih baik tentang masalah saya. teks alternatif

[EDIT] Sejauh ini saya sudah mencoba menyimpan semua objek poligon dalam daftar yang kemudian saya bandingkan dengan linestring poin pertama dan terakhir. Tetapi contoh Paolo terkait dengan menggunakan referensi Objek Titik dan referensi Objek Polygon, yang tidak akan bekerja dengan referensi objek garis karena tidak seluruh garis berada dalam poligon melainkan titik pertama atau terakhir dari linestringnya.

[EDIT3] Membuat objek titik Geometri baru dari koordinat titik pertama dan terakhir dari linestring dan kemudian menggunakannya untuk membandingkan terhadap objek geometri poligon yang disimpan dalam daftar tampaknya berfungsi dengan baik:

for findex in xrange(lyr.GetFeatureCount()):
    f = lyr.GetFeature(findex)
    flddata = getfieldinfo(lyr,f,fields)
    g = f.geometry()
    if g.GetGeometryType() == 2:
        for j in xrange(g.GetPointCount()):
            if j == 0 or j == g.GetPointCount():
                point = ogr.Geometry(ogr.wkbPoint)
                point.AddPoint(g.Getx(j),g.GetY(j))
                if point.Within(Network.polygons[x][0].GetGeometryRef()):
    print g.GetPoint(j)

Terima kasih Paolo dan Chris untuk petunjuknya.

pengguna39901230
sumber

Jawaban:

11

Bentuknya keren dan elegan, tapi mengapa tidak menggunakan ogr diam, dengan operator spasial (di kelas OGRGeometry)?

Kode sampel:

from osgeo import ogr
driver = ogr.GetDriverByName('ESRI Shapefile')
polyshp = driver.Open('/home/pcorti/data/shapefile/multipoly.shp')
polylyr = polyshp.GetLayer(0)
pointshp = driver.Open('/home/pcorti/data/shapefile/point.shp')
pointlyr = pointshp.GetLayer(0)
point = pointlyr.GetNextFeature()
polygon = polylyr.GetNextFeature()
point_geom = point.GetGeometryRef()
polygon_geom = polygon.GetGeometryRef()
print point_geom.Within(polygon_geom)

Perhatikan bahwa Anda perlu mengkompilasi GDAL dengan dukungan GEOS.

capooti
sumber
grzie Paolo, tetapi yang benar-benar saya butuhkan adalah tidak membandingkan referensi objek dari suatu titik dengan salah satu poligon, melainkan titik terakhir dan pertama dari linestring, yang saat ini saya akses dengan GetPoint. Tidak ada GetPointRef yang saya perhatikan. Bagaimana saya menerapkannya?
user39901230
1
linestring adalah kumpulan geometri titik (titik) yang dapat diubah, Anda dapat dengan mudah mengakses yang pertama dan terakhir.
Capooti
Saya sudah mencoba untuk menyimpan objek poligon dalam daftar yang nantinya akan saya gunakan untuk memeriksa titik pertama dan terakhir dari linestring. Namun, tidak ada poin yang ditambahkan ke daftar poin dalam poligon karena beberapa alasan: lihat di sini: codepad.org/Cm2BV5mp
user39901230
8

Saya tidak terbiasa dengan networkx tetapi jika saya mengerti dengan benar pertanyaan Anda, Anda dapat menggunakan lg indah dan OGR untuk menemukan titik dalam poligon dari shapefile. Berikut adalah salah satu contoh cara kerjanya untuk menemukan jika satu titik (2000.1200) gagal dengan setiap poligon dari satu shapefile. Untuk hasilnya, ia mencetak koordinat poligon itu.

from shapely.geometry import Point, Polygon
from shapely.wkb import loads
from osgeo import ogr

file1 = ogr.Open("d:\\fileWithData.shp")
layer1 = file1.GetLayerByName("fileWithData")

point1 = Point(2000,1200)

polygon1 = layer1.GetNextFeature()

while polygon1 is not None:
    geomPolygon = loads(polygon1.GetGeometryRef().ExportToWkb())
    if geomPolygon.contains(point1):
        xList,yList = geomPolygon.exterior.xy
        print xList
        print yList
    polygon1 = layer1.GetNextFeature()

Saya harap ini membantu.

Mario Miler
sumber