July 18, 2022
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 |
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.
Steps
- 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.
Open and click on the processing toolbox.
Search for
geometry by expression
function.Double click on the Geometry by expression tool to open the toolbox window.
For Input layer, select the first point layer (GEO_PLACE_NAME)
For Output geometry type, select Line
Click on the Ɛ button on right hand side of the geometry expression bar. A new window named Geometry expression should pop out.
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" )) )
Click OK to close the window
Click Run
You should see a new layer is created, with lines connecting the points with the same place name.
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.
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.
Therefore, geometry(get_feature('place-name-osm-clean', 'name_en', "PLACE_NAME_NAME_EN" ))
means:
- Get the first feature found in place-name-osm-clean layer with its
name_en
attribute same as thePLACE_NAME_NAME_EN
attribute in the current feature of GEO_PLACE_NAME layer.- 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.
So, in plain English, the whole expression is going to:
For all points in the GEO_PLACE_NAME layer, create a line with:
- The geometry of the current selected point feature in the GEO_PLACE_NAME layer
- The geometry of the point in place-name-osm-clean layer where it’s
name_en
value matches thePLACE_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.
Reference
- Creating line between two points with same value using QGIS? - GIS StackExchange Question
- QGIS Geometry Generator - Connect Point Data with Lines