5

My question is fairly straight-forward.

Would anyone know the PyQGIS equivalent of the Extract Nodes tool in QGIS? I don't seem to find it in the API documentation. If you do, kindly share the documentation too.

5

You can take the extractPoints() function from the fTools plugin by Carson Farmer:

# Generate list of QgsPoints from input geometry ( can be point, line, or polygon )
def extractPoints( geom ):
    multi_geom = QgsGeometry()
    temp_geom = []
    if geom.type() == 0: # it's a point
        if geom.isMultipart():
            temp_geom = geom.asMultiPoint()
        else:
            temp_geom.append(geom.asPoint())
    elif geom.type() == 1: # it's a line
        if geom.isMultipart():
            multi_geom = geom.asMultiPolyline() #multi_geog is a multiline
            for i in multi_geom: #i is a line
                temp_geom.extend( i )
        else:
            temp_geom = geom.asPolyline()
    elif geom.type() == 2: # it's a polygon
        if geom.isMultipart():
            multi_geom = geom.asMultiPolygon() #multi_geom is a multipolygon
            for i in multi_geom: #i is a polygon
                for j in i: #j is a line
                    temp_geom.extend( j )
        else:
            multi_geom = geom.asPolygon() #multi_geom is a polygon
            for i in multi_geom: #i is a line
                temp_geom.extend( i )
    # FIXME - if there is none of know geoms (point, line, polygon) show an warning message
    return temp_geom

Then just pass your geometry as argument:

points = extractPoints( feature.geometry() )

points will contain a Python list of points (pairs of coordinates). You could access, for example, the Y coordinate of the first point like this:

print points[0][1] 

I've tested it on QGIS 2.6.1, using the QGIS Python Console.

In general, for vector geoprocessing tools, you have the Python source code at hand. In my computer, fTools is located at /usr/share/qgis/python/plugins/fTools/

  • Any idea where I can find a list or an index of this? I can't seem to find fTools in my plugin folder (Windows 7 OS). I have actually been looking for an index or a list, as I am unable to access any of the vector geoprocessing tools... – Akhil Jan 10 '15 at 9:06
  • 1
    fTools is a QGIS core plugin , as such, it is accessible out of the box on recent QGIS installations. Here you find a list of available tools in fTools: docs.qgis.org/2.2/en/docs/user_manual/plugins/… The source code of fTools can be found at github.com/qgis/QGIS/tree/master/python/plugins/fTools If you enter the folder 'tools' you find all Python algorithms that conform the plugin. – Germán Carrillo Jan 10 '15 at 14:08
  • 1
    On a Windows 7, if you install QGIS from OSGeo4W, fTools should be at C:\OSGeo4W\apps\qgis\python\plugins\fTools, whereas if you install it from the standalone package, fTools should be at C:\Program Files\QGIS Brighton\apps\qgis\python\plugins\fTools – Germán Carrillo Jan 10 '15 at 14:10
1

If you are comfortable with Python you only need classic Python, list comprehensions and the understanding of PyQGIS: Geometry Handling:

  • A Point in PyQGIS is built with QgsPoint(x,y);
  • A LineString with QgsGeometry.fromPolyline([QgsPoint(x1,y1),QgsPoint(x2,y2)]))
  • A Polygon with QgsGeometry.fromPolygon([[QgsPoint(x1,y1),QgsPoint(x2,y2), QgsPoint(x3,y3),QgsPoint(x1,y1)]])

So the the LinearRing/boundary of a a polygon is [[QgsPoint(x1,y1),QgsPoint(x2,y2), QgsPoint(x3,y3),QgsPoint(x1,y1)]][0] = [QgsPoint(x1,y1),QgsPoint(x2,y2), QgsPoint(x3,y3),QgsPoint(x1,y1)].

With a Polygon Layer as example:

enter image description here

layer = qgis.utils.iface.activeLayer()
# examine the first element
elem = layer.getFeatures().next()
geom = elem.geometry()
# or elem = layer.getFeatures().next().geometry()
first_poly = geom.asPolygon()
print first_poly
[[(6.97738,53.361), (7.18994,52.8886), (6.70577,52.5698), (7.16632,52.2509), (6.59948,51.8258), (6.04445,51.8258), (5.87913,50.763), (5.70199,50.8575), (5.89093,51.2708), (5.31229,51.2472), (5.08791,51.4125), (4.69821,51.4833), (4.22584,51.3416), (3.49368,51.3534), (4.02509,52.062), (4.82811,52.9241), (5.18239,52.4399), (5.61932,52.5934), (5.59571,52.8532), (5.40676,52.9004), (5.43038,53.2547), (6.39873,53.4555), (6.74119,53.4791), (6.97738,53.361)]]

