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

Rencontres QGIS 2025

L'appel à participation est ouvert jusqu'au 19 janvier 2025!

#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é !  big_smile

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()

Blue Monkey a écrit:

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.

Blue Monkey a écrit:

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

 

Pied de page des forums

Powered by FluxBB