Skip to content

Instantly share code, notes, and snippets.

What would you like to do?
Using OSMnx, pull down a network and remove "unneeded" intersections from boulevards and like, so as to not double count.
import matplotlib
# Force matplotlib to not use any Xwindows backend.
import geopandas as gpd
import pandas as pd
from shapely.geometry import Point
import osmnx as ox
def plot(gdf):
global COUNTER
name = 'output_' + str(COUNTER) + '.png'
# let's start with beautiful Merced, CA
location_point = (37.3022, -120.4830)
# get the network graph for a radius of 500 meters
radius = 500 # meter unit measure
G = ox.graph_from_point(location_point, distance=radius)
G = remove_osmnx_false_intersections(G, min_streets_per_int=3)
G = remove_osmnx_unwalkable_intersections(G, unwalkable_types=['motorway','motorway_link','trunk','trunk_link','primary_link'])
node_geom = [Point(data['x'], data['y']) for _, data in G.nodes(data=True)]
gdf_nodes = gpd.GeoDataFrame({'node':pd.Series(G.nodes()), 'geometry':node_geom}) = G.graph['crs']
# create and visually inspect intersection nodes
gdf_nodes = gdf_nodes.to_crs(epsg=3310)
# create and visually inspect buffered nodes
gdf_nodes['geometry'] = gdf_nodes.buffer(20)
# set a bool column to track which intersections to use
gdf_nodes['use'] = True
list_of_nodes = gdf_nodes.index.values
for node_id in list_of_nodes:
current = gdf_nodes.loc[node_id]
# only proceed if has not already been marked as False (don't use)
if current['use']:
ints_with = gdf_nodes.intersects(current.geometry)
# review intersecting buffered nodes
sub_gdf = gdf_nodes[ints_with]
sub_gdf_sans_current = sub_gdf[sub_gdf.index != node_id]
# get the indexes of other rows and 'turn them off'
turn_these_off = sub_gdf_sans_current.index.values
for sub_node_id in turn_these_off:
gdf_nodes.loc[sub_node_id, 'use'] = False
# here is a dataframe of unique geometries
cleaned_ints = gdf_nodes[gdf_nodes['use'] == True]
# preserved osmnx helper functions
def remove_osmnx_false_intersections(G, min_streets_per_int=3):
if 'streets_per_node' in G.graph:
# get the degrees saved as a graph attribute (from an undirected representation of the graph)
# this is not the degree of the nodes in the directed graph, but rather represents the number
# of streets (unidirected edges) emanating from each node. see count_streets_per_node function.
streets_per_node = G.graph['streets_per_node']
# count how many street segments emanate from each node in this graph
streets_per_node = count_streets_per_node(G)
# count number of intersections in graph, as nodes with >1 street emanating from them
node_ids = set(G.nodes())
nodes_to_drop = [node for node, count in streets_per_node.items() if (count < min_streets_per_int) and (node in node_ids)]
return G
def remove_osmnx_unwalkable_intersections(G, unwalkable_types=['motorway',
unwalkable_nodes_to_drop = []
for node in G.nodes():
edge_types = [list(edge.values())[0]['highway'] for edge in G.edge[node].values()]
if any(unwalkable_type in edge_types for unwalkable_type in unwalkable_types):
return G
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.