Zadawałem to pytanie kilka razy na przepełnieniu stosu i IRC między #qgis a #postgis, a także próbowałem go zakodować lub zaimplementować samodzielnie w postgis bez prawdziwej odpowiedzi.
Korzystając z programowania (najkorzystniej w Pythonie), chciałbym narysować linię z warstwy punktowej do jej rzutowania na najbliższą linię warstwy lub warstwy wielokąta.
Obecnie większość moich danych jest w kształcie i formacie ESRI; wolałbym jednak trzymać się z dala od rozwiązania postgis, ponieważ jestem głównie użytkownikiem shp + qgis.
Idealnym rozwiązaniem byłoby wdrożenie GDAL / OGR za pomocą Pythona lub podobnych bibliotek
- Korzystanie z bibliotek GDAL / OGR od czego zacząć? czy można podać plan rozwiązania?
- Czy mogę użyć NetworkX do wykonania analizy najbliższego sąsiada?
- Czy to rzeczywiście możliwe?
Jeśli jest to łatwiejsze, punkty mogą łączyć się z punktem końcowym segmentu zamiast punktu rzutowanego
Odpowiedzi:
To pytanie okazało się nieco trudniejsze, niż się spodziewałem. Istnieje wiele implementacji samej najkrótszej odległości, takich jak Shapely zapewniona odległość (z GEOS). Niewiele rozwiązań zapewnia jednak sam punkt przecięcia, ale tylko odległość.
Moja pierwsza próba zbuforowała punkt o odległość między punktem a wielokątem i szukałam skrzyżowań, ale błędy zaokrąglania uniemożliwiają udzielenie dokładnej odpowiedzi.
Oto kompletne rozwiązanie wykorzystujące Shapely, oparte na tych równaniach :
Dla potomnych wygląda na to, że to rozszerzenie ArcView całkiem dobrze radzi sobie z tym problemem, szkoda, że jest na martwej platformie napisanej martwym językiem ...
źródło
pairs
że z algorytmem jest O (n) czy coś. Rozwiązanie @eprand może być może zostać zmodyfikowane, aby korzystać z KNN, ale jak dotąd udało mi się żyć bez PostGIS ...Odpowiedź PostGIS (dla multilinestring, jeśli linestring, usuń funkcję st_geometryn)
źródło
To jest trochę stare, ale szukałem dziś rozwiązania tego problemu (punkt -> linia). Najprostszym rozwiązaniem, z jakim natknąłem się na ten powiązany problem, jest:
źródło
Jeśli dobrze cię rozumiem, funkcjonalność, o którą prosisz, jest wbudowana w PostGIS.
Aby uzyskać punkt rzutowany na linię, możesz użyć ST_Closestpoint (na PostGIS 1.5)
Kilka wskazówek na temat korzystania z niego można znaleźć tutaj: http://blog.jordogskog.no/2010/02/07/how-to-use-the-new-distance-related-functions-in-postgis-part1/
Na przykład przydatne jest znalezienie najbliższego punktu wielokąta do innego wielokąta.
Jeśli chcesz uzyskać linię między dwoma najbliższymi punktami na obu geometriach, możesz użyć ST_Shortestline. ST_Closestpoint to pierwszy punkt w ST_Shortestline
Długość ST_Shortestline między dwiema geometriami jest taka sama jak ST_Distance między geometriami.
źródło
Zobacz komentarz poniżej, w jaki sposób moja odpowiedź nie powinna być uważana za wiarygodne rozwiązanie ... Zostawię ten oryginalny post tutaj, aby inni mogli zbadać problem.
Jeśli rozumiem pytanie, ta ogólna procedura powinna zadziałać.
Aby znaleźć najkrótszą ścieżkę między punktem (zdefiniowanym przez x, y lub x, y, z) i poliną (zdefiniowanym przez zestaw łączący x, y lub x, y, z) w przestrzeni euklidesowej:
1) Z danego punktu zdefiniowanego przez użytkownika (nazywam go pt0), znajdź najbliższy wierzchołek polilinii (pt1). OGRinfo może sondować wierzchołki polilinii, a następnie można wykonać obliczenia odległości za pomocą standardowych metod. Na przykład, iteruj w odległościach obliczeniowych, takich jak: distance_in_radians = 2 * matath.asin (math.sqrt (math.pow ((math.sin ((pt0_radians-ptx_radians) / 2)), 2) + math.cos (pt0_radians) * math.cos (ptx_radians) * math.pow ((math.sin ((pt0_radians-ptx_radians) / 2)), 2)))
2) Zapisz powiązaną minimalną odległość (d1) i (pt1)
3) spójrz na dwa segmenty odchodzące od pt1 (w linii ogrinfo będą to wcześniejsze i następne wierzchołki). Zapisz te wierzchołki (n2 i n3).
4) utwórz formułę y = mx + b dla każdego segmentu
5) Odnieś swój punkt (pt0) do prostopadłej dla każdej z tych dwóch formuł
6) Oblicz odległość i skrzyżowania (d2 i d3; pt2, pt3)
7) Porównaj najkrótsze trzy odległości (d1, d2, d3). Twój pt0 do powiązanego węzła (pt1, pt2 lub pt3) jest najkrótszym linkiem.
To jest strumień odpowiedzi świadomości - mam nadzieję, że mój mentalny obraz problemu i rozwiązania pasuje.
źródło
Oto skrypt Pythona dla QGIS> 2.0 wykonany na podstawie podanych wyżej wskazówek i rozwiązań. Działa dobrze dla rozsądnej liczby punktów i linii. Ale nie próbowałem tego z dużą ilością przedmiotów.
Oczywiście musiał on zostać skopiowany w trybie bezczynności lub w jakimkolwiek innym „pythonicznym rozwiązaniu” i zapisać go jako „closest.point.py”.
W przyborniku QGIS przejdź do skryptu, narzędzi, dodaj skrypt, wybierz go.
!!! OSTRZEŻENIE !!! Zwróć uwagę, że niektóre „dziwne” / nieprawidłowe rzutowane punkty mogą być generowane z powodu tego polecenia linii:
counterSelec
Wartość w nim ustawić ile nearestneighbor są zwracane. W rzeczywistości każdy punkt powinien być rzutowany w możliwie najkrótszej odległości do każdego obiektu linii; a znaleziona minimalna odległość dałaby prawidłową linię i rzutowany punkt jako najbliżsi sąsiedzi, których szukamy. Aby skrócić czas zapętlenia, używana jest najbliższa komenda Sąsiad. WybraniecounterSelec
wartości zmniejszonej do 1 zwróci „pierwszy” spełniony obiekt (a konkretnie jego ramkę ograniczającą) i może nie być właściwy. Obiekty o różnych rozmiarach linii mogą zobowiązać do wyboru 3 lub 5, a nawet najbliższe obiekty w celu ustalenia najkrótszej odległości. Im wyższa wartość, tym dłużej trwa. Z setkami punktów i linii zaczyna się bardzo powoli z 3 lub 5 najbliższymi sąsiadami, z tysiącami może powodować błędy z takimi wartościami.źródło
W zależności od zainteresowań i przypadku użycia przydatne może być zapoznanie się z „algorytmami dopasowywania map”. Na przykład istnieje projekt RoadMatcher na wiki OSM: http://wiki.openstreetmap.org/wiki/Roadmatcher .
źródło