Compter le nombre de sommets de l'objet sur la couche vectorielle PyQGIS

8

Tout d'abord, je tiens à dire que je sais qu'une question similaire a été soulevée auparavant, mais qu'elle n'a pas fourni de solution satisfaisante.

J'ai besoin d'obtenir le nombre de sommets de chaque objet sur le calque de ligne vectorielle. Sur la base de cet article: https://joseguerreroa.wordpress.com/2014/07/28/contar-y-extraer-nodos-vertices-para-vectoriales-de-linea-o-poligono-mediante-pyqgis/

J'ai fait ce code:

layer = qgis.utils.iface.activeLayer()
feat = layer.getFeatures()
for feature in feat:
    geom = feature.geometry()

n = 1
ver = geom.vertexAt(0)
points=[]

while(ver != QgsPoint(0,0)):
    n +=1
    points.append(ver)
    ver = geom.vertexAt(n)

print n

Et comme résultat, j'obtiens un certain nombre de sommets, mais seulement du dernier objet. Je suppose qu'il me manque une boucle while sur le calque (pour obtenir le numéro de chaque objet), ai-je raison? Mais je ne sais pas à quoi ça devrait ressembler.

Je sais qu'il existe un plugin 'Vertices counter', mais cela ne fonctionne pas (ne démarre même pas) dans mon cas (QGIS 2.12, Win 8.1). Et j'ai besoin que ce soit fait en Python.

Au fait, ne pensez-vous pas, les gars, qu'il est ridiculement difficile d'obtenir le nombre de sommets alors qu'il est si facile d'obtenir les coordonnées de chaque sommet?

EDIT: @nwduncan (@ArMoraer aussi) a suggéré de corriger une indentation, et c'était un bon indice. J'ai remarqué que la console Python a besoin d'être rafraîchie, car parfois elle ne peut pas gérer les indentations. J'espère que cela aidera d'autres débutants. Le code final est:

layer = qgis.utils.iface.activeLayer()
feat = layer.getFeatures()
for feature in feat:
    geom = feature.geometry()
    n   = 1
    ver = geom.vertexAt(0)
    points=[]

    while(ver != QgsPoint(0,0)):
        n +=1
        points.append(ver)
        ver=geom.vertexAt(n)

    print n
antonio
la source
1
Je ne suis pas familier avec les pyqgis, mais je peux voir dans votre code que votre fonction dans la boucle feat attribue l'objet géométrique à la variable geom, puis l'écrase avec l'objet géométrique suivant sans réellement compter les sommets. Essayez de mettre en retrait les lignes 6 à 15 afin qu'elles se trouvent sous la boucle for featuer in feat.
nwduncan
Je l'ai essayé avant, et j'ai eu beaucoup d'erreurs de «retrait inattendu». Mais ... parce que j'étais un peu frustré, j'ai suivi votre conseil. Encore une fois, j'ai changé l'indentation et cette fois, je l'ai enregistré dans un nouveau fichier aaa et cela a fonctionné! Je pense que le problème était que la console QGIS Python n'est pas parfaite et l'enregistrement du code dans un nouveau fichier a en quelque sorte aidé. Je ne sais pas comment, mais ça l'a fait :) Merci pour l'indice!
antonio
1
Si vous êtes nouveau dans Python, j'éviterais les boucles while si vous le pouvez. Très facile de vous mettre dans une boucle infinie. Est également QgsPoint(0,0)un point valable dans certaines projections.
Nathan W

Réponses:

4

Échancrure.

La première partie de votre code est correcte, mais le reste peut être grandement simplifié si vous voulez juste le nombre de sommets:

layer = qgis.utils.iface.activeLayer()
feat = layer.getFeatures()

for feature in feat:
    if feature.geometry().isMultipart(): # new part for multipolylines
        vertices = feature.geometry().asMultiPolyline()
        print [len(v) for v in vertices]
    else:
        vertices = feature.geometry().asPolyline()
        n = len(vertices)
        print n

Si vous souhaitez également les coordonnées des sommets, vous pouvez écrire (polylignes uniquement):

layer = qgis.utils.iface.activeLayer()
feat = layer.getFeatures()

for feature in feat:
    vertices = feature.geometry().asPolyline()
    points = []

    for v in vertices:
        points.append(v)
ArMoraer
la source
Merci beaucoup. Le code que vous avez écrit fonctionne pour Polyline. J'ai essayé la même chose pour MultiPolyline vertices = feature.geometry().asPolyline()à vertices = feature.geometry().asMultiPolyline()elle ne compte pas le nombre de sommets , mais l' impression sorte de nombres aléatoires (je ne peux pas le lier à toutes les données dont je dispose)
antonio
Ok, j'ai édité mon premier script. Cela devrait maintenant fonctionner pour MultiPolylines.
ArMoraer
2

Dans QGIS 2.14, une nouvelle fonction pour compter les sommets est disponible dans field calculator:

Calculatrice de champ dans QGIS 2.14

etrimaille
la source
1

Une autre approche consistera à utiliser une expression définie par l'utilisateur. Le moteur d'expression bouclera le calque pour vous. Le blog de Nathans a une bonne démo à ce sujet:

http://nathanw.net/2012/11/10/user-defined-expression-functions-for-qgis/

from qgis.utils import qgsfunction
from qgis.core import QGis

@qgsfunction(0, "Python")
def vertices(values, feature, parent):
    """
        Returns the number of vertices for a features geometry
    """
    count = None
    geom = feature.geometry()
    if geom is None: return None
    if geom.type() == QGis.Polygon:
        count = 0
        if geom.isMultipart():
          polygons = geom.asMultiPolygon()
        else:
          polygons = [ geom.asPolygon() ]
        for polygon in polygons:
          for ring in polygon:
            count += len(ring)
    return count
Jakob
la source