6

For an examination of a local power grid, I need to mark the transformation stations (substation) by simply create a point for each station.

What I want to do is that QGIS creates a point at the end of a line automatically.

How can I get there?

example

7 Answers 7

17

There is a possibility using a "Virtual Layer" through Layer > Add Layer > Add/Edit Virtual Layer....

Let's assume there is a polyline layer called 'polylines' (blue lines).

input

With the following query, it is possible to create a point at the end of each line.

SELECT
    st_endpoint(geometry), *
FROM
    "polylines"

The output point layer (yellow) with its attribute table will look like

output

Mind the difference between ST_StartPoint() and ST_EndPoint(). Basically, what @TeddyTedTed meant by Which one you need will depend on the direction of the line.

15

In the Processing Toolbox use the Extract Specific Vertices tool, for the Vertex indices use 0 for the first vertex and -1 for the last vertex. Which one you need will depend on the direction of the line.

EDIT: Apologies, I didn't read your question properly, you said automatically. If it's just for display purposed you could use a geometry generator symbology to show a point at the end of the line using end_point($geometry) as the expression. If you need to create an actual data point automatically every time a line is created then I'm not sure how to do that.

1
  • An additional good point for this answer is that is also gives the value of angle of the segment of the line, i.e. azimuth. Aug 20, 2021 at 15:23
7

You can use the processing tool "Geometry by Expression" and either use start_point($geometry) or end_point($geometry) as expression.

If you want them for display purposes only, you can use these expression within layersymbology and add an geometry generator.

4

Another example using pyqgis:

layer = iface.activeLayer()

def find_endpoint(feat):
    for item in feat.geometry().vertices(): #https://stackoverflow.com/questions/2138873/cleanest-way-to-get-last-item-from-python-iterator
        pass
    return QgsPointXY(item)

ends = [find_endpoint(f) for f in layer.getFeatures()]

vl = QgsVectorLayer("Point?crs={}&index=yes".format(layer.crs().authid()), "endpoints", "memory")
provider = vl.dataProvider()
for e in ends:
    g = QgsGeometry.fromPointXY(e)
    f = QgsFeature()
    f.setGeometry(g)
    provider.addFeature(f)
QgsProject.instance().addMapLayer(vl)

enter image description here

0
3

A simple solution could be:

Using Vector ‣ Geometry Tools ‣ Extract verticas. Afterwards simply delete all points but thoose which were generated at the end and beginning.

1
  • 1
    What if you have thousands of lines and each has at least 1000 vertices in each?
    – Taras
    Aug 18, 2020 at 8:10
3

Another approach via RMB > Duplicate Layer.

Then for a new layer by means of "Geometry Generator" apply RMB > Properties > Symbology > Geometry Generator as Point/MultiPoint. This will be for display purposes only.

output

If you are using "Geometry by Expression" from processing toolbox this is not for display purposes only. It creates the geometry as new layer.

0
3

Additionally, I may suggest using PyQGIS, tested on QGIS 3.10.4-A Coruña.

Let's assume there is a line layer 'lines', see image below.

input

Proceed with Plugins > Python Console > Show Editor and paste the script below

# providing the polyline layer's name
layer_name = "line"

# accessing the line layer by name
try:
    layer = QgsProject.instance().mapLayersByName(layer_name)[0]
except IndexError:
    raise ValueError("The layer {} does not exist.".format(layer_name))

# creating an empty point layer for output
point_layer = QgsVectorLayer("Point?crs={}&index=yes".format(layer.crs().authid()), "End Points", "memory")
provider = point_layer.dataProvider()

# detecting layer wkb and wkb type
layer_wkb = layer.wkbType() # integer
layer_wkb_type = QgsWkbTypes.displayString(layer_wkb) # string

# checking geometry type of the layer
if layer.wkbType() == QgsWkbTypes.MultiLineString: # getting end points for each part of a MultiLineString layer geometry type
    print("Your layer is a {}-geometry type".format(layer_wkb_type))
    for feature in layer.getFeatures():
        multi_geom = feature.geometry().asMultiPolyline()
        for part in multi_geom:
            end_point = QgsPoint(part[-1])
            f = QgsFeature()
            f.setGeometry(end_point)
            provider.addFeature(f)

elif layer.wkbType() == QgsWkbTypes.LineString: # getting end points for a LineString layer geometry type
    print("Your layer is a {}-geometry type".format(layer_wkb_type))
    for feature in layer.getFeatures():
        geom = feature.geometry().asPolyline()
        end_point = QgsPoint(geom[-1])
        f = QgsFeature()
        f.setGeometry(end_point)
        provider.addFeature(f)

else: # other layer geometry types are not accepted
    print("Your layer is a {}-geometry type, when only 'LineString' or 'MultiLineString' is accepted".format(layer_wkb_type))

# adding a new layer to the map
QgsProject.instance().addMapLayer(point_layer)

Press Run script run script and get the output that will look like

output


References:

Your Answer

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

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