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é ?

#1 Fri 09 November 2018 08:49

ENTECH
Participant occasionnel
Date d'inscription: 5 Oct 2018
Messages: 15

Couper une ligne à partir de points non positionnés sur la ligne

Bonjour,

Sur mon projet QGis, j'ai une ligne (conduite) qui représente la distribution AEP et autour de cette conduite, j'ai plusieurs points qui symbolisent les branchements particuliers. Ces points ne sont pas sur la conduite AEP.

J'aimerais savoir s'il est possible de créer une ligne (conduite) entre tous les points de branchements et la conduite principale AEP ? Et deuxièmement si on peut couper la conduite principale et créer un point au croisement de chaque conduite.

Merci pour votre aide.

Hors ligne

 

#2 Fri 09 November 2018 09:28

ChristopheV
Membre
Lieu: Ajaccio
Date d'inscription: 7 Sep 2005
Messages: 3191
Site web

Re: Couper une ligne à partir de points non positionnés sur la ligne

Bonjour,

Pour créer une ligne il faut deux points.

Donc soit vos branchement particuliers sont définis par deux points donc ce que vous cherchez et l'intersection de cette ligne avec la ligne symbolisant la conduite principale, soit vos branchement particuliers sont définis uniquement par un point, donc là il vous faut définir une règle, par exemple la perpendiculaire à la conduite passant par le point "branchement particulier".

Sur un logiciel comme autocad c'est facile. Avec une base de donnée comme postgis c'est un peu plus compliqué.


Christophe
L'avantage d'être une île c'est d'être une terre topologiquement close

Hors ligne

 

#3 Fri 09 November 2018 10:02

Nicolas Ribot
Membre
Lieu: Toulouse
Date d'inscription: 9 Sep 2005
Messages: 1544

Re: Couper une ligne à partir de points non positionnés sur la ligne

Bonjour,

Pour découper rapidement des lignes avec des points, regardez du coté des fn de référencement linéaire (st_lineLocatePoint par ex)
Pour construire une ligne avec des points, ordonnez ces points et appeler st_makeLine.

Sans plus de précision, ou de schéma, pas facile de savoir votre contexte.

Nicolas

Hors ligne

 

#4 Fri 09 November 2018 10:11

ChristopheV
Membre
Lieu: Ajaccio
Date d'inscription: 7 Sep 2005
Messages: 3191
Site web

Re: Couper une ligne à partir de points non positionnés sur la ligne

Bonjour,
Merci Nicolas je les connaissais pas celles là.


Christophe
L'avantage d'être une île c'est d'être une terre topologiquement close

Hors ligne

 

#5 Fri 09 November 2018 10:15

Nicolas Ribot
Membre
Lieu: Toulouse
Date d'inscription: 9 Sep 2005
Messages: 1544

Re: Couper une ligne à partir de points non positionnés sur la ligne

Hello Christophe: joue un peu avec: c'est tres rapide, super précis (abscisse curviligne) et ca permet de faire du calage auto de points sur des lignes ou PG (snapping), car st_lineLocatePoint "projète" le point sur la ligne.

Nicolas

Hors ligne

 

#6 Fri 09 November 2018 10:25

ChristopheV
Membre
Lieu: Ajaccio
Date d'inscription: 7 Sep 2005
Messages: 3191
Site web

Re: Couper une ligne à partir de points non positionnés sur la ligne

Bonjour,

Oui et du coup cela permettrait de régler efficacement des problèmes de cohérence entre deux référentiels topologiques. (problèmes de production avec les arrondis inhérents aux logiciels utilisés pour fabriquer les couches).


Christophe
L'avantage d'être une île c'est d'être une terre topologiquement close

Hors ligne

 

#7 Fri 16 November 2018 19:11

Rlucas
Participant occasionnel
Date d'inscription: 20 Apr 2018
Messages: 31

Re: Couper une ligne à partir de points non positionnés sur la ligne

Bonjour,

