Über meine Testdaten:
- Wie bei OSM Road Data endet jede einzelne Straßengeometrie an einer Kreuzung.
- Jede Straße hat eine eindeutige ID.
LÖSUNG I
Wenn es die zwei Annahmen gibt:
Straßen bauen Viertel.
Sie arbeiten in einem metrischen System.
Die Idee ist, die X- und Y-Koordinaten des Punktes zu erhöhen / zu verringern. Wenn Sie in einem metrischen System arbeiten, können Sie 1 m östlich von Ihrem Punkt einen neuen Punkt erstellen und eine Linie mit dem ursprünglichen Punkt erstellen. Sie fahren weiter nach Osten, bis die Linie eine Straße kreuzt. Um nach einer Kreuzung im Westen zu suchen, müssen Sie 1 m von der ursprünglichen X-Koordinate subtrahieren. Gleiches gilt für die Y-Koordinate. Wenn es im Norden / Osten / Süden / Westen keine Straße gibt, hält der Zähler bei 1000 (m). Wenn Sie wissen, dass sich eine Straße in einer Entfernung von mehr als 1000 m befindet, müssen Sie diesen Wert ändern.
Sie können die Aufgabe mit folgendem Code lösen:
Bearbeitet
for lyr in QgsMapLayerRegistry.instance().mapLayers().values():
if lyr.name() == "point":
startpoint = lyr
for lyr in QgsMapLayerRegistry.instance().mapLayers().values():
if lyr.name() == "roads":
roads = lyr
startpoint_iter = startpoint.getFeatures()
for feature in startpoint_iter:
geom = feature.geometry()
if geom.type() == QGis.Point:
xy = geom.asPoint()
x,y = xy[0], xy[1]
line_start = QgsPoint(x,y)
def reached(direction, count_m):
road_reached = None
road = None
count=1
while road_reached < 1 and count <=count_m:
count += 1
if direction == 'N':
line_end = QgsPoint(x, y+count)
if direction == 'E':
line_end = QgsPoint(x+count,y)
if direction == 'S':
line_end = QgsPoint(x,y-count)
if direction == 'W':
line_end = QgsPoint(x-count,y)
line = QgsGeometry.fromPolyline([line_start,line_end])
for f in roads.getFeatures():
if line.intersects(f.geometry()):
road_reached = 1
road = f['name']
print road
reached('N', 1000)
reached('E', 1000)
reached('S', 1000)
reached('W', 1000)
Ein weiteres Beispiel dafür, dass die Straße e im Osten nicht als nahe gelegene Straße des Punkts erkannt wird.
So rufen Sie die Funktion und den Ausgang auf:
>>>>reached('N', 1000)
road a
>>>>reached('E', 1000)
road b
>>>>reached('S', 1000)
road c
>>>>reached('W', 1000)
road d
Wenn der Punkt von mehr als 4 Straßen umschlossen ist, müssen Sie in mehrere Richtungen schauen (ändern Sie sowohl X als auch Y). Oder Sie können den Azimut Ihrer Linie ändern, dh Sie können sie um einen Grad im Bereich von 0 bis 360 ° drehen.
LÖSUNG II
Inspiriert von dem Kommentar kannst du auch zuerst Polygonize
deine Straßen. Dafür können Sie ein Werkzeug aus QGIS benutzen Processing > Toolbox > QGIS geoalgorithms > Vector geometry tools > Polygonize
. Benennen Sie die temporäre Ebene in um polygon
. Angenommen, Sie möchten nur die Straßennamen für den Punkt haben, der vollständig von Straßen umschlossen ist. Andernfalls müssen Sie LÖSUNG I verwenden . Dies funktioniert nur, wenn alle Straßen verbunden (eingerastet) sind!
Zuerst muss sich der Punkt mit dem Polygon schneiden. Die Idee ist nun, dass sich beide Start- und AND
Endpunkte einer umschließenden Linie mit dem Polygon schneiden müssen.
for lyr in QgsMapLayerRegistry.instance().mapLayers().values():
if lyr.name() == "point":
startpoint = lyr
for lyr in QgsMapLayerRegistry.instance().mapLayers().values():
if lyr.name() == "polygon":
poly = lyr
for lyr in QgsMapLayerRegistry.instance().mapLayers().values():
if lyr.name() == "roads":
roads = lyr
for h in startpoint.getFeatures():
for g in poly.getFeatures():
if h.geometry().intersects(g.geometry()):
poly_geom = g.geometry()
for f in roads.getFeatures():
geom = f.geometry().asPolyline()
start_point = QgsGeometry.fromPoint(QgsPoint(geom[0]))
end_point = QgsGeometry.fromPoint(QgsPoint(geom[-1]))
if poly_geom.intersects(start_point) and poly_geom.intersects(end_point):
print f['name']
Die Ausgabe:
road c
road b
road e
road f