2017-10-04 3 views
0

상당히 복잡하지만 긴 이야기가 짧습니다. 도시의 여러 지점 사이에 경로를 그리려면 OSMNx와 같은 여러 라이브러리를 사용했습니다. 이제 나는 그것을 shp 파일로 변환 할 것이다.Shapely : LineString이있는 쉼표가없는 튜플

경로는 노드의 ID로 가득 찬 목록입니다. 그런 다음이 ID를 사용하여 각 노드의 위도와 경도를 추출합니다.

journey = [] 
# previous list will contain tuples with coordinates of each node 

for node1, node2 in zip(route[:-1], route[1:]): 
    parcours.append(tuple((G.node[noeud1]['x'], G.node[noeud1]['y']))) # we create a tuple with coordinates of start's node 
    parcours.append(tuple((G.node[noeud2]['x'], G.node[noeud2]['y']))) # then we make the same for the arrival node 

여기에 인쇄 (여행)의 결과의 루프의 끝 :

나는 다음과 같이 루프에 대한 각 노드 쌍 (하나의 시작, 일 도착)의 좌표를 연결하는 튜플을했다
[(6.15815, 48.6996136), (6.1629696, 48.7007431), (6.1629696, 48.7007431), [...], (6.1994411, 48.6768434), (6.1994411, 48.6768434), (6.1995322, 48.6767583)] 

각 튜플이 올바르게 나타납니다. 나는의 매끈한 유도 선에서 여행을 변환 할 ... 그리고이 반환 때 :

import fiona 
schema = { 
    'geometry': 'Polygon', 
    "properties": {'id': 123} 
} 

with fiona.open('test.shp', 'w', 'ESRI Shapefile', schema) as c: 
    c.write({ 
     'geometry': mapping(trace) 
    }) 

