|
10 | 10 | import numpy as np
|
11 | 11 | import pandas
|
12 | 12 | import shapely.errors
|
| 13 | +try: |
| 14 | + import networkx as nx |
| 15 | + USE_NX = True |
| 16 | +except ImportError: |
| 17 | + USE_NX = False |
13 | 18 |
|
14 | 19 | from geopandas import GeoDataFrame
|
15 | 20 | from shapely.geometry import (
|
@@ -673,3 +678,60 @@ def set_precision(geom, precision):
|
673 | 678 | np.array(geom_mapping["coordinates"]), precision
|
674 | 679 | )
|
675 | 680 | return shape(geom_mapping)
|
| 681 | + |
| 682 | + |
| 683 | +def to_networkx(network,directed=False,weight_col=None): |
| 684 | + """Return a networkx graph |
| 685 | + """ |
| 686 | + if not USE_NX: |
| 687 | + raise ImportError('No module named networkx') |
| 688 | + else: |
| 689 | + # init graph |
| 690 | + if not directed: |
| 691 | + G = nx.Graph() |
| 692 | + else: |
| 693 | + G = nx.MultiDiGraph() |
| 694 | + # get nodes from network data |
| 695 | + G.add_nodes_from(network.nodes.id.to_list()) |
| 696 | + # add nodal positions from geom |
| 697 | + network.nodes['pos'] = list(zip(network.nodes.geometry.x, network.nodes.geometry.y)) |
| 698 | + pos = network.nodes.set_index('id').to_dict()['pos'] |
| 699 | + for n,p in pos.items(): |
| 700 | + G.nodes[n]['pos'] = p |
| 701 | + # get edges from network data |
| 702 | + if weight_col is None: |
| 703 | + network.edges['weight'] = network.edges.geometry.length |
| 704 | + edges_as_list = list(zip(network.edges.from_id,network.edges.to_id,network.edges.weight)) |
| 705 | + else: |
| 706 | + edges_as_list = list(zip(network.edges.from_id,network.edges.to_id,network.edges[weight_col])) |
| 707 | + # add edges to graph |
| 708 | + G.add_weighted_edges_from(edges_as_list) |
| 709 | + return G |
| 710 | + |
| 711 | + |
| 712 | +def get_connected_components(network): |
| 713 | + """Get connected components within network and id to each individual graph |
| 714 | + """ |
| 715 | + if not USE_NX: |
| 716 | + raise ImportError('No module named networkx') |
| 717 | + else: |
| 718 | + G = to_networkx(network) |
| 719 | + return sorted(nx.connected_components(G), key = len, reverse=True) |
| 720 | + |
| 721 | + |
| 722 | +def add_component_ids(network,id_col='component_id'): |
| 723 | + """Add column of component IDs to network data |
| 724 | + """ |
| 725 | + # get connected components |
| 726 | + connected_parts = get_connected_components(network) |
| 727 | + # add unique id to each graph |
| 728 | + network.edges[id_col] = 0 # init id_col |
| 729 | + network.nodes[id_col] = 0 # init id_col |
| 730 | + for count, part in enumerate(connected_parts): |
| 731 | + # edges |
| 732 | + network.edges.loc[ (network.edges.from_id.isin(list(part))) | \ |
| 733 | + (network.edges.to_id.isin(list(part))), id_col ] = count + 1 |
| 734 | + # nodes |
| 735 | + network.nodes.loc[ (network.nodes.id.isin(list(part))), id_col] = count + 1 |
| 736 | + # return |
| 737 | + return network |
0 commit comments