Tuesday 12 April 2016

qgis - Counting number of lines connected to point?


I have a water network which and I need to install elbows and Tees (T). When 2 lines connect to a point, I want to install an elbow, when 3 lines connect, I want to install a Tee.


How do I get ArcGIS or QGIS to determine how many lines are connected to a point and designate an elbow or a tee based on that criteria?


enter image description here



Answer



It is not a problem of geometry (buffer, etc.) but a simple problem of Graph Theory (nodes and connected edges) and Python has many modules for dealing with Graphs (PythonGraphApi, Graphs in Python, Python Patterns - Implementing Graphs, ...)


In your problem, you don't need a point layer, you only need the points/nodes of the polyline. They are the vertex/nodes of a Graph and the segments between two nodes are the edges of the same Graph. And you want to find the nodes with a degree 2 and 3 (number of edges incident to the vertex = when 2 lines connect to a point, I want to install an elbow, when 3 lines connect, I want to install a Tee)


The layer:



enter image description here


The corresponding Graph where we can see directly the desired points (2 and 3 lines connect - figure made with the NetworkX module):


enter image description here


I will use here the NetworkX module (pure Python module). The module can directly open shapefiles to generates a networkx.Graph (Networkx: GIS shapefile) but I do so in the Python console of QGIS:


We need to extract all the segments of the layer (from point to point): the LineString must be iterated over pairs to divide the polyline in segments.


def pairs(list):
'''generator to iterate over pairs in a list '''
for i in range(1, len(list)):
yield list[i-1], list[i]


Creation of the Graph:


import networkx as nx 
# select the polyline layer
layer = qgis.utils.iface.activeLayer()
# create a Graph
G = nx.Graph()
# add the nodes and the edges to the Graph = segment point i -> point i+1
for features in layer.getFeatures():
segment = features.geometry().asPolyline()
# add the two end points of a segment as two nodes and an edge (point1 -> point2) to the Graph

for seg_start, seg_end in pair(segment):
G.add_edges_from([(seg_start, seg_end)])

Now we have the nodes and the edges of the Graph:


 print G.nodes() # = nodes of the polyline in (x,y) form
[(198133,93258.8), (198757,93232.4), (197592,94296.2), (197579,93232.4), (198761,94274.3), (198146,94287.5)]
print G.edges() # = all the segments of the polyline
[((198133,93258.8), (198146,94287.5)), ((198757,93232.4), (198761,94274.3)), ((197592,94296.2), (197579,93232.4)), ((197592,94296.2), (198146,94287.5)), ((198761,94274.3), (198146,94287.5))]

We search the nodes which the degree is > 1



 for i in G.nodes():
if G.degree(i) > 1:
print QgsPoint(i), G.degree(i)
(197592,94296.2) 2
(198761,94274.3) 2
(198146,94287.5) 3

And we obtain the desired points:


Result:


enter image description here



No comments:

Post a Comment

arcpy - Changing output name when exporting data driven pages to JPG?

Is there a way to save the output JPG, changing the output file name to the page name, instead of page number? I mean changing the script fo...