--------------------------------------------------------------------------- TypeError Traceback (most recent call last) in() 4 } 5 ----> 6 with fiona.open('test.shp', 'w', 'ESRI Shapefile', schema) as c: 7 c.write({ 8 'geometry': mapping(trace)

/usr/local/lib/python3.5/dist-packages/fiona/init.py in open(path, mode, driver, schema, crs, encoding, layer, vfs, enabled_drivers, crs_wkt) 173 c = Collection(path, mode, crs=crs, driver=driver, schema=this_schema, 174 encoding=encoding, layer=layer, vsi=vsi, archive=archive, --> 175 enabled_drivers=enabled_drivers, crs_wkt=crs_wkt) 176 else: 177 raise ValueError(

/usr/local/lib/python3.5/dist-packages/fiona/collection.py in init(self, path, mode, driver, schema, crs, encoding, layer, vsi, archive, enabled_drivers, crs_wkt, **kwargs) 154 elif self.mode in ('a', 'w'): 155 self.session = WritingSession() --> 156 self.session.start(self, **kwargs) 157 except IOError: 158 self.session = None

fiona/ogrext.pyx in fiona.ogrext.WritingSession.start (fiona/ogrext2.c:16207)()

TypeError: argument of type 'int' is not iterable

: 결과적으로

from shapely.geometry import LineString 
final_journey = LineString(journey) 
print(final_journey) 
LINESTRING (6.15815 48.6996136, 6.1629696 48.7007431, 6.1629696 48.7007431, 6.1630717 48.7002871, [...], 6.1991794 48.677085, 6.1994411 48.6768434, 6.1994411 48.6768434, 6.1995322 48.6767583) 

, 나는 피오나를 사용하여 SHP에서 변환 할 수 없습니다 튜플이 위도와 경도 사이에 쉼표없이 변환되는 이유를 이해할 수 없습니다. 또한 몇 가지 중복이 있습니다 (세 번째 줄의 두 번째 좌표는 네 번째 줄의 첫 번째 좌표 등입니다 ...) 미래 shp에 대한 오류의 원인 일 수 있습니다.

미리 감사드립니다.

+0

을보고 무엇 print (final_journey)는 라인의 [Well Known Text] (https://en.wikipedia.org/wiki/Well-known_text) 표현입니다. 이 점에 아무런 문제가 없습니다 (예 : '쉼표가없는 튜플 (tuples in comma)'). 인터프리터에서 모양을 매끄럽게 표시하는 것입니다. – mgc

답변

1

노드 좌표를 얻은 다음이를 함께 연결하는 것이 가장 좋은 방법이라고 생각하지 않습니다. 거리가 직선이 아니라면 어떨까요? OSMnx는 거리의 정확한 형상을 제공합니다. 노드의 기하학을 추출하기 위해보다 나은 해답이 here으로 설명됩니다. 그러나 거리의 기하학이 필요합니다. 두 노드 사이에 둘 이상의 에지가있을 수 있으므로 항상 간단한 것은 아닙니다. 나는 ox.get_route_edge_attributes()이 그렇게 할 수 있어야한다고 믿는다. 실제로 다른 속성 (예 : highway)을 요청하면 잘 동작하지만 가장자리가 geometry 인 것은 아니다. 그 이유는 (내가 생각하기에) G의 모든 에지가 geometry이 아니지만, 네트워크의 gdf_edges을 얻는다면 항상 각 에지의 기하학적 모양을가집니다. 다음은 작업 주위에 다음 나는 발견

gdf_nodes, gdf_edges = ox.graph_to_gdfs(G) 
path = nx.shortest_path(G, G.nodes()[0], G.nodes()[1]) 

이 경로의 노드 GeoDataFrame를 얻으려면 :

output_points = gdf_nodes.loc[path] 
output_points.plot(color='red') 

enter image description here

가장자리의 형상을 얻기 위해 첫 번째의 튜플을 설정 u, v 값을 gdf_edges의 인덱스로 지정한 다음 경로의 GeoDataFrame을 선택하려면 loc

gdf_edges.index = gdf_edges.apply(lambda row: (row.u, row.v), axis=1) 
output_lines = gdf_edges.loc[list(zip(path[:-1], path[1:]))] 
output_lines.plot(color='red') 

enter image description here

당신은 그 Shape 파일에 저장할 수 있습니다 :

output_edges.to_file() 

한 가지 중요한 발언 : 이미 말했듯이, 두 노드 사이의 하나 이상의 가장자리가있을 수 있습니다.즉, 가장자리를 고유하게 식별하기 위해 uv (가장자리의 시작과 끝)이 충분하지 않은 경우 key이 필요하며 이는 OSMnx에 의해 자동으로 추가되며 모든 가장자리에 대해 그래프와 gdf_edges에서 모두 찾습니다. 그래서 위의 코드를 사용하는 경우 노드 사이에 둘 이상의 가장자리가있는 경우 all 가장자리를 제공한다는 점에 유의하십시오. 빠른 확인은 len(np.nonzero(output_edges['key'])[0])입니다. 평행 한 모서리가 없다면 이것은 반드시 0이 될 것입니다. 그렇지 않다면 평행 한 모서리가 있음을 의미합니다. 너무 작동 to_file()에 스키마를 추가

p = '/path/to/destination/' 
ox.save_gdf_shapefile(output_lines, 'output', p) 

가 보인다 :

UPDATE

OSMnx는 GeoDataFrame에서 Shape 파일을 저장하는 기능을 가지고 당신이 할 때

sch = {'geometry': 'LineString', 
     'properties': {'key': 'int', 
         'u': 'int', 
         'v': 'int'}} 

test = gpd.GeoDataFrame(output_lines[['u', 'v', 'key']], 
         geometry=output_lines['geometry'], crs='+init=EPSG:3740') 

test.to_file('/path/to/destination/test.shp', schema=sch) 
+0

안녕하세요 Alireza! 그냥 귀하의 솔루션을 테스트하고 output_edges.to_file() 단계까지 괜찮 았는데 (나는 그것이 좋은 변수라고 확신하지 않는다, 나는 그것이 output_lines로 더 낫다고 생각했다). 내 질문에 내 것과 같은 스키마를 제출해야합니까? 미리 감사드립니다! – Raphadasilva

+0

@Raphadasilva가 업데이트를 확인합니다. –

+0

Wonderful, 답변 확인. 다시 한 번 감사드립니다. – Raphadasilva