Pages: 1
- Sujet précédent - [PostgreSQL 9.3 / PostGIS] - découper deux couches de polygones - Sujet suivant
#1 Mon 09 February 2015 17:25
- schummi
- Participant actif
- Date d'inscription: 12 Mar 2009
- Messages: 88
[PostgreSQL 9.3 / PostGIS] - découper deux couches de polygones
Bonjour,
J'ai deux tables spatiales dans ma base PG :
- table A contenant 975 polygones. Certains de ces polygones pouvant être superposés avec d'autres polygones de la même couche
- table B contenant 790 polygones. Certains de ces polygones pouvant être superposés avec d'autres polygones de la même couche
Le résultat que j'aimerais obtenir est une table contenant :
- les polygones de la table B découpés pour ceux concernés par une intersection avec un ou plusieurs polygones de la table A
- les polygones de la table B restant (non concernés par l'intersection).
Je n'arrive pas à trouver la solution. J'imagine qu'il me faut traiter cela par requête récursive ? Car les tests que j'ai déjà effectué par ST_Difference ne sont pas corrects sur les polygones superposés ....
Aussi, j'aimerais optimiser le temps du traitement. Une fois encore, dans mes tests, j'ai essayé de gérer par des conditions ST_Intersects ou && pour traiter par bounding box mais les temps de calcul sont très longs : je précise que mes 2 tables ont un index spatial type GIST. Ce ne sont pas des multipolygon, leur forme peut être parfois un peu complexe mais sans plus.
Auriez-vous un exemple ou une solution à mon questionnement ?
Cordialement
Hors ligne
#2 Mon 09 February 2015 18:10
- Nicolas Ribot
- Membre
- Lieu: Toulouse
- Date d'inscription: 9 Sep 2005
- Messages: 1554
Re: [PostgreSQL 9.3 / PostGIS] - découper deux couches de polygones
Bonjour,
Si j'ai bien compris, vous voulez conserver tous les polygones de la table B découpés par la couche A.
C'est possible sans requete recursive:
D'abord unir les polygones de la couche A qui intersectent chaque polygone de la couche B. On a ainsi, pour tous les polygones de B concernés, le patch venant de A qui les recouvrent.
Ensuite on découpe chaque polygone de B avec ce patch, en se basant sur l'id du polygone.
Le trick pour garder tout le monde est de faire un left join entre la table B et les patchs, et d'appeler st_difference avec une GEOMETRYCOLLECTION EMPTY pour retourner le PG B original en cas de non-intersection avec A. En SQL:
Code:
with tmp as ( select b.id, st_union(a.geom) as geom from pgb b join pga a on st_intersects(a.geom, b.geom) group by b.id ) select b.id, st_difference(b.geom,coalesce(t.geom, 'GEOMETRYCOLLECTION EMPTY'::geometry)) as newgeom from pgb b left join tmp t on b.id = t.id;
Les images montrent les deux couches et le resultat en vert
Nicolas
Hors ligne
#3 Mon 09 February 2015 18:17
- Nicolas Ribot
- Membre
- Lieu: Toulouse
- Date d'inscription: 9 Sep 2005
- Messages: 1554
Re: [PostgreSQL 9.3 / PostGIS] - découper deux couches de polygones
Normalement sur une telle volumétrie, ca devrait etre très rapide.
Les polygons sont-ils très grands par rapport a l'extension spatiale des données ?
Si c'est le cas, vous pouvez booster la vitesse de la requete en découpant les gros polygones sur une grille carrée.
Nicolas
Hors ligne
#4 Mon 09 February 2015 20:20
- schummi
- Participant actif
- Date d'inscription: 12 Mar 2009
- Messages: 88
Re: [PostgreSQL 9.3 / PostGIS] - découper deux couches de polygones
Super merci !
Cela marche de manière impeccable.
Me reste maintenant à comprendre chacun des éléments de cette requête ;-)
Cordialement
Hors ligne
#5 Tue 10 February 2015 09:27
Re: [PostgreSQL 9.3 / PostGIS] - découper deux couches de polygones
Le trick pour garder tout le monde est de faire un left join entre la table B et les patchs, et d'appeler st_difference avec une GEOMETRYCOLLECTION EMPTY pour retourner le PG B original en cas de non-intersection avec A.
Merci Nicolas,
voici une belle "astuce" à laquelle je n’avais pas pensé il y a quelques temps pour un besoin similaire.
Mathieu BOSSAERT
Association GeoRezo
Hors ligne
Pages: 1
- Sujet précédent - [PostgreSQL 9.3 / PostGIS] - découper deux couches de polygones - Sujet suivant