Point (d'une chaîne de lignes) dans Polygon utilisant ogr et Python

10

Je travaille actuellement sur un projet dans lequel j'ai besoin de construire un réseau topologique à partir des fonctionnalités géométriques que je trouve dans les fichiers de formes. Jusqu'à présent, en utilisant le projet open source de Ben Reilly, j'ai réussi à transformer des chaînes de lignes en bords networkx, ainsi qu'à détecter des entités proches (d'autres chaînes de chaînes disent) et à les ajouter au point le plus proche afin de pouvoir exécuter les algorithmes de chemin le plus court.

Mais c'est bien pour un fichier de formes. Cependant, je dois maintenant connecter des fonctionnalités de différents fichiers de formes dans un grand graphique networkx. Ainsi, par exemple, si un point se trouve dans un polygone, je le connecterais (en le connectant, je veux dire ajouter un bord networkx - add_edge (g.GetPoint (1), g.GetPoint (2)) avec le point dans le fichier de formes suivant qui se trouve également dans un polygone qui partage un attribut similaire (par exemple, ID). Notez que les polygones des différents shps ne partagent que les mêmes ID et non les coordonnées. Les points qui se trouvent dans les polygones ne partagent pas non plus les mêmes coordonnées.

Ma solution à ce problème était d'identifier le point qui réside dans un polygone, de le stocker, de trouver le point dans le fichier de formes suivant qui réside dans le polygone avec le même identifiant, puis d'ajouter le bord networkx entre eux.

Comment savoir si un point réside dans un polygone? Eh bien, il y a un algorithme bien connu: l' algorithme RayCasting qui fait ça. C'est là que j'ai été bloqué, car pour implémenter l'algorithme, j'ai besoin des coordonnées du polygone et je ne sais pas comment y accéder en ce moment, même après avoir parcouru une documentation sur la géométrie de l'OGR. Donc, la question que je pose est de savoir comment accéder aux points du polygone ou aux coordonnées OU existe-t-il un moyen plus facile de détecter si un point se trouve dans un polygone? En utilisant python avec la bibliothèque osgeo.ogr, j'ai codé ce qui suit:

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

voir l'image pour une meilleure compréhension de mon problème. texte alternatif

[EDIT] Jusqu'à présent, j'ai essayé de stocker tous les objets polygonaux dans une liste avec laquelle je comparerais ensuite le premier et le dernier point de la chaîne de lignes . Mais l'exemple de Paolo est lié à l'utilisation de la référence d'objet point et de la référence d'objet polygone, qui ne fonctionnerait pas avec une référence d'objet ligne car la ligne entière ne se trouve pas dans le polygone mais plutôt le premier ou le dernier point de sa chaîne de lignes.

[EDIT3] La création d'un nouvel objet point géométrique à partir des coordonnées du premier et du dernier point de la chaîne de caractères, puis son utilisation pour comparer avec les objets géométriques polygonaux enregistrés dans une liste semble fonctionner correctement:

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)

Merci Paolo et Chris pour les conseils.

user39901230
la source

Réponses:

11

Shapely est cool et élégant, mais pourquoi ne pas utiliser encore ogr, avec ses opérateurs spatiaux (dans la classe OGRGeometry)?

exemple de code:

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)

Notez que vous devez compiler GDAL avec le support GEOS.

capooti
la source
grzie Paolo, mais ce dont j'ai vraiment besoin, ce n'est pas de comparer les références d'objet d'un point avec celles d'un polygone, mais plutôt le dernier et le premier point d'une chaîne de lignes, auquel j'accède actuellement avec GetPoint. Il n'y a pas de GetPointRef que j'ai remarqué. Comment pourrais-je procéder pour mettre cela en œuvre?
user39901230
1
linestring est une collection de géométrie itérable de point (sommet), vous pouvez facilement accéder au premier et au dernier d'entre eux.
capooti
J'ai essayé de stocker les objets polygonaux dans une liste que j'utiliserais plus tard pour comparer avec le premier et le dernier point d'une chaîne de lignes. Cependant, aucun point n'est ajouté à la liste des points dans un polygone pour une raison quelconque: jetez un œil ici: codepad.org/Cm2BV5mp
user39901230
8

Je ne suis pas familier avec NetworkX mais si je comprends bien votre question, vous pouvez utiliser galbe et OGR lib pour trouver le point dans le polygone de shapefile. Voici un exemple de la façon dont cela fonctionne pour trouver si un point (2000, 1200) échoue avec un polygone d'un fichier de formes. Pour le résultat, il imprime les coordonnées de ce polygone.

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

J'espère que ça aide.

Mario Miler
la source