Skip to content

Instantly share code, notes, and snippets.

@kuanb
Created April 26, 2017 23:07
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save kuanb/ca953faf85e7b2d3464470f5b2087615 to your computer and use it in GitHub Desktop.
Save kuanb/ca953faf85e7b2d3464470f5b2087615 to your computer and use it in GitHub Desktop.
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.
matplotlib.use('Agg')
import geopandas as gpd
import pandas as pd
from shapely.geometry import Point
import osmnx as ox
COUNTER = 0
def plot(gdf):
global COUNTER
COUNTER += 1
name = 'output_' + str(COUNTER) + '.png'
gdf.plot().get_figure().savefig(name)
# 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})
gdf_nodes.crs = G.graph['crs']
# create and visually inspect intersection nodes
gdf_nodes = gdf_nodes.to_crs(epsg=3310)
plot(gdf_nodes)
# create and visually inspect buffered nodes
gdf_nodes['geometry'] = gdf_nodes.buffer(20)
plot(gdf_nodes)
# 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']
else:
# 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)]
G.remove_nodes_from(nodes_to_drop)
return G
def remove_osmnx_unwalkable_intersections(G, unwalkable_types=['motorway',
'motorway_link',
'trunk',
'trunk_link']):
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):
unwalkable_nodes_to_drop.append(node)
G.remove_nodes_from(unwalkable_nodes_to_drop)
return G
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment