Nous utilisons des cookies pour vous garantir la meilleure expérience sur notre site. Si vous continuez à utiliser ce dernier, nous considèrerons que vous acceptez l'utilisation des cookies. J'ai compris ! ou En savoir plus !.
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

Printemps des cartes 2024

#1 Tue 27 July 2021 12:19

trynalearn
Juste Inscrit !
Date d'inscription: 19 Jul 2021
Messages: 9

QGIS: Attribution automatique de noms/prefixes

Bonjour, je m'excuse si le problème parait simple et qu'on y ait déjà répondu par le passé. J'ai essayé de chercher sur GeoRezo avec les mots clés préfixe, nommage, nommer et remplissage sans trop de succès.

Je possède une couche ligne (câbles) dont je souhaite que les éléments soient nommés automatiquement à la création (donc en passant par l'onglet formulaire d'attributs dans les propriétés de la couche) de l'élément comme suit: C01, C02, C03,... C10, C11, etc.

Pour l'instant, j'ai trouvé quelque chose de vraiment simple: (excusez la logique douteuse, je débute)

Code:

CASE
    WHEN $id = 0 THEN concat('C01')
    WHEN $id = 9 THEN concat('C10')
    WHEN $id < 9 THEN concat('C0',$id+1)
    WHEN $id > 9 THEN concat('C',$id+1)
END

Ce qui semble ne pas créer de problèmes pour l'instant… Il faudra que j'essaye avec 100+ attributs pour voir s'il y a erreurs de nommage à partir de là. Aussi, ça fonctionne avec la calculatrice de champs, je ne suis pas entièrement sur de ce que ça va donner si je mettais ce code comme valeur par défaut dans le formulaire d'attributs.
Par contre, considérant qu'il y aura souvent suppression d'attributs pour des corrections ou autres, j'aurais besoin que les attributs soient nommés dépendamment de ce à quoi il sont accrochés.


Exemple: C22 - C23 - C24. Les éléments sont accrochés l'un à l'autre de start_point à end_point.

Supposons que je supprime C23 et recréé un élément accroché aux mêmes éléments auxquels C23 était accroché: il faudrait que le nouvel élément prenne automatiquement C23 comme ID, que ce soit en détectant que son start_point est accroché au end_point du C22 ou que son end_point soit accroché au start_point du C24, etc.


Ou alors ne pas dépendre du ID ? Je ne suis pas sûr.

Hors ligne

 

#2 Tue 27 July 2021 18:23

aheurion
Participant actif
Lieu: NANTES
Date d'inscription: 8 Oct 2020
Messages: 141

Re: QGIS: Attribution automatique de noms/prefixes

Bonjour,

Avoir un ID automatique ? ok
Avoir un ID automatique qui prenne la valeur d'un ancien élément mais uniquement s'il est au même endroit et que l'ancien a été supprimé ? plus dur.

Pour ce qui de ton code je peux te conseiller d'utiliser ceci :

Code:

concat(
     'C',
     right(
          concat(
               '00000',
               $id+1
          ),
          5
     )
)

