4

I am trying to compute on QGIS the distance from some clusters (ie points) to their closest road (ie lines); no need for all combinations, just the distance from each cluster to the closest road. To do so, I saw on a forum (on this post) that a good method was to transform lines into points, which I did, and then to compute the distance between both point layers. Nonetheless, when trying to do the last step, I get this error :

"/Applications/QGIS.app/Contents/MacOS/../Resources/python/plugins/processing/tools/vector.py", line 211, in spatialindex

idx = QgsSpatialIndex(layer.getFeatures(request))

Exception: unknown"

I am using a MAC. I tried on both QGIS 2.18.2 and QGIS 3.0.3, and got the same error. I tried, as advised on a page, to export geometric attributes using MMQGIS, and then re-importing them on QGIS, but same error. I also heard that it could be useful to check the validity of points ; nonetheless as I am using all the major roads network in Africa, I get millions of points, and checking them would take hours and hours ... I tried on QGIS3 to compute the distance between points and line centers (which does not give me the answer I want, as it is not the closest distance, but I did so to check if it was working this way), and it worked well, so I guess the issue lays in the transformation of my line layer into points

Has someone faced this issue of spatial index error, and knows what is means exactly? Is there a way to correct the points, to get rid of those not correct if this is the issue ?

7
  • Could you provide the link to the tutorial, so people can replicate the steps you followed?
    – Kantan
    Commented Jun 19, 2018 at 8:54
  • Thanks for answering :) Here is the post I followed gis.stackexchange.com/questions/181636/…
    – Contie
    Commented Jun 19, 2018 at 8:56
  • Do you need all combinations? In other words, do you need shortest distance from each point to each line?
    – Kazuhito
    Commented Jun 19, 2018 at 10:29
  • Welcome to GIS SE. As a new user, please take the Tour, which stresses the importance of asking one question per Question. Please edit the question in response to requests for clarification. It's not fair to those who would answer to need to mine the comments for critical information.
    – Vince
    Commented Jun 19, 2018 at 10:47
  • @vince Hi, alright I corrected it, sorry for this.
    – Contie
    Commented Jun 19, 2018 at 12:02

2 Answers 2

1

(1) Collect your lines into single Multipart object.

  1. Open the attribute table of your line layer.
  2. Create a new field to group all lines. I assume you create a field group with all values set to '1'.
  3. Run Singleparts to Multipart tool (in Vector | Geometry Tool).
  4. Open the attribute table of newly created layer Multipart and check if the record (row) is only one in this layer; and there is a group field (it's value is '1' apparently).

(2) Calculate distance

  1. Open the attribute table of your point layer.
  2. Create a new field (integer or decimal) with following expression:

 distance(
    closest_point(geometry(get_feature('Multipart', 'group', '1')), $geometry), $geometry
 )
1

From QGIS 3.22 you can use the Shortest line between features algorithm that does exactly what you want:

enter image description here

This is the result from a point and a line layer:

enter image description here

On the other hand, you can use the QgsSpatialIndex API to get what you want:

project = QgsProject.instance()

source = project.mapLayersByName('points')[0]
destination = project.mapLayersByName('streets')[0]

index = QgsSpatialIndex(QgsSpatialIndex.FlagStoreFeatureGeometries)
index.addFeatures(destination.getFeatures(), QgsFeatureSink.FastInsert)

features = []

for in_feature in source.getFeatures():

    igeom = in_feature.geometry()

    # 1 is to get only the first and closest feature
    nearest_list = index.nearestNeighbor(igeom, 1)

    request.setFilterFids(nearest_list)

    for dest_feature in destination.getFeatures(request):

        jgeom = dest_feature.geometry()

        shortest_line = igeom.shortestLine(jgeom)
        feature = QgsFeature()

        attrs = in_feature.attributes()
        attrs.extend(dest_feature.attributes())

        feature.setAttributes(attrs)
        feature.setGeometry(shortest_line)
        
        features.append(feature)

where features il the list with all the shortest lines between each point and the closest line. Then you can write all these features to a new vector layer.

Be aware if your source and destination layers have different CRS!

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.