Przyciąganie początkowych i końcowych węzłów linii do innych linii w PostGIS
9
Istnieje wiele przykładów pokazujących, jak przyciągać linie do punktów, ale nie znalazłem (szybkiego!) Sposobu przyciągania początkowych i końcowych węzłów ciągów linii do węzłów innych linii.
Zasadniczo chcę „wyczyścić” moją warstwę w postgis (2.0), przesuwając prawie podobne punkty razem i szyjąc małe otwory między strunami linii.
Nie miałoby to większego znaczenia, czy dodam kolejny węzeł, przesunę pierwszy / ostatni węzeł którejkolwiek linii, czy przesunę oba punkty na środek.
Znalazłem dwie opcje, ale nie jestem pewien, jak zacząć od jednej z nich:
Udało mi się to rozwiązać bez użycia wspomnianych narzędzi GRASS lub funkcji topologicznych.
Zasadniczo biorę wszystkie węzły początkowy i końcowy, umieszczam je w nowej, tymczasowej tabeli, umieszczam wokół nich bufor, łączę obiekty buforów i przenoszę wszystkie znalezione węzły w każdym buforze do środka ciężkości bufora.
Kiedy to się stanie, przeniosę oryginalne punkty początkowe i końcowe do nowej lokalizacji.
Łatwiej niż się spodziewałem i wciąż szybko, ale spodziewałem się, że PostGIS będzie miał do tego wbudowaną funkcję - będzie to jeszcze szybsze.
Edycja: w celu oddania społeczności, to na razie mój (dość gówniany) kod.
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;
Ta odpowiedź wygląda trochę jak sugestia „nie topologiczna” z mojej odpowiedzi. Byłoby miło, gdybyś wyraził opinię lub wybrał odpowiedź. To one karmią społeczność tutaj :)
katahdin
Masz rację. Poparłem twoją odpowiedź i dokonam edycji mojej odpowiedzi, aby uwzględnić mój kod.
Jelmer Baas
4
Oto trzy opcje. Mam nadzieję, że ktoś pomoże.
v.clean
Za pomocą narzędzi GRASS w QGIS możesz wyczyścić topologię obiektu przestrzennego. Użytkownik @RK podaje dobry zestaw instrukcji, jak to zrobić, w odpowiedzi na inne pytanie . Zaletą GRASS jest to, że wywnioskuje topologię pliku kształtu. Wadą twojej sytuacji jest to, że twoich danych nie ma w pliku kształtu. Oczywiście możesz wyeksportować dane z Postgres do pliku kształtu za pomocą narzędzia „Dodaj warstwę PostGIS”, ale to dodatkowy krok.
Nie topologiczne funkcje PostGIS
W PostGIS możesz użyć funkcji ST_EndPoint i ST_StartPoint, aby uzyskać koniec i punkt początkowy dla linii. Następnie, używając kombinacji ST_DWithi n i ST_Distance , możesz znaleźć najbliższy punkt początkowy lub końcowy na pobliskiej geometrii. Jeśli masz dużo punktów, to ST_DWithin znacznie przyspieszy zapytanie - zakładając, że masz indeks. Następnie musisz ustalić regułę, która określa, które punkty mają zostać zmodyfikowane, a które stałe.
Zaletą jest to, że nie musisz wysyłać swoich danych do GRASS w celu wyczyszczenia, ale są pewne pułapki, na które należy uważać.
Topologiczne funkcje PostGIS
Pytanie dotyczyło funkcji topologicznych PostGIS. Działa to świetnie, ale jak opisuje wiki , musisz jawnie zdefiniować krawędzie, węzły i ściany. Oczywiście będzie to stanowić problem dla twojego zestawu danych, ponieważ znasz problemy z topologią.
Dzięki, znam te funkcje. ST_Snap przyciąga WSZYSTKIE węzły, chcę tylko węzeł początkowy i końcowy. ST_SnapToGrid nie jest tak naprawdę odpowiedni, ponieważ modyfikuje całą istniejącą geometrię i ma szansę na przesunięcie węzłów, które są blisko, ponieważ ledwo wpadają w inny segment.
Oto trzy opcje. Mam nadzieję, że ktoś pomoże.
v.clean
Za pomocą narzędzi GRASS w QGIS możesz wyczyścić topologię obiektu przestrzennego. Użytkownik @RK podaje dobry zestaw instrukcji, jak to zrobić, w odpowiedzi na inne pytanie . Zaletą GRASS jest to, że wywnioskuje topologię pliku kształtu. Wadą twojej sytuacji jest to, że twoich danych nie ma w pliku kształtu. Oczywiście możesz wyeksportować dane z Postgres do pliku kształtu za pomocą narzędzia „Dodaj warstwę PostGIS”, ale to dodatkowy krok.
Nie topologiczne funkcje PostGIS
W PostGIS możesz użyć funkcji ST_EndPoint i ST_StartPoint, aby uzyskać koniec i punkt początkowy dla linii. Następnie, używając kombinacji ST_DWithi n i ST_Distance , możesz znaleźć najbliższy punkt początkowy lub końcowy na pobliskiej geometrii. Jeśli masz dużo punktów, to ST_DWithin znacznie przyspieszy zapytanie - zakładając, że masz indeks. Następnie musisz ustalić regułę, która określa, które punkty mają zostać zmodyfikowane, a które stałe.
Zaletą jest to, że nie musisz wysyłać swoich danych do GRASS w celu wyczyszczenia, ale są pewne pułapki, na które należy uważać.
Topologiczne funkcje PostGIS
Pytanie dotyczyło funkcji topologicznych PostGIS. Działa to świetnie, ale jak opisuje wiki , musisz jawnie zdefiniować krawędzie, węzły i ściany. Oczywiście będzie to stanowić problem dla twojego zestawu danych, ponieważ znasz problemy z topologią.
źródło
PostGIS ma funkcje przyciągania. Może pomogą?
ST_Snap
: Przyciągaj segmenty i wierzchołki geometrii wejściowej do wierzchołków geometrii odniesienia.ST_SnapToGrid
: Przyciągnij wszystkie punkty geometrii wejściowej do zwykłej siatki.źródło