Now, if you want the LinearRing of this polygon:

enter image description here

ring = first_poly[0])
print ring # = a list of coordinates of the points
[(6.97738,53.361), (7.18994,52.8886), (6.70577,52.5698), (7.16632,52.2509), (6.59948,51.8258), (6.04445,51.8258), (5.87913,50.763), (5.70199,50.8575), (5.89093,51.2708), (5.31229,51.2472), (5.08791,51.4125), (4.69821,51.4833), (4.22584,51.3416), (3.49368,51.3534), (4.02509,52.062), (4.82811,52.9241), (5.18239,52.4399), (5.61932,52.5934), (5.59571,52.8532), (5.40676,52.9004), (5.43038,53.2547), (6.39873,53.4555), (6.74119,53.4791), (6.97738,53.361)]

And the nodes/points:

enter image description here

for pt in ring:
     print QgsPoint(pt)
(6.97738,53.361)
(7.18994,52.8886)
(6.70577,52.5698)
....

or

ring = QgsGeometry.fromPolyline(first_poly[0])
for point in ring.asPolyline():
     print point

So the list of nodes is given by:

nodes = [point for point in ring.asPolyline()] = [point for point in geometry[0].asPolygon()[0]] 

And you can extract all the nodes of a Polygon layer with :

for elem in layer.getFeatures():
    for point in elem.geometry().asPolygon()[0]:
         print point

You can try with a double list comprehension but PyQGIS not like them very much...

nodes = [point for point in elem.geometry().asPolygon()[0] for elem in layer.getFeatures()]
print nodes
[(6.97738,53.361), (6.97738,53.361), (6.97738,53.361), (7.18994,52.8886), (7.18994,52.8886), (7.18994,52.8886), (6.70577,52.5698), (6.70577,52.5698), (6.70577,52.5698), (7.16632,52.2509), (7.16632,52.2509), (7.16632,52.2509), (6.59948,51.8258), (6.59948,51.8258), (6.59948,51.8258), (6.04445,51.8258), (6.04445,51.8258), (6.04445,51.8258), (5.87913,50.763), (5.87913,50.763), (5.87913,50.763), (5.70199,50.8575), (5.70199,50.8575), (5.70199,50.8575), (5.89093,51.2708), (5.89093,51.2708), (5.89093,51.2708), (5.31229,51.2472), (5.31229,51.2472), (5.31229,51.2472), (5.08791,51.4125), (5.08791,51.4125), (5.08791,51.4125), (4.69821,51.4833), (4.69821,51.4833), (4.69821,51.4833), (4.22584,51.3416), (4.22584,51.3416), (4.22584,51.3416), (3.49368,51.3534), (3.49368,51.3534), (3.49368,51.3534), (4.02509,52.062), (4.02509,52.062), (4.02509,52.062), (4.82811,52.9241), (4.82811,52.9241), (4.82811,52.9241), (5.18239,52.4399), (5.18239,52.4399), (5.18239,52.4399), (5.61932,52.5934), (5.61932,52.5934), (5.61932,52.5934), (5.59571,52.8532), (5.59571,52.8532), (5.59571,52.8532), (5.40676,52.9004), (5.40676,52.9004), (5.40676,52.9004), (5.43038,53.2547), (5.43038,53.2547), (5.43038,53.2547), (6.39873,53.4555), (6.39873,53.4555), (6.39873,53.4555), (6.74119,53.4791), (6.74119,53.4791), (6.74119,53.4791), (6.97738,53.361), (6.97738,53.361), (6.97738,53.361)]

and the nodes of a LineStrings layer:

 for elem in layer.getFeatures():
    for point in elem.geometry().asPolyline():
         print point

or with the same restrictions:

nodes = [point for point in elem.geometry().asPolyline() for elem in layer.getFeatures()]

It is the same for MultiGeometries, add a for loop/

  • At first_poly = elem.asPolygon() the error pops up QgsFeature has no attribute asPolygon. Any clues or suggestions? – Akhil Jan 10 '15 at 9:07
  • sorry, I forgot the essential element geometry(), corrected now. Thanks – gene Jan 10 '15 at 11:38

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.