3

Is there any plugin in QGIS (or code) that is used to connect multiple polygons with lines using distance as parameter. Let say that I put 10 meters, than all polygons within that distance will be connected with lines where is shortest distance from polygons. Something like on images below:

enter image description here

enter image description here

3

With PyQGIS, following code works. It calculates lines for shortest distances between vertices of adjacent features; but distance as parameter is 14 meters instead 10 (it was due to my own polygon layer).

import itertools

layer = iface.activeLayer()

feats = [ feat for feat in layer.getFeatures() ]

comb = range(len(feats))

lines = []

for i, j in itertools.combinations(comb, 2):
    d = feats[i].geometry().distance(feats[j].geometry())
    if d < 14:

        vertices1 = [ vertex for vertex in feats[i].geometry().vertices() ]
        vertices2 = [ vertex for vertex in feats[j].geometry().vertices() ]

        dist = []

        for k in range(len(vertices1)):
           for l in range(len(vertices2)):
              dist.append([k,l, vertices1[k].distance(vertices2[l])])
        res = [[i.index(min(i)), min(i)] for i in zip(*dist)][2]

        lines.append([vertices1[dist[res[0]][0]], vertices2[dist[res[0]][1]]])

epsg = layer.crs().postgisSrid()

uri = "LineString?crs=epsg:" + str(epsg) + "&field=id:integer""&index=yes"

mem_layer = QgsVectorLayer(uri,
                           'shortest_distances',
                           'memory')

prov = mem_layer.dataProvider()

feats = [ QgsFeature() for i in range(len(lines)) ]

for i, feat in enumerate(feats):
    feat.setAttributes([i])
    feat.setGeometry(QgsGeometry.fromPolyline(lines[i]))

prov.addFeatures(feats)

QgsProject.instance().addMapLayer(mem_layer)

Above code was run with layer of following image; where it is also observed produced lines.

enter image description here

Editing Note:

Following code also works in QGIS 2.18:

import itertools

layer = iface.activeLayer()

feats = [ feat for feat in layer.getFeatures() ]

comb = range(len(feats))

lines = []

for i, j in itertools.combinations(comb, 2):
    d = feats[i].geometry().distance(feats[j].geometry())
    if d < 14:
        print(d)

        vertices1 = feats[i].geometry().asPolygon()[0]
        vertices2 = feats[j].geometry().asPolygon()[0]

        dist = []

        for k in range(len(vertices1)):
           for l in range(len(vertices2)):
              dist.append([k,l, QgsPoint(vertices1[k]).distance(QgsPoint(vertices2[l]))])
        res = [[i.index(min(i)), min(i)] for i in zip(*dist)][2]

        lines.append([vertices1[dist[res[0]][0]], vertices2[dist[res[0]][1]]])

epsg = layer.crs().postgisSrid()

uri = "LineString?crs=epsg:" + str(epsg) + "&field=id:integer""&index=yes"

mem_layer = QgsVectorLayer(uri,
                           'shortest_distances',
                           'memory')

prov = mem_layer.dataProvider()

feats = [ QgsFeature() for i in range(len(lines)) ]

for i, feat in enumerate(feats):
    feat.setAttributes([i])
    feat.setGeometry(QgsGeometry.fromPolyline(lines[i]))

prov.addFeatures(feats)

QgsMapLayerRegistry.instance().addMapLayer(mem_layer)

After running it with same shapefile, I got an equivalent result as it can be observed in following image:

enter image description here

2
  • It seems that your code doesn't work in QGIS 2.18. I got error: AttributeError: 'QgsProject' object has no attribute 'addMapLayer'. Then I tried it in QGIS 3.10 and it works. Is there any way to make it work in QGIS 2.18? – Ivan Feb 24 '20 at 10:13
  • @Ivan In my Editing Note you can observe a code that also works in QGIS 2.18. – xunilk Feb 24 '20 at 12:26

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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