Difference of two polyline layers in QGIS

differenceslineqgis

I have an original polyline layer and a modified one representing only a part of the original network. In an example case I cut 10 meters at start and end of each feature using Geometry by expression tool in QGIS. Then I use the Difference tool to have a layer only containing the parts where the original layer and the cut lines do not overlap.

Unfortunately, this does not work as expected. There seems to be a critical accuracy issue, as nothing is being subtracted or only some "random" parts are being erased.

As a workaround I add a minimal buffer to the cut features (not even that minimal actually, but 0.001 meters in my example case). Then it works, but with reduced accuracy.

Obviously this is not a working solution to subtract polyline layer B from polyline layer A, where layer B basically has the same geometry in exactly the same positions, but e.g. with some erased parts. The Difference tool somehow seems to be suitable only for cases where the overlay is a polygon layer.

What is the best way to get the accurate difference between two polyline layers in QGIS?

Best Answer

where layer B basically has the same geometry in exactly the same positions

The problem is that it is not true.

LineString geometries are defined by their vertices. But since this vector data model (the Simple Features, or Simple Feature Access model) is not topological, layer B has vertices where layer A don't. Layer B geometries are not a subset of layer A ones.


Spatial operations (like Union, Intersection, Difference) in non-topological data models tend to fail. It also happens with polygons (peaks and gaps that are created from a difference are famous).

The only way to perform fail-safe spatial operations in this data model, is by creating a pseudo-topology. It means create vertices at layer A where there are vertices at layer B.

If vertices of layer B are a subset of vertices of layer A, the difference will work.


  • Create a new layer A, with geometry by expression:
line_merge(
 collect_geometries(
  array(
   line_substring($geometry, 0, 10),
   line_substring($geometry, 10, length($geometry) - 10),
   line_substring($geometry, length($geometry) - 10, length($geometry)))))

You can check new layer A vertices in edit mode with the vertex tool. New vertices at 10 meters from start and end must be created.

  • Perform the Difference.

Note: Look at the expression, there was no need to extract the mid line substring first, to next get the first and end portions through a difference. You can extract the first and end substrings just with:

collect_geometries(
 array(
   line_substring($geometry, 0, 10),
   line_substring($geometry, length($geometry) - 10, length($geometry))))
Related Question