Fang von Start- und Endknoten von Linien an anderen Linien in PostGIS

9

Es gibt viele Beispiele, die zeigen, wie Linien an Punkten gefangen werden, aber ich konnte keine (schnelle!) Möglichkeit finden, die Start- und Endknoten von Linienzeichenfolgen an Knoten anderer Linien zu fangen.

Im Wesentlichen möchte ich meine Ebene in Postgis (2.0) "reinigen", fast ähnliche Punkte zusammen verschieben und winzige Öffnungen zwischen Linienstrings zusammennähen.

Es wäre nicht so wichtig, ob ich einen weiteren Knoten hinzufüge, den ersten / letzten Knoten einer Linie verschiebe oder beide Punkte in die Mitte verschiebe.

Ich habe zwei Optionen gefunden, bin mir aber nicht sicher, wie ich mit einer von beiden beginnen soll:

Die zweite Option klingt machbar, aber jede Hilfe, wie man dieser Methode folgt, wäre sehr dankbar.

Jelmer Baas
quelle

Antworten:

6

Ich habe es geschafft, dieses Problem zu lösen, ohne die genannten GRASS-Tools oder topologischen Funktionen zu verwenden.

Grundsätzlich nehme ich alle Start- und Endknoten, füge sie in eine neue temporäre Tabelle ein, lege einen Puffer um sie, verbinde die Pufferobjekte und verschiebe alle gefundenen Knoten in jedem Puffer zum Schwerpunkt des Puffers.

Wenn das erledigt ist, verschiebe ich den ursprünglichen Start- und Endpunkt an den neuen Ort.

Einfacher als erwartet und immer noch schnell, aber ich hatte erwartet, dass PostGIS eine integrierte Funktion dafür hat - das wäre noch schneller.

Bearbeiten: Um der Community etwas zurückzugeben, ist dies vorerst mein (ziemlich beschissener) Code.

drop table if exists nodes;
drop table if exists nodes2;
drop table if exists buffers;

-- Get Start and End nodes
select ST_StartPoint(wkb_geometry) startnode,  ST_EndPoint(wkb_geometry) endnode,    ogc_fid into nodes  from sourceTable;
-- Combine all nodes into one table for easier queries
select startnode node, ogc_fid into nodes2 from nodes;
insert into nodes2 select endnode node, ogc_fid from nodes;

-- Some indexes to speed everything up
CREATE INDEX nodesstart_idx ON nodes USING gist  (startnode);
CREATE INDEX nodesend_idx ON nodes USING gist  (endnode);
CREATE INDEX nodes2_idx ON nodes2 USING gist  (node);
CREATE INDEX nodes_ogcfid_idx ON nodes USING btree (ogc_fid ASC NULLS LAST);

-- Create buffers, combine them, split combined objects again
select (ST_Dump(ST_Union(ST_Buffer(node, 1)))).geom geom into buffers from nodes2;
CREATE INDEX buffers_idx ON buffers USING gist  (geom);

-- Update start/end nodes table
UPDATE 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 points
update 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));

DROP TABLE nodes;
DROP TABLE nodes2;
DROP TABLE buffers;
Jelmer Baas
quelle
Diese Antwort ähnelt ziemlich dem "nicht topologischen" Vorschlag aus meiner Antwort. Es wäre nett, wenn Sie eine Gegenstimme abgeben oder die Antwort auswählen würden. Das ist es, was die Community hier
füttert
Du hast recht. Ich habe Ihre Antwort positiv bewertet und werde meine Antwort so bearbeiten, dass sie meinen Code enthält.
Jelmer Baas
4

Hier sind drei Optionen. Hoffentlich hilft man.

v.clean

Mit den GRASS-Werkzeugen in QGIS können Sie die Topologie eines räumlichen Objekts bereinigen. Der Benutzer @RK gibt in einer Antwort auf eine andere Frage eine Reihe guter Anweisungen dazu . Der Vorteil von GRASS besteht darin, dass auf die Topologie des Shapefiles geschlossen wird. Der Nachteil für Ihre Situation ist, dass sich Ihre Daten nicht in einem Shapefile befinden. Natürlich können Sie die Daten von Postgres mit dem Werkzeug "PostGIS-Ebene hinzufügen" in ein Shapefile exportieren, aber das ist ein zusätzlicher Schritt.

Nicht topologische PostGIS-Funktionen

In PostGIS können Sie die Funktionen ST_EndPoint und ST_StartPoint verwenden, um den End- und Startpunkt für einen Linestring abzurufen. Mithilfe einer Kombination aus ST_DWithi n und ST_Distance können Sie dann den nächsten Start- oder Endpunkt auf einer nahe gelegenen Geometrie finden. Wenn Sie viele Punkte haben, beschleunigt ST_DWithin die Abfrage erheblich - vorausgesetzt, Sie haben einen Index. Von dort aus müssen Sie eine Regel festlegen, die definiert, welche Punkte geändert und welche festgelegt werden sollen.

Der Vorteil hierbei ist, dass Sie Ihre Daten nicht zur Reinigung an GRASS senden müssen, aber es gibt einige Fallstricke, auf die Sie achten müssen.

Topologische PostGIS-Funktionen

Die Frage bezog sich auf die topologischen Funktionen von PostGIS. Diese funktionieren hervorragend, aber wie im Wiki beschrieben , müssen Sie die Kanten, Knoten und Flächen explizit definieren. Dies ist eindeutig ein Problem für Ihren Datensatz, da Sie Probleme mit der Topologie kennen.

Katahdin
quelle
1

PostGIS hat Fangfunktionen. Vielleicht helfen sie?

ST_Snap: Fang Segmente und Scheitelpunkte der Eingabegeometrie an Scheitelpunkten einer Referenzgeometrie.

ST_SnapToGrid: Fangen Sie alle Punkte der Eingabegeometrie an einem regulären Raster.

Jordan Arseno
quelle
1
Danke, ich bin mir dieser Funktionen bewusst. ST_Snap schnappt ALLE Knoten, ich möchte nur den Start- und Endknoten. ST_SnapToGrid ist nicht wirklich geeignet, da es die gesamte vorhandene Geometrie ändert und die Möglichkeit hat, Knoten zu verschieben, die sich weiter entfernt befinden, da sie kaum in ein anderes Segment fallen.
Jelmer Baas