def simple_get_roads(city): """ Use osmnx to get a simplified version of open street maps for the city Writes osm_nodes and osm_ways shapefiles to MAP_FP Args: city Returns: None, but creates the following shape files: osm_ways.shp - the simplified road network osm_nodes.shp - the intersections and dead ends And creates the following directory: all_nodes - containing edges and nodes directories for the unsimplified road network """ G1 = ox.graph_from_place(city, network_type='drive', simplify=False) G = ox.simplify_graph(G1) # Label endpoints streets_per_node = ox.count_streets_per_node(G) for node, count in list(streets_per_node.items()): if count <= 1: G.nodes()[node]['dead_end'] = True # osmnx creates a directory for the nodes and edges # Store all nodes, since they can be other features ox.save_graph_shapefile(G1, filename='all_nodes', folder=MAP_FP) # Store simplified network ox.save_graph_shapefile(G, filename='temp', folder=MAP_FP) # Copy and remove temp directory tempdir = os.path.join(MAP_FP, 'temp') for filename in os.listdir(os.path.join(tempdir, 'edges')): name, extension = filename.split('.') shutil.move(os.path.join(tempdir, 'edges', filename), os.path.join(MAP_FP, 'osm_ways.' + extension)) for filename in os.listdir(os.path.join(tempdir, 'nodes')): name, extension = filename.split('.') shutil.move(os.path.join(tempdir, 'nodes', filename), os.path.join(MAP_FP, 'osm_nodes.' + extension)) shutil.rmtree(tempdir)
def clean_intersections(G, tolerance=15, dead_ends=False): """ Clean-up intersections comprising clusters of nodes by merging them and returning their centroids. Divided roads are represented by separate centerline edges. The intersection of two divided roads thus creates 4 nodes, representing where each edge intersects a perpendicular edge. These 4 nodes represent a single intersection in the real world. This function cleans them up by buffering their points to an arbitrary distance, merging overlapping buffers, and taking their centroid. For best results, the tolerance argument should be adjusted to approximately match street design standards in the specific street network. Parameters ---------- G : networkx multidigraph tolerance : float nodes within this distance (in graph's geometry's units) will be dissolved into a single intersection dead_ends : bool if False, discard dead-end nodes to return only street-intersection points Returns ---------- G : modified and cleaned networkx multidigraph """ if not dead_ends: if 'streets_per_node' in G.graph: streets_per_node = G.graph['streets_per_node'] else: streets_per_node = ox.count_streets_per_node(G) dead_end_nodes = [ node for node, count in streets_per_node.items() if count <= 1 ] # G = G.copy() G.remove_nodes_from(dead_end_nodes) return G
def get_dead_end_nodes(network): """ Get nodes representing dead ends in the street network. These are not necessarily nodes with degree of 1, in the undirected representation of the street network, Parameters ---------- network : nx.MultiDiGraph A street network Returns ------- network : nx.MultiDiGraph The same network, but without dead end nodes and edges """ if not 'streets_per_node' in network.graph: network.graph['streets_per_node'] = ox.count_streets_per_node(network) streets_per_node = network.graph['streets_per_node'] return [node for node, count in streets_per_node.items() if count <= 1]
def simple_get_roads(config): """ Use osmnx to get a simplified version of open street maps for the city Writes osm_nodes and osm_ways shapefiles to MAP_FP Args: city Returns: None, but creates the following shape files: osm_ways.shp - the simplified road network osm_nodes.shp - the intersections and dead ends And creates the following directory: all_nodes - containing edges and nodes directories for the unsimplified road network """ # confirm if a polygon is available for this city, which determines which # graph function is appropriate print("searching nominatim for " + str(config['city']) + " polygon") polygon_pos = find_osm_polygon(config['city']) if (polygon_pos is not None): print("city polygon found in OpenStreetMaps at position " + str(polygon_pos) + ", building graph of roads within " + "specified bounds") G1 = ox.graph_from_place(config['city'], network_type='drive', simplify=False, which_result=polygon_pos) else: # City & lat+lng+radius required from config to graph from point if ('city' not in list(config.keys()) or config['city'] is None): sys.exit('city is required in config file') if ('city_latitude' not in list(config.keys()) or config['city_latitude'] is None): sys.exit('city_latitude is required in config file') if ('city_longitude' not in list(config.keys()) or config['city_longitude'] is None): sys.exit('city_longitude is required in config file') if ('city_radius' not in list(config.keys()) or config['city_radius'] is None): sys.exit('city_radius is required in config file') print("no city polygon found in OpenStreetMaps, building graph of " + "roads within " + str(config['city_radius']) + "km of city " + str(config['city_latitude']) + " / " + str(config['city_longitude'])) G1 = ox.graph_from_point( (config['city_latitude'], config['city_longitude']), distance=config['city_radius'] * 1000, network_type='drive', simplify=False) G = ox.simplify_graph(G1) # Label endpoints streets_per_node = ox.count_streets_per_node(G) for node, count in list(streets_per_node.items()): if count <= 1: G.nodes()[node]['dead_end'] = True # osmnx creates a directory for the nodes and edges # Store all nodes, since they can be other features ox.save_graph_shapefile(G1, filename='all_nodes', folder=MAP_FP) # Store simplified network ox.save_graph_shapefile(G, filename='temp', folder=MAP_FP) # Copy and remove temp directory tempdir = os.path.join(MAP_FP, 'temp') for filename in os.listdir(os.path.join(tempdir, 'edges')): name, extension = filename.split('.') shutil.move(os.path.join(tempdir, 'edges', filename), os.path.join(MAP_FP, 'osm_ways.' + extension)) for filename in os.listdir(os.path.join(tempdir, 'nodes')): name, extension = filename.split('.') shutil.move(os.path.join(tempdir, 'nodes', filename), os.path.join(MAP_FP, 'osm_nodes.' + extension)) shutil.rmtree(tempdir)
ville = [ 'Province de Sidi Slimane إقليم سيدي سليمان', ' Province de Midelt إقليم ميدلت', 'Berrechid Province', 'Province de Sidi Bennour إقليم سيدي بنور', 'Rhamna Province', 'Province de Fquih Ben Saleh إقليم الفقيه بن صالح', ' Province de Youssoufia إقليم اليوسفية', ' Province de Tinghir إقليم تنغير', 'Sidi Ifni Province', 'Tarfaya Province' ] ox.config(log_console=True, use_cache=True) # download the street network for Rabat,Maroc street_count = [] for vil in ville: a = 0 print(vil) G = ox.graph_from_place(vil + ',Maroc', network_type='all_private') street = ox.count_streets_per_node(G, nodes=None) for v in street.values(): a = v + a street_count.append([vil, a]) print( "#################################################################################################################" ) print(a) print(street_count) print( "#################################################################################################################" )
def simple_get_roads(config, mapfp): """ Use osmnx to get a simplified version of open street maps for the city Writes osm_nodes and osm_ways shapefiles to mapfp Args: config object Returns: None This function creates the following files features.geojson - traffic signals, crosswalks and intersections osm_ways.shp - the simplified road network osm_nodes.shp - the intersections and dead ends """ ox.settings.useful_tags_path.append('cycleway') G1 = get_graph(config) G = ox.simplify_graph(G1) # Label endpoints streets_per_node = ox.count_streets_per_node(G) for node, count in list(streets_per_node.items()): if count <= 1: G.nodes()[node]['dead_end'] = True G1.nodes()[node]['dead_end'] = True # osmnx creates a directory for the nodes and edges # Store all nodes, since they can be other features # Get relevant node features out of the unsimplified graph nodes, data = zip(*G1.nodes(data=True)) gdf_nodes = geopandas.GeoDataFrame(list(data), index=nodes) node_feats = gdf_nodes[gdf_nodes['highway'].isin( ['crossing', 'traffic_signals'])] intersections = gdf_nodes[gdf_nodes['dead_end'] == True] names = {'traffic_signals': 'signal', 'crossing': 'crosswalk'} features = [] for _, row in node_feats.iterrows(): features.append( geojson.Feature( geometry=geojson.Point((row['x'], row['y'])), id=row['osmid'], properties={'feature': names[row['highway']]}, )) for _, row in intersections.iterrows(): features.append( geojson.Feature( geometry=geojson.Point((row['x'], row['y'])), id=row['osmid'], properties={'feature': 'intersection'}, )) features = geojson.FeatureCollection(features) with open(os.path.join(mapfp, 'features.geojson'), "w") as f: json.dump(features, f) # Store simplified network ox.save_graph_shapefile(G, filename='temp', folder=mapfp) # Copy and remove temp directory tempdir = os.path.join(mapfp, 'temp') for filename in os.listdir(os.path.join(tempdir, 'edges')): _, extension = filename.split('.') shutil.move(os.path.join(tempdir, 'edges', filename), os.path.join(mapfp, 'osm_ways.' + extension)) for filename in os.listdir(os.path.join(tempdir, 'nodes')): _, extension = filename.split('.') shutil.move(os.path.join(tempdir, 'nodes', filename), os.path.join(mapfp, 'osm_nodes.' + extension)) shutil.rmtree(tempdir)
def graph_from_jsons(response_jsons, network_type='all_private', simplify=True, retain_all=False, truncate_by_edge=False, name='unnamed', timeout=180, memory=None, max_query_area_size=50 * 1000 * 50 * 1000, clean_periphery=True, infrastructure='way["highway"]'): """ Create a networkx graph from OSM data within the spatial boundaries of the passed-in shapely polygon. This is a modified routine from osmnx Parameters ---------- response_jsons : list of responses from osmnx the shape to get network data within. coordinates should be in units of latitude-longitude degrees. network_type : string what type of street network to get simplify : bool if true, simplify the graph topology retain_all : bool if True, return the entire graph even if it is not connected truncate_by_edge : bool if True retain node if it's outside bbox but at least one of node's neighbors are within bbox name : string the name of the graph timeout : int the timeout interval for requests and to pass to API memory : int server memory allocation size for the query, in bytes. If none, server will use its default allocation size max_query_area_size : float max size for any part of the geometry, in square degrees: any polygon bigger will get divided up for multiple queries to API clean_periphery : bool if True (and simplify=True), buffer 0.5km to get a graph larger than requested, then simplify, then truncate it to requested spatial extent infrastructure : string download infrastructure of given type (default is streets (ie, 'way["highway"]') but other infrastructures may be selected like power grids (ie, 'way["power"~"line"]')) Returns ------- networkx multidigraph """ if clean_periphery and simplify: g_buffered = ox.create_graph(response_jsons, name=name, retain_all=True, network_type=network_type) # simplify the graph topology g = ox.simplify_graph(g_buffered) # count how many street segments in buffered graph emanate from each # intersection in un-buffered graph, to retain true counts for each # intersection, even if some of its neighbors are outside the polygon g.graph['streets_per_node'] = ox.count_streets_per_node( g, nodes=g.nodes()) else: # create the graph from the downloaded data g = ox.create_graph(response_jsons, name=name, retain_all=True, network_type=network_type) # simplify the graph topology as the last step. don't truncate after # simplifying or you may have simplified out to an endpoint beyond the # truncation distance, in which case you will then strip out your entire # edge if simplify: g = ox.simplify_graph(g) return g