Search code examples
pythonnetworkxshapefiledelaunay

How to make NetworkX graph from Delaunay preserving attributes of the input nodes?


I have a point shape-file (each point have several attributes) and make a Delaunay triangulation graph (with no duplicating edges) out of it. I found some code that creates needed graph but unfortunately nodes attributes are completely lost.

The code I use to get Delaunay graph:

import networkx as nx

# import point data 
points = nx.read_shp('/path_to_file') 


# make a Delaunay triangulation of the point data
import scipy.spatial
delTri = scipy.spatial.Delaunay(points)

# create a set for edges that are indexes of the points
edges = set()
# for each Delaunay triangle
for n in xrange(delTri.nsimplex):
    # for each edge of the triangle
    # sort the vertices
    # (sorting avoids duplicated edges being added to the set)
    # and add to the edges set
    edge = sorted([delTri.vertices[n,0], delTri.vertices[n,1]])
    edges.add((edge[0], edge[1]))
    edge = sorted([delTri.vertices[n,0], delTri.vertices[n,2]])
    edges.add((edge[0], edge[1]))
    edge = sorted([delTri.vertices[n,1], delTri.vertices[n,2]])
    edges.add((edge[0], edge[1]))


# make a graph based on the Delaunay triangulation edges
graph = nx.Graph(list(edges))

# plot graph
import matplotlib.pyplot as plt
pointIDXY = dict(zip(range(len(points)), points))
nx.draw(graph, pointIDXY)
plt.show()

Here is the data for the input nodes:

>>>points.nodes(data = True)
>>>[((653854.2887252048, 6676443.725469278), {'ShpName': 'check_points', 'cp_id': '51', 'pkuid': '15'}), ((651880.5105124662, 6677858.581665079), {'ShpName': 'check_points', 'cp_id': '0', 'pkuid': '17'}), ((655433.3302676764, 6679596.752591419), {'ShpName': 'check_points', 'cp_id': '33', 'pkuid': '12'}), ((654739.8072938774, 6681295.233334893), {'ShpName': 'check_points', 'cp_id': '63', 'pkuid': '4'}), ((654424.43862939, 6679762.249781273), {'ShpName': 'check_points', 'cp_id': '48', 'pkuid': '11'}), ((656352.7651133023, 6682630.2863400215), {'ShpName': 'check_points', 'cp_id': '71', 'pkuid': '2'}), ((652171.0352182373, 6680403.878163689), {'ShpName': 'check_points', 'cp_id': '61', 'pkuid': '6'}), ((657526.8446215878, 6681796.9322037045), {'ShpName': 'check_points', 'cp_id': '34', 'pkuid': '1'}), ((655048.9892074043, 6678474.725799518), {'ShpName': 'check_points', 'cp_id': '49', 'pkuid': '14'}), ((653576.844982715, 6677334.967596577), {'ShpName': 'check_points', 'cp_id': '31', 'pkuid': '16'}), ((652642.464297833, 6679192.287594619), {'ShpName': 'check_points', 'cp_id': '55', 'pkuid': '7'}), ((653383.6360820442, 6679887.990946876), {'ShpName': 'check_points', 'cp_id': '64', 'pkuid': '8'}), ((654075.960724057, 6679142.807192051), {'ShpName': 'check_points', 'cp_id': '32', 'pkuid': '13'}), ((652202.7024457924, 6682304.823924673), {'ShpName': 'check_points', 'cp_id': '70', 'pkuid': '5'}), ((655313.5670240957, 6682933.524067418), {'ShpName': 'check_points', 'cp_id': '62', 'pkuid': '3'}), ((654771.537087416, 6680395.075728455), {'ShpName': 'check_points', 'cp_id': '50', 'pkuid': '9'}), ((653870.7028004956, 6680276.006017963), {'ShpName': 'check_points', 'cp_id': '54', 'pkuid': '10'})]

And here is the data for Delaunay graph:

>>>graph.edges(data = True)
>>>{0: (653854.2887252048, 6676443.725469278), 1: (651880.5105124662, 6677858.581665079), 2: (655433.3302676764, 6679596.752591419), 3: (654739.8072938774, 6681295.233334893), 4: (654424.43862939, 6679762.249781273), 5: (656352.7651133023, 6682630.2863400215), 6: (652171.0352182373, 6680403.878163689), 7: (657526.8446215878, 6681796.9322037045), 8: (655048.9892074043, 6678474.725799518), 9: (653576.844982715, 6677334.967596577), 10: (652642.464297833, 6679192.287594619), 11: (653383.6360820442, 6679887.990946876), 12: (654075.960724057, 6679142.807192051), 13: (652202.7024457924, 6682304.823924673), 14: (655313.5670240957, 6682933.524067418), 15: (654771.537087416, 6680395.075728455), 16: (653870.7028004956, 6680276.006017963)}
[(0, 8, {}), (0, 1, {}), (0, 9, {}), (0, 7, {}), (1, 9, {}), (1, 10, {}), (1, 13, {}), (1, 6, {}), (2, 8, {}), (2, 15, {}), (2, 3, {}), (2, 4, {}), (2, 7, {}), (3, 5, {}), (3, 7, {}), (3, 13, {}), (3, 14, {}), (3, 15, {}), (3, 16, {}), (4, 8, {}), (4, 11, {}), (4, 12, {}), (4, 15, {}), (4, 16, {}), (5, 14, {}), (5, 7, {}), (6, 16, {}), (6, 10, {}), (6, 11, {}), (6, 13, {}), (7, 8, {}), (8, 9, {}), (8, 12, {}), (9, 10, {}), (9, 12, {}), (10, 11, {}), (10, 12, {}), (11, 16, {}), (11, 12, {}), (13, 16, {}), (13, 14, {}), (15, 16, {})]

>>>graph.nodes(data = True)
>>>[(0, {}), (1, {}), (2, {}), (3, {}), (4, {}), (5, {}), (6, {}), (7, {}), (8, {}), (9, {}), (10, {}), (11, {}), (12, {}), (13, {}), (14, {}), (15, {}), (16, {})]

Solution

  • Here is the code to re-attribute nodes after Delaunay graph creation:

    #add nodes attributes to the Delaunay graph from the original points
      original_nodes = points.nodes(data = True)
      for n in xrange(len(original_nodes)):
        XY = original_nodes[n][0] # X and Y tuple - coordinates of the original points
        graph.node[n]['XY'] = XY
        # add other attributes
        original_attributes = original_nodes[n][1]
        for i in original_attributes.iteritems():
          graph.node[n][i[0]] = i[1]