4

So I have these multiple vertical lines as shown below. enter image description here

So what I am aiming for is to connecting these unconnected lines into one lines automatically. What I've been done so far is to connected it manually using join multiple lines plugin. The result is given below,

enter image description here

When using this plugin I can only select one vertical lines that I want to merge, I can't really like select all the unconnected lines and running the plugin because it will give me result like this. enter image description here

Any idea as to how to do this task automatically using QGIS ?

2
  • 2
    I don't think it's possible simply because they are not vertical. – FelixIP May 30 at 3:50
  • 3
    By the way: providing your data (or a sample of it) could help testing and finding a solution. – Babel May 30 at 9:11
4

Look for a definition

Not in every case it is clear to which next line the end of one line should be connected. So the first step is to find a defnition what means "vertical line" in your case and based on what criteria to select the lines than should be connected.

As of now, you do it manually, thus you have an implicit understanding. Make it explicit. 2nd step than is how to transform this definition in a machine-readable workflow (algorithm).

An algorithmic approach (workflow)

I propose one such algorithmic approach. Maybe someone else can help implementing it with Python.

One such definition could be based on 2 criteria, each with a variable value that increases with each iteration:

  • 1: connect each end point of a line to the nearest start point of another line. Set a maximum distance: points further away will not be considered.
  • 2: exclude connections with a certain deviation in x-direction: say, created lines should be vertical (azimuth=0 degrees) +/- a tolerance of e.g. 5 degrees.

It is an iterative approach. Start with low values for maximum distance (criteria 1) and devation (criteria 2), than increase the values for the remaining lines. Stop iteration when no more points, fulfilling both criteria with the increased values, are left.

Or: Insted of using azimuth, with a somehow similar approach you could define as a condition that values for x-coordinates for start- and connected end-point should not deviate for more than a certain amount (like 1 meter or so, depending on your data). So the line should not shit too much to the left or right.

Depending on how the result than looks, - you might want to add an additional criteria for the rest of the lines.

Without iteration

Probably even better and maybe to realize in just one run (without iteration), you could first define a number of nearest points as "candidates" to which the line could be connected. Let's say: for each end-point, get the five or ten nearest start-points and than keep the one where the azimuth of the connecting line has the smallest value.

Pre-conditions for the data to use

Of course, as a prepartion you should make sure that all the lines you already have run in the same direction (northto south or inverse). If you have lines N to S, than you could exclude all end-points with a higher y-value than the start-point as you want the line to follow one direction and not to go back and forth.

Illustration

Screenshot of your upper right section: considering just connecting to the nearest start-point of the next line, you would get the blue lines. However, you want the black lines. Difference between blue and black lines, as can be clearly seen, is their azimuth, so this should be the key to select those lines you're interested in: enter image description here

2

This solution uses QGIS expressions to implement what I proposed as an algorithmic approach in the other answer. Proceed as follows:

Befor starting, make sure all your lines have the same direction (N to S).

  1. From your lines, extract separately start- end end-points using Geometry by expression with this expression: start_point ($geometry) and end_point($geometry). You get two layers, name it start and end.

  2. On the end-layer, paste the following expression to create the lines you're looking for. First try it with [Geometry generator][3] to find the best settings, than create actual geometries with the same expression, using this time Geometry by expression ([see here for differences of both][4]). You have to adapt a few things:

  • The value 5 in line 3 defines how many nearest start_points are taken into consideration. Increase this value when start- end end-points to connect are far away. Reduce or increase it to find the best fitting setting for your data.

  • In line 7, replace start with the name of your start-points layer.

  • On line 12, replace the value (in my case: 1267200) with the value of the y-coordinate for the southernmost end-point that should be connected (to avoid that the line goes back north).

This is the expression to use:

with_variable (
    'limit',
    5,
    with_variable (
        'nearest',
        overlay_nearest (
            'start', 
            $geometry,
            limit:=@limit
        ),
        if (
            y($geometry) >1267200,
            make_line (
                $geometry, 
                array_get( 
                    @nearest,
                    array_find( 
                        array_foreach(
                            @nearest,
                            abs (180-degrees (
                                azimuth (
                                    $geometry,
                                    @element
                        )))),
                        array_min( 
                            array_foreach(
                                @nearest,
                                abs (180-degrees (
                                    azimuth (
                                        $geometry,
                                        @element
                        )))))
            ))),
            ''
        )
    )
)

Screenshot: original lines at the left (0) with start-points indicated in red, end-points in blue. Image 1: red dotted line created with the expression above and setting 1 for limit in line 3. Image 3 with setting 2, image 5 with setting 5. This fits perfectly, connecting the lines as demanded:

enter image description here

Screenshot showing how the solution works:

enter image description here

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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