How to: connect lines from two points with same attribute values in QGIS

A step-by-step walkthrough of creating a line layer from existing point layers using QGIS expressions

 1047 words  |   5-min read  |    GIS, QGIS, QGIS Expression


2022-07-connect-lines-from-same-values-pts/cover-photo-connect-lines.jpg

TL;DR

I have a new task to generate lines from two points with the same attribute value. After finishing this task with some googling, I believe it will be great to write a learning note of how to use the powerful QGIS Expressions to create geometries.


The Problem

TL;DR version:

I need to create a bunch of lines which connect two points having the same attribute.

Full version with context of the task:

The first point layer (GEO_PLACE_NAME) includes some location points with an attribute PLACE_NAME_NAME_EN storing the place name of the points. The second layer (place-name-osm-clean) also includes some locations with an attribute name_en storing the place names.

My task is to connect the points in these two layers with a straight line when they have the same place name.

For example, both points with the place name “Mong Kok” should be connected, while both points with name “Tai Kok Tsui” should also be connected. The points labelled in underlined red text belongs to place-name-osm-clean layer, while those labelled in black text belongs to GEO_PLACE_NAME layer.

dot-wihtout-n-with-lines

The points from two layers (left), with the lines to be created (right)

Steps

  1. Ensure the two point datasets have the same geographic coordinate system (GCS).

This sanity check is essential, since the geometry generated relies on the actual coordinate provided in the points dataset. If the first layer is in HK1980 GCS (e.g. 838048,817801) and the second layer is in WGS 1984 (e.g. 114.176,22.299), QGIS will treat the coordinate values in the second layers as HK1980 also. Thus the lines will ends up in the origin point (0,0) of HK1980 GCS, which is somewhere in the middle of nowhere in Laos1.

  1. Open and click on the processing toolbox.

  2. Search for geometry by expression function.

    processing-toolbox-location

  3. Double click on the Geometry by expression tool to open the toolbox window.

  4. For Input layer, select the first point layer (GEO_PLACE_NAME)

  5. For Output geometry type, select Line

    geometry-expression-arguments

  6. Click on the Ɛ button on right hand side of the geometry expression bar. A new window named Geometry expression should pop out.

    geometry-expression-window

  7. Type the following expression into the box.

    make_line(
      -- the current feature's geometry (point from sensor layer).
      $geometry,
      -- the matching feature's geometry from the layer 'place-name-osm-clean'
      -- where the attribute 'name_en' matches the current feature's attribute
      -- "PLACE_NAME_NAME_EN"
      geometry(get_feature('place-name-osm-clean', 'name_en', "PLACE_NAME_NAME_EN" ))
    )
    

    geometry-expression

  8. Click OK to close the window

  9. Click Run

run-function

You should see a new layer is created, with lines connecting the points with the same place name.

results-with-connected-lines

The output: A line layer of lines connecting points with same attribute value

How it works

So, what the heck is going on? What does that geometry expression mean?

What the tool does

In a nutshell, Geometry by expression is a function that allows you to create spatial data (i.e. geometries) programmatically.

Geometry by expression allows users to create geometries using QGIS expression. Based on the properties of the input layer, you could create any type of geometry you want (point, line or polygon). For example, with a polygon input layer, you could build a expression to generate a new point layer of the centroid of the polygons.

What the expression does

Now you know what Geometry by expression is doing. The next is the code block using the generate the desired geometry.

make_line(
  -- the current feature's geometry (point from sensor layer).
  $geometry,
  -- the matching feature's geometry from the layer 'place-name-osm-clean'
  -- where the attribute 'name_en' matches the current feature's attribute
  -- "PLACE_NAME_NAME_EN"
  geometry(get_feature('place-name-osm-clean', 'name_en', "PLACE_NAME_NAME_EN" ))
)

Lines start with -- are comments and won’t be executed, just like # in Python and R. Thus, the code could be shorten as:

make_line(
  $geometry,
  geometry(get_feature('place-name-osm-clean', 'name_en', "PLACE_NAME_NAME_EN" ))
)

The $geometry variable refers to the geometry of the current feature. A feature includes many information - at its basis, it includes geometry and attributes2. Since we are only interested in its geometry and spatial form, we use $geometry to get the geometry.

In QGIS expressions, variables start with the dollar sign $ refers to the current feature. In fact, you could search for the manual by typing the name of the functions in the Search box next to the expression builder. The user manual will appear in the white box on the right.

geometry-manual

User manual of `$geoemtry` in the expression builder

In the next row, there’s a geometry() function outside. This function, as its name suggests, returns the geometry of the computed feature. The get_feature() function inside acts like Select by Attributes function in ArcGIS, or Select by Expression in QGIS. You could check the manual and see what this function does.

get-feature-manual

User manual of `$get_feature` in the expression builder

Therefore, geometry(get_feature('place-name-osm-clean', 'name_en', "PLACE_NAME_NAME_EN" )) means:

  1. Get the first feature found in place-name-osm-clean layer with its name_en attribute same as the PLACE_NAME_NAME_EN attribute in the current feature of GEO_PLACE_NAME layer.
  2. return the geometry of that point.

Finally, the things above are wrapped inside a make_line() function. This function, as explicitly tell by its name, creates a line geometry from a number of points. It takes all arguments and create a line in the order of arguments provided.

make-line-manual

User manual of `$make_line` in the expression builder

So, in plain English, the whole expression is going to:

For all points in the GEO_PLACE_NAME layer, create a line with:

  1. The geometry of the current selected point feature in the GEO_PLACE_NAME layer
  2. The geometry of the point in place-name-osm-clean layer where it’s name_en value matches the PLACE_NAME_NAME_EN value of the first point.

Exactly my task I stated at the top of this blog, yet in a more programmatic way.


TIP: When you press control and click on the get_feature function inside the expression editor, the right hand side will automatically pop up the manual of the function.

click-function.webp

Immediately get the manual of the function using `Ctrl + Left Click`

Reference


  1. Yep, I screwed up on my first try. That’s why I put a warning here and hope you do not get screwed up by map projection (again). wrong-projection ↩︎

  2. Recall your introduction to GIS course - a feature basically includes its location (i.e. geometry) and information related to that feature (i.e. attributes). ↩︎

The Latest