Comment utiliser python à l'information recherche à spécifique latitude / longitude dans un Esri shapefile?
Question
J'ai un Esri shapefile (d'ici: http://pubs.usgs.gov/ds/ 425 / ). Je cherche à python utilisé pour rechercher des informations à partir du fichier de forme (matériaux de surface dans ce cas) à une latitude / longitude donnée.
Quelle est la meilleure façon de s'y prendre pour résoudre ce problème?
Merci.
La solution finale:
#!/usr/bin/python
from osgeo import ogr, osr
dataset = ogr.Open('./USGS_DS_425_SHAPES/Surficial_materials.shp')
layer = dataset.GetLayerByIndex(0)
layer.ResetReading()
# Location for New Orleans: 29.98 N, -90.25 E
point = ogr.CreateGeometryFromWkt("POINT(-90.25 29.98)")
# Transform the point into the specified coordinate system from WGS84
spatialRef = osr.SpatialReference()
spatialRef.ImportFromEPSG(4326)
coordTransform = osr.CoordinateTransformation(
spatialRef, layer.GetSpatialRef())
point.Transform(coordTransform)
for feature in layer:
if feature.GetGeometryRef().Contains(point):
break
for i in range(feature.GetFieldCount()):
print feature.GetField(i)
La solution
Vous pouvez utiliser les liaisons Python au GDAL / OGR . Voici un exemple:
from osgeo import ogr
ds = ogr.Open("somelayer.shp")
lyr = ds.GetLayerByName("somelayer")
lyr.ResetReading()
point = ogr.CreateGeometryFromWkt("POINT(4 5)")
for feat in lyr:
geom = feat.GetGeometryRef()
if geom.Contains(point):
sm = feat.GetField(feat.GetFieldIndex("surface_material"))
# do stuff...
Autres conseils
Cela devrait vous donner la géométrie et des informations différentes.
Une autre option consiste à utiliser Shapely (une bibliothèque Python basée sur GEOS, le moteur pour PostGIS) et Fiona (qui est essentiellement pour la lecture / écriture de fichiers):
import fiona
import shapely
with fiona.open("path/to/shapefile.shp") as fiona_collection:
# In this case, we'll assume the shapefile only has one record/layer (e.g., the shapefile
# is just for the borders of a single country, etc.).
shapefile_record = fiona_collection.next()
# Use Shapely to create the polygon
shape = shapely.geometry.asShape( shapefile_record['geometry'] )
point = shapely.geometry.Point(32.398516, -39.754028) # longitude, latitude
# Alternative: if point.within(shape)
if shape.contains(point):
print "Found shape for point."
Notez que faire des tests de point dans un polygone peut être coûteux si le polygone est grand / compliqué (par exemple, pour certains pays shapefiles avec des côtes très irrégulières). Dans certains cas, il peut aider à utiliser des boîtes englobantes pour écarter rapidement les choses avant de faire le test plus intensif:
minx, miny, maxx, maxy = shape.bounds
bounding_box = shapely.geometry.box(minx, miny, maxx, maxy)
if bounding_box.contains(point):
...
Enfin, gardez à l'esprit qu'il faut un certain temps à la charge et parse grande / irrégulière shapefiles (malheureusement, ces types de polygones sont souvent coûteux à garder en mémoire, aussi).