#1 Wed 04 October 2017 15:22
- fassa222
- Participant occasionnel
- Date d'inscription: 18 Jan 2012
- Messages: 36
découper une seule ligne en plusieurs
Bonjour,
J'ai une couche ligne qui est composée d'une seule entité (comme en faisant un st_union de plusieurs lignes pour en former une seule) et une couche points qui est composée de plusieurs entités. Mon objectif est de découper cette une seule ligne en plusieurs tout en se basant sur la couche point. Au final je souhaite avoir plusieurs lignes dont leur extrémités sont en intersection avec les entités de la couche point. C'est à dire que chaque ligne découpée doit être compris entre deux points de la couche point.
Merci de votre aide
CDT.
Hors ligne
#2 Wed 04 October 2017 15:35
- meonais
- Participant occasionnel
- Date d'inscription: 17 Jan 2017
- Messages: 35
Re: découper une seule ligne en plusieurs
Bonjour,
J'ai résolu le même type de problématique (probablement pas vraiment optimisé mais ça fonctionne) ici : https://georezo.net/forum/viewtopic.php?id=104853, post n°7
A bientôt
Hors ligne
#3 Wed 04 October 2017 16:23
- fassa222
- Participant occasionnel
- Date d'inscription: 18 Jan 2012
- Messages: 36
Re: découper une seule ligne en plusieurs
Bonjour,
J'ai résolu le même type de problématique (probablement pas vraiment optimisé mais ça fonctionne) ici : https://georezo.net/forum/viewtopic.php?id=104853, post n°7
A bientôt
Bonjour Meonais,
J'ai essayé votre solution mais aparement ça marche que pour les lignes ayant plusieurs entités alors que moi je pars du principe que ma couche ligne est composée d'une seule entité. J'essaiyé de partir à une couche d'une seule entité mais j'ai un problème de validé de la couche ligne avec cette erreur "line_locate_point: 1st arg isn't a line" que j'ai essaiyé de corrigé avec un st_linemerge mais çà fonction pas
Hors ligne
#4 Wed 04 October 2017 16:30
- fassa222
- Participant occasionnel
- Date d'inscription: 18 Jan 2012
- Messages: 36
Re: découper une seule ligne en plusieurs
Bonjour Meonais,
J'ai essayé votre solution mais aparement ça marche que pour les lignes ayant plusieurs entités alors que moi je pars du principe que ma couche ligne est composée d'une seule entité. J'essaiyé de partir à une couche d'une seule entité mais j'ai un problème de validé de la couche ligne avec cette erreur "line_locate_point: 1st arg isn't a line" que j'ai essaiyé de corrigé avec un st_linemerge mais çà fonction pas
Hors ligne
#5 Wed 04 October 2017 16:36
- meonais
- Participant occasionnel
- Date d'inscription: 17 Jan 2017
- Messages: 35
Re: découper une seule ligne en plusieurs
Bonjour,
De mémoire il faut que ce soit des linestring et pas des multilignes
Ça vient peut être de là ?
Mes lignes ont plusieurs entités mais je les regroupe (si je ne me suis pas trompée) en une seule, justement parce que j'avais besoin de délimiter les tronçons résultants par les points (ou les extrémités de lignes), et ne pas avoir plusieurs tronçons entre deux points.
Hors ligne
#6 Wed 04 October 2017 17:28
- fassa222
- Participant occasionnel
- Date d'inscription: 18 Jan 2012
- Messages: 36
Re: découper une seule ligne en plusieurs
ma couche ligne est en linestring et c'est une seule entité, donc j'ai appliqué le code mais il y a un problème au niveau du calcul des positions
Hors ligne
#7 Wed 04 October 2017 17:40
- meonais
- Participant occasionnel
- Date d'inscription: 17 Jan 2017
- Messages: 35
Re: découper une seule ligne en plusieurs
Désolée, mais de mémoire et d'après votre message d'erreur, c'est la fonction st_linelocatepoint() qui ne trouve pas les éléments "à manger correctement ou suffisamment bons" ;-)
Sans plus d'infos sur vos données que je pourrais essayer de comparer aux miennes, je ne vois pas ce que ça peut être d'autre
Je ne vois pas non plus pourquoi cette requête ne fonctionnerait pas sur une seule ligne si elle fonctionne sur plusieurs :
si j'ai bien suivi le code, elle identifie
- la position du début de la ligne (== crée un point avec la valeur 0 pour la position du point sur la ligne),
-celle de la fin (== crée un autre point avec la valeur 1 pour la position du point sur la ligne = le max possible)
- chaque position de chaque point de votre couche de points sur votre ligne (entre 0 et 1)
et réunie le tout dans une seule table de points
puis elle les ordonne pour pouvoir appliquer la fonction st_linesubstring() entre les bons couples de points et générer ainsi les tronçons.
Hors ligne
#8 Wed 04 October 2017 18:03
- fassa222
- Participant occasionnel
- Date d'inscription: 18 Jan 2012
- Messages: 36
Re: découper une seule ligne en plusieurs
Bonjour,
je vous joins mes deux couches ainsi que le code sql afin que vous pouvez faire unecomparaison, pour que ca marche pour moi. Des fois j'ai un résultat mais le découpage n'est exact.
CDT
Hors ligne
#9 Wed 04 October 2017 19:11
- meonais
- Participant occasionnel
- Date d'inscription: 17 Jan 2017
- Messages: 35
Re: découper une seule ligne en plusieurs
Je n'arrive pas à charger vos couches dans Postgesql
pourquoi avoir rajouté un round() ?
et enlevé la condition
Code:
AND st_linelocatepoint(l.geom, p.geom) NOT IN (0,1)
?
ce sont les différences que je vois entre mon script que je fais tourner plusieurs fois par jours en ce moment et le votre
Hors ligne
#10 Wed 04 October 2017 19:18
- meonais
- Participant occasionnel
- Date d'inscription: 17 Jan 2017
- Messages: 35
Re: découper une seule ligne en plusieurs
Je viens de réussir à charger vos couches
J'ai décomposé votre code
Je m'arrête aux deux premières étapes car vous générez des GEOMETRY au lieu de LINESTRING ou POINT (d'après la table geometry_columns)
Je débute en Postgres/postgis mais je crois bien que ce n'est pas bon pour ensuite faire tourner les différentes fonctions st() de la suite.
Code:
DROP TABLE IF EXISTS lignes_dumped CASCADE; CREATE TABLE lignes_dumped as ( SELECT row_number() over() as gid , (ST_Dump(geom)).geom as geom ---(ST_Dump(geom)).geom FROM public.lignes l -- multilinestring ); -->>> ca donne une couche GEOMETRY ---Création de la couche de points, snappés sur les lignes CREATE TABLE ptsnapAS as ( SELECT o.gid as id, ST_Closestpoint(ST_Collect(r.geom), o.geom) AS geom FROM public."noeud" o INNER JOIN public."lignes" r ON ST_Dwithin(r.geom, o.geom, 50) GROUP BY o.gid, o.geom) ; -->>> ca donne une couche GEOMETRY locus as ( -- premiere table des positions des points par rapport a "leurs" lignes ---DROP TABLE IF EXISTS locus CASCADE; -- on genere la position du debut de la ligne (index 0) pour le premier segment à découper select l.gid, 0 as l from lignes_dumped l UNION ALL -- on genere la position de la fin de la ligne (index 1) pour le dernier segment à découper select l.gid, 1 as l from lignes_dumped l UNION ALL -- calcul des positions des points par rapport aux lignes select l.gid, round(st_linelocatepoint((l.geom), p.geom)) as l -- il faut LINESTRING from lignes_dumped l, ptsnapAS p where st_dwithin(l.geom, p.geom, 0.01) GROUP BY l.gid, l order by gid, l ), --- deuxieme table qui ajoute un index croissant par position croissante, pour permettre de faire la jointure plus tard sur elle-meme: ---DROP TABLE IF EXISTS loc_with_idx CASCADE; loc_with_idx as ( select gid, l, rank() over (partition by gid order by l) as idx from locus ), --- decoupage final de chaque ligne avec les positions des points sur la ligne, grace a st_line_substring-- ---DROP TABLE IF EXISTS splitang CASCADE; splitang AS ( select l.gid, st_linesubstring(l.geom, loc1.l, loc2.l) as geom from loc_with_idx loc1, loc_with_idx loc2, lignes_dumped l where l.gid = loc1.gid and loc1.gid = loc2.gid and loc2.idx = loc1.idx+1 GROUP BY l.gid, l.geom, loc1.l, loc2.l ) select * from splitang
Hors ligne
#11 Thu 05 October 2017 12:26
- fassa222
- Participant occasionnel
- Date d'inscription: 18 Jan 2012
- Messages: 36
Re: découper une seule ligne en plusieurs
Je n'arrive pas à charger vos couches dans Postgesql
pourquoi avoir rajouté un round() ?
et enlevé la conditionCode:
AND st_linelocatepoint(l.geom, p.geom) NOT IN (0,1)?
ce sont les différences que je vois entre mon script que je fais tourner plusieurs fois par jours en ce moment et le votre
Bonjour Meonais,
Le round il sert à arrondir nos positions, puisse que des fois on a des valeurs décimales. Exemple 0.1111111 qui devient 0 ou 0.9999999 qui devient 1
Hors ligne
#12 Thu 05 October 2017 12:29
- fassa222
- Participant occasionnel
- Date d'inscription: 18 Jan 2012
- Messages: 36
Re: découper une seule ligne en plusieurs
Je viens de réussir à charger vos couches
J'ai décomposé votre code
Je m'arrête aux deux premières étapes car vous générez des GEOMETRY au lieu de LINESTRING ou POINT (d'après la table geometry_columns)
Je débute en Postgres/postgis mais je crois bien que ce n'est pas bon pour ensuite faire tourner les différentes fonctions st() de la suite.Code:
DROP TABLE IF EXISTS lignes_dumped CASCADE; CREATE TABLE lignes_dumped as ( SELECT row_number() over() as gid , (ST_Dump(geom)).geom as geom ---(ST_Dump(geom)).geom FROM public.lignes l -- multilinestring ); -->>> ca donne une couche GEOMETRY ---Création de la couche de points, snappés sur les lignes CREATE TABLE ptsnapAS as ( SELECT o.gid as id, ST_Closestpoint(ST_Collect(r.geom), o.geom) AS geom FROM public."noeud" o INNER JOIN public."lignes" r ON ST_Dwithin(r.geom, o.geom, 50) GROUP BY o.gid, o.geom) ; -->>> ca donne une couche GEOMETRY locus as ( -- premiere table des positions des points par rapport a "leurs" lignes ---DROP TABLE IF EXISTS locus CASCADE; -- on genere la position du debut de la ligne (index 0) pour le premier segment à découper select l.gid, 0 as l from lignes_dumped l UNION ALL -- on genere la position de la fin de la ligne (index 1) pour le dernier segment à découper select l.gid, 1 as l from lignes_dumped l UNION ALL -- calcul des positions des points par rapport aux lignes select l.gid, round(st_linelocatepoint((l.geom), p.geom)) as l -- il faut LINESTRING from lignes_dumped l, ptsnapAS p where st_dwithin(l.geom, p.geom, 0.01) GROUP BY l.gid, l order by gid, l ), --- deuxieme table qui ajoute un index croissant par position croissante, pour permettre de faire la jointure plus tard sur elle-meme: ---DROP TABLE IF EXISTS loc_with_idx CASCADE; loc_with_idx as ( select gid, l, rank() over (partition by gid order by l) as idx from locus ), --- decoupage final de chaque ligne avec les positions des points sur la ligne, grace a st_line_substring-- ---DROP TABLE IF EXISTS splitang CASCADE; splitang AS ( select l.gid, st_linesubstring(l.geom, loc1.l, loc2.l) as geom from loc_with_idx loc1, loc_with_idx loc2, lignes_dumped l where l.gid = loc1.gid and loc1.gid = loc2.gid and loc2.idx = loc1.idx+1 GROUP BY l.gid, l.geom, loc1.l, loc2.l ) select * from splitang
Mes couches sont bien en linestring, donc forcement ils doivent etre appropriées à la catégorie geometry
Hors ligne
#13 Thu 05 October 2017 14:14
- meonais
- Participant occasionnel
- Date d'inscription: 17 Jan 2017
- Messages: 35
Re: découper une seule ligne en plusieurs
Bonjour,
Pour le Round() je ne pense pas que ce soit optimal puisque justement l'idée de st_linelocatepoint() est de donner une valeur de position entre zéro (début de la ligne) et 1 (fin de la ligne) pour chaque point
Donc le début de la ligne = 0 ; le premier point = 0.2 (par exemple), le deuxième = 0.3345, le quatrième = 0.5658 etc. jusqu'au dernier = 1 (fin de la ligne)
Pour la géométrie des couches utilisées, en décomposant votre requête, pour moi vous créez des tables de format GEOMETRY (multi collection je suppose) et non LINESTRING. Voici ce que j'obtiens dans la table geometry_columns en appliquant juste vos deux sous requêtes lines_dumped et ptsnapAS :
Code:
[i]-- vos deux couches en entrée de sous-requête [/i] "lignes";"geom";2;0;"MULTILINESTRING" "noeud";"geom";2;0;"POINT" [i]-- vos deux couches en sortie de sous-requête[/i] "lignes_dumped";"geom";2;0;[b]"GEOMETRY"[/b] "ptsnapas";"geom";2;0;[b]"GEOMETRY"[/b]
Pour moi, la couche ligne doit être en linestring pour pouvoir l'incorporer dans le reste de la requête (locus, loc_with_idx, et split) :
Code:
-- format de ma couche que je découpe "selectcdotrhydromerge";"geom";2;2154;[b]"LINESTRING"[/b]
peut-être utiliser un st_collectionextract() pour ne récupérer que les linestring ?
Hors ligne