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 Fri 24 November 2017 17:51

p.jeremie
Participant assidu
Lieu: Valence
Date d'inscription: 10 Sep 2017
Messages: 380

[Postgis] Soustraction de polygones

Bonjour,

Je suis en train de me casser les dents sur l'opération suivante :
- j'ai une table dans postgres avec tous les polygones correspondants à des contraintes (zones à exclure)
- j'ai une table avec tous les polygones des communes de ma région

Je souhaite créer une table avec :
- tous les polygones des communes, soustraits des zones à exclure.

J'ai essayé avec le code suivant, mais je ne récupère que les communes pour lesquels au moins un bout de polygone a été enlevé :

Code:

create materialized view tmp.non_eclu
AS 
-- 
select communes.insee, st_difference(communes.geom,contraintes.geom) as geom 
from tmp.communes_osm_aura communes,
     tmp.table_contraintes contraintes
where 
     st_intersects(communes.geom, contraintes.geom);

Une piste pour m'aider ?

En ligne

 

#2 Fri 24 November 2017 22:41

Nicolas Ribot
Membre
Lieu: Toulouse
Date d'inscription: 9 Sep 2005
Messages: 1536

Re: [Postgis] Soustraction de polygones

Bonsoir:

Faites une jointure type LEFT JOIN

... FROM tmp.communes_osm_aura communes left join
     tmp.table_contraintes contraintes on st_intersects(...)

Nico

Hors ligne

 

#3 Fri 24 November 2017 22:55

gvellut
Participant actif
Lieu: Annecy
Date d'inscription: 13 Apr 2006
Messages: 112
Site web

Re: [Postgis] Soustraction de polygones

Il faudrait faire aussi un coalesce(st_difference(....), communes.geom)

Hors ligne

 

#4 Sun 26 November 2017 01:14

Theos2000
Participant assidu
Date d'inscription: 15 Jun 2015
Messages: 221

Re: [Postgis] Soustraction de polygones

Bonjour,


je me permet de participer car je suis sur la même problématique que p.jeremie,
mon cas est similaire puisque dans le cas d'une conso foncière je dois exclure des bâtiments polygones
j'ai essayé plusieurs manière de différencier en utilisant des left join sans succès :

-St_difference qui tourne en boucle

-Case when st_intersects, st_contains, st_within  qui à la particularité de bien indiquer les alias issue du case when et meme lorsque l'alias est spécifié dans un where ===> affiche malgrés tout tous les batiments.

Quelle est la requête type pour exclure une géométrie , il y aurait il une subtilité qui m'échappe...sans doute !

Merci pour votre aide ou vos remarques

PJ : Exemple de requête

Dernière modification par Theos2000 (Sun 26 November 2017 01:15)


Fichier(s) joint(s) :
Pour accéder aux fichiers vous devez vous inscrire.

Hors ligne

 

#5 Sun 26 November 2017 13:50

p.jeremie
Participant assidu
Lieu: Valence
Date d'inscription: 10 Sep 2017
Messages: 380

Re: [Postgis] Soustraction de polygones

Merci pour les réponses.

Comme il s'agissait de mon premier message sur le forum, j'ai pu continuer à chercher avant que mon message soir en ligne, et j'avais en effet inclus un left join.

Concernant

gvellut a écrit:

Il faudrait faire aussi un coalesce(st_difference(....), communes.geom)


En me basant sur la réponse de Nicolas à ce message https://georezo.net/forum/viewtopic.php … difference
J'arrivais à la requête suivante :

Code:

create materialized view tmp.non_exclu
AS
select communes.insee, st_difference(communes.geom, coalesce(contraintes.geom, 'GEOMETRYCOLLECTION EMPTY'::geometry)) as geom 
from 
tmp.communes_osm_aura communes
left join 
  (
  select a.insee, st_union(b.geom) as geom
  from tmp.communes_osm_aura a
  join 
  tmp.table_contraintes b
  on (a.geom && b.geom
  and st_intersects(a.geom, b.geom) )
  group by a.insee
  )  contraintes on (communes.insee = contraintes.insee) ;

Si je comprends bien, gvellut tu ferais plutôt

Code:

(...)
select communes.insee, coalesce(st_difference(communes.geom, contraintes.geom), communes.geom) as geom 
(...)

Les deux ont l'air de créer les mêmes données dans la vue.

Par contre, il y a un truc qui me chiffonne, c'est que je me retrouve avec 3 sortes de geometry :

Code:

select geometrytype(geom), count(*)
from tmp.non_exclu
group by 1
---
'GEOMETRYCOLLECTION','75'
'MULTIPOLYGON','3938'
'POLYGON','82'

Alors que dans la table des communes, j'ai seulement des MULTIPOLYGON

Code:

select geometrytype(geom), count(*)
from tmp.communes_osm_aura
group by 1
---
'MULTIPOLYGON','4095'

Et surtout, comment ça se fait que j'ai autant de communes dans la vue, alors que certaines sont chevauchées à 100% par une contrainte ?
Autrement dit, je devrais avoir moins que 4095 lignes dans la vue... Je suppose que ça a un lien avec mes 3 types de geometry mais je ne comprends pas bien pourquoi...

edit : suppression mise en gras dans sections code, ce qui ne fonctionne pas, pour ne pas perturber la lecture...

Dernière modification par p.jeremie (Tue 28 November 2017 14:07)

