Pages: 1
- Sujet précédent - Segmenter multilinestring en fonction d'une distance et création point - Sujet suivant
#1 Tue 27 March 2018 12:27
- bruhnild
- Participant actif
- Lieu: Lyon
- Date d'inscription: 7 Jun 2014
- Messages: 130
Segmenter multilinestring en fonction d'une distance et création point
Bonjour à toutes et à tous,
J’ai une table spatiale d’adresses avec pour chaque entité adresse une géométrie de routes. Ainsi pour un type de voie + nom de voie (ex : avenue habib bourguiba) je vais avoir 20 adresses avec la même géométrie de route.
- 28 avenue habib bourguiba
- 29 avenue habib bourguiba
- 30 avenue habib bourguiba
- 21 avenue habib bourguiba
- …
- 48 avenue habib bourguiba
Connaissant la longueur de chaque route (st_length) et le nombre d’adresses (intervalle) pour chacune d’entre elle, je peux obtenir st_length/intervalle (intervalle_m) soit la distance théorique entre chaque point adresse.
J’aimerais pouvoir segmenter mes lignes (routes) en fonction de intervalle_m et créer un point (adresse) à chaque brisure de lignes. J’ai essayé sous postgis les fonctions St_Segmentize
Code:
(SELECT ST_DumpPoints( (ST_Segmentize((geom),intervale_m -- st_length/intervalle ))) as geom from ban.v_ban_travail_generate_series group by geom, intervale_m )
et St_interpolate_points
Code:
(select id, ST_line_interpolate_point(st_makeline(st_linemerge(geom)),fraction --1/intervalle ) as geom from ban.v_ban_travail_generate_series group by id, fraction)
mais les résultats ne sont pas bons.
Auriez vous une idée de comment procéder ?
Merci d’avance pour vos retours !
Marine.
Dernière modification par bruhnild (Wed 28 March 2018 08:12)
Hors ligne
#2 Wed 28 March 2018 11:23
- tumasgiu
- Membre
- Lieu: Ajaccio
- Date d'inscription: 5 Jul 2010
- Messages: 1160
Re: Segmenter multilinestring en fonction d'une distance et création point
Voici un exemple très simplifié,
l'astuce est d'utiliser la window function lag qui permet de récupérer
la valeur d'une colonne de l''enregistrement précédent.
Code:
with foo as (select 'LINESTRING(0 0, 0 100)'::geometry geom) , points as (select s, st_line_interpolate_point(geom, s / st_length(geom)) p ,geom FROM foo, generate_series(1, 10) s ) SELECT s, st_makeline(coalesce(lag(p) OVER (ORDER BY s), st_startpoint(geom)) , p) m FROM points
Hors ligne
#3 Wed 28 March 2018 16:46
- bruhnild
- Participant actif
- Lieu: Lyon
- Date d'inscription: 7 Jun 2014
- Messages: 130
Re: Segmenter multilinestring en fonction d'une distance et création point
Merci tumasgiu pour l'idée!
J'ai essayé de reproduire ton exemple
Code:
with interpolate as (select id_voie, geom , num_deb_fr, num_fin_fr from ban.v_ban_travail), points as (select id_voie, s, ST_line_interpolate_point(st_makeline(st_linemerge(geom)), s / st_length(geom)) p ,geom FROM interpolate, generate_series(num_deb_fr,num_fin_fr) s group by s.s, interpolate.geom, interpolate.id_voie) SELECT id_voie, s as serie, st_makeline(coalesce(lag(p) OVER (ORDER BY s), st_startpoint(geom)) , p) new_geom FROM points
mais j'ai une erreur de ce type : ERREUR: line_interpolate_point: 2nd arg isn't within [0,1]
Lorsque j'écris des valeurs dans le generate serie j'ai bien un résultat mais il ne correspond pas à ce que je souhaite (voir capture resultat_obtenu)
Code:
with interpolate as (select id_voie, geom , num_deb_fr, num_fin_fr from ban.v_ban_travail), points as (select id_voie, s, ST_line_interpolate_point(st_makeline(st_linemerge(geom)), s / st_length(geom)) p ,geom FROM interpolate, generate_series(1,10) s group by s.s, interpolate.geom, interpolate.id_voie) SELECT id_voie, s as serie, st_makeline(coalesce(lag(p) OVER (ORDER BY s), st_startpoint(geom)) , p) new_geom FROM points
J'ai mis en PJ une capture du résultat attendu.
Dernière modification par bruhnild (Wed 28 March 2018 16:51)
Hors ligne
#4 Thu 29 March 2018 18:32
- Nicolas Ribot
- Membre
- Lieu: Toulouse
- Date d'inscription: 9 Sep 2005
- Messages: 1554
Re: Segmenter multilinestring en fonction d'une distance et création point
Bonjour,
Si je comprends bien, vous voulez a la fois segmenter les lignes et créer des points d'adresse ?
Pour la génération des points d'adresse, pas besoin de la longueur de la route: les fonctions de référencement linéaire se basent sur une fraction de la longueur de la ligne, entre 0 (debut) et 1 (fin de la ligne). Comme vous disposez des numéros d'adresse de debut et de fin, vous pouvez calculer le nombre d'adresses de chaque route. (dans votre exemple, 43 points d'adresse)
Il faut alors découper la route par autant de points d'adresse avec st_lineInterpolatePoint(route, fraction):
Code:
WITH tmp AS ( SELECT id_voie, num_fin - num_debut AS num_add, geom FROM route ), tmp1 AS ( SELECT t.*, g, g / num_add :: FLOAT AS fraction FROM tmp t CROSS JOIN generate_series(0, num_add) AS g ) select id_voie, g as num_add, st_lineinterpolatepoint(geom, fraction) as geom_add from tmp1;
Requete à ajuster si on veut mapper les adresses aux extrémités de la route: adresses aux fractions 0 et 1 de la ligne (startPoint et endPoint de la route)
Pour segmenter la route, la méthode de tumasgiu est smart (pas besoin de faire un croisement sur la meme table), mais attention: dans l'exemple, la ligne n'est découpée que sur 10% de sa longueur:
Avec st_lineInterpolatePoint, si on veut découper une geom en n morceaux, il faut générer les valeurs: 0/n, 1/n, 2/n ... n/n pour découper entre 0 et 1.
Nico
Hors ligne
#5 Sun 01 April 2018 17:43
- bruhnild
- Participant actif
- Lieu: Lyon
- Date d'inscription: 7 Jun 2014
- Messages: 130
Re: Segmenter multilinestring en fonction d'une distance et création point
Bonjour,
Merci beaucoup pour votre aide, j'ai pu terminer ma requête. Je suis sure qu'elle est simplifiable mais elle répond aux besoins. Certaines adresses ne commencent pas à systématiquement à 1. J'ai du faire une jointure sur le gid pour pouvoir retrouver mes bons numéros d'adresses:
Code:
CREATE OR REPLACE VIEW ban.v_ban AS SELECT a.gid, concat(b.num_voi_fr,'_',b.suffixe_fr,'_',b.nom_imm_fr,'_',b.typ_voi_fr,'_',b.nom_voi_fr,'_',b.ville_fr,'_',b.cd_post_fr)::varchar as id, b.id_voie, b.typ_voi_fr, b.typ_voi_ar, b.nom_voi_fr, b.nom_voi_ar, b.num_voi_fr, b.num_voi_ar, b.suffixe_fr, b.suffixe_ar, b.nom_imm_fr, b.nom_imm_ar, b.cd_post_fr, b.cd_post_ar, b.ville_fr,b.ville_ar, b.pays_fr, b.pays_ar, b.cd_tour_fr, b.cd_tour_ar, b.ctr_rat_fr, b.ctr_rat_ar, b.nb_pro_fr, b.nb_pro_ar, b.nb_ind_fr, b.nb_ind_ar, b.nb_tot_af, b.nb_tot_ar, b.source, b.dat_maj, b.geonyme, a.geom FROM (SELECT gid, id_voie, typ_voi_fr, nom_voi_fr, num_voi_fr+1 as num_voi_fr, geom_add as geom FROM (WITH num_voi AS ( SELECT id_voie, typ_voi_fr, nom_voi_fr, num_fin_fr - num_deb_fr AS num_voi_fr, geom FROM ban.v_ban_travail ), genere_add AS ( SELECT t.*, g, g / num_voi_fr :: FLOAT AS fraction FROM num_voi t CROSS JOIN generate_series(0, num_voi_fr) AS g ) select row_number() over() AS gid, id_voie, typ_voi_fr,nom_voi_fr,g as num_voi_fr, st_lineinterpolatepoint(ST_LineMerge(geom), fraction) as geom_add from genere_add)a)a LEFT JOIN ( SELECT row_number() over() AS gid, * FROM (SELECT id_voie, typ_voi_fr, typ_voi_ar, nom_voi_fr, nom_voi_ar, generate_series(num_deb_fr,num_fin_fr)as num_voi_fr,null::int as num_voi_ar, suffixe_fr, suffixe_ar, nom_imm_fr, nom_imm_ar, cd_post_fr, cd_post_ar, ville_fr,ville_ar, pays_fr, pays_ar, cd_tour_fr, cd_tour_ar, ctr_rat_fr, ctr_rat_ar, nb_pro_fr, nb_pro_ar, nb_ind_fr, nb_ind_ar, nb_tot_af, nb_tot_ar, source, dat_maj, geonyme, geom from ban.v_ban_travail)a)b ON a.gid=b.gid ;
Je travaille sur une base de route avec beaucoup d'erreurs dans les noms d'adresses et je me retrouve fréquemment avec des bouts de tronçons portant le même nom à des endroits différents d'une unité administrative. J'ai du corriger quelques routes afin d'aller au bout de mes tests, sinon j'obtenais cette erreur: ERREUR: line_interpolate_point: 1st arg isn't a line
Hors ligne
Pages: 1
- Sujet précédent - Segmenter multilinestring en fonction d'une distance et création point - Sujet suivant