5

I'm completely new using PyQGIS and developing plugins.

Currently I have a layer with the X and Y coordinates of electric distribution poles, where each pole is a feature. What I need to do is measure the distance between all the features in the map, but it must be done pole by pole. By example, take the first pole and get all the distances between the first pole and all the others, then, take the second pole and repeat until the end of the dataset.

Any ideas or references for doing this?

As a reference, I was doing the same thing in Matlab with a dataset of 20 features with something like this:

for i=1:20
  for j=1:20
      if i~=j
        distance = euclidean(P1(i), P1(j));

Where P1(i) and P1(j) are the X-Y coordinates of two different points (Each one Written as a complex number) and "euclidean" is a function that calculates the distance between these two points.

3 Answers 3

8

By using PyQGIS this code works:

from math import sqrt

layer = iface.activeLayer()

features = layer.getFeatures()

points = []

for feature in features:
    geom = feature.geometry().asPoint()
    points.append(geom)

n = len(points)

for i in range(n-1):
    for j in range(n):
        if i < j:
            print i, j, sqrt(points[i].sqrDist(points[j]))

I tried out the code at the Python Console with the layer point (projected in meters) of next image:

enter image description here

and the result was (for upper triangular distance matrix):

i j  distance(m)
0 1 28415.4381005
0 2 48380.9487158
0 3 63608.9197655
0 4 44111.1282702
0 5 19609.1738225
1 2 27252.6459011
1 3 47850.7529946
1 4 37821.6827176
1 5 27147.7980092
2 3 21588.551469
2 4 23663.3870275
2 5 34764.3290912
3 4 23048.9959669
3 5 45857.2099628
4 5 24822.4756566

Editing Note:

The code with gene suggestions:

from math import sqrt
import itertools

layer = iface.activeLayer()

features = layer.getFeatures()

points = [feature.geometry().asPoint() for feature in features]

n = len(points)

list = range(n)

for i,j in itertools.combinations(list, 2):
    print i, j, sqrt(points[i].sqrDist(points[j]))

and the results in a QGIS plugin with the same suggestions:

enter image description here

3
  • Great! This is exactly what I needed.Thank you very much. I have another question (I will place it here but please tell me if I have to do it somewhere else). Sorry to bother @xunilk What do I have to modify in the code from above if I want to know the distances between vertices of a line? By example, find the distance between the start of a line and all the other vertices in the layer. I guess I must modify this line geom = feature.geometry().asPoint() but I really can't find how
    – PabloQG
    Commented Sep 27, 2015 at 22:45
  • @PabloQG Site rules only allow a topic by a question. Please, don't hesitate to do your new question because a 'line' is another type of geometry and it could be necessary more than one modification at this code. Thanks.
    – xunilk
    Commented Sep 28, 2015 at 0:03
  • Understood, I have already made the new question. Thanks again!
    – PabloQG
    Commented Sep 28, 2015 at 15:15
2

Xulnik propose a solution with detailed explanations but if you want to learn Python you can simplify the script using the standard itertools module (itertools combination) and the sqrDist property of Points (as Xulnik), or the distance property of a QGIS geometry and List Comprehensions

layer = iface.activeLayer()
import itertools
# points with list comprehension
points = [geom.geometry().asPoint() for geom in layer.getFeatures()]
# with itertools
for point1,point2 in itertools.combinations(points, 2):
     print math.sqrt(poin1.sqrDist(point2))

or

for point1,point2 in itertools.combinations(points, 2):
    print QgsGeometry().fromPoint(point1).distance(QgsGeometry().fromPoint(point2))

Explication of itertools.combinations

a = [1,2,3,4]
for i,j  in itertools.combinations(a,2):
     print i,j 
1 2
1 3
1 4
2 3
2 4
3 4
1
  • Thank you very much, it does exactly what I needed. And thanks for the documentation.
    – PabloQG
    Commented Sep 27, 2015 at 22:36
0

I am working with geographic coordinates, not projected, and I found that the answers given here do not solve my version of the same problem. On the other hand, the cookbook has the answer I needed, maybe it will help others, too, to see it repeated here:

## the variable 'layer' is defined in code not shown here
# just the first few point pairs
from_to = [("04", "10"), ("04", "18"), ("04", "19"), ("19", "10")]

from qgis.core import QgsDistanceArea
d = QgsDistanceArea()
d.setEllipsoid('WGS84')
d.setEllipsoidalMode(True)
points = dict((f['code'], f.geometry().asPoint()) 
    for f in layer.getFeatures())
for (f, t) in from_to:
    print "%s,%s,%0.2f" % (
        f, t, 
        d.measureLine(points['2007.%s.1' % f], points['2007.%s.1' % t]))

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.