J'ai essayé plusieurs exemples de code utilisant des bibliothèques telles que shapefile, fiona et ogr pour tenter de vérifier si un point (x, y) se situe dans les limites d'un multipolygone créé avec ArcMap (et donc au format shapefile). Cependant, aucun des exemples ne fonctionne bien avec les multipolygones, bien qu'ils fonctionnent bien avec les fichiers de formes polygonaux réguliers. Quelques extraits que j'ai essayés sont ci-dessous:
# First example using shapefile and shapely:
from shapely.geometry import Polygon, Point, MultiPolygon
import shapefile
polygon = shapefile.Reader('shapefile.shp')
polygon = polygon.shapes()
shpfilePoints = []
for shape in polygon:
shpfilePoints = shape.points
polygon = shpfilePoints
poly = Polygon(poly)
point = Point(x, y)
# point in polygon test
if polygon.contains(point):
print 'inside'
else:
print 'OUT'
# Second example using ogr and shapely:
from shapely.geometry import Polygon, Point, MultiPolygon
from osgeo import ogr, gdal
driver = ogr.GetDriverByName('ESRI Shapefile')
dataset = driver.Open("shapefile.shp", 0)
layer = dataset.GetLayer()
for index in xrange(layer.GetFeatureCount()):
feature = layer.GetFeature(index)
geometry = feature.GetGeometryRef()
polygon = Polygon(geometry)
print 'polygon points =', polygon # this prints 'multipoint' + all the points fine
point = Point(x, y)
# point in polygon test
if polygon.contains(point):
print 'inside'
else:
print 'OUT'
Le premier exemple fonctionne correctement avec un seul polygone à la fois, mais lorsque j'entre un point dans l'une des formes de mon fichier de formes multipolygone, il renvoie "out" même s'il tombe à l'intérieur d'une des nombreuses parties.
Pour le deuxième exemple, j'obtiens une erreur "objet de type 'Geometry' n'a pas de len ()" qui je suppose est parce que le champ de géométrie ne peut pas être lu comme une liste / un tableau indexé normal.
J'ai également essayé de remplacer le point réel dans le code du polygone comme suggéré ici pour m'assurer que ce n'était pas la partie du code qui ne fonctionnait pas. Et bien que les exemples de ce lien fonctionnent correctement avec des fichiers de formes polygonales simples, je ne peux pas faire tester correctement mon multipolygone complexe.
Je ne peux donc pas penser à un autre moyen de tester si un point se trouve dans un fichier de formes multipolygone via python ... Peut-être qu'il y a d'autres bibliothèques là-bas qui me manquent?
la source
polygon = Polygon(geometry)
par une sorte de boucle d'essai où elle passepolygon = MultiPolygon(geometry)
si cette erreur se produit.Réponses:
Les fichiers de formes n'ont pas de type MultiPolygon (type = Polygon), mais ils les prennent quand même en charge (tous les anneaux sont stockés dans une seule entité = liste de polygones, voir Conversion d'énormes multipolygones en polygones )
Le problème
Si j'ouvre un fichier de formes MultiPolygon, la géométrie est 'Polygon'
Solution 1 avec Fiona
Fiona interprète la fonctionnalité comme un MultiPolygon et vous pouvez appliquer la solution présentée dans Jointure spatiale plus efficace en Python sans QGIS, ArcGIS, PostGIS, etc. (1)
Solution 2 avec pyshp (shapefile) et le protocole geo_interface (de type GeoJSON)
Ceci est un complément à la réponse de xulnik.
Solution 3 avec ogr et le protocole geo_interface ( applications Python Geo_interface )
Solution 4 avec GeoPandas comme dans la jointure spatiale plus efficace en Python sans QGIS, ArcGIS, PostGIS, etc. (2)
Les points 1,3,5,6 se situent dans les limites du MultiPolygon
la source
multi = shape(polys.shapeRecords()[0].shape.__geo_interface__)
solution 2? Je ne parviens pas à appeler une méthode shape () à partir deshapefile.py
. J'ai même essayéshapefile.Shape()
; il y a une classe pour ça mais ça ne marche pas.within()
méthode?from shapely.geometry import shape,mapping, Point, Polygon, MultiPolygon
)File "C:\WinPython\python-3.6.5.amd64\lib\site-packages\geopandas\tools\sjoin.py", line 43, in sjoin if left_df.crs != right_df.crs:
AttributeError: 'MultiPolygon' object has no attribute 'crs'
Le problème dans votre premier exemple est dans cette boucle:
Il ajoute uniquement les derniers points de fonctionnalité. J'ai essayé mon approche avec ce fichier de formes:
J'ai modifié votre code pour:
Le code ci-dessus a été exécuté sur la console Python de QGIS et le résultat était:
Cela fonctionne parfaitement et maintenant, vous pouvez vérifier si un point (x, y) se situe dans les limites de chaque entité.
la source
Si vous essayez de vérifier un point de latitude et de longitude dans un polygone, assurez-vous que vous avez un objet point créé par ce qui suit:
Le point prend la longitude, puis la latitude dans l'argument. Pas la latitude d'abord. Vous pouvez appeler la
polygon_object.within
fonction pour vérifier si le point se trouve dans la forme.la source