Examples¶
This page includes examples of usage of the Wayfarer library.
Page Contents
Named Tuples¶
Wayfarer includes an Edge class that can be used to access values using properties.
import networkx
from wayfarer import Edge, to_edge
from wayfarer import functions
net = networkx.MultiGraph()
edge = Edge(start_node=0, end_node=1, key=1, attributes={})
# use the helper function to add the Edge named tuple to the network
functions.add_edge(net, *edge)
# use some networkx functions to get edges back
node_ids = [1]
edges = net.edges(nbunch=node_ids, data=True, keys=True)
# now use the to_edge function to convert back to a named tuple
edges = [to_edge(e) for e in edges]
edge = edges[0]
# now we can access the properties as below
print(edge.key)
print(edge.start_node)
print(edge.end_node)
print(edge.attributes)
Node to Node Routing¶
from wayfarer import loader, routing
from shapely.geometry import mapping
from shapely.ops import transform
import json
import pyproj
net = loader.load_network_from_file("./data/riga.pickle")
path = routing.solve_shortest_path(net, start_node=1390592196, end_node=1812435081)
features = []
transformer = pyproj.Transformer.from_crs(
"EPSG:3857", "EPSG:4326", always_xy=True
).transform
for edge in path:
# convert to EPSG:4326
geom = transform(transformer, edge.attributes["geometry"])
feature = {
"type": "Feature",
# convert the Shapely geometry to a GeoJSON geometry
"geometry": mapping(geom),
"properties": {"id": edge.key},
}
features.append(feature)
geojson_obj = {"type": "FeatureCollection", "features": features}
# save to a geojson file
with open("./data/riga.geojson", "w") as f:
json.dump(geojson_obj, f, indent=4)
print("Done!")
Node to Node Routing¶
from wayfarer import loader, routing
from shapely.geometry import mapping
from shapely.ops import transform
import json
import pyproj
net = loader.load_network_from_file("./data/riga.pickle")
path = routing.solve_shortest_path(net, start_node=1390592196, end_node=1812435081)
features = []
transformer = pyproj.Transformer.from_crs(
"EPSG:3857", "EPSG:4326", always_xy=True
).transform
for edge in path:
# convert to EPSG:4326
geom = transform(transformer, edge.attributes["geometry"])
feature = {
"type": "Feature",
# convert the Shapely geometry to a GeoJSON geometry
"geometry": mapping(geom),
"properties": {"id": edge.key},
}
features.append(feature)
geojson_obj = {"type": "FeatureCollection", "features": features}
# save to a geojson file
with open("./data/riga.geojson", "w") as f:
json.dump(geojson_obj, f, indent=4)
print("Done!")
Loading a network using GeoPandas¶
"""
python ./docs/examples/create_network_geopandas.py
"""
import geopandas as gpd
from wayfarer import loader
import os
def load_network(input_lines, output_network, overwrite=False):
lines = gpd.read_file(input_lines, layer="edges")
# add a unique field
lines["oid"] = range(1, len(lines) + 1)
lines.drop(columns="key", inplace=True)
print(lines.head())
if not os.path.exists(output_network) or overwrite is True:
net = loader.load_network_from_records(
lines.to_dict("records"),
key_field="oid",
length_field="length",
from_field="from",
to_field="to",
)
loader.save_network_to_file(net, output_network)
return loader.load_network_from_file(output_network)
if __name__ == "__main__":
# works with any GDAL supported dataset
input_lines = "./data/dublin.gpkg"
output_network = "./data/net.pickle"
net = load_network(input_lines, output_network, overwrite=False)
print("Done!")
Loading a network from OSM¶
import osmnx as ox
from wayfarer import loader
from osmnx import convert, projection
def download_osm():
"""
Download roads from OSM centered around Riga, Latvia
This only needs to be run once.
"""
location_point = (56.94105, 24.09682)
# get roads within a distance of 500m from this point
bbox = ox.utils_geo.bbox_from_point(location_point, dist=500)
G = ox.graph_from_bbox(bbox=bbox)
# save as a graph
ox.save_graphml(G, filepath="./data/riga.graphml")
# also save the data as a GeoPackage for review (not required for routing)
ox.save_graph_geopackage(G, filepath="./data/riga.gpkg")
def create_wayfarer_graph():
# load the OSMnx graph from the previously saved file
G = ox.load_graphml("./data/riga.graphml")
# get data frames from the graph
_, gdf_edges = convert.graph_to_gdfs(convert.to_undirected(G))
# project to Web Mercator from EPSG:4326 so we can work with planar distance calculations
gdf_edges = projection.project_gdf(gdf_edges, to_crs="EPSG:3857")
# get a dictionary of all edges in the network
d = gdf_edges.to_dict("records")
# loop through the edges and add a unique key
recs = []
for fid, props in enumerate(d):
# we can't use osmid as the key as sometimes it is not always unique and sometimes a list
# instead use the enumerator which will match the FID in the GeoPackage
props.update({"key": fid})
# we reprojected the geometry to Web Mercator, so we also need to update the length field
props["length"] = props["geometry"].length
recs.append(props)
# create the wayfarer network
net = loader.load_network_from_records(
recs,
key_field="key",
length_field="length",
from_field="from",
to_field="to",
)
# save the network
loader.save_network_to_file(net, "./data/riga.pickle")
if __name__ == "__main__":
download_osm()
create_wayfarer_graph()
print("Done!")
Snapping Points to a Network¶
from shapely.geometry import shape, Point
from wayfarer import loader, to_edge, linearref
def get_closest_edge(net, pt):
closest_line = None
min_dist = float("inf")
for edge in net.edges(data=True, keys=True):
edge = to_edge(edge)
geom = shape(edge.attributes["geometry"])
dist = pt.distance(geom)
if dist < min_dist:
min_dist = dist
closest_line = geom
fid = edge.key
# find snapped point on the line
snap_point, _ = linearref.get_nearest_vertex(pt, closest_line)
# get the measure along the line
distance_along = linearref.get_measure_on_line(closest_line, snap_point)
return (fid, distance_along)
net = loader.load_network_from_file("./data/riga.pickle")
start_pt = Point(2682555, 7748329)
end_pt = Point(2682585, 7747272)
print(get_closest_edge(net, start_pt))
# (281, 55.395036218377086)
print(get_closest_edge(net, end_pt))
# (1103, 7.734503415793048)