7

How do I remove all vertices except for the last 2 from a whole layer of lines?

Currently, for each line I have to right-click it, and then delete all vertices manually until I'm only left with 0,1. This works fine, but I have thousands of lines I have to do this to.

PolyGeo
  • 65,136
  • 29
  • 109
  • 338
David
  • 73
  • 2
  • 1
    Please clarify, do you mean that if a line has vertices A-B-C-D-F, your aim is to get a line with vertices D-F? – user30184 May 23 '23 at 06:22
  • 1
    Correct. When I start a line might have vertices 0,1,2,3,4. I start with 0 and delete until I'm only left with that was originally 3,4. – David May 23 '23 at 14:04

4 Answers4

10

Get last segment of a line (connect 2nd last to last vertex)

To create the last segment of a line (connecting second last and last vertex), use this expression with Geometry Generator (for visualization) or Geometry by Expression (for actual geometries), see here for details:

make_line (
    point_n ($geometry,-2),
    end_point ($geometry)
)

Instead of end_point ($geometry), you could also use point_n ($geometry,-1).

enter image description here


Connect first and last vertex

This was the initial answer, before your clarification, when I supposed you want to just connect the start- with the end-point of a line. This can be done with this expression:

make_line(start_point($geometry), end_point($geometry))

Another option to create the last segment (by @Matt)

And here another version, proposed by @Matt (thanks for the initiative!):

with_variable('points',
    nodes_to_points($geometry),
    make_line(
        geometry_n(@points, num_geometries(@points) - 1),
        geometry_n(@points, num_geometries(@points))
    )
)

enter image description here

Matt
  • 16,843
  • 3
  • 21
  • 52
Babel
  • 71,072
  • 14
  • 78
  • 208
  • Unfortunately this is an answer to another question - but it was not obvious before the OP clarified what they want to achieve. – user30184 May 23 '23 at 14:09
  • Agreed, my apologies for not being more clear. – David May 23 '23 at 15:32
  • 1
    @Matt thanks for your edit. I added another version to your proposal. Feel free to post your idea as a separate answer or leave it here, as you wish. – Babel May 23 '23 at 19:00
  • 2
    Nice refinement! I overlooked the point_n function. I took the long route :) Good to know it can be reverse indexed too. – Matt May 23 '23 at 19:14
6

You can achieve this using a virtual layer.

The idea is to count the number of vertices, then to create a new line using the last two.

Go to the menu Layer > Add Layer > Add/Edit Virtual Layer..., enter the following query and adjust for your layer name. You can then export the layer to persist its content.

SELECT MAKELINE(
        ST_PointN(geometry,ST_NumPoints(geometry)-1),
        ST_PointN(geometry,ST_NumPoints(geometry))) as geometry
     , *  --all, or some other fields from the original layer
FROM myLine;

enter image description here

JGH
  • 41,794
  • 3
  • 43
  • 89
3

You can also use pyqgis. This will modify your input layer so back it up first.

layer = QgsProject.instance().mapLayersByName("randomlines")[0]

with edit(layer): for f in layer.getFeatures(): #For each feature geom = f.geometry() #Extract the geometry polyline = geom.asPolyline() #And the polyline: #polyline is a list of the vertices in the line: [<QgsPointXY: POINT(630824.0968556385487318 7220488.52948093973100185)>, <QgsPointXY: POINT(638793.75292058940976858 7220541.49230758380144835)>, <QgsPointXY: POINT(641220.008017772808671 7226172.50639093946665525)>, <QgsPointXY: POINT(637517.33679036144167185 7227930.06985464505851269)>, <QgsPointXY: POINT(636037.26971452590078115 7232838.5401100916787982)>, <QgsPointXY: POINT(639733.94647306203842163 7234705.58669823314994574)>]

    newline = QgsLineString(polyline[-2:]) #Create a new line from the last two vertices
    f.setGeometry(QgsGeometry(newline)) #Set the geometry of the feature to the new line
    layer.updateFeature(f) #Update the feature

print("Done")

enter image description here

BERA
  • 72,339
  • 13
  • 72
  • 161
1

Meanwhile, there is a more elegant option than the one proposed in my other solution. However, geometries_to_array() function only works for newer QGIS versions (3.28 +).

geometries_to_array (
    segments_to_lines($geometry)
)[-1]

Use the expression with Geometry Generator (for visualization) or Geometry by Expression (for actual geometries)

enter image description here

Babel
  • 71,072
  • 14
  • 78
  • 208