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Ă© ?

#1 Fri 10 May 2019 16:46

zack
Participant occasionnel
Date d'inscription: 16 Jul 2014
Messages: 33

POSTGIS - Découper polygones par des lignes

Bonjour,

Dans une chaßne de traitement QGIS j'essaye de découper des polygones par des lignes.
Ces lignes sont issus de st_shortestline sur postgis. J'ai étendue chaque ligne de 1m pour éviter des problÚmes de précision.
L'outil "couper avec des lignes" de QGIS fonctionne sur une petite zone de test, mais pas sur une commune entiĂšre, beaucoup trop de lignes et de polygones (quelques milliers pour chaque).
Du coup j'essaye de voir pour intégrer la fonction st_split. Elle semble marcher en une demi-heure pour la commune entiÚre. Mais le résultat n'est pas du tout bon, j'ai des dizaines de milliers de lignes dans la table, et pourtant en les chargeant dans QGIS mes polygones semblent non découpés.
Je pense que ça vient du fait que st_split crée une geometry_collection et que le ST_CollectionExtract ne marche justement pas dans le cas d'un st_split.
Du coup est-ce que quelqu'un sait quelle fonction écrire ? Je ne suis pas hyper à l'aise avec PostGIS

La fonction suivante ne marche pas donc, il me donne une erreur à cause du multilinestring qui n'est pas supporté...

Code:

DROP TABLE if exists blabla;
CREATE TABLE blabla AS 
SELECT ST_CollectionExtract(ST_Split(rect.geom, line.the_geom),3)
FROM public.polygones_zone_test as rect, public.lignes_zone_test as line

Merci Ă  vous !

Hors ligne

 

#2 Mon 13 May 2019 13:54

tumasgiu
Membre
Lieu: Ajaccio
Date d'inscription: 5 Jul 2010
Messages: 1226

Re: POSTGIS - Découper polygones par des lignes

Salut,

tout d'abord,
le message d'erreur semble indiquer que la colonne géométrique
de votre table lignes_zone_test est de type multi linestring.
A ce moment lĂ , il faudrait les extraire avec st_dump.

Ensuite, le résultat que vous obtenez vient du fait que
votre requĂȘte exĂ©cute pour st_split pour chaque combinaison
des géométries de vos deux tables.
Cette fonction, utilisée avec une géométrie et une ligne de découpe
qui sont géométriquement disjointes, aura pour résultat la géométrie originale.
Pour supprimer ces résultats inutiles, il faudrait rajouter une condition de jointure
entre vos deux tables pour ne retenir que les éléments qui s'intersectent :

Code:

SELECT ST_CollectionExtract(ST_Split(rect.geom, line.the_geom),3)
FROM public.polygones_zone_test as rect 
JOIN public.lignes_zone_test as line
ON st_intersects(rect.geom, line.the_geom)

Si vous ne l'avez pas déjà fait, vous devriez ajouter un index géométrique
sur l'une de vos deux tables (typiquement celles qui contient le plus
grand nombre de ligne), cela accélérera probablement le temps de traitement.

Mais je ne suis pas sur que cela soit le résultat que vous attendiez,
supposez un polygone traversé par plusieurs lignes,
chaque découpage se déroulera indépendamment avec toujours le polygone orignal en entier.
Pour dĂ©couper avec une multi ligne, il vous  faudrait passer Ă  postgis 2.5

Dernière modification par tumasgiu (Mon 13 May 2019 13:55)

Hors ligne

 

#3 Thu 16 May 2019 17:23

zack
Participant occasionnel
Date d'inscription: 16 Jul 2014
Messages: 33

Re: POSTGIS - Découper polygones par des lignes

Bonjour,

Merci pour cette rĂ©ponse. J'ai installĂ© PostgreSQL 10 et Postgis 2.5.2 en local (windows 10) pour faire des tests avant d'upgrader le PostgreSQL de mon serveur Debian. Le code que vous donnez ne donne pas d'erreur, mĂȘme avec du multi-linestring.
Le nombre de polygones en sortie semble cohĂ©rent, et visuellement, les polygones apparaissent dĂ©coupĂ©s Ă  certains emplacements de lignes mais pas Ă  tous. Certains polygones ont disparu. Mais lorsque j'essaye de faire une sĂ©lection d'un polygone, il me sĂ©lectionne le mĂȘme grand ensemble qu'avant la dĂ©coupe. Et je ne peux faire aucune modification, mĂȘme suppression de polygone, QGIS indique que le fournisseur de donnĂ©es ne gĂšre pas l'effacement des entitĂ©s.

