1

I have a network project in QGIS:

network project screenshot

Where arcs is a LineString layer, but all the arcs must be connected. I was able to detect subnetworks using the Disconnected Islands plugin which populates a NetworkGrp field.

The nodes layer is just the output of Extract Vertices algorithm, and wanted layer is what i need.

The conditions are:

  • If there are 3 subnetworks, i need 2 lines connecting them. In general, one line less than the number of groups is needed.
  • The lines can go from nearest points of each subnetwork group, without the need of a node there (preferred way, but they can go from one node to another one). Next to find the lines, i can clean the topology to add the required nodes and break the arcs accordingly.
  • I need to solve this for a lot of unconnected networks, so i can't do it manually.
  • I want to solve it in QGIS (using 3.22 right now), but can use GRASS GIS if needed. Python solutions are also welcome.
  • There isn't a distance threshold, i just need to connect all groups in a layer. But i don't want to connect arcs or nodes of the same network subgroup.
  • I need new arcs, but if a snap method is the only solution i can accept it.

The arcs layer to test can be downloaded from this link.

1 Answer 1

1
  1. Aggregate your lines to create multipart lines, based on subnetworks: each subnetwork consists of one feature. Use Menu Processing > Toolbox > Aggregate for this.

  2. For each line, find the nearest line and on this, create the closest point to the current feature.

  3. Create the shortest line from this closest point to the current geometry. You're done.

Steps 2 and 3 can be done at once using the following expression with Geometry generator or Geometry by expression.

Initial lines and the small red lines created by the expression, connecting the gaps: enter image description here

This is the expression you can use for the data you provided with settings made for your layer and attribute names:

with_variable (
    'point',
with_variable (
    'group',
    "NetworkGrp",  -- use your attribute name
array_foreach (
    eval ('overlay_nearest (
        ''arcs'',  -- use your layer name
        $geometry,
        filter:= NetworkGrp<>' || @group || ')' -- use your attribute name
    ),
    closest_point (
        @element,
        $geometry
    )
))[0],
make_line (
    @point,
    closest_point (
        $geometry, 
        @point
    )
))
8
  • Thank you. I don't know why, but it doesn't work in my case. I replaced "group" with "NetworkGrp", replaced @layer with ''arcs'', replaced filter:=group<>' with filter:=NetworkGrp<>' and replaced all the case ... end sentence with @line to return all the lines, but it returns features without geometry. Also, I don't understand something like filter:=NetworkGrp <> "NetworkGrp" can return something different to False. Dec 21, 2022 at 0:17
  • 2
    I understand now, it works like filter:=NetworkGrp <> 0 if my current feature is in that group. But I think overlay_nearest function can't be used against the same layer (github.com/qgis/QGIS/issues/47201), because it does not evaluate a feature after being the current one? I will try against a copy. Dec 21, 2022 at 0:41
  • I don't know, it seems like only work for the first group. I don't know if this is a Geometry by Expression limitation: i.stack.imgur.com/ETrOW.jpg. I will attach the layer in the question. Dec 21, 2022 at 1:38
  • overlay_nearest works on the same layer, for this I added the limit:=10 part. Depending on how many features you have, you might want to change that. As you see in the screenshot, in my case it works - also when using Geometry by expression. Can't test right now with your data, will come back later.
    – Babel
    Dec 21, 2022 at 6:06
  • 1
    Thank you very much, it works. I have a problem with real data that I did not take into account when creating the sample data, which is that there are subgroups that are close to each other but far from the rest of the network. However, being able to draw all the lines is already progress. Thanks! Dec 21, 2022 at 21:49

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.