I have CSV sets of navigation points, with the following scheme: Easting, Northing, Line_name, Fiducial.

I can connect the lines with Points to Path, using the Line_name as the Group field and Fiducial as the Order field.

However, I also need to create multiple segments of the same line, if the points are too far apart. Example: We have points every 0.5 m along a line, but there are two instances, where the following point is 10 m away. As an end result, I need three line segments with no connection across the 10 m gap. Ideally, those line segments will preserve the Line_name in their attributes.

I need a tool that can batch process very large files with thousands of lines.

I was thinking of calculating the distance to the previous point and every time this distance is above a given critical limit, I would increment an indicator field, which I can then use to create subgroups, but this is a bit involved.

Is there an easier way?


Here is a PyQGIS code for do this, comment in code.

Just adapt variables in the beginning of the script. The result is a new mutliline layer with one field "Line".

from qgis.PyQt.QtCore import QVariant

# variables
layer_name = "My_layer_name"
line_field_name = "Line"
m_threshold = 0.5
new_name = "new_lines"
order_variable = "Fiducial"

# find point vector layer
vl = QgsProject.instance().mapLayersByName(layer_name)[0]

# create a new line layer
crs = vl.crs().authid()
vline = QgsVectorLayer("multilinestring?crs=" + crs, new_name , "memory")
pr = vline.dataProvider()
pr.addAttributes([QgsField(line_field_name, QVariant.String)])

new_geometry = QgsGeometry()

idx = vl.fields().indexOf(line_field_name)
line_values = vl.uniqueValues(idx)

for line in line_values:
    # init for
    expr = QgsExpression('"' + line_field_name + '"= \'' + line + '\'')
    request = QgsFeatureRequest(expr)
    wkt = "MultiLineString (("
    previous_linename = None
    previous_geometry = None

    for feat in vl.getFeatures(request):

        if previous_linename is not None:
            segment = feat.geometry().shortestLine(previous_geometry)

            if segment.length() > m_threshold:
                # delete last comma and begin next part
                wkt = wkt[:-1] + "),("

            pt = feat.geometry().asPoint()
            wkt += str(pt.x()) + " " + str(pt.y()) + ","

        previous_linename = line
        previous_geometry = feat.geometry()
        pt = feat.geometry().asPoint()
        wkt += str(pt.x()) + " " + str(pt.y()) + ","

    # delete last comma and close wkt
    wkt = wkt[:-1] + "))"
    new_feat = QgsFeature()

# update extent for the new line layer
# load new line layer to canvas
  • This was the right idea! I had to fix the script, since it skips the first fiducial of every line - we need to add to the wkt string in the first instance of the for loop as well. Also modified the code to make sure all variables are specified only in the beginning and not in the middle of the code. The edited version can be seen here: pastebin.com/wFe8DWfs – miln40 Jul 16 at 1:38
  • 1
    I've edited my code with your modifications. – J. Monticolo Jul 17 at 8:12

If you prefer a solution using the built-in tools, this can be done in two steps using tools from the Processing Toolbox.

  1. Use densify by interval to add vertices in any lines longer than 0.5m. (Note: this tool measures distance in the same units used by the layer CRS.)
  2. Use explode lines to split the lines at their vertices.
  • 3. delete the line segments longer than 0.5m and remerge the rest. This can work, however, I'd have to remerge the exploded segments of the same line per hand - I can't remerge them by attribute, or I will get a connection across the longer gaps. – miln40 Jul 16 at 1:43

Not the answer you're looking for? Browse other questions tagged or ask your own question.