[GIS] adding points to a line shapefile at specified distance in python

gdalpythonshapefile

I want to add create nodes\points at an interval on a line shapefile let say at every 100 meters and save those points as shapefile.

I came across a plugin for Qgis called Qchainage, this exactly performs the task i want to do, but I am not sure how to adapt this plugin into my python script.

Best Answer

In PyQGIS you can use interpolate method from QgsGeometry to do that. Generated points can be stored as a memory layer. Complete example code is:

layer = iface.activeLayer()

feat = layer.getFeatures().next()

geom = feat.geometry()

length = geom.length()

distance = 100

points = []

iter = distance

while iter <= length:

    pt = feat.geometry().interpolate(iter).exportToWkt()

    points.append(pt)

    iter += distance

epsg = layer.crs().authid()

uri = "Point?crs=" + epsg + "&field=id:integer""&index=yes"

mem_layer = QgsVectorLayer(uri,
                           'points',
                           'memory')

prov = mem_layer.dataProvider()

feats = [ QgsFeature() for i in range(len(points)) ]

for i, feat in enumerate(feats):
    feat.setAttributes([i])
    feat.setGeometry(QgsGeometry.fromWkt(points[i]))

prov.addFeatures(feats)

QgsMapLayerRegistry.instance().addMapLayer(mem_layer)

I tried it out with line shapefile of next image; where it is also observed memory point layer produced.

enter image description here

Editing Note:

A shorter code could be generated if you have installed in your system fiona and shapely python modules.

import fiona
from shapely.geometry import shape, mapping

line = fiona.open('pyqgis_data/new_line.shp')

crs = line.crs

line = line.next()

geom = shape(line['geometry'])

# length of the LineString
length = geom.length

# creation of the resulting shapefile
schema = {'geometry': 'Point','properties': {'id': 'int'}}

with fiona.open('pyqgis_data/new_shape.shp', 'w', 'ESRI Shapefile', schema, crs=crs) as output:
    # create points every 100 meters along the line
    for i, distance in enumerate(range(0, int(length), 100)):
         point = geom.interpolate(distance)   
         output.write({'geometry':mapping(point),'properties': {'id':i}}) 

It produces same result layer (but it's saved in disk as shapefile; not as memory layer).

Related Question