Ainsi tu auras forcément un id de la forme C00001, C00054, ou C07541 par exemple (toujours 5 chiffres après le C, en supposant que tu n'auras jamais plus de 99999 entités^^)

Pour ce qui est de trouver une valeur en fonction des câbles existants en start_point et end_point il y a peut-être moyen de jouer avec un aggregate (oui j'aime les aggregate^^) :

Code:

aggregate(
     'ID_couche_cables',
     'concatenate_unique',
     to_int(right("ID",5))+1,
     intersects(start_point(geometry(@parent)),end_point($geometry)),
     ';'
)

Ainsi ça devrait prendre l'id du câble précédent+1 (on utilisant la première partie de code pour refaire un C000XX à partir du résultat de l'aggregate).

Par contre il faudra bidouiller pour prendre en compte les cas où l'id proposé par l'aggregate existe déjà (avec un CASE WHEN THEN par exemple).
Bon courage !

Hors ligne

 

#3 Wed 28 July 2021 08:32

SANTANNA
Moderateur
Lieu: Angers
Date d'inscription: 18 Jan 2008
Messages: 3804

Re: QGIS: Attribution automatique de noms/prefixes

Hello

aheurion a écrit:

Ainsi tu auras forcément un id de la forme C00001, C00054, ou C07541 par exemple (toujours 5 chiffres après le C, en supposant que tu n'auras jamais plus de 99999 entités^^)


La fonction lpad fait cela, soit

Code:

concat('C', lpad($id, 5, '0'))
trynalearn a écrit:

Ou alors ne pas dépendre du ID ?


$id est une valeur interne à QGIS, cela veut dire que vous n'avez pas, du moins dans l'interface graphique, de moyen de l'attribuer/l'éditer pour une entité. C'est QGIS qui attribue cette valeur à l'entité en fonction de l'ordre d'intégration dans la couche. Donc difficile de réattribuer automatiquement un ID = C23 sur la base de la première formule. Ensuite ce que je ne comprends pas, c'est que ce même champ ID que vous voulez incrémenter automatiquement, vous voulez qu'il soit fonction du placement de l'entité. Quelle option prédomine?

Hors ligne

 

#4 Wed 28 July 2021 12:13

trynalearn
Juste Inscrit !
Date d'inscription: 19 Jul 2021
Messages: 9

Re: QGIS: Attribution automatique de noms/prefixes

Bonjour,

Merci beaucoup pour ta proposition Aheurion! Je rencontre un problème en fin de compte' j'avais testé mon code sur un tableau d'attributs déjà rempli, donc en remplissant re-remplissant la colonne ID via la calculatrice de champs, j'obtenais de bons résultats mais à la création de nouveaux éléments, ceux-ci prennent automatiquement C01 comme valeur, constamment.

$id dans la formule semble toujours partir de 0.

En ce qui concerne le deuxième code, il me retourne soit des vides ('') soit une erreur avec l'impossibilité de de calculer l'agrégat.

Est-ce à quoi tu fais allusion dans ton commentaire?

Hors ligne

 

#5 Wed 28 July 2021 12:56

trynalearn
Juste Inscrit !
Date d'inscription: 19 Jul 2021
Messages: 9

Re: QGIS: Attribution automatique de noms/prefixes

SANTANNA a écrit:
trynalearn a écrit:

Ou alors ne pas dépendre du ID ?


$id est une valeur interne à QGIS, cela veut dire que vous n'avez pas, du moins dans l'interface graphique, de moyen de l'attribuer/l'éditer pour une entité. C'est QGIS qui attribue cette valeur à l'entité en fonction de l'ordre d'intégration dans la couche. Donc difficile de réattribuer automatiquement un ID = C23 sur la base de la première formule. Ensuite ce que je ne comprends pas, c'est que ce même champ ID que vous voulez incrémenter automatiquement, vous voulez qu'il soit fonction du placement de l'entité. Quelle option prédomine?


C'est bien ce dont je me doutais.

L'attribution automatique durant la création d'une entité prédomine. Je préfèrerai éviter de passer par la calculatrice de champs pour incrémenter quoi que ce soit. Concrètement, ce que j'essaye de faire c'est de me dédouaner du besoin de renommer manuellement durant les différentes phases de travail. J'aurais fréquemment le besoin de supprimer des éléments et en créer d'autres, ne pas avoir à refaire le tour des éléments pour éviter les répétitions me permettrait de gagner pas mal de temps.

Sinon, en cherchant un peu, je trouve ce sujet sur stackexchange: https://gis.stackexchange.com/questions … -with-qgis et j'y trouve le code python suivant:


Code:

from qgis.core import *
from qgis.gui import *

@qgsfunction(args='auto', group='Custom')
def update(feature, parent):
    layer = qgis.utils.iface.activeLayer()
    x = layer.featureCount()
    return x + 1

je considère bidouiller pour convertir la valeur retournée et la concat au C mais quand je l'essaye, j'obtiens le résultat comme ici https://streamable.com/wop6hy

Dernière modification par trynalearn (Wed 28 July 2021 13:01)

Hors ligne

 

#6 Tue 03 August 2021 14:56

aheurion
Participant actif
Lieu: NANTES
Date d'inscription: 8 Oct 2020
Messages: 141

Re: QGIS: Attribution automatique de noms/prefixes

En ce qui concerne le deuxième code, il me retourne soit des vides ('') soit une erreur avec l'impossibilité de de calculer l'agrégat


Ah ça doit être à cause du passage entre int et string : l'aggregate va chercher un string (avec 'concatenate_unique') donc pour pouvoir incrémenter il faut le transformer en int (

Code:

to_int(right("ID",5))+1

)
Le souci c'est que Qgis ne comprend pas que ces string qu'il récupère peuvent effectivement être transformés en int (ce qu'on ne peut pas faire avec toutes les chaînes de caractères).
J'avais eu ce souci une fois, pour le régler il faut utiliser le to_int en dehors de l'aggregate.

Sinon j'ai planché un peu sur ton problème et je pense avoir trouvé une solution qui couvre toutes les possibilités.

1) commencer par vérifier qu'on a bien coché la contrainte d'unicité (et la renforcer si besoin), comme ça le formulaire indiquera si l'ID par défaut est en doublon (même si on verra dans la formule ci-après que ça ne devrait pas arriver)

2) on va renseigner une formule dans la valeur par défaut et il faudra bien cocher la case "Appliquer la valeur par défaut sur la mise à jour". On est obligé de cocher la case avec la formule qu'on va utiliser mais pas de souci, il n'y a aucun risque puisqu'on va dire au départ de la formule :

