Alignement des nœuds de début et de fin de lignes sur d'autres lignes dans PostGIS
9
Il existe de nombreux exemples qui montrent comment accrocher des lignes à des points, mais je n'ai pas trouvé de moyen (rapide!) D'aligner les nœuds de début et de fin des chaînes de lignes sur les nœuds d'autres lignes.
Essentiellement, je veux «nettoyer» mon calque dans Postgis (2.0), en rapprochant des points presque similaires et en cousant de minuscules ouvertures entre les chaînes de lignes.
Peu importe que j'ajoute un autre nœud, que je déplace le premier / dernier nœud de l'une des lignes ou que je déplace les deux points au centre.
J'ai trouvé deux options, mais je ne sais pas comment commencer avec l'une ou l'autre:
J'ai réussi à résoudre ce problème, sans utiliser les outils GRASS mentionnés ou les fonctions topologiques.
Fondamentalement, je prends tous les nœuds de début et de fin, les place dans une nouvelle table temporaire, place un tampon autour d'eux, union les objets tampon et déplace tous les nœuds trouvés dans chaque tampon vers le centroïde du tampon.
Une fois cela fait, je déplace les points de début et de fin d'origine vers le nouvel emplacement.
Plus facile que prévu et toujours rapide, mais je m'attendais à ce que PostGIS ait une fonction intégrée pour cela - ce serait encore plus rapide.
Edit: dans l'intérêt de redonner à la communauté, c'est mon code (assez merdique) pour l'instant.
droptableifexists nodes;droptableifexists nodes2;droptableifexists buffers;-- Get Start and End nodesselect ST_StartPoint(wkb_geometry) startnode, ST_EndPoint(wkb_geometry) endnode, ogc_fid into nodes from sourceTable;-- Combine all nodes into one table for easier queriesselect startnode node, ogc_fid into nodes2 from nodes;insertinto nodes2 select endnode node, ogc_fid from nodes;-- Some indexes to speed everything upCREATEINDEX nodesstart_idx ON nodes USING gist (startnode);CREATEINDEX nodesend_idx ON nodes USING gist (endnode);CREATEINDEX nodes2_idx ON nodes2 USING gist (node);CREATEINDEX nodes_ogcfid_idx ON nodes USING btree (ogc_fid ASC NULLS LAST);-- Create buffers, combine them, split combined objects againselect(ST_Dump(ST_Union(ST_Buffer(node,1)))).geom geom into buffers from nodes2;CREATEINDEX buffers_idx ON buffers USING gist (geom);-- Update start/end nodes tableUPDATE nodes SET startnode = ST_Centroid((select geom from buffers WHERE geom && startnode));UPDATE nodes SET endnode = ST_Centroid((select geom from buffers WHERE geom && endnode));-- Update original pointsupdate sourceTable set wkb_geometry = ST_SetPoint(
ST_SetPoint(wkb_geometry,0,(select startnode from nodes where ogc_fid=sourceTable.ogc_fid)),
ST_NumPoints(wkb_geometry)-1,(select endnode from nodes where ogc_fid=sourceTable.ogc_fid));DROPTABLE nodes;DROPTABLE nodes2;DROPTABLE buffers;
Cette réponse ressemble un peu à la suggestion "non topologique" de ma réponse. Il serait bon que vous donniez un vote positif ou que vous choisissiez la réponse. Voilà ce qui nourrit la communauté ici :)
katahdin
Tu as raison. J'ai voté pour votre réponse et modifierai ma réponse pour inclure mon code.
Jelmer Baas
4
Voici trois options. Si tout va bien on aidera.
v.clean
À l'aide des outils GRASS de QGIS, vous pouvez nettoyer la topologie d'un objet spatial. L'utilisateur @RK donne un bon ensemble d'instructions sur la façon de procéder dans une réponse à une question différente . L'avantage de GRASS est qu'il permet de déduire la topologie du fichier de formes. L'inconvénient de votre situation est que vos données ne sont pas dans un fichier de formes. Bien sûr, vous pouvez exporter les données de Postgres dans un fichier de formes à l'aide de l'outil "Ajouter une couche PostGIS", mais c'est une étape supplémentaire.
Fonctions PostGIS non topologiques
Dans PostGIS, vous pouvez utiliser les fonctions ST_EndPoint et ST_StartPoint pour obtenir le point de fin et de début d'une chaîne de lignes. Ensuite, en utilisant une combinaison de ST_DWithi n et ST_Distance , vous pouvez trouver le point de début ou de fin le plus proche sur une géométrie proche. Si vous avez beaucoup de points, ST_DWithin accélérera beaucoup la requête - en supposant que vous avez un index en place. À partir de là, vous devrez établir une règle qui définit les points à modifier et ceux qui sont fixes.
L'avantage ici est que vous n'avez pas à envoyer vos données à GRASS pour le nettoyage, mais il y a quelques pièges à surveiller.
Fonctions topologiques PostGIS
La question faisait référence aux fonctions topologiques de PostGIS. Cela fonctionne très bien, mais, comme le décrit le wiki , vous devez définir explicitement les arêtes, les nœuds et les faces. De toute évidence, ce sera un problème pour votre ensemble de données car vous avez des problèmes connus avec la topologie.
Merci, je connais ces fonctions. ST_Snap snaps TOUS les nœuds, je veux seulement le nœud de début et de fin. ST_SnapToGrid n'est pas vraiment adapté car il modifie toute la géométrie existante et a une chance de déplacer des nœuds plus proches, car ils tombent à peine dans un autre segment.
Voici trois options. Si tout va bien on aidera.
v.clean
À l'aide des outils GRASS de QGIS, vous pouvez nettoyer la topologie d'un objet spatial. L'utilisateur @RK donne un bon ensemble d'instructions sur la façon de procéder dans une réponse à une question différente . L'avantage de GRASS est qu'il permet de déduire la topologie du fichier de formes. L'inconvénient de votre situation est que vos données ne sont pas dans un fichier de formes. Bien sûr, vous pouvez exporter les données de Postgres dans un fichier de formes à l'aide de l'outil "Ajouter une couche PostGIS", mais c'est une étape supplémentaire.
Fonctions PostGIS non topologiques
Dans PostGIS, vous pouvez utiliser les fonctions ST_EndPoint et ST_StartPoint pour obtenir le point de fin et de début d'une chaîne de lignes. Ensuite, en utilisant une combinaison de ST_DWithi n et ST_Distance , vous pouvez trouver le point de début ou de fin le plus proche sur une géométrie proche. Si vous avez beaucoup de points, ST_DWithin accélérera beaucoup la requête - en supposant que vous avez un index en place. À partir de là, vous devrez établir une règle qui définit les points à modifier et ceux qui sont fixes.
L'avantage ici est que vous n'avez pas à envoyer vos données à GRASS pour le nettoyage, mais il y a quelques pièges à surveiller.
Fonctions topologiques PostGIS
La question faisait référence aux fonctions topologiques de PostGIS. Cela fonctionne très bien, mais, comme le décrit le wiki , vous devez définir explicitement les arêtes, les nœuds et les faces. De toute évidence, ce sera un problème pour votre ensemble de données car vous avez des problèmes connus avec la topologie.
la source
PostGIS a des fonctions de capture. Peut-être qu'elles aideront?
ST_Snap
: Accrochez les segments et les sommets de la géométrie en entrée aux sommets d'une géométrie de référence.ST_SnapToGrid
: Accrochez tous les points de la géométrie en entrée sur une grille standard.la source