Je travaille actuellement sur la correction de bases de données reseau d'eau et d'assainissement. Je suis tombé sur le même type de problème et je ne résiste pas à partager mes recherches et ma requête, pour la projection des points sur la canalisation principales. Je suis parti de cette requête que j'ai adaptée :

Code:

SELECT
st_line_interpolate_point(géométrie de la ligne, st_line_locate_point(géométrie de la ligne, géométrie du point)) AS géométrie projetée,
FROM table des lignes
JOIN  table des points ON st_distance(géométrie de ligne, géométrie du point) < distance_tampon_maximum_pour_l'accrochage

Source : http://blog.martzluff.net/le-map-matchi … stgisqgis/

Pour ne prendre que la projection sur la canalisation la plus proche (et non uniquement celles prises par la distance tampon), il faut utiliser une table intermédiaire avec les fonctions de fenètrage d'agrégats Rank() Over(Partition BY) qui permettent de hiérachiser les valeurs prises par le select en fonction d'un champ (ici la distance à la canalisation).

https://docs.postgresql.fr/8.4/tutorial-window.html
http://www.bortzmeyer.org/postgresql-quantiles.html


J'y ai aussi associé une partie de requête me permettant d'exclure tous les points de piquages déjà présents sur une canalisation (j'ai une table présentant des piquages situés sur la canalisation et d'autres à côté, on ne s'en rend compte qu'en zoomant, merci les dessinateurs autocad...)

J'ai aussi du créer une table dump avec de passer mes géometries en linestring simple au lieu d'une polyline (je n'ai pas trouvé comment l'intégrer dans la requête) avec SELECT (ST_Dump(geom)).geom

Ma requête, à laquelle il faut ensuite appliquer le st_makeline comme recommandé par Nicolas Ribot (et ajuster le select).

Code:

SELECT idappareil, geom, geom_projetee
FROM
(
SELECT
st_distance(canalisation_dump.geom, piquages.geom), 
st_lineinterpolatepoint(canalisation_dump.geom, st_linelocatepoint(canalisation_dump.geom, piquages.geom)) AS geom_projetee, 
piquages.idappareil,
RANK() OVER(PARTITION BY piquages.idappareil ORDER BY st_distance(canalisation_dump.geom, piquages.geom)) as rang
FROM canalisation_dump
JOIN piquages ON st_distance(canalisation_dump.geom, piquages.geom) < distance_tampon
WHERE piquages.idappareil IN (
SELECT 
piquages.idappareil
FROM piquages
EXCEPT
SELECT piquages.idappareil
FROM piquages, canalisations
WHERE ST_Intersects(piquages.geom, canalisations.geom)
GROUP BY piquages.idappareil)
) AS temp
WHERE 
rang = 1 (la distance la plus courte)

Bon après la requête pourrait être mieux formulée à mon avis, mais elle marche. Bon courage!

PS : les recommendations topologiques du standard COVADIS en aep n'imposent pas le découpage des canalisations principales pour les noeuds de branchements individuels, seulements pour les autres appareillages/ouvrages)

Dernière modification par Rlucas (Fri 16 November 2018 19:15)

Hors ligne

 

#8 Sat 17 November 2018 17:18

sam92
Juste Inscrit !
Date d'inscription: 6 Nov 2018
Messages: 7

Re: Couper une ligne à partir de points non positionnés sur la ligne

Bonjour,

Vous pouvez utiliser la fonction ST_ClosestPoint(line.geom,point.geom) http://www.postgis.org/docs/ST_ClosestPoint.html, qui réalise la même tâche que ST_LineInterpolatePoint(line.geom,ST_LineLocatePoint(line.geom,point.geom)).

Au lieu de "ST_Distance(line.geom,point.geom) < distance_tampon", vous devriez utiliser la fonction ST_DWithin(line.geom,point.geom,distance_tampon) http://postgis.net/docs/ST_DWithin.html, elle exploite les index spatiaux, ce qui vous permettra de réduire considérablement le temps d'exécution de la requête.


Sam

Hors ligne

 

#9 Sat 17 November 2018 19:02