Code:

if("ID_STRING" is not null, "ID_STRING",
---------reste de l'expression----------
)

3) Dans la formule on va chercher quelques infos : l'ID du câble précédent et l'ID max dans la couche. On va les utiliser dans une variable pour pouvoir les utiliser autant de fois qu'on veut sans avoir à tout réécrire :

Code:

with_variable('ID_precedent',
aggregate(
    'lignes_reperes_84fb1a4d_e1bb_4412_9bc1_46c4f465ee79',
    'concatenate_unique',
    "ID_STRING",
    intersects(start_point(geometry(@parent)),end_point($geometry))
),
---------reste de l'expression----------
)

Code:

with_variable('ID_max',
array_last(array_sort(aggregate(
    'lignes_reperes_84fb1a4d_e1bb_4412_9bc1_46c4f465ee79',
    'array_agg',
    "ID_STRING"
))),
---------reste de l'expression----------
)

4) On crée notre ID à l'aide de l'ID du câble précédent :

Code:

with_variable('proposition_ID',
concat(
    'C',
    lpad(
        to_int(
            right(@ID_precedent,5)
        )+1,
        5,
        '0'
    )
),
---------reste de l'expression----------
)

5) On regarde s'il y a doublon entre ce nouvel ID et les autres déjà présents dans la couche :

Code:

with_variable('booleen_doublon',
aggregate(
    'lignes_reperes_84fb1a4d_e1bb_4412_9bc1_46c4f465ee79',
    'count',
    1,
    @proposition_ID="ID_STRING"
)>0
,
---------reste de l'expression----------
)

6)On crée un nouvel ID qui sera ID_max+1 (dans le cas d'un doublon ou d'un câble non créé à la suite d'un autre) :

Code:

with_variable('proposition_ID_2',
concat(
    'C',
    lpad(
        to_int(
            right(@ID_max,5)
        )+1,
        5,
        '0'
    )
),
---------reste de l'expression----------
)

7)Enfin on va sortir ce qu'on veut en fonction de la situation : câble à la suite d'un autre et pas de doublon : ID_X+1 / câble isolé ou doublon : IDmax+1 :

Code:

CASE
    WHEN @ID_precedent is not null AND NOT @booleen_doublon THEN @proposition_ID
    ELSE @proposition_ID_2
END

Ce qui donne si on colle tout bout à bout :

Code:

if("ID_STRING" is not null, "ID_STRING",

with_variable('ID_precedent',
aggregate(
    'lignes_reperes_84fb1a4d_e1bb_4412_9bc1_46c4f465ee79',
    'concatenate_unique',
    "ID_STRING",
    intersects(start_point(geometry(@parent)),end_point($geometry))
),

with_variable('proposition_ID',
concat(
    'C',
    lpad(
        to_int(
            right(@ID_precedent,5)
        )+1,
        5,
        '0'
    )
),

with_variable('ID_max',
array_last(array_sort(aggregate(
    'lignes_reperes_84fb1a4d_e1bb_4412_9bc1_46c4f465ee79',
    'array_agg',
    "ID_STRING"
))),

with_variable('booleen_doublon',
aggregate(
    'lignes_reperes_84fb1a4d_e1bb_4412_9bc1_46c4f465ee79',
    'count',
    1,
    @proposition_ID="ID_STRING"
)>0
,

with_variable('proposition_ID_2',
concat(
    'C',
    lpad(
        to_int(
            right(@ID_max,5)
        )+1,
        5,
        '0'
    )
),


CASE
    WHEN @ID_precedent is not null AND NOT @booleen_doublon THEN @proposition_ID
    ELSE @proposition_ID_2
END


))))))

Désolé si c'est un peu indigeste, mais ça devrait fonctionner pas trop mal ^^

Hors ligne

 

Pied de page des forums

Powered by FluxBB