这很复杂,但长话短说:我已经使用了几个像OSMNx这样的图书馆来绘制一个城市的几个景点之间的路线。现在我将其转换为shp文件。
路由是一个充满节点ID的列表。然后使用这些id来提取每个节点的纬度和经度。我制作了元组来连接每个节点的坐标(一个开始,一个到达)和一个for循环,如下所示:
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)]
每个元组都正确显示。但是当我想在一个匀称的LineString中转换旅程时......它会返回:
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)
因此,我无法使用fiona将其转换为shp:
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(最近一次调用 最后)in() 4} 五 ----> 6用fiona.open('test.shp','w','ESRI Shapefile',schema)作为c: 7 c.write({ 8'几何':映射(跟踪)
/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 =集合(路径,模式,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其他: 177引发ValueError(
/usr/local/lib/python3.5/dist-packages/fiona/collection.py in init (自我,路径,模式,驱动程序,架构,crs,编码,图层,vsi,存档,enabled_drivers,crs_wkt,** kwargs) 154 elif self.mode in('a','w'): 155 self.session = WritingSession() - > 156 self.session.start(self,** kwargs) 157除了IOError: 158 self.session =无
fiona.ogrext.WritingSession.start中的fiona / ogrext.pyx (菲奥娜/ ogrext2.c:16207)()
TypeError:'int'类型的参数不可迭代
我不明白为什么在纬度和经度之间没有逗号的情况下转换元组。此外,有几个重复(第三行的第二个坐标是第四行的第一个坐标,等等),也许它可能是未来shp的错误来源。
提前致谢!
答案 0 :(得分: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')
并获得边的几何形状首先设置u的元组,v值作为gdf_edges
的索引,然后loc
选择路径的GeoDataFrame:
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')
然后你可以将它保存到shapefile:
output_edges.to_file()
一个重要的评论:正如我已经说过的,两个节点之间可能有多个边缘。这意味着要唯一地标识边缘,u
并且v
(边缘的开始和结束)是不够的,您还需要key
,它由OSMnx自动添加,您可以在图形和gdf_edges中找到每个边缘。因此,如果您使用上面的代码,请注意它将为您提供all
节点之间的边(如果有多个边)。快速检查是:len(np.nonzero(output_edges['key'])[0])
。如果没有平行边缘,这肯定会为零。如果不是,则表示存在平行边缘。
<强>更新强>
OSMnx具有从GeoDataFrame保存shapefile的功能:
p = '/path/to/destination/'
ox.save_gdf_shapefile(output_lines, 'output', p)
向to_file()
添加架构似乎也有效:
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)