QGIS를 사용하는데 포인트와 도로망이 있습니다. 특정 지점을 둘러싼 도로 이름을 자동으로 추출해야합니다.
가장 가까운 이웃 분석 및 버퍼 구역은 많은 경우에 측정 된 거리 문제로 인해 주변 도로가 아닌 주변 도로에 더 가깝기 때문에 작업을 수행 할 수 없습니다. 주변 도로 만 추출 할 수있는 방법에 대한 아이디어가 있습니까?
답변
내 테스트 데이터에 관하여 :
- OSM 도로 데이터와 마찬가지로 모든 단일 도로 지오메트리는 교차로에서 끝납니다.
- 모든 도로에는 고유 한 ID가 있습니다.
솔루션 I
두 가지 가정이있는 경우 :
-
도로는 숙소를 짓고 있습니다.
-
미터법 시스템에서 작업하고 있습니다.
아이디어는 점의 X 및 Y 좌표를 늘리거나 줄이는 것입니다. 미터법 시스템 내에서 작업하는 경우 포인트 동쪽으로 1m 이동하여 새 포인트를 작성하고 원래 포인트로 선을 작성할 수 있습니다. 선이 도로를 교차 할 때까지 동쪽으로 더갑니다. 서부에서 교차점을 찾으려면 원래 X 좌표에서 1m를 뺍니다. Y 좌표에 대해서도 동일합니다. 북 / 동 / 남 / 서에 도로가 없으면 카운터는 1000 (m)에서 멈 춥니 다. 1000m 이상의 거리에 도로가있을 수 있음을 알고 있으면이 값을 변경해야합니다.
다음 코드를 사용하여 작업을 해결할 수 있습니다.
편집
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)
동쪽의 도로 e가 지점의 가까운 도로로 인식되지 않음을 보여주는 또 다른 예입니다.
함수를 호출하고 출력하는 방법 :
>>>>reached('N', 1000)
road a
>>>>reached('E', 1000)
road b
>>>>reached('S', 1000)
road c
>>>>reached('W', 1000)
road d
지점을 둘러싸고있는 도로가 4 개 이상인 경우 더 많은 방향을 살펴 봐야합니다 (X와 Y 모두 변경). 또는 선의 방위각을 변경할 수 있습니다. 즉, 0-360 ° 범위 내에서 1도 회전 할 수 있습니다.
솔루션 II
의견에서 영감을 얻어 Polygonize
도로를 먼저 할 수도 있습니다. 따라서 QGIS의 도구를 사용할 수 있습니다 Processing > Toolbox > QGIS geoalgorithms > Vector geometry tools > Polygonize
. 임시 레이어의 이름을로 바꿉니다 polygon
. 도로로 완전히 둘러싸인 지점의 도로 이름 만 원한다고 가정합니다. 그렇지 않으면 솔루션 I 을 사용해야 합니다. 모든 도로가 연결 (스냅) 된 경우에만 작동합니다!
먼저 점이 다각형과 교차해야합니다. 이제는 AND
둘러싸는 선의 시작 끝 점이 둘 다 다각형과 교차해야합니다.
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']
출력 :
road c
road b
road e
road f