TransWikia.com

Snapping lines to points according to attribute field value with PyQGIS

Geographic Information Systems Asked by Jess8070 on December 3, 2020

I would like to snap line features (.shp) to the corresponding point features based on a common attribute field they have (and not according to any distance). I have around 150 different attribute values, and for each I do have only one corresponding point feature but several lines to snap to it.


I thought of doing the following steps to achieve this goal:

1) Creating a list of values containing uniques values from the line attribute field

2) Iterating over the point and the line layer to select features corresponding to each unique value

3) Snap the selected lines to the selected point


I did the first step but I do not manage to code the following steps in PyQGIS. Does someone have any ideas how it could be done?


Here is my network in the first place :
Here is my network in the first place :

Here the result after snapping the lines to the plot outlet :
Here the result after snapping the lines to the plot outlet :

One Answer

Try this code:

linelyr = QgsProject.instance().mapLayersByName('Single parts')[0] #Change to match you layername
lineidfield = 'id' #Change
pointlyr = QgsProject.instance().mapLayersByName('New scratch layer')[0] #Change
pointidfield = 'id' #Change

max_distance = 500 #Change. It is the maximum distance to search for points to snap to

d = {} #Dictionary to store each lines id and the point it should be snapped to
for line in linelyr.getFeatures():
    verts = [v for v in line.geometry().vertices()]
    lastvert = verts[-1]
    potential_points = []
    for p in pointlyr.getFeatures():
        potential_points = []
        dist = p.geometry().distance(QgsGeometry.fromPointXY(QgsPointXY(lastvert)))
        if dist <=max_distance and line[lineidfield]==p[pointidfield]:
            potential_points.append([QgsPoint(p.geometry().asPoint()), dist])
            d[line.id()] = min(potential_points, key=lambda x: x[1])[0] #If multiple points with the same id as the line, then snap to the closest point 
    
#d is each lines id and the point it should be snapped to:
#{1: <QgsGeometry: Point (340686.33727786090457812 6426865.10069382563233376)>, 4: <QgsGeometry: Point (337979.94456608395557851 6427246.28276590723544359)>}

#Update line geometries using dictionary
with edit(linelyr):
    for f in linelyr.getFeatures():
        if f.id() in d:
            g = [v for v in f.geometry().vertices()]
            g[-1] = d[f.id()] #Replace last vertice (-1) with the point from the dictionary
            f.setGeometry(QgsGeometry.fromPolyline(g))
            linelyr.updateFeature(f)

From: enter image description here To: enter image description here

Correct answer by BERA on December 3, 2020

Add your own answers!

Ask a Question

Get help from others!

© 2024 TransWikia.com. All rights reserved. Sites we Love: PCI Database, UKBizDB, Menu Kuliner, Sharing RPP