Point (of a linestring) all'interno di Polygon utilizzando ogr e Python


10

Attualmente sto lavorando a un progetto in cui ho bisogno di costruire una rete topologica a partire dalle caratteristiche geometriche che trovo nei file di forma. Finora usando il progetto open source di Ben Reilly sono riuscito a trasformare i linestring in edge networkx, oltre a rilevare funzionalità vicine (dicono altri linestring) e aggiungerle al punto più vicino in modo da poter eseguire algoritmi di percorso più brevi.

Ma va bene per uno shapefile. Tuttavia, ora ho bisogno di collegare funzionalità di diversi shapefile in un grande grafico networkx. Ad esempio, se un punto si trova all'interno di un poligono, lo collegherei (per connessione intendo aggiungere un bordo networkx - add_edge (g.GetPoint (1), g.GetPoint (2)) con il punto nel prossimo shapefile che inoltre si trova all'interno di un poligono che condivide un attributo simile (diciamo, ID). Si noti che i poligoni nei diversi shp condividono solo gli stessi ID e non le coordinate. I punti che rientrano nei poligoni non condividono le stesse coordinate.

La mia soluzione a questo problema era identificare il punto che risiede in un poligono, memorizzarlo, trovare il punto nel prossimo shapefile che risiede nel poligono con lo stesso id e quindi aggiungere il bordo networkx tra di loro.

Come scoprire se un punto risiede all'interno di un poligono? Bene, c'è un noto algoritmo: l' algoritmo RayCasting che lo fa. Questo è il punto in cui mi sono effettivamente bloccato, perché per implementare l'algoritmo ho bisogno delle coordinate del poligono e non so come accedervi adesso, anche dopo aver sfogliato una documentazione della Geometria di OGR. Quindi, la domanda che sto ponendo è come accedere ai punti poligonali o alle coordinate OPPURE esiste un modo più semplice per rilevare se un punto rientra in un poligono? Usando python con la libreria osgeo.ogr ho codificato quanto segue:

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

vedi l'immagine per una migliore comprensione del mio problema. testo alternativo

[EDIT] Finora ho provato a memorizzare tutti gli oggetti poligonali in un elenco con il quale avrei quindi confrontato il primo e l'ultimo punto della stringa lineare . Ma l'esempio di Paolo è correlato all'uso del riferimento Oggetto punto e del riferimento Oggetto poligonale, che non funzionerebbe con un riferimento all'oggetto linea poiché non l' intera linea si trova all'interno del poligono ma piuttosto il primo o l'ultimo punto della sua stringa lineare.

[EDIT3] La creazione di un nuovo oggetto punto Geometria dalle coordinate del primo e ultimo punto della stringa lineare e quindi l'utilizzo di quello per confrontare gli oggetti geometria poligonale salvati in un elenco sembra funzionare perfettamente:

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)

Grazie Paolo e Chris per i suggerimenti.

Risposte:


11

Shapely è bello ed elegante, ma perché non usare ancora ogr, con i suoi operatori spaziali (nella classe OGRGeometry)?

codice di esempio:

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)

Nota che devi compilare GDAL con il supporto GEOS.


grzie Paolo, ma ciò di cui ho veramente bisogno non è confrontare i riferimenti dell'oggetto di un punto con quello di un poligono, ma piuttosto l'ultimo e il primo punto di un linestring, a cui attualmente accedo con GetPoint. Non ho notato GetPointRef. Come potrei fare per implementarlo?
user39901230,

1
linestring è una raccolta geometrica iterabile di punto (vertice), è possibile accedere facilmente al primo e all'ultimo di essi.
capooti,

Ho provato a memorizzare gli oggetti poligonali in un elenco che in seguito avrei usato per verificare il primo e l'ultimo punto di una stringa lineare. Tuttavia, nessun punto viene aggiunto all'elenco di punti all'interno di un poligono per qualche motivo: dai un'occhiata qui: codepad.org/Cm2BV5mp
user39901230

8

Io non sono a conoscenza NetworkX ma se ho capito bene la tua domanda, è possibile utilizzare formosa e OGR lib per la ricerca di punto nel poligono dalla shapefile. Ecco un esempio di come funziona se un punto (2000,1200) non riesce con un poligono di uno shapefile. Per il risultato, stampa le coordinate di quel poligono.

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()

Spero possa essere d'aiuto.

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.