#1 Thu 22 February 2018 23:34
- Blue Monkey
- Participant occasionnel
- Date d'inscription: 9 Dec 2016
- Messages: 23
[PostGIS] erreurs de dimensions avec ST_MakeValid()
Bonjour.
Pour PostgreSQL 9.5 et PostGIS 2.2.
J'ai diverses tables contenant des données avec dans chacune une colonne de géométrie de type Multipolygone.
Ces données ont été récupérées sur internet et concernent des zonages de type risque inondation, zones naturelles protégées, etc ..
Suite à des difficultés en tentant de les fusionner, je me suis rendu compte que les géométries de certains enregistrements ne sont pas valides (résultat de ST_IsValid() faux).
J'ai donc entrepris de corriger ces géométries avec ST_MakeValid() (exemple pour une table) :
Code:
UPDATE schema.table SET geom = ST_MakeValid(geom) WHERE NOT ST_IsValid(geom);
Mais j'ai eu l'erreur suivante :
Code:
ERROR: Column has M dimension but geometry does not État SQL :22023
J'avais pourtant préalablement vérifié le nombre de dimensions des géométries :
Code:
SELECT count(gid), ST_Dimension(geom) FROM schema.table GROUP BY ST_Dimension(geom)
Et les géométries de tous les enregistrements de la table avaient bien toutes 2 dimensions.
Finalement, ce qui a marché est :
Code:
UPDATE schema.table SET geom = ST_Force4D(ST_MakeValid(geom)) WHERE NOT ST_IsValid(geom);
Donc si je comprends bien, je dois forcer en 4D le résultat de ST_MakeValid() parce que celui-ci est en 2D et que le type de la colonne attend du 4D. Pourtant la requête avec ST_Dimension m'indique que tous les enregistrements présents sont en 2D !?
J'ai eu ce même problème sur diverses tables, toutes de données récupérées sur le web, mais parfois c'est ST_Force2D ou ST_Force3D que j'ai dû exécuter, suivant la table.
D'abord, j'aimerais bien comprendre ce qui se passe.
Ensuite, il me reste toutefois une paire d'erreurs où ST_MakeValid renvoie visiblement une géométrie de type GeometryCollection. Du coup, pour mettre ça dans une colonne de type geometry (Multipolygon), ça ne passe pas.
PS: j'ai aussi un fil sur Stack Overflow sur ce sujet.
Hors ligne
#2 Fri 23 February 2018 00:12
- tumasgiu
- Membre
- Lieu: Ajaccio
- Date d'inscription: 5 Jul 2010
- Messages: 1160
Re: [PostGIS] erreurs de dimensions avec ST_MakeValid()
Salut,
vous confondez la fonction st_dimensions avec la fonction st_ndims.
Le terme de dimension peut s'appliquer à l'espace dans laquelle sont décrites les géométries,
ou bien à la géométrie elle même, mais son sens n'est pas le même.
St_MakeValid ne gére la dimension M, et c'est pour cela que vous devez forcer le passage
pour mettre à jour votre colonne.
J'ai également répondu sur StackOverflow.
Dernière modification par tumasgiu (Fri 23 February 2018 00:40)
En ligne
#3 Fri 23 February 2018 01:06
- tumasgiu
- Membre
- Lieu: Ajaccio
- Date d'inscription: 5 Jul 2010
- Messages: 1160
Re: [PostGIS] erreurs de dimensions avec ST_MakeValid()
Pour la seconde partie de la question,
vous pouvez rajouter une condition dans votre update pour éviter
les cas problématiques.
Vous pouvez essayer ST_CollectionHomogenize
au cas ou les geometrycollections soient exclusivement composés de polygones,
sinon il faudra passer par une sous requête pour filtrer les composants de la collection.
En ligne
#4 Fri 23 February 2018 09:18
- Nicolas Ribot
- Membre
- Lieu: Toulouse
- Date d'inscription: 9 Sep 2005
- Messages: 1554
Re: [PostGIS] erreurs de dimensions avec ST_MakeValid()
Un st_collectionExtract(geom, num) permet de sortir les pt, lignes ou pg d'une collection avant update.
Code:
st_multi(st_collectionExtract(st_makeValid(geom), 3));
Nico
Hors ligne
#5 Fri 23 February 2018 09:19
- Blue Monkey
- Participant occasionnel
- Date d'inscription: 9 Dec 2016
- Messages: 23
Re: [PostGIS] erreurs de dimensions avec ST_MakeValid()
Bonjour et merci pour vos réponses.
ST_CollectionHomogenize ne fonctionne pas. En effet ST_GeometryType(ST_CollectionHomogenize(ST_MakeValid(geom))) me renvoie la valeur ST_GeometryCollection .
Je regarde de quoi sont composés les éléments de cette collection :
Code:
SELECT ST_IsValidReason(geom), ST_GeometryType(geom), ST_GeometryType(ST_Multi(geom)), ST_IsValidReason(ST_Multi(geom)) FROM ( SELECT (ST_Dump(geom)).geom FROM donnees.conservatoire_espaces_naturels WHERE NOT ST_IsValid(geom) AND ST_GeometryType(ST_MakeValid(geom))='ST_GeometryCollection' ) AS dumpedGeom ;
Ceci me renvoie que la collection contient un unique ST_Polygon. Je me suis dit que je devais pouvoir le transformer en multipolygone avec ST_Multi , ce qui fonctionne (appel de ST_GeometryType(ST_Multi(geom)), ST_IsValidReason(ST_Multi(geom))), mais ce multipolygone est à nouveau non-valide (je soupçonne que ce soit le même multipolygone qu'à l'origine).
Pour les histoires de dimension, si je comprends bien : ST_Dimension renvoie la dimension inhérente, c'est-à-dire que un polygone sera toujours en 2 dimensions, même s'il a des coordonnées x,y,z, auquel cas ST_NDims renvoie 3. Correct ?
Dernière modification par Blue Monkey (Fri 23 February 2018 09:20)
Hors ligne
#6 Fri 23 February 2018 09:28
- Blue Monkey
- Participant occasionnel
- Date d'inscription: 9 Dec 2016
- Messages: 23
Re: [PostGIS] erreurs de dimensions avec ST_MakeValid()
J'ai trouvé !
Le problème fondamental est que ST_MakeValid renvoie une GeometryCollection qui est valide, mais qui contient un unique ST_Polygon qui lui ne l'est pas (Self-Intersection).
J'ai testé diverses transformations, et entre autres, j'ai lu quelque part que en cas de Self-Intersection de polygone, il était possible de faire appel à ST_Buffer pour éliminer ce problème.
A titre de test, j'ai donc utilisé :
Code:
SELECT ST_IsValidReason(geom), ST_GeometryType(geom), ST_GeometryType(ST_Multi(geom)), ST_IsValidReason(ST_Multi(geom)), ST_IsValidReason(ST_MakeValid(geom)), ST_GeometryType(ST_MakeValid(geom)), ST_IsValidReason(ST_Multi(ST_MakeValid(geom))), ST_GeometryType(ST_Multi(ST_MakeValid(geom))), ST_IsValidReason(ST_Buffer(geom, 0.1)), ST_GeometryType(ST_Buffer(geom, 0.1)), ST_IsValidReason(ST_Multi(ST_Buffer(geom, 0.01))), ST_GeometryType(ST_Multi(ST_Buffer(geom, 0.01))) FROM ( SELECT (ST_Dump(geom)).geom FROM donnees.conservatoire_espaces_naturels WHERE NOT ST_IsValid(geom) AND ST_GeometryType(ST_MakeValid(geom))='ST_GeometryCollection' ) AS dumpedGeom ;
Et ST_Multi(ST_Buffer(geom, 0.01)) me renvoie donc une géométrie valide de type ST_Multipolygone. Certes, ce n'est plus exactement la même géométrie qu'avant, mais un buffer de 1 cm, c'est acceptable !
Dernière modification par Blue Monkey (Fri 23 February 2018 09:32)
Hors ligne
#7 Fri 23 February 2018 09:34
- tumasgiu
- Membre
- Lieu: Ajaccio
- Date d'inscription: 5 Jul 2010
- Messages: 1160
Re: [PostGIS] erreurs de dimensions avec ST_MakeValid()
Ceci me renvoie que la collection contient un unique ST_Polygon. Je me suis dit que je devais pouvoir le transformer en multipolygone avec ST_Multi , ce qui fonctionne (appel de ST_GeometryType(ST_Multi(geom)), ST_IsValidReason(ST_Multi(geom))), mais ce multipolygone est à nouveau non-valide (je soupçonne que ce soit le même multipolygone qu'à l'origine).
Ce polygone est certainement ce qu'on appelle dans le jargon un polygone papillon, ou polygonus farfalis,
qui a une intersection avec lui même.
Pour les histoires de dimension, si je comprends bien : ST_Dimension renvoie la dimension inhérente, c'est-à-dire que un polygone sera toujours en 2 dimensions, même s'il a des coordonnées x,y,z, auquel cas ST_NDims renvoie 3. Correct ?
Faites le test vous même :
Code:
SELECT st_ndims(geom) = 4 , st_dimension(geom) = 2 FROM ( select 'POLYGON((0 0 0 0, 1 0 1 1, 0.5 1 1 1, 0 0 0 0))'::geometry geom) foo
Dernière modification par tumasgiu (Fri 23 February 2018 13:55)
En ligne