banniere

Le portail francophone de la géomatique


Toujours pas inscrit ? Mot de passe oublié ?
Nom d'utilisateur    Mot de passe              Toujours pas inscrit ?   Mot de passe oublié ?

Annonce

GEODATA DAYS 2024

#1 Thu 25 August 2016 18:47

Pedro69
Juste Inscrit !
Date d'inscription: 25 Aug 2016
Messages: 3

QGIS / PyQGIS: Ecraser couche avec des modifications

Bonjour à tous,

Je viens de créer mon premier code PyQGIS. Il fonctionne très bien mais je m'interroge s'il n'y avait pas de solution plus simple pour faire ce que j'ai fait !

Un utilisateur dessine un shapefile sur une couche "reseau". Lorsqu'il a terminé, il exécute le code ci-dessous pour faire quelques traitement sur son dessin et mettre à jour des attributs. Tout fonctionne bien mais j'ai du passer par une copie de fichiers pour pouvoir fermer le fichier source, l'écraser avec les modifications et puis réinsérer la couche.

N'y avait-il pas plus simple pour faire cette simple manipulation que de passer par des fichiers temporaires ?

Voici le code :

Code:

import sys
import shutil
sys.path.append('/home/user/.qgis2/python/plugins')
from processing.core.Processing import Processing
Processing.initialize()
from processing.tools import *

canvas = iface.mapCanvas()

#Recherche de la couche "reseau", sauvegarde de sa source et de son id et suppression de la couche
for layer in canvas.layers ( ):
    print layer.name()
    if layer.name()=='reseau':
        id=layer.id()
        source=layer.publicSource()
        QgsMapLayerRegistry.instance().removeMapLayer(id)
        
#Copie de tous les fichiers associes a la couche source dans des fichiers temporaire
source_tmp = source.replace('reseau', 'reseau_tmp')
shutil.copyfile(source, source_tmp)
shutil.copyfile(source.replace('shp','shx'), source_tmp.replace('shp','shx'))
shutil.copyfile(source.replace('shp','dbf'), source_tmp.replace('shp','dbf'))
shutil.copyfile(source.replace('shp','qpj'), source_tmp.replace('shp','qpj'))
shutil.copyfile(source.replace('shp','prj'), source_tmp.replace('shp','prj'))

#Traitement de la couche temporaire
tmp_layer = QgsVectorLayer(source_tmp, 'tmp', 'ogr')
outputs_1 = general.runalg('qgis:splitlineswithlines', tmp_layer, tmp_layer, None)
outputs_2 = general.runalg('qgis:fieldcalculator', outputs_1['OUTPUT'], 'id_troncon', 1, 5.0, 0.0, False, '$id', None)
outputs_3 = general.runalg('qgis:fieldcalculator', outputs_2['OUTPUT_LAYER'], 'x_dep', 0, 10.0, 6.0, False, 'xat(0)', None)
outputs_4 = general.runalg('qgis:fieldcalculator', outputs_3['OUTPUT_LAYER'], 'y_dep', 0, 10.0, 6.0, False, 'yat(0)', None)
outputs_5 = general.runalg('qgis:fieldcalculator', outputs_4['OUTPUT_LAYER'], 'x_arr', 0, 10.0, 6.0, False, 'xat(-1)', None)
outputs_6 = general.runalg('qgis:fieldcalculator', outputs_5['OUTPUT_LAYER'], 'y_arr', 0, 10.0, 6.0, False, 'yat(-1)', None)

#Le dernier traitement modifie le fichier source
outputs_7 = general.runalg('qgis:fieldcalculator', outputs_6['OUTPUT_LAYER'], 'longueur', 0, 10.0, 6.0, False, '$length', source)

#On reinsere dans QGIS le fichier source
iface.addVectorLayer(source, "reseau", "ogr")

#On fait d'autres traitements derriere

Je vous remercie pour votre aide !

Bonne journée, Pedro

Hors ligne

 

#2 Fri 26 August 2016 10:42

JD
Moderateur
Date d'inscription: 8 Aug 2013
Messages: 726

Re: QGIS / PyQGIS: Ecraser couche avec des modifications

Bonjour,

A priori, comme processing travaille beaucoup avec des couches temporaires, il ne semble pas possible d'éditer directement la couche en cours.
Néanmoins je pense que c'est possible de l'améliorer

Code:

registry = QgsMapLayerRegistry.instance()


#Recherche de la couche "reseau", sauvegarde de sa source et de son id

layer = registry.mapLayersByName('reseau')[0]
id=layer.id()
source=layer.publicSource()

#Traitement

outputs_1 = general.runalg('qgis:splitlineswithlines', layer, layer, None)
outputs_2 = general.runalg('qgis:fieldcalculator', outputs_1['OUTPUT'], 'id_troncon', 1, 5.0, 0.0, False, '$id', None)
outputs_3 = general.runalg('qgis:fieldcalculator', outputs_2['OUTPUT_LAYER'], 'x_dep', 0, 10.0, 6.0, False, 'xat(0)', None)
outputs_4 = general.runalg('qgis:fieldcalculator', outputs_3['OUTPUT_LAYER'], 'y_dep', 0, 10.0, 6.0, False, 'yat(0)', None)
outputs_5 = general.runalg('qgis:fieldcalculator', outputs_4['OUTPUT_LAYER'], 'x_arr', 0, 10.0, 6.0, False, 'xat(-1)', None)
outputs_6 = general.runalg('qgis:fieldcalculator', outputs_5['OUTPUT_LAYER'], 'y_arr', 0, 10.0, 6.0, False, 'yat(-1)', None)

