如何解决OSMNX + NetworkX graph_from_gdfs 使用 nx.ego_graph
尝试将地理包边和节点图层加载为 NetworkX Graph,但在使用“nx.ego_graph”时未能获得返回的正确节点。使用版本 OSMNX 1.0,NetworkX 2.5。
在之前的 question G 波音公司协助使用 Geopackage to Graph 功能。
我现在有一个 Graph 对象,但分析似乎不像使用 True Graph 对象时那样工作,例如G = ox.graph_from_point((53.956748,-1.081676)).
我想为不同的旅行时间创建等时线,并重复使用波音先生在此 example 中已经完成的聪明工作。我想主要使用 'buffer' 选项 - 而不是凸包。
当使用 G = ox.graph_from_point((53.956748,-1.081676),dist=2000,dist_type='network') 即动态下载 osm 数据时,上面示例中的分析目前工作正常,但我有一个特定的工作流程,其中我将数据导出到地理包并进行编辑、添加一些节点和边以表示可能的新道路。
即使不编辑 Geopackage 数据,我也无法进行分析,不同旅行时间返回的节点出现错误。 10 分钟行程时间的等时线多边形与 5 分钟行程时间相同。而且我不相信 5 分钟旅行时间多边形是正确的,因为它是一个非常小的区域。
如果您运行下面的脚本,您已经可以看到在设置节点颜色时存在问题,因为行程时间 5 和 10 返回相同的确切节点(子图 = nx.ego_graph(G=G,n=origin_node,radius =trip_time,distance='time')).
有谁知道这是否表明在使用'ox.graph_from_gdfs'时可能没有正确生成Graph对象?或者是否需要进行更改?
我尝试在 nx.ego_graph 中使用 'undirected=True' 并返回......可能是颜色设置部分中的正确节点,但在生成多边形时,我收到此错误:>
edge_lookup = G.get_edge_data(n_fr,n_to)[0].get('geometry',Linestring([f,t]))
KeyError: 0
在测试中我发现:
- 使用缓冲区等时线方法和 nx.ego_graph: undirected=True - 给出上面的错误
- 使用缓冲区等时线方法和 nx.ego_graph: undirected=False - 给出了最奇异的梨形多边形,它覆盖了北欧的一半(应该是英国的一个小站点
- 使用凸包等时线方法和 nx.ego_graph: undirected=False- 为每次旅行提供相同的多边形,并且这两个多边形的形状都不正确 - 太小了
- 使用凸包等时线方法和 nx.ego_graph: undirected=True- 为每次旅行提供正确的多边形,10 分钟大于 5 分钟等
希望有人知道如何纠正错误。
代码:
geopPath = "Transport_Analysis.gpkg"
geopPath2 = "Transport_Analysis2.gpkg"
yG = 53.9582559586775 # epsg:4326 Geographic
xG = -1.07662649048548 # epsg:4326 Geographic
yP = 451746.474534685 # epsg:27700 Projected
xP = 460685.875721401 # epsg:27700 Projected
distance = 2000
network_type = 'walk'
trip_times = [5,10,15,20,25,30]
travel_speed = 4.5
trip_times = trip_times[0:2] # limit to just first 2 for testing
usewgs84 = True # True False Choose to use Geographic or Projected Coordinates
if usewgs84 == True:
epsg = 4326
orig = (yG,xG) # epsg:4326
print("Using Geographic coords: {},{}".format(xG,yG))
graph_attrs = {'crs': 'epsg:4326','simplified': True}
else:
epsg = 27700 # for my project site in the UK
orig = (yP,xP) # epsg:27700
print("Using Projected coords: {},{}".format(xP,yP))
graph_attrs = {'crs': 'epsg:{}'.format(epsg),'simplified': True}
download = 0
if download == 1:
print("Downloading OSMNX")
G = ox.graph_from_point(orig,dist=distance,dist_type='network')
origin_node = ox.get_nearest_node(G,orig)
print("Downloaded OSMNX")
ox.io.save_graph_geopackage(G,filepath=geopPath2,encoding='utf-8')
geopPath = geopPath2
else:
print("Using existing geopackage: {}".format(geopPath))
# geopPath edges and nodes in native osm epsg:4326
# load GeoPackage as node/edge GeoDataFrames indexed as described in OSMnx docs
gdf_nodes = gpd.read_file(geopPath,layer='nodes').set_index('osmid')
gdf_edges = gpd.read_file(geopPath,layer='edges').set_index(['u','v','key'])
assert gdf_nodes.index.is_unique and gdf_edges.index.is_unique
print("### Loading Existing geopackage road edges and nodes as Graph")
# convert the node/edge GeoDataFrames to a MultiDiGraph
G = ox.graph_from_gdfs(gdf_nodes,gdf_edges,graph_attrs)
if usewgs84 != True: # choose to use projected coordinates for origin/graph instead of geographic
crsObj = CRS.from_user_input(epsg)
# Finally converting graph to projected CRS
G = ox.project_graph(G,to_crs=crsObj)
origin_node = ox.get_nearest_node(G,orig)
print("closest node to coordinate: {} (coord Y,X: {})".format(origin_node,orig))
# add an edge attribute for time in minutes required to traverse each edge
meters_per_minute = travel_speed * 1000 / 60 #km per hour to m per minute
for u,v,k,data in G.edges(data=True,keys=True):
#print(data['time'])
data['time'] = data['length'] / meters_per_minute
iso_colors = ox.plot.get_colors(n=len(trip_times),cmap='plasma',start=0,return_hex=True)
# color the nodes according to isochrone then plot the street network
node_colors = {}
for trip_time,color in zip(sorted(trip_times,reverse=False),iso_colors):
subgraph = nx.ego_graph(G=G,radius=trip_time,undirected=True,distance='time') #
print("Trip time: {}. Subgraph.nodes: {}. Subnodes: {}".format(trip_time,len(subgraph.nodes()),subgraph.nodes()))
for node in subgraph.nodes():
node_colors[node] = color
tripReverse = False
edge_buff=25
node_buff=0
infill=False
isochrone_polys = []
#trip_times = list(trip_times)
for trip_time in sorted(trip_times,reverse=tripReverse): #,undirected=True
subgraph = nx.ego_graph(G=G,distance='time')
node_points = [Point((data['x'],data['y'])) for node,data in subgraph.nodes(data=True)]
nodes_gdf = gpd.GeoDataFrame({'id': list(subgraph.nodes())},geometry=node_points)
nodes_gdf = nodes_gdf.set_index('id')
print("Trip time: {}. Nodes: {}".format(trip_time,len(node_points)))
#print("node_points: {}".format(node_points))
edge_lines = []
for n_fr,n_to in subgraph.edges():
f = nodes_gdf.loc[n_fr].geometry
t = nodes_gdf.loc[n_to].geometry
edge_lookup = G.get_edge_data(n_fr,t]))
edge_lines.append(edge_lookup)
n = nodes_gdf.buffer(node_buff).geometry
e = gpd.GeoSeries(edge_lines).buffer(edge_buff).geometry
all_gs = list(n) + list(e)
new_iso = gpd.GeoSeries(all_gs).unary_union
# try to fill in surrounded areas so shapes will appear solid and blocks without white space inside them
if infill:
new_iso = polygon(new_iso.exterior)
isochrone_polys.append(new_iso)
#print("new_iso: {}".format(new_iso))
iso_df = pd.DataFrame({'trip_times_mins':trip_times[::-1],'color':colors,'geom':polys[::-1]})
iso_df = gpd.GeoDataFrame(iso_df,crs='epsg:{}'.format(epsg),geometry='geom')
# export isochrones to geopackage
iso_df.to_file(geopPath,driver='GPKG',layer='isochrone_{}'.format(network_type))
print("Written isochrone")
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。