sam92
Juste Inscrit !
Date d'inscription: 6 Nov 2018
Messages: 7

Re: Couper une ligne à partir de points non positionnés sur la ligne

Rlucas, cela donnerait quelque chose comme ça :

Code:

WITH l AS
    (SELECT id, (st_dump(geom)).geom FROM lignes)
SELECT DISTINCT ON (p.id) p.id as idpoint, st_makeline(st_geometryn(p.geom,1),st_closestpoint(l.geom,p.geom)) as geom
FROM points as p
JOIN l ON st_dwithin(l.geom,p.geom,distance_tampon)
ORDER BY idpoint, st_distance(l.geom,p.geom);

La clause DISTINCT ON (colonnes ou ensemble de colonnes) https://www.postgresql.org/docs/9.5/sql … L-DISTINCT ne garde pour chaque colonne ou ensemble de colonnes que le premier résultat, les suivants sont retirés.
En l'occurrence, couplé à un tri sur la distance, cette clause conserve le point projeté sur la ligne le plus proche du point...
Par ailleurs, dans le cas où il existerait plusieurs lignes situées à une même distance d'un point, cette clause ne conserve tout de même qu'un résultat, à la différence de l'utilisation de la fonction de fenêtrage RANK qui en a été faite, qui aurait retourné plusieurs points projetés.


En outre, il a été intégré dans la requête le dump des lignes.
Enfin, grâce à la fonction ST_GeometryN(geom,Nième_Point) https://postgis.net/docs/ST_GeometryN.html, la requête est capable de travailler avec des Points contenus dans une table dont le type géométrique a été renseigné comme étant MultiPoint.


Pour ne pas créer de liens pour les points qui se trouvent déjà sur une ligne, la méthode la moins coûteuse en temps que j'ai pu trouver est de supprimer à la fin de la requête ces points-là :

Code:

WITH l AS
    (SELECT id, (st_dump(geom)).geom FROM lignes)
,proj AS
    (SELECT DISTINCT ON (p.id) p.id as idpoint, st_makeline(st_geometryn(p.geom,1),st_closestpoint(l.geom,p.geom)) as geom, 
    st_distance(l.geom,p.geom) as dist
    FROM points as p
    JOIN l ON st_dwithin(l.geom,p.geom,distance_tampon)
    ORDER BY idpoint, st_distance(l.geom,p.geom))
SELECT idpoint, geom
FROM proj
WHERE dist != 0;

Sam

Hors ligne

 

#10 Tue 20 November 2018 06:28

zang
Participant actif
Date d'inscription: 4 Oct 2005
Messages: 55

Re: Couper une ligne à partir de points non positionnés sur la ligne

Bonjour,
Pour découper ensuite les lignes de conduite à partir des points localisés sur ces lignes, j'avais trouvé cette requête mais elle ne fonctionne pas très bien (ou bien je ne l'utilise pas très bien au choix). En effet, certaines lignes sont supprimées aléatoirement. J'ai mis ça sur le compte de la topologie des lignes qui n'étaient pas parfaite car venant d'un plan autocad mais je n'ai pas persévéré...

Code:

CREATE TABLE ln_cut AS
 -- premiere table des positions des points par rapport a "leurs" lignes
with locus as (
        -- on genere la position du debut de la ligne (index 0)  pour le premier segment à découper
    select l.gid, 0 as l
    from ln 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 ln l

    UNION ALL

        -- calcul des positions des points par rapport aux lignes
    select l.gid, ST_LineLocatePoint(l.geom, pt.geom) as  l
    from ln l, pt pt
    where st_dwithin(l.geom, pt.geom, 0.01)
    
    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:
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
select l.gid, ST_LineSubstring(l.geom, loc1.l, loc2.l) as geom 
from loc_with_idx loc1, loc_with_idx loc2, ln l
where l.gid = loc1.gid
and loc1.gid = loc2.gid
and loc2.idx = loc1.idx+1;

Hors ligne

 

Pied de page des forums

Powered by FluxBB