This question is similar to this one: Get attribute from touching line layer (QGIS) but there is a new and more komplex problem in that context I need to solve:

I have to plan drains, usually along a road network or any existing network digitized with snapping and tracing. In in that drains will be cables. The cables will also be digitized with tracing and end in every drain junction. No cables cross a junction. There could be up to 10 cables inside one drain. The drains are identified by ID's.

Every cable need a (virtual)field with the ID of the drain in which it lies. With the refFunctions solution:


from the question linked above, I will get the drain ID for every cable, BUT the cables are also touching other drains at their end/start nodes if there is a junction. The results will become something like random! If the drains are not touching at their junctions (digitizing a small gab), the expression will work fine. But that is not a well suiting solution for me.

You can reproduce the situation with the following package:

enter image description here

  • 1
    I may be mistaken, but at first glance it would be better for you to move away from the symbolization of the pipe to the actualization, i.e. really try to model your situation, for example, show the pipe in the form of a polygon with a real width, and cables in the form of lines by their number, with their identifiers ... May 3, 2019 at 8:57

2 Answers 2


In theory, if the refFunctions plugin defines the spatial relation predicates as per the OGC standard, contains or overlaps should work, if your geometries are as precise as you describe. In your example data-set however, the cables extent out of the drains so that where contains fails, within succeeds. And in the reality of floating point numbers, both contains and within are tricky with entities like lines, but overlaps, or crosses even, might catch them.

So just check them all:

COALESCE( geomwithin( 'drains', 'ID' ),  geomcontains( 'drains', 'ID' ),  geomoverlaps( 'drains', 'ID' ),  geomcrosses( 'drains', 'ID' ))

If you convert your pipes from lines to polygons as Cyril suggested, the solution becomes simple. Now it doesn't matter that a cable intersects multiple pipe polygons, because it's only within the one corresponding pipe polygon. Use geomwithin() instead of geomintersects() in the expression you already wrote.

  • I also thought about going that way, but for several reasons, I cant convert the lines to polygons. I also thought about doing it temporary inside an expression like: geomwithhin(buffer(geometry,1)) - but that seems not to be possible with refFunctions
    – MartinMap
    May 3, 2019 at 16:17
  • 1
    No, the RefFunctions are user-friendly but limited in scope. You'll need to graduate to the more complicated aggregate functions. Try something like aggregate( 'drain', 'array_agg',"drainid",intersects($geometry,buffer(geometry(@parent),1))) or possibly aggregate( 'drain', 'array_agg',"drainid",intersects(buffer($geometry,1),geometry(@parent))).
    – csk
    May 3, 2019 at 16:40
  • Both functions results in NULL... what does that 'array_agg' mean?
    – MartinMap
    May 5, 2019 at 18:46
  • Array_agg is one of the aggregate functions. Have a look at the Expression Builder help section about the aggregate() function, and the section about the array_agg() function. Basically, aggregate('layer name', 'array_agg', ...)' means, "run the array_agg` function on features in the layer called 'layer name' "
    – csk
    May 5, 2019 at 18:49
  • here's a good blog post about how the aggregate functions work: anitagraser.com/2017/06/08/…
    – csk
    May 5, 2019 at 18:50

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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