Bienvenue! Inscrivez-vous et rejoignez notre communauté :)
  • Login:

Bienvenue sur Forum SIG - Systèmes d'Information Géographique et Géomatique.

Bienvenue sur le forumSIG. S'il s'agit de votre première visite, assurez vous de faire une recherche préalable dans les FAQ SIG. Vous devez vous inscrire avant de pouvoir poster.

Affichage des résultats 1 à 10 sur 10
  1. #1
    Rédacteur Supporter(rice)

    Date d'inscription
    février 2011
    Localisation
    Nord
    Emploi
    Administrateur SIG
    Organisme
    Mairie
    Âge
    31
    Messages
    712

    Mes réseaux sociaux

    Follow Bescu On Twitter
    Add Bescu on Linkedin

    Par défaut Script pour symbologie différentes entre polygones adjacentes

    Bonjour,

    Suite à cette discution sur le forum ESRI j'ai décidé de tenter un script python avec PyQgis (plutôt qu'avec ArcPy parce que pour le moment j'ai plus besoin d'apprendre PyQgis qu'ArcPy). Du coup je fais le suivi sur ce forum.

    Comme expliqué dans l'autre discussion le but de mon script est de :

    - fait passer un curseur sur chacun des polygones
    - pour chaque polygone je liste les numéros de classes qui existent déjà sur les polygones voisins
    - je tire un numéro au hasard parmi les numéros qui restent disponible

    Par contre comme je l'avais anticipé il y a des cas où plus aucun numéro de classe n'est disponible pour le polygone sur lequel se trouve le curseur. Dans ces cas là j'avais pensé refaire un tirage au sort sur les numéros des polygones voisins en excluant un numéro qui ne serait impératif pour aucun des voisins. Là, j'ai l'impression que ça se complique pas mal, je vais essayer d'y réfléchir mais pour le moment j'ai d'autres urgences et j'ai réussi à faire ce dont j'avais besoin juste avec ce premier script basique.

    Je vous laisse le script pour info et pour le suivi (et pourquoi pas pour la critique). Je suis débutant en Python et en PyQgis, je sais qu'il est très imparfait (je pense notamment qu'il faudrait utiliser un index spatiale pour gagner du temps!!).


    from random import randint
    from PyQt4 import QtCore

    # ouverture de la couche à classer et attribution d'une variable à cette couche

    macouche=QgsVectorLayer("C:/macouche.shp","macouche","ogr")
    QgsMapLayerRegistry.instance().addMapLayer(macouche)
    macouche=qgis.utils.iface.activeLayer()

    # création du champ id_class (suppression préalable de ce dernier s'il existe déjà)

    macouche.startEditing()
    ind_field=macouche.fieldNameIndex("id_class")
    if ind_field!=-1:
    macouche.dataProvider().deleteAttributes([ind_field])
    macouche.dataProvider().addAttributes([QgsField("id_class", QtCore.QVariant.Int)])
    macouche.commitChanges()
    ind_field=macouche.fieldNameIndex("id_class") # enregistrement dans une variable de l'id du champs

    # sélection de tous les polygones

    macouche.select([])
    macouche.setSelectedFeatures([obj.id() for obj in macouche])

    # début du classement

    for i,elem in enumerate (macouche.selectedFeatures()):
    geom=elem.geometry()
    list_vois=[] # va accueillir la liste des ID des polygones voisins
    list_inter=[] # va accueillir la liste des classes déjà attribuées aux polygones voisins
    for i2,elem2 in enumerate (macouche.selectedFeatures()):
    geom2=elem2.geometry()
    attrs=elem2.attributeMap()
    if i != i2: # déterminer les polygones voisins
    if geom.intersects(geom2):
    list_vois.append(i2)
    list_inter.append(attrs[ind_field].toInt()[0])
    list_num=range(1,7) # détermine le nombre de classe à attribuer
    for num_inter in list_inter: # détermine la liste des classes possibles à attribuer au polygone en fonction de ses voisins
    if num_inter in list_num:
    list_num.remove(num_inter)
    try: # attribut la classe au polygone
    macouche.dataProvider().changeAttributeValues({i:{ind_field:list_num[randint(0,len(list_num)-1)]}})
    except: # Si toutes les classes sont déjà attribué à chaque polygone voisin, afficher un message d'avertissement
    print "Avertissement : un polygone n'a pas été classé"
    Dernière modification par Bescu ; 05/09/2013 à 07h58.

  2. #2
    Modérateur et rédacteur Supporter(rice)


    Date d'inscription
    octobre 2005
    Localisation
    Louvain-la-neuve
    Emploi
    Géologue
    Organisme
    Université Catholique de Louvain - Région Wallonne
    Messages
    2 619

    Par défaut Re : Script pour symbologie différentes entre polygones adjacentes

    Cela me semble plus clair pour comprendre le script Python mais vérifies si les indentations sont correctes.

    Dans le cas de PyQGIS, ce n'est pas un curseur, mais une simple boucle passant par tous les éléments, ce qui facilite la vie !
    Dernière modification par gene ; 03/09/2013 à 17h04.
    "Caminante, no hay camino, el camino se hace al andar" A. Machado

  3. #3
    Rédacteur Supporter(rice)

    Date d'inscription
    février 2011
    Localisation
    Nord
    Emploi
    Administrateur SIG
    Organisme
    Mairie
    Âge
    31
    Messages
    712

    Mes réseaux sociaux

    Follow Bescu On Twitter
    Add Bescu on Linkedin

    Par défaut Re : Script pour symbologie différentes entre polygones adjacentes

    Citation Envoyé par gene Voir le message
    Cela me semble plus clair pour comprendre le script Python mais vérifies si les indentations sont correctes.
    Oui c'est plus clair, je ne savais pas comment on faisait ça merci beaucoup Gene! (je vais vérifierer l'indentation ce soir)

    Citation Envoyé par gene Voir le message
    Dans le cas de PyQGIS, ce n'est pas un curseur, mais une simple boucle passant par tous les éléments, ce qui facilite la vie !
    Merci pour la précision! Effectivement, pour cela je me suis aidé de ton post qui m'a été très utile.

  4. #4

    Date d'inscription
    février 2009
    Messages
    491

    Par défaut Re : Script pour symbologie différentes entre polygones adjacentes

    Dernière modification par baobazz ; 04/09/2013 à 08h55.

  5. #5
    Rédacteur Supporter(rice)

    Date d'inscription
    février 2011
    Localisation
    Nord
    Emploi
    Administrateur SIG
    Organisme
    Mairie
    Âge
    31
    Messages
    712

    Mes réseaux sociaux

    Follow Bescu On Twitter
    Add Bescu on Linkedin

    Par défaut Re : Script pour symbologie différentes entre polygones adjacentes

    Oui j'ai déjà testé ces 2 plugins mais le problème pour moi est qu'on ne peut pas choisir le nombre de classe que l'on veut : par défault ils choisissent le nombre de classe le plus petit possible!

  6. #6
    Modérateur et rédacteur Supporter(rice)


    Date d'inscription
    octobre 2005
    Localisation
    Louvain-la-neuve
    Emploi
    Géologue
    Organisme
    Université Catholique de Louvain - Région Wallonne
    Messages
    2 619

    Par défaut Re : Script pour symbologie différentes entre polygones adjacentes

    Somme toutes, ce que tu veux, c'est trouver les polygones qui sont jointifs (qui s'intersectent du point de vue topologique), à savoir dans l'exemple ci-joint:
    Cliquez sur l'image pour la voir en taille réelle 