#avant de réécrire dedans on ferme la couche
QgsMapLayerRegistry.instance().removeMapLayer(id)
outputs_7 = general.runalg('qgis:fieldcalculator', outputs_6['OUTPUT_LAYER'], 'longueur', 0, 10.0, 6.0, False, '$length', source)

#On fait d'autres traitements derriere

Cordialement,

Dernière modification par lejedi76 (Fri 26 August 2016 10:44)

Hors ligne

 

#3 Tue 06 September 2016 15:25

Pedro69
Juste Inscrit !
Date d'inscription: 25 Aug 2016
Messages: 3

Re: QGIS / PyQGIS: Ecraser couche avec des modifications

Merci beaucoup lejedi76 !

Je viens de tester et ça marche bien mieux !

Dernière petite question, maintenant que mon script python fonctionne, existe-t-il un moyen de l'associer directement à mon fichier qgis et d'ajouter un bouton pour l'exécuter ?

Je m'explique : je ne souhaite pas passer par une nouvelle extension, le fichier qgs pourra être ouvert sur différents postes. J'ai créé un fichier traitement.py dans le même dossier que mon fichier qgis. Je souhaiterai créer un bouton pour ouvrir ce script python directement dans l'interface de qgis.

Je suis allé farfouiller dans Projet / Propriété du projet / Macros où j'ai vu que je pouvais insérer du code mais j'aimerai ajouter un bouton au démarrage de qgis un peu comme il est possible de le faire en vba avec excel.

Avez-vous une solution ?

Merci pour votre réponse,

Pedro

Hors ligne

 

#4 Tue 06 September 2016 23:55

JD
Moderateur
Date d'inscription: 8 Aug 2013
Messages: 726

Re: QGIS / PyQGIS: Ecraser couche avec des modifications

Bonjour,

vous allez ajouter dans les propriétés de votre projets dans l'onglet macro
ceci :

Code:

from qgis.utils import iface
from traitement import *
mygui = None

def openProject():
    global mygui
    mygui = MyGui(iface)

Ensuite votre fichier traitement.py sera comme ceci :

Code:

from PyQt4.QtCore import *
from PyQt4.QtGui import *

from qgis.utils import iface

class MyGui():
    '''add processing button in toolbar'''
    def __init__ (self, iface):
        self.iface = iface
        self.action = QAction(u'Traitement', self.iface.mainWindow())
        self.action.triggered.connect(self.processing)
        self.iface.addToolBarIcon(self.action)

    def processing(self):
       '''copier votre précédent code'''

Pour chacun des postes qui utilisera votre projet aller dans
options > Général > Activer les macros et changer en "Toujours (Non recommandé)"

Cordialement,

Dernière modification par lejedi76 (Wed 07 September 2016 10:34)

Hors ligne

 

#5 Wed 07 September 2016 19:20

Pedro69
Juste Inscrit !
Date d'inscription: 25 Aug 2016
Messages: 3

Re: QGIS / PyQGIS: Ecraser couche avec des modifications

C'est impeccable lejedi76 ! Ca marche quasiment parfaitement bien !!! J'ai bien le bouton qui s'ajoute. Juste un message d'erreur que je n'arrive pas à éliminer quand je clique dessus :

Traceback (most recent call last):
  File "C:/Users/Utilisateur/Desktop/outil qgis/outil_modelisation_qgis\traitement.py", line 45, in processing
    outputs_1 = general.runalg('qgis:splitlineswithlines', layer_reseau, layer_reseau, None)
NameError: global name 'general' is not defined


Qu'est-ce que j'ai mal déclaré ?

Je m'emmêle les pinceaux avec general.runalg ou processing.runalg ?

Du coup, au début de mon fichier traitement.py j'ai mis tout ça :

import sys, os
sys.path.append('/home/user/.qgis2/python/plugins')
from processing.core.Processing import Processing
Processing.initialize()
from PyQt4.QtCore import *
from PyQt4.QtGui import *
from qgis.core import *
from qgis.utils import iface


Ca fait beaucoup d'importations non ?

Merci pour tout !!!

Pedro

Hors ligne

 

#6 Thu 08 September 2016 07:41

JD
Moderateur
Date d'inscription: 8 Aug 2013
Messages: 726

Re: QGIS / PyQGIS: Ecraser couche avec des modifications

Tu peux effectivement enlever 

Code:

from PyQt4.QtCore import *

À dire vrai j ai jamais utilisé cette nouvelle formule pour utiliser les scripts du module Processing.
Moi je faisais un truc du genre

Code:

import processing
processing.runalg()

Pour éviter la confusion renomme la fonction "processing" de ta classe en "traitement" et connecte ton bouton en remplaçant le self.processing par self.traitement

Hors ligne

 

Pied de page des forums

Powered by FluxBB