Ich habe Probleme, die Verwendung von räumlichen Indizes mit RTree zu verstehen.
Beispiel: Ich habe 300 gepufferte Punkte und muss den Schnittbereich jedes Puffers mit einem Polygon-Shapefile kennen. Das Polygon Shapefile hat> 20.000 Polygone. Es wurde vorgeschlagen, räumliche Indizes zu verwenden, um den Prozess zu beschleunigen.
SO ... Wenn ich einen räumlichen Index für mein Polygon-Shapefile erstelle, wird dieser in irgendeiner Weise an die Datei "angehängt", oder wird der Index eigenständig sein? Das heißt, kann ich nach dem Erstellen einfach meine Schnittfunktion für die Polygondatei ausführen und schnellere Ergebnisse erzielen? Wird intersection "sehen", dass es räumliche Indizes gibt und wissen, was zu tun ist? Oder muss ich es auf dem Index ausführen und diese Ergebnisse dann über FIDs oder dergleichen wieder mit meiner ursprünglichen Polygondatei verknüpfen?
Die RTree-Dokumentation hilft mir nicht sehr (wahrscheinlich, weil ich gerade Programmieren lerne). Sie zeigen, wie Sie einen Index erstellen, indem Sie manuell erstellte Punkte einlesen und ihn dann mit anderen manuell erstellten Punkten abfragen. Dabei werden die im Fenster enthaltenen IDs zurückgegeben. Macht Sinn. Sie erklären jedoch nicht, wie sich dies auf eine Originaldatei beziehen würde, aus der der Index stammen würde.
Ich denke, es muss ungefähr so gehen:
- Ziehen Sie Bboxes für jedes Polygon-Feature aus meinem Polygon-Shapefile und platzieren Sie sie in einem räumlichen Index. Geben Sie ihnen eine ID, die mit ihrer ID im Shapefile identisch ist.
- Fragen Sie diesen Index ab, um die IDs zu ermitteln, die sich überschneiden.
- Führen Sie dann meine Überschneidung nur für die Features in meinem ursprünglichen Shapefile erneut aus, die durch Abfragen meines Index identifiziert wurden (nicht sicher, wie ich diesen letzten Teil ausführen würde).
Habe ich die richtige idee Vermisse ich etwas?
Im Moment versuche ich, diesen Code für ein Punkt-Shapefile zu verwenden, das nur ein Punkt-Feature und ein Polygon-Shapefile mit mehr als 20.000 Polygon-Features enthält.
Ich importiere die Shapefiles mit Fiona, füge den räumlichen Index mit RTree hinzu und versuche, die Schnittmenge mit Shapely zu erstellen.
Mein Testcode sieht so aus:
#point shapefile representing location of desired focal statistic
traps = fiona.open('single_pt_speed_test.shp', 'r')
#polygon shapefile representing land cover of interest
gl = MultiPolygon([shape(pol['geometry']) for pol in fiona.open('class3_aa.shp', 'r')])
#search area
areaKM2 = 20
#create empty spatial index
idx = index.Index()
#set initial search radius for buffer
areaM2 = areaKM2 * 1000000
r = (math.sqrt(areaM2/math.pi))
#create spatial index from gl
for i, shape in enumerate(gl):
idx.insert(i, shape.bounds)
#query index for ids that intersect with buffer (will eventually have multiple points)
for point in traps:
pt_buffer = shape(point['geometry']).buffer(r)
intersect_ids = pt_buffer.intersection(idx)
Aber ich bekomme immer wieder TypeError: Das Objekt 'Polygon' kann nicht aufgerufen werden
.qix
Ist auch der MapServer / GDAL / OGR / SpatiaLite Quadtree- IndexTypeError: 'Polygon' object is not callable
mit Ihrem Aktualisierungsbeispielshape
for i, shape in enumerate(gl):
Antworten:
Das ist das Wesentliche. Mit dem R-Tree können Sie einen sehr schnellen ersten Durchgang durchführen und erhalten eine Reihe von Ergebnissen, die "falsch-positive" Ergebnisse liefern (Begrenzungsrahmen können sich schneiden, wenn die Geometrien nicht genau übereinstimmen). Dann gehen Sie die Kandidatenmenge durch (holen sie anhand ihres Index aus dem Shapefile) und führen einen mathematisch präzisen Schnittpunkttest durch, z. B. mit Shapely. Dies ist die gleiche Strategie, die in räumlichen Datenbanken wie PostGIS angewendet wird.
quelle
Sie haben es fast geschafft, aber Sie haben einen kleinen Fehler gemacht. Sie müssen die
intersection
Methode für den räumlichen Index verwenden, anstatt den Index an dieintersection
Methode für den gepufferten Punkt zu übergeben. Wenn Sie eine Liste von Features gefunden haben, bei denen sich die Begrenzungsrahmen überlappen, müssen Sie überprüfen, ob der gepufferte Punkt tatsächlich die Geometrien schneidet.Wenn Sie Punkte finden möchten, die sich in einem Mindestabstand zu Ihrer Landklasse befinden, können Sie
distance
stattdessen die Methode verwenden (tauschen Sie den entsprechenden Abschnitt aus dem vorherigen Abschnitt aus).Wenn die Erstellung Ihres räumlichen Index sehr lange dauert und Sie dies mehrmals tun, sollten Sie den Index in eine Datei serialisieren. Die Dokumentation beschreibt die Vorgehensweise : http://toblerity.org/rtree/tutorial.html#serializing-your-index-to-a-file
Sie können sich auch ansehen, wie Sie die Begrenzungsrahmen mithilfe eines Generators in den rtree laden:
quelle
Ja das ist die Idee. Hier ist ein Auszug aus diesem Tutorial über die Verwendung eines räumlichen R-Tree-Index in Python unter Verwendung von Shapely, Fiona und Geopandas:
quelle