I would like to calculate the shortest path from mines to ports, along the rail network. Since the mines and ports are not directly on the network, I first worked out the nearest rail point for each mine and port.
However, I am now struggling to convert the rail network into a NetworkX graph and from there, calculating the shortest distance between each mine and port. Please see below for the code I have written thus far. The rail network can be downloaded from here. I would kindly appreciate any assistance that can be provided. Thank you.
# Ports
ports =
[{'port_name': 'Geraldton', 'geometry': POINT (114.59786 -28.77688)},
{'port_name': 'Bunbury', 'geometry': POINT(115.673447 -33.318797)},
{'port_name': 'Albany', 'geometry': POINT(117.895025 -35.032831)},
{'port_name': 'Esperance', 'geometry': POINT(121.897114 -33.871834)}]
# Mine sites
mines =
[{'mine_name': 'Gold', 'geometry': POINT (117.94568 -34.93467),
{'mine_name': 'Silver', 'geometry': POINT (115.16923 -29.65613)},
{'mine_name': 'Bronze', 'geometry': POINT (115.11039 -29.51287)},
{'mine_name': 'Platinum', 'geometry': POINT (115.11130 -29.42621)}]
# Convert to GeoDataFrame
crs = 'EPSG:4326'
ports = gpd.GeoDataFrame(ports, crs=crs, geometry = 'geometry')
mine_sites = gpd.GeoDataFrame(ports, crs=crs, geometry = 'geometry')
# Column for nearest rail point
ports['nearest_rail_point'] = None
mine_sites['nearest_rail_point'] = None
# Nearest rail point
for index, row in ports.iterrows():
port_point = row['geometry']
nearest_point = nearest_points(port_point, rail_network.unary_union)[1]
ports.at[index, 'nearest_rail_point'] = nearest_point
for index, row in mine_sites.iterrows():
mine_site_point = row['geometry']
nearest_point = nearest_points(mine_site_point, rail_network.unary_union)[1]
mine_sites.at[index, 'nearest_rail_point'] = nearest_point
G = momepy.gdf_to_nx(rail_network)
shortest_distances = {}
# Calculate shortest path
for mine_index, mine_row in mines.iterrows():
mine_name = mine_row['mine_name']
mine_point = mine_row['geometry']
shortest_distances[mine_name] = {}
for port_index, port_row in ports.iterrows():
port_name = port_row['port_name']
port_point = port_row['geometry']
try:
shortest_distance = nx.shortest_path_length(G,
source=(mine_point.x, mine_point.y),
target=(port_point.x, port_point.y),
weight='length')
shortest_distances[mine_name][port_name] = shortest_distance
except nx.NetworkXNoPath:
shortest_distances[mine_name][port_name] = float('inf') # No path found