Peut-ĂȘtre que passer par une commande postgis n'est pas la solution Ă  mon problĂšme...

Hors ligne

 

#4 Thu 16 May 2019 17:59

tumasgiu
Membre
Lieu: Ajaccio
Date d'inscription: 5 Jul 2010
Messages: 1226

Re: POSTGIS - Découper polygones par des lignes

Les polygones ayant disparus sont certainement ceux n'intersectant avec
aucune ligne.

Je crois comprendre à quel résultat vous voulez aboutir, il faudrait changer
un peu la requĂȘte :

Code:

SELECT 
    st_collectionextract(
        st_split(rect.geom,
                coalesce(ST_CollectionHomogenize(st_collect(line.the_geom))), 
                    'LINESTRING EMPTY'::geometry('LINESTRING')),
        3) AS geom
FROM
    polygones_zone_test as rect
LEFT JOIN
    public.lignes_zone_test as line
ON 
    st_intersects(rect.geom, line.the_geom)
GROUP BY
    rect.geom

L'idée est de regrouper, pour chaque polygone,
toutes les LINESTRING qui le traverse en une seule MULTILINESTRING
et d'appeler st_split avec celle ci.

Les polygones qui ne sont traversés par aucune ligne
sont quand mĂȘme renvoyĂ©es grĂące au LEFT JOIN,
et on transforme la MULTILINESTRING NULL qui leur sont associée
par une LINESTRING vide, pour que le st_split fonctionne et
renvoie le polygone tel quel.

Dernière modification par tumasgiu (Thu 16 May 2019 18:04)

Hors ligne

 

#5 Thu 16 May 2019 18:01

tumasgiu
Membre
Lieu: Ajaccio
Date d'inscription: 5 Jul 2010
Messages: 1226

Re: POSTGIS - Découper polygones par des lignes

Le fait que vous ne puissiez faire aucune modification via QGIS vient du fait
que celui ci ne permet de modification qui si une clef primaire est présente
dans la table.

Hors ligne

 

#6 Wed 22 May 2019 17:47

zack
Participant occasionnel
Date d'inscription: 16 Jul 2014
Messages: 33

Re: POSTGIS - Découper polygones par des lignes

Bonjour,

Merci pour votre réponse. Je n'ai pas eu de notification Georezo donc je ne l'avais pas vu jusqu'à aujourd'hui... désolé...
J'ai donc testé votre code.

Code:

DROP TABLE if exists blabla;
CREATE TABLE blabla AS
SELECT 
    st_collectionextract(
        st_split(rect.geom,
                coalesce((ST_CollectionHomogenize(st_collect(line.geom))), 
                    'LINESTRING EMPTY'::geometry('LINESTRING'))),
        3) AS geom
FROM
    polygones_zone_test as rect
LEFT JOIN
    public.lignes_zone_test as line
ON 
    st_intersects(rect.geom, line.geom)
GROUP BY
    rect.geom

J'ai ajouté des parenthÚses dans la condition COALESCE puisque que le st_split avait trois conditions de géométrie ce qui ne lui plaisait pas, je ne sais pas si cette correction est bien juste mais il me semble que oui.
Il ne pose plus de problĂšme sur le st_split, mais il me dit que le SRID n'est pas le mĂȘme sur les deux couches (ERROR:  ERREUR:  Operation on mixed SRID geometries) alors que j'ai fait un st_srid et j'ai bien 2154 sur les deux couches... est-ce qu'une fonction prĂ©alable modifie le SRID?

Merci du temps consacré à me répondre !

Hors ligne

 

#7 Wed 22 May 2019 18:01

tumasgiu
Membre
Lieu: Ajaccio
Date d'inscription: 5 Jul 2010
Messages: 1226

Re: POSTGIS - Découper polygones par des lignes

Non je pense que le problĂšme vient du second argument de la fonction coalesce.

Pour rappel coalesce renvoie son premier argument si il est different de NULL
et son second argument sinon.

Donc dans le cas ou aucune ligne n'intersecte avec une zone,
la requĂȘte va tenter de faire un split avec une linestring vide.
Hors votre zone est en EPSG:2154, alors que la linestring vide
n'a pas de SRID défini.

Pour remédier à cela, changer la chaine "LINESTRING EMPTY"::Geometry('LINESTRING'),
par "SRID=2154;LINESTRING EMPTY"::Geometry('LINESTRING', 2154).

Dernière modification par tumasgiu (Wed 22 May 2019 18:02)

Hors ligne

 

#8 Wed 22 May 2019 18:07

