5

I have a set of points that fall along a trail, as in this image:

enter image description here

and I need to convert these points to line segments.

The points fall along a polyline, and points on the same line share a common ID "Road_ID". I want to connect them as in the coloured segments below:

enter image description here

I have tried using points to a path with the order field as an ID which skips (e.g. 108, 110, 112) and the group field "Road_ID". This gave me a result with many connected points that were not even close to what I wanted:

enter image description here

What is the best way to approach this?

Edit to add detail:

Points data: | ID | Road_ID | |----|---------| | 28 | A | | 29 | B | | 30 | A | | 31 | B |

So each even-numbered ID is on one side, each odd-numbered is on the opposite side.

0

2 Answers 2

4

I wrote this code with the same proposal some time ago, maybe it can be useful for you, but you will need to fix some geometry parts manually because the code works from connecting nearest points with Pythagorean theorem.

First load the points layer to the project, then paste this code as a new Python script in the QGIS python console and remember to set the layer name (not the path) in the code. If you want the line to start at a particular point you can select it.

import qgis.core
import math
layer_name = '' # put inside the quotes the layer name (not the layer path)
close_line = True # true if you want to close the line
project = QgsProject().instance()
layer = project.mapLayersByName(layer_name)[0]
connected_points = []

def nearest_p(p1_id):
    p_distances = []
    p1_geometry_as_point = layer.getFeature(p1_id).geometry().asPoint()
    for feature in layer.getFeatures():
        if feature.id() != p1_id and not feature.id() in connected_points:
            p2_geometry_as_point = feature.geometry().asPoint()
            x_dif = p1_geometry_as_point.x() - p2_geometry_as_point.x()
            y_dif = p1_geometry_as_point.y() - p2_geometry_as_point.y()
            distance = math.sqrt(x_dif ** 2 + y_dif ** 2)
            p_distances.append([distance, feature.id()])
    p_distances.sort(key=lambda a : a[0])
    return p_distances[0][1]
    
if layer.selectedFeatureCount() > 0:
    init_ids = layer.selectedFeatureIds()[0]
else:
    init_ids = 1
    
connected_points.append(init_ids)
for i in range(1, layer.featureCount()):
    init_ids = nearest_p(init_ids)
    connected_points.append(init_ids)
    
XY_line = [layer.getFeature(feature_id).geometry().asPoint() for feature_id in connected_points]
if close_line:
    XY_line.append(XY_line[0])

line_crs = layer.crs().authid().lower()
line = QgsVectorLayer('LineString?crs=' + line_crs, 'Line', 'memory')
line.startEditing()
feature = QgsFeature(0)
feature.setGeometry(QgsGeometry.fromPolylineXY(XY_line))
line.addFeature(feature)
line.endEditCommand()
line.commitChanges()
project.addMapLayer(line)
3
  • Thanks for this code- unfortunately trying to adapt and run this has caused QGIS to freeze and crash twice. Just as a sanity check, layer_name should just be whatever is displayed in the Layers section (e.g. "markers" in this case). And I am a little new to using python in QGIS- how would I modify this to use the ID column "ESRI_ID"?
    – Amie
    Commented Mar 14, 2022 at 21:46
  • This script doesn't use any attributes of the point layer, it works by connecting the nearest points. So you don't need to specify any fields, all you need to set is the layer name and whether you want to close the path. But if you know that all the odd ids are on one side of the path and all the even ids are on the other side, you can use the 25.1.15.8. Points to path tool.
    – Mayo
    Commented Mar 14, 2022 at 23:08
  • Yes, you can run the 25.1.15.8. Points to path algorithm setting the parameters like this: CLOSE_PATH: False, ORDER_EXPRESSION must be your 'ESRI_ID' field, GROUP_EXPRESSION can be calculated like this: 'ESRI_ID' % 2.
    – Mayo
    Commented Mar 14, 2022 at 23:19
0

EDIT:

My earlier answer (following this edit) describes the use of the PointsToPaths tool, which has inexplicably been removed from the Plugins repository, after having been updated to 3.x (https://github.com/chiatt/pointstopaths). More's the pity.

Fortunately, however, there is a functionally equivalent alternative:

How to to create lines from points where the point attributes are transferred to the line segments?

Finally, if a user absolutely required the PointsToPaths tool, they could download a separate install of the last version of QGIS 2.x (2.18.28), and then install the 2.x version of the PointsToPaths plugin.

End of edit......

Your question is somewhat confusing, because you share nothing of your attribute data (in particular your ID and Road_ID fields), and as Bera has requested, it would be very helpful to see a little of that.

However, if your data meets three simple requirements, there is a wonderful QGIS plugin that should provide a solution. The plugin is named PointsToPaths. Note the plural Paths; this plugin has additional functionality not available in the stock Points to Path tool.

The first requirement is that the two sets of points (I'll call them "left" and "right" are found in the same layer.

The second requirement is that "left" and "right" can be distinguished from each other. I'm assuming that is the purpose of the Road_ID field, wherein all of the "left" points contain a value, such as 1, an all of the "right" points contain a different value, such as 2.

The third requirement is that the "left" and "right" points are each separately ordered sequentially (that is, from top to bottom, or vice versa), like children's "connect the dots" books. The values may skip, but they must at least ascend in a connected order. Let's call this field sequence.

In the plugin, the "Point group field" dropdown would be the Road_ID field. The "Point order field" dropdown would be the sequence field. You must check the Line to Vertex box.

Voila! The output will be a line shapefile with two new lines. Look closely at its output attribute table, and you'll see that it has three fields: group, begin, and end. The group field contains the input point's Road_ID value, which allows you to distinguish between the two new lines (aka "left" and "right"). The begin and end fields contain the two sequence values that comprise each output line segment. Using your screenshot as an example, there will be 5 output records, one for each new line segment.

4
  • 1
    I am not able to use PointsToPaths because that is not available in QGIS for version 3- do you know of a version that is available in QGIS3?
    – Amie
    Commented Mar 14, 2022 at 21:41
  • Good news, Amie! PointsToPaths was updated to V3 last fall. You'll find it in the Plugin Manager.
    – Stu Smith
    Commented Mar 14, 2022 at 23:14
  • @StuSmith I am using QGIS 3.34, and PointsToPaths is not listed in the Plugin Manager. When I look it up in the QGIS Plugins Repository, it shows as incompatible with v3. plugins.qgis.org/plugins/pointstopaths_v02/#plugin-versions
    – Kirkman14
    Commented Apr 11 at 14:39
  • @Kirkman14, please see my updated answer.
    – Stu Smith
    Commented Apr 13 at 14:47

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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