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

PolyGeo
  • 65,136
  • 29
  • 109
  • 338
Ma Fo
  • 671
  • 7
  • 15

7 Answers7

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.

Taras
  • 32,823
  • 4
  • 66
  • 137
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.

TeddyTedTed
  • 6,100
  • 1
  • 11
  • 36
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.

MrXsquared
  • 34,292
  • 21
  • 67
  • 117
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

BERA
  • 72,339
  • 13
  • 72
  • 161
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.

Ma Fo
  • 671
  • 7
  • 15
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:

Taras
  • 32,823
  • 4
  • 66
  • 137
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.

MrXsquared
  • 34,292
  • 21
  • 67
  • 117
Taras
  • 32,823
  • 4
  • 66
  • 137