Pasq.fr

Parce-qu'il y a forcément du sens à tout ce bordel !

Transfert points sur extrémités de ligne

Rédigé par Alain 1 commentaire
point sur ligne

Souvent, pour s’amuser, les hommes d’équipage
Prennent des points, vastes éléments isolés,
Qui suivent, indolents compagnons de voyage,
des lignes glissantes sur des topologies amères...

C'est beau, Baudelaire, quand même.

Allez, on va essayer de transférer des identifiants de points vers les extrémités de lignes, la base d'un réseau topologique. Je ne sais pas pourquoi je n'ai pas fait cet article avant, vu que l'on m'a posé cette question y'a 2 ans (retard covid...excuse à tout) !!

Espérant que cela puisse vous aider.

Une couche de points, une couche de lignes.

Tout réseau topologique qui se respecte est composé de vertices, vertex, lignes si vous préférez, qui sont caractérisés par un point amont et un point aval, début, fin, départ et arrivée si vous préférez. Je laisse de coté les cotés et j'efface les faces adjacentes dans cet article.

Dans un réseau topologique, une ligne commence par un point et fini sur un point, toujours. Ce qui a beaucoup de sens pour des réseaux d'eau, informatique, électrique, chauffage... Même pour les routes. Le système topologique (l'autre type étant appelé spaghetti, pour son analogie avec un amas de ligne sans relation) a l'avantage de créer des réseaux continus logiques. Et évites tous les effets de gap, recouvrance...

Cela évite les trucs comme ça.

bref, ce n'est pas le sujet, soyons concret.

Relier points et ligne

Imaginons comme dans l'image plus haut (POSTGIS TOPOLOGY) que j'ai une ligne et besoin de noeud_amont (comme start_node) et noeud_aval (comme end_node).

exemple

table des points (tout simplement)

table points

Dans QGIS, sans base de données

En 3 temps, pour bien comprendre. Le détail qui change tout est qu'il faut que les points soient bien "en face" des extrémités des lignes

Dans votre couche de point, ajouter une colonne avec la calculatrice de champs avec la formule : geom_to_wkt($geometry), vous l'aurez compris, cela rajoutes les coordonnées de vos points en format wkt (well know text)

Puis dans la couche de ligne, toujours avec la calculatrice de champs, mettre à jour la colonne noeud_amont avec 

attribute(get_feature('point','wkt',geom_to_wkt(start_point($geometry))),'id_point')

Attribute permet de renseigner la colonne en cours (noeud_amont) avec le contenu d' id_point, que l'on récupère grâce à get_feature, où l'attribut 'wkt' de la couche 'point' doit être égal à la géométrie du premier point de ma ligne (start_point).

mise à jour champs noeud amont

On refait la même chose pour le point final (noeud_aval) mais avec end_point

attribute(get_feature('point','wkt',geom_to_wkt(end_point($geometry))),'id_point')

Pas pratique mais didactique, cela permet ponctuellement de faire le job. J'avoue que j'ai cherché plus direct, mais finalement, c'était ce qui me paraissait le plus simple. Si vous avez une solution plus directe, merci de partager.

Dans une base POSTGIS

Le plus simple reste en base de donnée, pour le coup, c'est très simple :

On met à jour (update) la table avec l'attribut qui va bien en comparant les géométries. On imagine pour cela que mes 2 couches sont sous postgis (je ne vous fais pas l'affront de vous montrer comment faire)

UPDATE ligne SET noeud_amont = id_point FROM point WHERE st_Dwithin(point.the_geom,st_startpoint(ligne.the_geom),0.25);

UPDATE ligne SET noeud_aval = id_point FROM point WHERE st_Dwithin(point.the_geom,st_endpoint(ligne.the_geom),0.25);

Donc UPDATE (mise à jour) la table "ligne" en mettant noeud_amont égal à id_point de la table "point" quand (en fait : où - where) la géométrie de "point" est proche, à 25 cm près, du point de départ de "ligne" et pareil pour le point aval (endpoint)

On peut donc ainsi régler une tolérance avec ST_DWITHIN, sinon utiliser ST_WITHIN pour une superposition exacte.

J'ai également rencontré et testé du " WHERE st_equals(st_startpoint(ligne.geom),st_snap(point.geom,st_startpoint(ligne.geom),0.25));" mais les performances sont moins bonnes (0.224ms contre 0.129ms pour mes 4 lignes). MAis elles aussi meilleures quand on enlève le ST_SNAP pour la tolérance : juste WHERE st_equals(st_startpoint(ligne.geom),point.geom); (0.097 ms)

Plusieurs couches de points ?

Alors, Jean-Michel me dit : et si tu as plusieurs couches avec des points mais, tu fais comment pour tous les id ? Il est sympa Jean-Mich...

Si vous avez plusieurs couches de point, je pense que je passerai par une vue matérialisée (indexée, pour la vitesse) qui regroupe les identifiants et géométries de toutes les couches de points, et j'appliquerai sur le update à partir de la couche matérialisée.

CREATE MATERIALIZED VIEW points_amont_aval
AS SELECT DISTINCT id_point AS tous_les_id,
   the_geom,
   FROM point1
UNION ALL
 SELECT DISTINCT id_point AS tous_les_id,
    the_geom,
   FROM point2
UNION ALL
... (ajouter autant de table que nécessaire)
WITH DATA;

ATTENTION, l'ordre des couches a sont importance : en effet, en cas de point aux mêmes coordonnées, c'est le dernier dans la liste qui gagne ! dans l'exemple ci-dessus point1 serait ignoré et point2 pris en compte

Une tâche à faire, genre toutes les nuits, ou toutes les heures, ou toutes les secondes... suivant vos besoins et taille de base.

Vous avez des solutions plus élégantes, rapides ou mieux...Je suis toujours preneur. a+

Fin du Poème

Le Géomaticien est semblable au prince des nuées
Qui hante la tempête et se rit des BDD ;
Exilé dans un service au milieu des huées,
Son SQL de géant l’empêchent de marcher.


Classé dans : QGIS, Trucs, QGIS 3.x Mots clés : noeud, amont, aval, id, couches, couche, géométries, table, st, start, qgis, extrémité

1 commentaire


Écrire un commentaire

Quelle est le premier caractère du mot 84q1jl ?