3

I want to find two lines which are very close to each other within the same layer (spatially).

See the image below where there are two lines which are very close (distance of ~18 cm). I wanted to find such features which are very close and belong to the same layer. These lines generally run parallel to each other and do not intersect.

enter image description here


After @Babel’s answer I used `overlay_nearest' but it looks like even though the features having distance more than 1 meters it is getting selected.

Is there another configuration i need to change?

See below screenshots.

enter image description here

enter image description here

I'm using below CRS system.

enter image description here

2
  • 2
    You already found a possible solution: Look for them. I guess this is not feasible, but then you have to provide some details please. How do you define "close"? Do you want to delete or snape or merge them? What have you tried? How large is your dataset? Is this a one time task, or a repetitive one?
    – Erik
    Commented Sep 7, 2021 at 9:14
  • 2
    You may try to buffer the line by a very short distance and select intersecting buffer
    – J.R
    Commented Sep 7, 2021 at 9:34

2 Answers 2

6

If you have no intersecting lines, use "Select by expression" with this expression including overlay_nearest() and change the max_distance:

overlay_nearest(@layer, max_distance:=1)

Be aware: your layer must be saved in a CRS using meters as units, thus don't use a geographic CRS like EPSG:4326 (WGS84). In this case, first reproject your layer.

The two yellow lines are selected (their closest points having a distance of ca. 0.5 m), the others have a distance of more than 1 meter:

enter image description here

If you have lines that intersect, you have to use another expression: wehre the lines cross, the have a distance of 0 and thus would always be selected. For this reason, we want to exclude cases of lines that intersect and only consider lines that do not touch.

This can be done with this expression - change max_distance to the distance you want and replace 100 in limit:=100 with a number that corresponds to the max. number of other lines crossing each line and add 1 (increase the number for better results, but with huge layers, it might get slow):

array_sum(
    array_foreach (
        overlay_nearest( 
            @layer, 
            $geometry,
            max_distance:=1,
            limit:=100
        ),
        if ( 
            length (
                shortest_line( 
                    $geometry, 
                    @element
                )
            )>0,
            1,
            0
        )
    )
)

enter image description here

5
  • Thank you so much Babel for guiding me here. I used the overlay_nearest as mostly in my use case the lines are parallel. But looks I'm doing some mistake. even though the distance is more than 1 meter the features are getting selected. Commented Sep 11, 2021 at 16:23
  • Updated my original post based on the above answer shared by @Babel. Commented Sep 11, 2021 at 16:31
  • @Hussain Khan : What CRS are your data in ? Can you share the data or the project?
    – Babel
    Commented Sep 11, 2021 at 19:39
  • CRS is WGS 84 and Authority ID =EPSG:4326 Commented Sep 12, 2021 at 6:13
  • Thats why you get wrong results: this CRS has units in degrees. Thismakes no sense for measurements. Reproject your data to a CRS that uses meters as units - e.g. the local UTM zone.
    – Babel
    Commented Sep 12, 2021 at 7:43
2

You can also use PyQGIS. This doesnt take the "parallelness" into account, only distance. Although it could be adapted to do so.

import itertools #To get all pairwise combinations of lines
lyr = QgsProject.instance().mapLayersByName('lines')[0] #Change
reproject_to = "EPSG:32633" #Change
mindist = 1 #Change

#Reproject so distance is in meters and not degrees. Pick a coordinate system for your location
reprojected = processing.run("native:reprojectlayer", {'INPUT':lyr,
    'TARGET_CRS':QgsCoordinateReferenceSystem(reproject_to),'OUTPUT':'TEMPORARY_OUTPUT'})['OUTPUT']

nearby_lines = []

for l1, l2 in itertools.combinations(reprojected.getFeatures(), 2):
    dist = l1.geometry().distance(l2.geometry())
    if dist <=mindist:
        print('{0} to {1}: {2} m'.format(l1.id(), l2.id(), round(dist,2)))
        nearby_lines.extend([l1.id(), l2.id()])

lyr.select(nearby_lines)

enter image description here

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.