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 ?

underdark
  • 84,148
  • 21
  • 231
  • 413
Contie
  • 41
  • 3
  • Could you provide the link to the tutorial, so people can replicate the steps you followed? – Kantan Jun 19 '18 at 08:54
  • Thanks for answering :) Here is the post I followed https://gis.stackexchange.com/questions/181636/nearest-distance-between-point-layer-and-line-layer-qgis – Contie Jun 19 '18 at 08:56
  • Do you need all combinations? In other words, do you need shortest distance from each point to each line? – Kazuhito Jun 19 '18 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 Jun 19 '18 at 10:47
  • @vince Hi, alright I corrected it, sorry for this. – Contie Jun 19 '18 at 12:02
  • @kazuhito : nope I would just need the distance to the closest line, and not every combinations :) Thanks ! – Contie Jun 19 '18 at 12:03
  • The question has me confused about the point "clusters". The OP wants "...just the distance from each cluster..." What then, defines a "cluster", and how is one cluster demarcated from all other clusters? And once a cluster is defined, what location within the cluster should be used to calculate the distance to the nearest road: the cluster's centroid? The nearest point within the cluster? The farthest point within the cluster? – Stu Smith Aug 11 '20 at 15:29

2 Answers2

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
 )
Kazuhito
  • 30,746
  • 5
  • 69
  • 149
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!

matteo
  • 3,304
  • 1
  • 23
  • 47