En ligne

 

#6 Sun 26 November 2017 16:23

Nicolas Ribot
Membre
Lieu: Toulouse
Date d'inscription: 9 Sep 2005
Messages: 1536

Re: [Postgis] Soustraction de polygones

Bonjour,

Les différents types de géométries sont normaux:
la diff entre deux polygones peut donner un PG, un MPG, une ligne, un point, une combinaison de tout cela => GeometryCollection

Dans votre cas, vous vous interessez à des surfaces, il faut donc filtrer ces collections pour ne garder que des éléments surfaciques (PG ou MPG): st_collectionExtract(geom, 3).

Ca explique aussi pourquoi toutes les communes ressortent dans votre vue: meme en cas de recouvrement quasi parfait, la différence doit générer des géométries (lignes, point...). Elles devraient disparaitre lors de l'extraction des surfaces.

Il faudra ensuite forcer le résultat final en multipolygon (st_multi), pour garder une table clean au niveau géométrique.

Pour mieux visualiser les étapes du processus, vous pouvez créer une table intermédiaire contenant l'union des contraintes par commune:

Code:

create unlogged table comm_contrainte as (
     SELECT
        a.insee,
        st_union(b.geom) AS geom
      FROM tmp.communes_osm_aura a
        JOIN
        tmp.table_contraintes b
          ON (st_intersects(a.geom, b.geom))
      GROUP BY a.insee
 );

Puis faire la différence entre les communes et cette table:

Code:

... 
st_multi(
   st_collectionExtract(
      st_difference(
          c.geom, 
          coalesce(cc.geom, 'GEOMETRYCOLLECTION EMPTY'::geometry)
      ),
      3
   )
) as geom 
from commune c left join comm_contrainte cc on c.insee = cc.insee
...

Nicolas

Hors ligne

 

#7 Tue 28 November 2017 16:37

p.jeremie
Participant assidu
Lieu: Valence
Date d'inscription: 10 Sep 2017
Messages: 380

Re: [Postgis] Soustraction de polygones

merci.

Nicolas Ribot a écrit:

Pour mieux visualiser les étapes du processus, vous pouvez créer une table intermédiaire contenant l'union des contraintes par commune:
(...)
Puis faire la différence entre les communes et cette table


J'ai procédé comme ça pour mieux comprendre le cheminement, mais j'ai toujours un truc qui me chiffonne.

La première partie est claire, j'ai pour chaque commune l'union de ses contraintes dans une table intermédiaire.

C'est la deuxième partie qui me pose soucis.
J'ai autant de lignes dans la table finale que dans la table des communes.
Je m'attendais à n'avoir que les communes qui ont encore un bout "dispo" (autrement dit qui n'ont pas 100% de leur surface chevauchée par une contrainte).

Je précise que j'ai des zones de contraintes qui sont plus grandes que certaines communes (et donc ces communes sont bien complètement chevauchées).

J'ai donc ajouté une condition pour ne garder que les geometry non vides.

Je n'ai pas trouvé d'autre moyen que d'ajouter une requête qui englobe la requête avec les st_multi, st_collectionExtract et st_difference, car sinon je dois répéter tout le paquet de fonctions dans le where ! Autrement dit, pas possible de faire référence à l'alias geom car ambigu.

J'arrive à la requête suivante (j'ai choisi de faire un WITH plutôt qu'une table intermédiaire) :

Code:

create materialized view tmp.non_exclu
AS
-- union des contraintes par commune
with contraintes_communes as (
    select
        communes.insee_com as insee,
        st_union(contraintes.geom) as geom
    from ressources.communes_ign_aura communes
    join
    tmp.table_contraintes contraintes
      on (st_intersects(communes.geom, contraintes.geom))
    group by communes.insee_com
)
select insee, geom from
    (select communes.insee_com as insee, 
        -- récupération des multipolygones correspondants à la différence 
        -- entre les geom des communes et l'union des contraintes des communes
        st_multi(
            st_collectionExtract(
                st_difference(
                    communes.geom, 
                    coalesce(cc.geom, 'GEOMETRYCOLLECTION EMPTY'::geometry)
                ),
            3
            )
        ) as geom
    from ressources.communes_ign_aura communes
    left join contraintes_communes cc
    on communes.insee_com = cc.insee
    ) as s
-- filtrage des géométries vides
where st_isempty(s.geom) is not true;

Et comme ça je ne récupère plus les communes 100% concernées par des contraintes.

Nicolas Ribot a écrit:

Ca explique aussi pourquoi toutes les communes ressortent dans votre vue: meme en cas de recouvrement quasi parfait, la différence doit générer des géométries (lignes, point...). Elles devraient disparaitre lors de l'extraction des surfaces.


Remarque : du coup j'ai constaté que les communes ne disparaissent par lors de l'extraction !
Je me demande même si elle est bien nécessaire maintenant que j'ai ajouté un un filtre sur les géométries vide... car je récupère la même table avec et sans le st_collectionExtract().

Remarque 2 : ça pourrait être sympa sur ce forum d'avoir des blocs code larges comme le message et la coloration syntaxique du SQL en mettant par exempe [ code = sql ]. Une piste : https://fluxbb.org/resources/mods/flux-geshi/

Remarque 3 : j'accepte le tutoiement smile

En ligne

 

Pied de page des forums

Powered by FluxBB