Nom : 		poly.jpg 
Affichages :	110 
Taille :		36,3 Ko 
ID : 			5963

    1-2, 1-4, 1-5, 2-3, 2-4, 3-4
    en sachant que 1-2 et 2-1 sont la même chose et que 1-1 et 2-2 n'ont aucun sens.

    Alors plutôt que de passer par une double boucle comme dans ton script, utilise plutôt le module itertools qui travaille sur des itérateurs.
    Il contient des fonctions très intéressantes dans ton cas:
    • product() génère toutes les paires possibles d'éléments dans un itérateur (boucles, etc.) avec tous les doublons
    • permutations() idem mais en éliminant les doublons de type x,x:
    • combinations() idem mais en éliminant tous les doublons, c.a.d. x,x, x,y et y,x et dans l'ordre lexicographique


    Dans ton cas, pour choisir une couleur, c'est la dernière fonction qui t'intéresse.

    1) C'est plus facile à expliquer avec les modules Fiona et Shapely, beaucoup plus souples et faciles à utiliser que PyQGIS:

    import fiona
    #ouverture du fichier shapefile
    c = fiona.open('poly.shp')
    # maintenant tout est dans la variable c sous forme de dictionnaire
    import itertools
    # recherche des paires uniques dans c
    for paire in itertools.combinations(c, r=2):
    print paire[0]['properties']['id'], paire[1]['properties']['id'],",",

    1 2 , 1 3 , 1 4 , 1 5 , 2 3 , 2 4 , 2 5 , 3 4 , 3 5 , 4 5


    Maintenant il faut choisir celles qui sont jointives. Je traiterai les géométries avec le module Shapely.


    from shapely.geometry import shape
    c = fiona.open('poly.shp')
    # état des intersections -> True ou False avec les fonctions shape() pour transformer en objet shapefile et intersects() qui renvoie TRUE ou FALSE
    for paire in itertools.combinations(c, r=2):
    print paire[0]['properties']['id'], paire[1]['properties']['id'],":",shape(paire[0]['geometry']).intersects(shape(paire[1]['geometry']))
    1 2 : True
    1 3 : False
    1 4 : True
    1 5 : True
    2 3 : True
    2 4 : True
    2 5 : False
    3 4 : True
    3 5 : False
    4 5 : False


    et donc pour avoir directement les polygones qui sont jointifs pour te permettre de choisir les couleurs

    for paire in itertools.combinations(c, r=2):
    if shape(paire[0]['geometry']).intersects(shape(paire[1]['geometry'])): # si = TRUE
    print paire[0]['properties']['id'], paire[1]['properties']['id'],",",

    1 2 , 1 4 , 1 5 , 2 3 , 2 4 , 3 4 ,


    avec une compréhension de liste, directement en une seule ligne !

    jointifs = [paire for paire in itertools.combinations(fiona.open('poly.shp', r=2) if shape(paire[0]['geometry']).intersects(shape(paire[1]['geometry']))]


    et tu as directement les polygones jointifs d'une manière beaucoup plus simple et rapide que les 2 boucles.

    2) Avec PyQGIS, dans ton cas


    import itertools
    for paire in itertools.combinations(macouche.selectedFeatures(), r=2):
    if paire[0].geometry().intersects(paire[1].geometry()):
    ...


    Malheureusement en essayant la compréhension de liste avec PyQGIS (1.8 et 2.0), ça ne marche pas


    [paire for paire in itertools.combinations(macouche.selectedFeatures(), r=2) if paire[0].geometry().intersects(paire[1].geometry)]
    Traceback (most recent call last):
    File "<input>", line 1, in <module>
    TypeError: arguments did not match any overloaded call:
    QgsGeometry.intersects(QgsRectangle): argument 1 has unexpected type 'builtin_function_or_method'
    QgsGeometry.intersects(QgsGeometry): argument 1 has unexpected type 'builtin_function_or_method'
    Dernière modification par gene ; 04/09/2013 à 21h04.
    "Caminante, no hay camino, el camino se hace al andar" A. Machado

  7. #7
    Rédacteur Supporter(rice)

    Date d'inscription
    février 2011
    Localisation
    Nord
    Emploi
    Administrateur SIG
    Organisme
    Mairie
    Âge
    31
    Messages
    712

    Mes réseaux sociaux

    Follow Bescu On Twitter
    Add Bescu on Linkedin

    Par défaut Re : Script pour symbologie différentes entre polygones adjacentes

    Merci Gene! Comme toujours c'est très clair!

    En effet je ne connaissais pas le module itertools mais dans mon cas il va être très pratique!

    Content aussi de voir tes exemples avec Fiona et Shapely. J'avais hésité à faire mon script de cette façon, mais j'aurais peut-être dû, ça semble plus simple pour manipuler un shape!

  8. #8
    Modérateur et rédacteur Supporter(rice)


    Date d'inscription
    octobre 2005
    Localisation
    Louvain-la-neuve
    Emploi
    Géologue
    Organisme
    Université Catholique de Louvain - Région Wallonne
    Messages
    2 619

    Par défaut Re : Script pour symbologie différentes entre polygones adjacentes

    beaucoup, beaucoup plus simple, sans les "dédales" de PyQGIS et autres modules géospatiaux...
    voir Python: traitement des couches vectorielles dans une perspective géologique, lecture et enregistrement des couches sous forme de dictionnaires avec le module Fiona
    Tant qu'il ne faut pas une fioriture propre à PyQGIS, j'utilise essentiellement ces deux modules.
    "Caminante, no hay camino, el camino se hace al andar" A. Machado

  9. #9
    Rédacteur Supporter(rice)

    Date d'inscription
    février 2011
    Localisation
    Nord
    Emploi
    Administrateur SIG
    Organisme
    Mairie
    Âge
    31
    Messages
    712

    Mes réseaux sociaux

    Follow Bescu On Twitter
    Add Bescu on Linkedin

    Par défaut Re : Script pour symbologie différentes entre polygones adjacentes

    Je viens de me rendre compte que je n'avais pas mis la dernière version de mon script que j'avais un peu amélioré (index spatial, variables modifiables placées au début du script, ajout d'un champ erreur dans la table attributaire, infos sur la progression du processus...). Il doit être un peu plus simple à réutiliser du coup.


    from PyQt4.QtCore import QVariant
    from random import randint

    buf=35 # taille du buffer à appliquer
    nb_class=6 # Nombre de classe à attribuer

    macouche=qgis.utils.iface.activeLayer() # Instancie la couche sélectionnée (QgsVectorLayer)

    # création des champs id_class et advert(suppression préalable de ces derniers s'ils existent déjà)
    macouche.startEditing()
    ind_field_id_class,ind_field_advert=macouche.fieldNameIndex("id_class"),macouche.fieldNameIndex("advert")
    if ind_field_id_class!=-1 or ind_field_advert!=-1:
    macouche.dataProvider().deleteAttributes([ind_field_id_class,ind_field_advert])
    macouche.dataProvider().addAttributes([QgsField("id_class", QVariant.Int),QgsField("advert", QVariant.String)])
    macouche.commitChanges()
    ind_field_id_class,ind_field_advert=macouche.fieldNameIndex("id_class"),macouche.fieldNameIndex("advert")

    macouche.removeSelection() # Déselection des entités
    elem_tout=macouche.getFeatures() # Instancie un itérateur sur toutes les entités de la couche (QgsFeatureIterator)
    index=QgsSpatialIndex() # Création d'un index spatial
    for f in elem_tout: # Insère toutes les entités de la couche dans l'index spatial
    index.insertFeature(f)

    elem_tout=macouche.getFeatures() # Instancie un itérateur sur toutes les entités de la couche (QgsFeatureIterator)
    for f in elem_tout:
    # retourne la liste des ID des entités intersectant la boudingBox de l'entité f (QgsRectangle obligatoire en entrée pour la méthode intersects sur les index)
    # avec le buffer défini (buf) et 5 segments (nombres de segments pour les courbes)
    list_vois=[] # Liste qui va accueillir les ID des entités voisins
    list_inter=[] # va accueillir la liste des classes déjà attribuées aux polygones voisins
    intersection=index.intersects(f.geometry().buffer(buf,5).boundingBox())
    macouche.select(intersection) # sélection des entités qui sont ressorties de l'instersection avec l'index spatial
    elem_inter=macouche.selectedFeatures() # Liste d'instances des entités ressorties de l'intersection avec l'index spatial
    macouche.removeSelection() # Déselection des entités
    for f2 in elem_inter:
    if f2.id()!=f.id():
    if f.geometry().buffer(buf,5).intersects(f2.geometry()): # Vérifie si l'entité s'intersecte avec l'entité nb
    list_vois.append(f2.id()) # Si oui on ajoute son ID à la liste
    list_inter.append(f2.attributes()[ind_field_id_class])
    list_num=range(1,nb_class+1)
    for num_inter in list_inter: # détermine la liste des classes possibles à attribuer au polygone en fonction de ses voisins
    if num_inter in list_num:
    list_num.remove(num_inter)
    if len(list_vois)==0:
    macouche.dataProvider().changeAttributeValues({f.id():{ind_field_advert:u"Pas de polygones adjacents détecté"}})
    try: # attribut la classe au polygone
    macouche.dataProvider().changeAttributeValues({f.id():{ind_field_id_class:list_num[randint(0,len(list_num)-1)]}})
    except: # Si toutes les classes sont déjà attribué à chaque polygone voisin, afficher un message d'avertissement
    macouche.dataProvider().changeAttributeValues({f.id():{ind_field_advert:u"Le script n'a pas pu déterminer de classe"}})
    macouche.dataProvider().changeAttributeValues({f.id():{ind_field_id_class:randint(1,nb_class)}})

    print (int(f.id()*1./macouche.featureCount()*10000))/100., " %" # Pourcentage d'avancement

  10. #10
    Admin' Général Supporter(rice)

    Date d'inscription
    septembre 2003
    Localisation
    ...dans mon TARDIS
    Organisme
    Bad Wolf
    Âge
    37
    Messages
    9 657

    Mes réseaux sociaux

    Follow Le Docteur On Twitter Add Le Docteur on Google+

    Par défaut Re : Script pour symbologie différentes entre polygones adjacentes

    Merci Bescu
    >>>>>>>> Pas d'assistance technique par email ou mp : le forum est là pour ça <<<<<<<<<<<<


 

 

Discussions similaires

  1. [ArcGIS 10.x] Symbologie différentes entre polygones voisins / les plus proches
    Par Bescu dans le forum Assistance Technique
    Réponses: 14
    Dernier message: 03/09/2013, 19h19
  2. [ArcGIS 10.x] Une même symbologie pour différentes entitées
    Par rhadamanthys dans le forum Assistance Technique
    Réponses: 0
    Dernier message: 23/11/2012, 16h08
  3. [gvSIG 1.9] Union polygones de couches différentes
    Par MelleCel dans le forum Assistance et Programmation
    Réponses: 2
    Dernier message: 11/10/2010, 14h23
  4. [MapInfo 7.x] Fusion de polygones de 2 tables différentes
    Par Nemrod dans le forum Assistance Technique
    Réponses: 6
    Dernier message: 15/06/2009, 10h31
  5. [ArcGIS 8.x] Coller les polygones de 2 entités différentes
    Par isa 14 dans le forum Assistance Technique
    Réponses: 2
    Dernier message: 22/12/2006, 07h45

Les tags pour cette discussion

Liens sociaux

Règles de messages

  • Vous ne pouvez pas créer de nouvelles discussions
  • Vous ne pouvez pas envoyer des réponses
  • Vous ne pouvez pas envoyer des pièces jointes
  • Vous ne pouvez pas modifier vos messages
  •