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 Wed 14 April 2021 16:24

Nighthawk
Participant actif
Date d'inscription: 17 Sep 2014
Messages: 129

QGIS: Polygones multiples a unique constructeur d'expressions

Bonjour,

Le titre est un poil court pour tout expliquer donc laissez-moi détailler ma question.

Il s'agit de trouver un moyen, par le biais du générateur de géométries, d'étiqueter ou non certains polygones en fonction d'une couche d'Atlas.
C'est à dire que j'ai des zones qui couvrent plusieurs communes et je voulais n'afficher que les étiquettes concernant la commune affichée sur l'Atlas en cours. J'ai déjà un bout de solution.
1. En farfouillant sur le github du plugin mask j'ai trouvé des solutions pour trier les étiquettes à afficher selon l'emprise géographique de l'entité de l'atlas concernée. Il s'agit notamment, dans l'onglet rendu des étiquettes, de "Montrer l'étiquette" suivant une formule :

Code:

intersects(   geometry(  get_feature('COUCHE_COMMUNES','NOM_COMMUNE', attribute(  @atlas_feature ,'NOM_COMMUNE_DS_COUCHE_ATLAS'))), $geometry)

Toutes les entités qui intersectent la géométrie de la commune dont le nom est identique au nom de commune présent dans le champ 'NOM_COMMUNE_DS_COUCHE_ATLAS' verront leur étiquette affichée. Seulement voilà, avec de grandes entités je me retrouve avec des noms un peu partout autour de ma commune (dans le masque finalement) et c'est pas trop "joli"...
2. Du coup je me suis aidé du générateur de géométrie dans l'onglet position des étiquettes. Je ne voulais utiliser que les géométries présentes dans le périmètre de la commune :

Code:

 intersection(  $geometry , geometry(  get_feature( 'COUCHE_COMMUNES', 'NOM_COMMUNE',  attribute(  @atlas_feature , 'NOM_COMMUNE_DS_COUCHE_ATLAS'))))

Ici je ne garde que la géométrie résultant de l'intersection entre ma couche de zone et la géométrie de la commune dont le nom est identique au nom de commune présent dans le champ 'NOM_COMMUNE_DS_COUCHE_ATLAS'. J'ai donc des étiquettes qui sont placées à l'intérieur de mon périmètre de commune.

Seulement j'ai un dernier problème qui survient : j'ai parfois des petites zones qui trainent après cette intersection (en limites de communes), et qui me font un tas d'étiquettes qui viennent polluer les bords de ma carte. Pour simplifier la lecture de mes cartes je voulais limiter l'affichage des étiquettes aux géométries résultant de l'intersection dont la surface est supérieure à 10m² (filtre largement suffisant pour des cartos au 5000e).
J'ai donc remplacé ma première fonction par un truc du genre :

Code:

area( intersection(  $geometry , geometry(  get_feature( 'Contour_com_CCLP_NEW_a75d8c06_74f1_4e84_8d8f_daf69128a6dc', 'NOM_COM',  attribute(  @atlas_feature , 'NOM_COM')))))>10

Et là ça ne marche pas comme voulu parce que quand je fais l'intersection d'une entité par une autre, les différentes géométries résultant de cette intersection forment une géométrie multi-partie dont la surface (cumulée), dépasse mon seuil...
Est-ce que quelqu'un saurait comment je peux éclater une géométrie (donc ici le résultat de mon intersection) afin d'en mesurer la surface, depuis le constructeur de chaîne d'expression de QGIS.
Je note tout de même que les algorithmes fournis par QGIS permettent de créer une géométrie multi-parties à partir de plusieurs géométries (collect_geometries), d'utiliser une géométrie d'une entité multi-parties (geometry_n), ou encore de compter les géométries d'une entité multi-parties (num_geometries). Seulement voilà, je ne sais pas trop quelle fonction peut m'être utile, s'il faut que j'en fasse une par le biais de l'éditeur de fonctions (mais je ne connais pas le python, donc je ne sais pas trop par où commencer),...

Quelqu'un aurait-il une piste pour résoudre ce problème ?
D'avance merci ! smile

Hors ligne

 

#2 Thu 15 April 2021 09:19

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

