Wie puffere ich ein Vektor-Shapefile mit ogr python?

10

Ich versuche zu lernen, wie man ogr in Python verwendet, indem ich die Datensätze des Landes und der bevölkerten Orte von http://www.naturalearthdata.com/downloads/50m-cultural-vectors/ verwende.. Ich versuche, Filter und Puffer zu verwenden, um Punkte (ne_50m_populated_places.shp) in einem angegebenen Puffer eines benannten Landes zu finden (gefiltert nach der Feature-Class ADMIN in ne_50m_admin_0_countries.shp). Das Problem scheint zu sein, dass ich nicht verstehe, welche Einheiten für buffer () verwendet werden sollen. Im Skript habe ich einfach einen beliebigen Wert von 10 verwendet, um zu testen, ob das Skript funktioniert. Das Skript wird ausgeführt, gibt jedoch besiedelte Orte aus der Karibik für das benannte Land "Angola" zurück. Idealerweise möchte ich in der Lage sein, eine Pufferentfernung von beispielsweise 500 km anzugeben, kann aber nicht herausfinden, wie dies zu tun ist, da nach meinem Verständnis buffer () die Einheiten von country.shp verwendet, die im Lat / Long-Format wgs84 vorliegen . Ratschläge zur Methode, um dies zu erreichen, wären sehr willkommen.

# import modules
import ogr, os, sys


## data source
os.chdir('C:/data/naturalearth/50m_cultural')

# get the shapefile driver
driver = ogr.GetDriverByName('ESRI Shapefile')

# open ne_50m_admin_0_countries.shp and get the layer
admin = driver.Open('ne_50m_admin_0_countries.shp')
if admin is None:
  print 'Could not open ne_50m_admin_0_countries.shp'
  sys.exit(1)
adminLayer = admin.GetLayer()

# open ne_50m_populated_places.shp and get the layer
pop = driver.Open('ne_50m_populated_places.shp')
if pop is None:
  print 'could not open ne_50m_populated_places.shp'
  sys.exit(1)
popLayer = pop.GetLayer()

# use an attribute filter to restrict ne_50m_admin_0_countries.shp to "Angola"
adminLayer.SetAttributeFilter("ADMIN = ANGOLA")

# get the Angola geometry and buffer it by 10 units
adminFeature = adminLayer.GetFeature(0)
adminGeom = adminFeature.GetGeometryRef()
bufferGeom = adminGeom.Buffer(10)

# use bufferGeom as a spatial filter on ne_50m_populated_places.shp to get all places
# within 10 units of Angola
popLayer.SetSpatialFilter(bufferGeom)

# loop through the remaining features in ne_50m_populated_places.shp and print their
# id values
popFeature = popLayer.GetNextFeature()
while popFeature:
  print popFeature.GetField('NAME')
  popFeature.Destroy()
  popFeature = popLayer.GetNextFeature()

# close the shapefiles
admin.Destroy()
pop.Destroy()
user1765941
quelle

Antworten:

2

Zwei Optionen, die mir einfallen, sind:

  1. Berechnen Sie das Gradäquivalent von 500 Kilometern. Sie können dann die Funktion Buffer () eingeben. Sie müssten jedoch vorsichtig sein, da ein Abschluss kein konstantes metrisches Äquivalent hat. Es hängt davon ab, auf welchem ​​Breitengrad Sie sich befinden. Sie können die Haversine-Formel überprüfen, wenn Sie diesen Weg gehen möchten.

  2. Eine andere Möglichkeit wäre, das Shapefile erneut in UTM zu projizieren . Auf diese Weise können Sie nur 500 Kilometer direkt nutzen. Sie haben jedoch die UTM-Zone für Ihr Interessengebiet gefunden. (Welches sollte UTM Zone 32S für Angola sein, wenn ich mich nicht irre)

RK
quelle
3
Es gibt kein "Gradäquivalent" von 500 Kilometern oder einer anderen Entfernung, außer ungefähr für kleine Entfernungen in der Nähe des Äquators: Dies liegt daran, dass sich das Verhältnis zwischen Entfernungen und Graden sowohl mit der Peilung als auch mit dem Breitengrad ändert. Daher funktioniert die erste Option normalerweise nicht richtig.
whuber
0
  1. Wenn Sie Puffer mit Grad erstellen möchten, berücksichtigen Sie, dass Grad je nach Richtung einen sehr unterschiedlichen Abstand haben, wenn Sie sich nicht in der Nähe des Äquators befinden. Der Breitengrad bleibt gleich, aber ein Längengrad von einem Grad ist in hohen Breitengraden viel kleiner. Unten ist meine Tabelle mit 500-km-Quadraten in Grad in verschiedenen Breiten. Ich denke, dass für Angola ein Wert von 4,4 eine gute Vermutung sein kann, wenn Sie keine hohe Präzision benötigen.
  2. Sie können Objekte in Python ogr (es gibt eine Transformationsfunktion dafür) während des Lesens neu projizieren, dann müssen keine Conversion-Dateien konvertiert werden.
500 km bei Lat 0.0 sind 4.491576420597608 x 4.486983030705042 Grad
500 km bei Lat 10,0 sind 4,491576420597608 x 4,389054945583991 Grad
500 km bei Lat 20.0 sind 4.491576420597608 x 4.16093408959923 Grad
500 km bei Lat 30.0 sind 4.491576420597608 x 3.8117296267699388 Grad
500 km bei 40,0 Lat sind 4,491576420597608 x 3,3535548944407267 Grad
500 km bei Lat 50.0 sind 4.491576420597608 x 2.8010165014556634 Grad
500 km bei Lat 60,0 sind 4,491576420597608 x 2,170722673038327 Grad
500 km bei Lat 70.0 sind 4.491576420597608 x 1.4808232946314916 Grad
500 km bei Lat 80,0 sind 4,491576420597608 x 0,7505852760718597 Grad
500 km bei Lat 84.0 sind 4.491576420597608 x 0.4516575041056399 Grad
JaakL
quelle
4
Benutzer @ Dave X stellt fest, dass diese Tabelle fehlerhaft ist: Ein fester Abstand erstreckt sich über eine größere Anzahl von Grad in höheren Breiten, nicht über einen geringeren. Es scheint, dass es durch eine Multiplikation konstruiert wurde, bei der eine Division erforderlich ist. Trotzdem erklärt dies die Diskrepanzen nicht vollständig: Es bleiben Fehler in der Größenordnung von mehreren Prozent. Wie genau haben Sie diese Zahlen berechnet?
whuber