在 Python 中迭代 OSMNX 中的等时线
Iterating over an isochrone in OSMNX in Python
我正在尝试使用 Python based on this example 中的 OSMNX
遍历一些多边形,但我遇到了输出问题。
设置:
import geopandas as gpd
import matplotlib.pyplot as plt
import networkx as nx
import osmnx as ox
from descartes import PolygonPatch
from shapely.geometry import Point, LineString, Polygon
ox.config(log_console=True, use_cache=True)
ox.__version__
# get one color for each isochrone
iso_colours = ox.get_colors(n=len(trip_times), cmap='Reds', start=0.3, return_hex=True)
#info for later on
network_type = 'walk'
trip_times = [5, 10] #in minutes
travel_speed = 4.8 #walking speed in km/hour
metres_per_minute = travel_speed * 1000 / 60 #km per hour to m per minute
# isochrone function
def make_iso_polys(G, edge_buff=25, node_buff=50, infill=False):
isochrone_polys = []
for trip_time in sorted(trip_times, reverse=True):
subgraph = nx.ego_graph(G, centre_node, radius=trip_time, distance='time')
node_points = [Point((data['x'], data['y'])) for node, data in subgraph.nodes(data=True)]
nodes_gdf = gpd.GeoDataFrame({'id': subgraph.nodes()}, geometry=node_points)
nodes_gdf = nodes_gdf.set_index('id')
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_lines.append(LineString([f,t]))
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)
return isochrone_polys
# the area
mv = ox.graph_from_bbox(-37.705, -37.796, 144.949, 144.84, network_type='walk')
mv_projected = ox.project_graph(mv)
ox.plot_graph(mv_projected)
multiple_coords = ((-37.773981, 144.915669),
(-37.765443, 144.863070),
(-37.736089, 144.888972),
(-37.764914, 144.924148),
(-37.788513, 144.930533))
问题出在哪里。我添加了一些额外的文本来跟踪代码中发生的事情:
# test function to do multiple ones
def iterate_multiple_coords(the_coordinates):
for i in the_coordinates:
centre_node = ox.get_nearest_node(mv, (i[0], i[1]))
print("starting" + str(i)) # to check
# add an edge attribute for time in minutes required to traverse each edge
for u, v, k, data in mv_projected.edges(data=True, keys=True):
data['time'] = data['length'] / metres_per_minute
# make the polygons
isochrone_polys_iter = make_iso_polys(mv_projected, edge_buff=25, node_buff=0, infill=True)
print("done " + str([i])) # to check
poly_list.append(isochrone_polys_iter)
print("appended " + str([i])) # to check
return(poly_list)
#list of shapely objects
test = iterate_multiple_coords(multiple_coords)
这似乎可行,但是当您查看已创建的多边形时,它们只是其中两个的副本。他们应该都是不同的。
for i in test:
print(i[0].area)
print(i[1].area)
只生产副本:
[<shapely.geometry.polygon.Polygon object at 0x00000252EED81048>, <shapely.geometry.polygon.Polygon object at 0x0000025299DCD7B8>]
1221891.0262004482
278954.2285476034
[<shapely.geometry.polygon.Polygon object at 0x000002529A0FF978>, <shapely.geometry.polygon.Polygon object at 0x00000252F0884978>]
1170723.0839951886
254020.00263692273
我该如何解决这个问题?谢谢。
试图重现这个问题,我运行陷入了两个错误。解决这些似乎会产生正确的结果。首先,make_iso_polys
还需要有 centre_node
作为参数:
def make_iso_polys(G, centre_node, edge_buff=25, node_buff=50, infill=False):
isochrone_polys = []
for trip_time in sorted(trip_times, reverse=True):
subgraph = nx.ego_graph(G, centre_node, radius=trip_time, distance='time')
node_points = [Point((data['x'], data['y'])) for node, data in subgraph.nodes(data=True)]
nodes_gdf = gpd.GeoDataFrame({'id': subgraph.nodes()}, geometry=node_points)
nodes_gdf = nodes_gdf.set_index('id')
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_lines.append(LineString([f,t]))
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)
return isochrone_polys
我怀疑这就是您的问题所在。如果您在某个时候在函数外部定义了 centre_node
,那么 make_iso_poly
将在名称空间中进行搜索,直到找到一个值。
我也 运行 遇到错误 iterate_multiple_coords
没有要追加的列表,这很容易解决:
def iterate_multiple_coords(the_coordinates):
poly_list = []
for i in the_coordinates:
centre_node = ox.get_nearest_node(mv, (i[0], i[1]))
print("starting" + str(i)) # to check
# add an edge attribute for time in minutes required to traverse each edge
for u, v, k, data in mv_projected.edges(data=True, keys=True):
data['time'] = data['length'] / metres_per_minute
# make the polygons
isochrone_polys_iter = make_iso_polys(mv_projected,
centre_node,
edge_buff=25,
node_buff=0,
infill=True)
print("done " + str([i])) # to check
poly_list.append(isochrone_polys_iter)
print("appended " + str([i])) # to check
return(poly_list)
我尝试使用更多输出进行测试以确定多边形不同:
#list of shapely objects
test = iterate_multiple_coords(multiple_coords)
for i, poly in enumerate(test):
print(i)
print(poly[0].bounds)
print(poly[0].area)
print(poly[1].bounds)
print(poly[1].area)
这个returns对我来说
0
(315719.9722479802, -4183576.0970487385, 317146.7585685815, -4182104.248355794)
1064783.069852857
(316092.45915179665, -4183138.881268308, 316857.3685328224, -4182352.8318315353)
207488.55915115002
1
(311160.15906794026, -4182601.4787744572, 312318.75050440413, -4181146.474157421)
844021.6754682651
(311491.4241338904, -4182296.4498064136, 312171.21314883756, -4181535.6374544636)
181959.15194429446
2
(313349.77854383545, -4179191.5691777603, 314706.9086066517, -4177874.3106440073)
697618.2735243046
(313611.9777962584, -4178837.4315966303, 314316.9596420839, -4178365.0333478907)
105808.08447317046
3
(316506.3163716192, -4182533.536447418, 317712.9680439883, -4181044.336753285)
1042931.7802330595
(316764.0345564607, -4182162.9997046595, 317463.6017386513, -4181398.2886200016)
276870.23606513516
4
(317045.2449636515, -4185110.519037448, 318554.4721278832, -4183677.93438998)
1170827.5838636972
(317408.8052150706, -4184702.3494480574, 318143.3573653238, -4184063.5647333027)
253939.04383932063
我正在尝试使用 Python based on this example 中的 OSMNX
遍历一些多边形,但我遇到了输出问题。
设置:
import geopandas as gpd
import matplotlib.pyplot as plt
import networkx as nx
import osmnx as ox
from descartes import PolygonPatch
from shapely.geometry import Point, LineString, Polygon
ox.config(log_console=True, use_cache=True)
ox.__version__
# get one color for each isochrone
iso_colours = ox.get_colors(n=len(trip_times), cmap='Reds', start=0.3, return_hex=True)
#info for later on
network_type = 'walk'
trip_times = [5, 10] #in minutes
travel_speed = 4.8 #walking speed in km/hour
metres_per_minute = travel_speed * 1000 / 60 #km per hour to m per minute
# isochrone function
def make_iso_polys(G, edge_buff=25, node_buff=50, infill=False):
isochrone_polys = []
for trip_time in sorted(trip_times, reverse=True):
subgraph = nx.ego_graph(G, centre_node, radius=trip_time, distance='time')
node_points = [Point((data['x'], data['y'])) for node, data in subgraph.nodes(data=True)]
nodes_gdf = gpd.GeoDataFrame({'id': subgraph.nodes()}, geometry=node_points)
nodes_gdf = nodes_gdf.set_index('id')
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_lines.append(LineString([f,t]))
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)
return isochrone_polys
# the area
mv = ox.graph_from_bbox(-37.705, -37.796, 144.949, 144.84, network_type='walk')
mv_projected = ox.project_graph(mv)
ox.plot_graph(mv_projected)
multiple_coords = ((-37.773981, 144.915669),
(-37.765443, 144.863070),
(-37.736089, 144.888972),
(-37.764914, 144.924148),
(-37.788513, 144.930533))
问题出在哪里。我添加了一些额外的文本来跟踪代码中发生的事情:
# test function to do multiple ones
def iterate_multiple_coords(the_coordinates):
for i in the_coordinates:
centre_node = ox.get_nearest_node(mv, (i[0], i[1]))
print("starting" + str(i)) # to check
# add an edge attribute for time in minutes required to traverse each edge
for u, v, k, data in mv_projected.edges(data=True, keys=True):
data['time'] = data['length'] / metres_per_minute
# make the polygons
isochrone_polys_iter = make_iso_polys(mv_projected, edge_buff=25, node_buff=0, infill=True)
print("done " + str([i])) # to check
poly_list.append(isochrone_polys_iter)
print("appended " + str([i])) # to check
return(poly_list)
#list of shapely objects
test = iterate_multiple_coords(multiple_coords)
这似乎可行,但是当您查看已创建的多边形时,它们只是其中两个的副本。他们应该都是不同的。
for i in test:
print(i[0].area)
print(i[1].area)
只生产副本:
[<shapely.geometry.polygon.Polygon object at 0x00000252EED81048>, <shapely.geometry.polygon.Polygon object at 0x0000025299DCD7B8>]
1221891.0262004482
278954.2285476034
[<shapely.geometry.polygon.Polygon object at 0x000002529A0FF978>, <shapely.geometry.polygon.Polygon object at 0x00000252F0884978>]
1170723.0839951886
254020.00263692273
我该如何解决这个问题?谢谢。
试图重现这个问题,我运行陷入了两个错误。解决这些似乎会产生正确的结果。首先,make_iso_polys
还需要有 centre_node
作为参数:
def make_iso_polys(G, centre_node, edge_buff=25, node_buff=50, infill=False):
isochrone_polys = []
for trip_time in sorted(trip_times, reverse=True):
subgraph = nx.ego_graph(G, centre_node, radius=trip_time, distance='time')
node_points = [Point((data['x'], data['y'])) for node, data in subgraph.nodes(data=True)]
nodes_gdf = gpd.GeoDataFrame({'id': subgraph.nodes()}, geometry=node_points)
nodes_gdf = nodes_gdf.set_index('id')
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_lines.append(LineString([f,t]))
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)
return isochrone_polys
我怀疑这就是您的问题所在。如果您在某个时候在函数外部定义了 centre_node
,那么 make_iso_poly
将在名称空间中进行搜索,直到找到一个值。
我也 运行 遇到错误 iterate_multiple_coords
没有要追加的列表,这很容易解决:
def iterate_multiple_coords(the_coordinates):
poly_list = []
for i in the_coordinates:
centre_node = ox.get_nearest_node(mv, (i[0], i[1]))
print("starting" + str(i)) # to check
# add an edge attribute for time in minutes required to traverse each edge
for u, v, k, data in mv_projected.edges(data=True, keys=True):
data['time'] = data['length'] / metres_per_minute
# make the polygons
isochrone_polys_iter = make_iso_polys(mv_projected,
centre_node,
edge_buff=25,
node_buff=0,
infill=True)
print("done " + str([i])) # to check
poly_list.append(isochrone_polys_iter)
print("appended " + str([i])) # to check
return(poly_list)
我尝试使用更多输出进行测试以确定多边形不同:
#list of shapely objects
test = iterate_multiple_coords(multiple_coords)
for i, poly in enumerate(test):
print(i)
print(poly[0].bounds)
print(poly[0].area)
print(poly[1].bounds)
print(poly[1].area)
这个returns对我来说
0
(315719.9722479802, -4183576.0970487385, 317146.7585685815, -4182104.248355794)
1064783.069852857
(316092.45915179665, -4183138.881268308, 316857.3685328224, -4182352.8318315353)
207488.55915115002
1
(311160.15906794026, -4182601.4787744572, 312318.75050440413, -4181146.474157421)
844021.6754682651
(311491.4241338904, -4182296.4498064136, 312171.21314883756, -4181535.6374544636)
181959.15194429446
2
(313349.77854383545, -4179191.5691777603, 314706.9086066517, -4177874.3106440073)
697618.2735243046
(313611.9777962584, -4178837.4315966303, 314316.9596420839, -4178365.0333478907)
105808.08447317046
3
(316506.3163716192, -4182533.536447418, 317712.9680439883, -4181044.336753285)
1042931.7802330595
(316764.0345564607, -4182162.9997046595, 317463.6017386513, -4181398.2886200016)
276870.23606513516
4
(317045.2449636515, -4185110.519037448, 318554.4721278832, -4183677.93438998)
1170827.5838636972
(317408.8052150706, -4184702.3494480574, 318143.3573653238, -4184063.5647333027)
253939.04383932063