Re: QGIS: Polygones multiples a unique constructeur d'expressions

Salut,
Challenge intéressant que tu proposes, là big_smile Peut-être qu'il y a une piste en passant par du array et en itérant (for_each) sur la géométrie collection stockée en variable (with_variable), générant pour chaque élément sa surface, pour ne finalement garder que celles à surface suffisante. Mais je me demande pas s'il ne manquerait pas une fonction de dump de géométrie. Un joli casse-tête que je pourrais essayer de regarder si tu me fournis un jeu de données et bout de projet.

Mais, ne serait-il pas plus simple de générer une couche virtuelle à partir de ta donnée et de l'étiqueter? A défaut de Python, on a le SQL, même si les expressions QGIS peuvent être encore plus fun, je te le concède!!!

Hors ligne

 

#3 Fri 16 April 2021 09:08

Nighthawk
Participant actif
Date d'inscription: 17 Sep 2014
Messages: 129

Re: QGIS: Polygones multiples a unique constructeur d'expressions

Salut,

Effectivement, j'ai un peu galéré à trouver la fonction qui me permettrait de finaliser l'opération. J'en venais même à me dire "Si besoin, il faudra la créer avec l'éditeur de fonctions", mais comme je ne connais pas bien le python, je voulais voir s'il existait une autre alternative... big_smile

Du coup c'est vrai que je ne pense jamais à la couche virtuelle ! Maintenant il faut que je trouve comment appeler l'entité d'atlas correspondante en SQL...

En tous cas merci beaucoup pour cette piste ! J'explore et je reviens faire mon rapport ! big_smile

Hors ligne

 

#4 Fri 07 May 2021 09:38

Nighthawk
Participant actif
Date d'inscription: 17 Sep 2014
Messages: 129

Re: QGIS: Polygones multiples a unique constructeur d'expressions

Rebonjour à tous,

Ça a été le feu et je n'ai finalement pas trouvé de solutions élégantes. En effet, je n'ai pas trouvé d'expression qgis et n'ai pas le niveau suffisant pour créer une fonction qui puisse réaliser cette opération. En SQL je ne suis pas fortiche non plus... big_smile

Du coup j'ai fait la technique de bourrin : Intersection entre ma couche polygone à étiqueter et ma couche de géométries de l'atlas > Morceaux multiples vers morceaux uniques > Calcul des surfaces. En gros je garde 3 champs : Le champs de nom de commune (qui me servira à faire le lien entre ma couche d'atlas et ma géométrie), le champ surface, et le champ qui servira d'étiquettes.
Et je fais mes étiquettes en conditionnant leur affichage à l'atlas et à leur surface :

Code:

"NOM_COMMUNE"  =  attribute(  @atlas_feature ,'NOM_COM') AND  "SURF_M2" >30

Voilà voilà. La bourrinitude fût la solution la plus simple ! big_smile

Hors ligne

 

#5 Fri 07 May 2021 15:56

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

Re: QGIS: Polygones multiples a unique constructeur d'expressions

Hello,
Tu veux bien essayer ce code? Pour la partie intersection, je te laisse réajuster par rapport à ton scénario, je l'ai fait vis-à-vis de l'atlas direct. Le plus intéressant est la deuxième partie, je pense.

Code:

with_variable(
 'geomInt' -- on crée une variable pour récupérer la géométrie en superposition
 , collect_geometries(
        intersection( $geometry  , geometry( @atlas_feature ) )
        )

 , with_variable( 'nbrParts' -- une autre variable qui stocke le nombre de parts dans la geom en superposition
                   , generate_series( 1, num_geometries(@geomInt))
                   
                   , with_variable( 'geomCibleListe' -- on convertit la geometrie multipolygone en array, en itérant sur le nbre de parts
                                    , array_foreach( 
                                                    @nbrParts
                                                    , geometry_n( @geomInt, @element ) )
                                    , collect_geometries( -- on regénère une géométrie multipolygone dont on filtrera les parties indésirées
                                                        array_filter( @geomCibleListe
                                                                      , area(@element) > 100000 -- on indique la surface seuil
                                                                    )
                                                        )
                                 )
                )
)

Hors ligne

 

Pied de page des forums

Powered by FluxBB