#1 Tue 24 January 2023 19:40
- Geo
- Participant occasionnel
- Lieu: Liège (Belgique)
- Date d'inscription: 18 Sep 2007
- Messages: 27
[PostGIS] - Identification microlignes dans polygones
Bonjour,
Je dispose d’une table de polygone [z_pop] dans une BD PostGIS. Les géométries des polygones peuvent contenir des artefacts sous forme de microlignes dues à des erreurs de numérisation ou de groupement.
Je cherche à identifier les polygones présentant ces erreurs, en récupérant l’identifiant [agr_id] du polygone et, si possible, la géométrie de la microligne concernée ou des vertex constitutifs. L'identification suffit. Je ne cherche pas à solutionner les problèmes topologiques qui feront l’objet d’une révision manuelle.
Vous trouverez un jeu de données test [z_pop] postgis en attaché, avec 3 polygones présentant des artefacts. Cette table peut être restaurée dans le schéma Public. Je joins également une image du problème.
Voici les traitements que j'ai réalisé pour l'instant.
1. Générer une sortie qui présente les vertex via [ST_DumpPoints] se trouvant complétement inclus dans leur polygone d’appartenance
Code:
WITH cte_1 as ( SELECT agr_id, (ST_DumpPoints(geom)).geom AS pt FROM z_pop), geom_envelop AS ( SELECT agr_id as id_pol, geom AS geom_ext FROM z_pop) SELECT row_number() over w as gid, pt FROM geom_envelop JOIN cte_1 ON ST_WITHIN (geom_ext, pt) WINDOW w AS (ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW)
Cette méthode ne marche pas car il faudrait récupérer les polygones sans les microlignes. Or, un simple dump sur les polygones ne renvoie qu'une seule géométrie [Polygone] et ne permet pas d'identifier les vertex totalement compris dans l’aire d’intérêt.
2. J'ai réalisé la méthodologie suivante
Code:
--1. Explosion des polygones en tronçons WITH geom_transf AS ( SELECT agr_id, ST_MakeLine(lag((pt).geom, 1, NULL) OVER (PARTITION BY agr_id ORDER BY agr_id, (pt).path), (pt).geom) AS geom_line FROM (SELECT agr_id, ST_DumpPoints(geom) AS pt FROM z_pop) as dumps ), --2. Génération de l’enveloppe externe des polygones geom_envelop AS ( SELECT agr_id as id_pol, ST_EXTERIORRING((st_dump(z_pop.geom)).geom) AS geom_ext FROM z_pop ) -- 3. Croisement du résultat de 1) et du résultat de 2) afin d’individualiser les lignes qui ne s’intersectent pas avec l’enveloppe extérieure. SELECT row_number() over w as gid, geom_line as geom_line_erreur FROM geom_envelop JOIN geom_transf ON NOT st_intersects(geom_ext, geom_line) AND agr_id=id_pol WINDOW w AS (ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW)
Certaines lignes, mais pas toutes, sont identifiées. Le résultat est donc assez moyen.
En suivant cette voie, il faudrait réaliser un [ST_EXTERIORRING] puis une opération de reconstitution des polygones [ST_Polygonize] mais je crains un traitement trop lourd (environ 65.000 polygones dans le jeu de données)
Quelqu’un aurait-il une méthode plus efficace et moins couteuse ou aurait déjà réalisé un traitement similaire ?
Merci d'avance
Dernière modification par Geo (Wed 25 January 2023 08:39)
Hors ligne
#2 Wed 25 January 2023 16:48
- tumasgiu
- Membre
- Lieu: Ajaccio
- Date d'inscription: 5 Jul 2010
- Messages: 1146
Re: [PostGIS] - Identification microlignes dans polygones
Bonjour,
avez-vous essayer d'utiliset st_simplify, ST_SimplifyVW et ST_SimplifyPreserveTopology ?
Si la précision des coordonnées de vos polgyones ne vous importe pas trop, cela peut-être vous apporter un résultat satisfaisant.
Hors ligne
#3 Mon 06 February 2023 12:39
- Geo
- Participant occasionnel
- Lieu: Liège (Belgique)
- Date d'inscription: 18 Sep 2007
- Messages: 27
Re: [PostGIS] - Identification microlignes dans polygones
Bonjour,
J'ai repris le traitement, qui n'avait pas donné de résultats séduisants. J'ai testé en simplifiant les polygones mais ça n'améliore pas la sortie.
J'ai donc opté pour une requête qui identifie le nombre de vertex superposés, en faisant les hypothèses suivantes:
- que les erreurs topologiques indiquées dans mon premier post devaient disposer d'un nombre de vertex superposés supérieur à 1
- que le dernier vertex du polygone = premier vertex, et donc le premier point peut être ignoré
Par ce biais, les erreur sont identifiées et ce sous la forme des vertex dupliqués. Néanmoins, des exceptions apparaissent à certains endroits de la couche de données.
Pour établir les correspondances, je me base sur les coordonnées de vertex arrondies à deux chiffres.
Voici le code de la requête
Code:
CREATE TABLE d_vertice_overlap as WITH cte_dump AS ( SELECT agr_id, (st_dumppoints(geom)).* FROM z_pop ) , cte_pt_inter as ( SELECT agr_id, round(st_x(geom)::numeric,2) as x, round(st_y(geom)::numeric,2) as y, geom FROM cte_dump WHERE path[1]=1 -- Prendre le premier polygone si multipart AND path[3] > 1 --Ne pas considérer le premier point ), cte_ct as ( SELECT agr_id, x, y, count(*) over (partition by agr_id, x, y) as num_pt_overlap, geom FROM cte_pt_inter ) SELECT row_number() over (order by agr_id, x,y) as id, agr_id, x, y, num_pt_overlap, NULL::boolean as excepcion, geom FROM cte_ct WHERE num_pt_overlap>1 ORDER BY 2,3; ALTER TABLE d_vertice_overlap ADD CONSTRAINT id_pk PRIMARY KEY (id)
Malgré tout, je reste à l'écoute d'une meilleure option, si quelqu'un a déjà fait face à ce type de problématique
Bonne journée
Dernière modification par Geo (Mon 06 February 2023 17:36)
Hors ligne
#4 Mon 06 February 2023 12:54
- Nicolas Ribot
- Membre
- Lieu: Toulouse
- Date d'inscription: 9 Sep 2005
- Messages: 1542
Re: [PostGIS] - Identification microlignes dans polygones
d
Dernière modification par Nicolas Ribot (Mon 06 February 2023 12:56)
Hors ligne