zack
Participant occasionnel
Date d'inscription: 16 Jul 2014
Messages: 33

Re: POSTGIS - Découper polygones par des lignes

Rebonjour,
Merci j'avais solutionné ce problÚme en faisant un setSRID sur le coalesce mais votre solution marche aussi.
Du coup la fonction marche, je conserve bien tous les polygones, et ils sont, d'apparence, bien découpés aux emplacements des lignes.
En revanche, j'ai toujours le mĂȘme nombre de polygones que sur la couche initiale. Il me crĂ©e des polygones multi-part.
Je peux solutionner ça en Ă©clatant ensuite mes polygones en single part mais peut-ĂȘtre y a t'il une solution sur le code d'origine.

Un grand merci !

Hors ligne

 

#9 Wed 22 May 2019 22:46

tumasgiu
Membre
Lieu: Ajaccio
Date d'inscription: 5 Jul 2010
Messages: 1226

Re: POSTGIS - Découper polygones par des lignes

Pas Ă  ma connaissance, je pense qu'il faut que vous les eclatiez
Ă  l'aide st_dump.

De rien pour l'aide.

Hors ligne

 

#10 Thu 23 May 2019 15:07

zack
Participant occasionnel
Date d'inscription: 16 Jul 2014
Messages: 33

Re: POSTGIS - Découper polygones par des lignes

Bonjour,
J'ai encore un petit message d'erreur que je n'avais pas sur ma petite zone de test...

ERROR:  ERREUR:  GEOSUnion: TopologyException: found non-noded intersection

Il s'agit d'endroits ou j'ai des lignes qui se croisent, ce qui est rare mais qui peut arriver.
J'ai essayĂ© d'utiliser st_makevalid, d'aprĂšs ce que j'ai pu trouver comme info sur les diffĂ©rents forums, en le plaçant Ă  divers endroits du code, mais il me renvoie toujours la mĂȘme erreur.
De ce que je comprend, il suffirait de crĂ©er des nƓuds aux croisements des lignes pour avoir une topologie valide?

Hors ligne

 

#11 Thu 23 May 2019 17:02

tumasgiu
Membre
Lieu: Ajaccio
Date d'inscription: 5 Jul 2010
Messages: 1226

Re: POSTGIS - Découper polygones par des lignes

Est ce que la requĂȘte suivante fonctionne ?

Code:

select st_split(
       'POLYGON((0 0, 0 1, 1 1, 1 0, 0 0))',
       'MULTILINESTRING((-1 -1, 2 2), (2 -1,  -1 2))'
       )
;

Hors ligne

 

#12 Thu 23 May 2019 17:05

zack
Participant occasionnel
Date d'inscription: 16 Jul 2014
Messages: 33

Re: POSTGIS - Découper polygones par des lignes

Oui, sans problĂšme

Hors ligne

 

#13 Thu 23 May 2019 17:20

tumasgiu
Membre
Lieu: Ajaccio
Date d'inscription: 5 Jul 2010
Messages: 1226

Re: POSTGIS - Découper polygones par des lignes

Donc, st_split sait gérer une multiligne qui a deux élements se croisant.

Je pencherais plus pour un problÚme de coordonnée trop proches.
Vous pouvez essayer de régler le problÚme avec st_snaptogrid.

Avant il faudrait isoler la paritĂ© de la requĂȘte qui coince,
le st_intersects ou le st_split...

Hors ligne

 

#14 Thu 23 May 2019 17:59

zack
Participant occasionnel
Date d'inscription: 16 Jul 2014
Messages: 33

Re: POSTGIS - Découper polygones par des lignes

Merci !

J'ai donc rajouté un st_snaptogrid sur la partie lignes de la fonction st_split. Je l'ai mis un peu arbitrairement je l'avoue, ne sachant pas trop ce que ça donnerait. Et ça marche bien. Le paramÚtre de 0.0001 est parfaitement arbitraire également.

Code:

DROP TABLE if exists blabla;
CREATE TABLE blabla AS
SELECT 
    st_collectionextract(
        st_split(rect.geom,
                st_snaptogrid(coalesce((ST_CollectionHomogenize(st_collect(st_makevalid(line.geom)))), 
                    'SRID=2154;LINESTRING EMPTY'::geometry('LINESTRING')),0.0001)),
        3) AS geom
FROM
    public.polygones as rect
LEFT JOIN
    public.lignes as line
ON 
    st_intersects(rect.geom, line.geom)
GROUP BY
    rect.geom

Hors ligne

 

Pied de page des forums

Copyright Association GeoRezo