Ostatnio przeglądałem strony internetowe linii lotniczych, które wyświetlają ich trasy odlatujące z określonego miasta do wszystkich obsługiwanych przez nich miast. Chciałbym móc tworzyć podobne zakrzywione trasy między punktami. Czy ktoś stworzył skrypty lub funkcje, które wygenerują zakrzywione łuki, takie jak te przedstawione w tym przykładzie ?
Czy w PostGIS jest implementacja ST_MakeLine, która pozwala określić ilość krzywych, które należy zastosować przy łączeniu 2 punktów?
Podczas gdy obecnie używam PostGIS i QGIS, chętnie usłyszę o innych opcjach oprogramowania, które mogą stworzyć taki sam wygląd.
Odpowiedzi:
Tworzenie świetnych kręgów może dać pożądany efekt.
Może coś takiego jak omówione na http://lists.osgeo.org/pipermail/postgis-users/2008-F February/018620.html
Aktualizacja:
Kontynuowałem ten pomysł w „Wizualizacji globalnych połączeń” . Jest to rozwiązanie oparte wyłącznie na PostGIS, wykorzystujące reprojection do tworzenia łuków.
(Definicja CRS dla 953027 można znaleźć tutaj: http://spatialreference.org/ref/esri/53027/ )
źródło
Problem polega na tym, aby dowiedzieć się, jak zgiąć łuki, aby zwiększyć ich rozdzielczość wizualną.
Oto jedno rozwiązanie (spośród wielu możliwych). Rozważmy wszystkie łuki pochodzące ze wspólnego pochodzenia. Łuki są tutaj najbardziej zatłoczone. Aby je najlepiej rozdzielić, ułóżmy je tak, aby rozkładały się pod równymi kątami . Problem polega na tym, że narysujemy odcinki linii prostej od początku do miejsc docelowych, ponieważ zwykle będą skupienia miejsc docelowych w różnych kierunkach. Wykorzystajmy naszą swobodę do wyginania łuków, aby możliwie równomiernie rozmieszczać odchodzące kąty.
Dla uproszczenia użyjmy łuków kołowych na mapie. Naturalną miarą „zgięcia” łuku od punktu y do punktu x jest różnica między jego łożyskiem w punkcie y a łożyskiem bezpośrednio od y do x . Taki łuk jest sektorem koła, na którym leżą oba y i x ; geometria elementarna pokazuje, że kąt gięcia jest równy połowie kąta zawarcia w łuku.
Aby opisać algorytm, potrzebujemy trochę więcej notacji. Niech y będzie punktem początkowym (zgodnie z rzutem na mapie) i niech x_1 , x_2 , ..., x_n będą punktami docelowymi. Zdefiniuj a_i jako namiar od y do x_i , i = 1, 2, ..., n .
Na wstępie przyjmijmy, że łożyska (wszystkie od 0 do 360 stopni) są w porządku rosnącym: wymaga to obliczenia łożysk, a następnie ich posortowania; oba są prostymi zadaniami.
Idealnie byłoby, gdyby łożyska łuków były równe 360 / n , 2 * 360 / n itd. W stosunku do niektórych łożysk początkowych. Różnice między pożądanymi a rzeczywistymi łożyskami są zatem równe i * 360 / n - a_i plus łożysko początkowe, a0 . Największa różnica to maksimum tych n różnic, a najmniejsza różnica to ich minimum. Ustawmy a0 tak, aby znajdowało się w połowie drogi między wartością maksymalną a minimalną; jest to dobry kandydat na łożysko początkowe, ponieważ minimalizuje maksymalną liczbę zgięć, które wystąpią . W związku z tym zdefiniuj
b_i = i * 360 / n - a0 - a_i:
to jest gięcie do użycia .
Narysowanie okrągłego łuku od y do x, który obejmuje kąt 2 b_i, polega na elementarnej geometrii , więc pominę szczegóły i przejdę od razu do przykładu. Oto ilustracje rozwiązań dla 64, 16 i 4 losowych punktów umieszczonych na prostokątnej mapie
Jak widać, rozwiązania wydają się ładniejsze wraz ze wzrostem liczby punktów docelowych. Rozwiązanie dla n = 4 wyraźnie pokazuje, w jaki sposób łożyska są równomiernie rozmieszczone, ponieważ w tym przypadku odstęp wynosi 360/4 = 90 stopni i oczywiście ten odstęp jest dokładnie osiągnięty.
To rozwiązanie nie jest idealne: prawdopodobnie możesz zidentyfikować kilka łuków, które można ręcznie ulepszyć, aby poprawić grafikę. Ale to nie zrobi okropnej roboty i wydaje się, że to naprawdę dobry początek.
Algorytm ma tę zaletę, że jest prosty: najbardziej skomplikowana część polega na sortowaniu miejsc docelowych według ich położenia.
Kodowanie
Nie znam PostGIS, ale być może kod użyty do narysowania przykładów może służyć jako przewodnik dla implementacji tego algorytmu w PostGIS (lub innym GIS).
Za pseudokod należy uważać następujące (ale Mathematica go wykona :-). (Jeśli ta strona obsługuje TeX, podobnie jak matematyka, statystyki i TCS, mógłbym to uczynić o wiele bardziej czytelnym.) Notacja obejmuje:
Wykonalna część kodu jest na szczęście krótka - mniej niż 20 wierszy - ponieważ ponad połowa z nich to albo deklaratywne obciążenie, albo komentarze.
Narysuj mape
z
to lista miejsc docelowych iy
pochodzenie.Utwórz łuk kołowy od punktu
x
do punktu,y
zaczynając od kąta\[Beta]
względem łożyska x -> y.Oblicz łożyska od początku do listy punktów.
Oblicz średnicę resztek zestawu łożysk.
x
to lista łożysk w posortowanej kolejności. Idealnie, x [[i]] ~ 2 [Pi] i / n.źródło
Wypróbuj ST_CurveToLine
Coś jak na przykład:
Możesz to sobie wyobrazić, kopiując zapytanie do pola tekstowego i naciskając Map1 na http://www.postgisonline.org/map.php
źródło
Wydaje mi się, że chcesz po prostu rzucić własną polilinię za pomocą matematyki wektorowej, http://en.wikipedia.org/wiki/B%C3%A9zier_curve , lub jeśli twój gis ma interfejs ICurve .
źródło
Skończyło się na wypróbowaniu tego, aby zakrzywić zestaw „dwupunktowych” linijek za pomocą funkcji ST_CurveToLine, jak sugeruje @Nicklas Avén.
Do funkcji ST_OffsetCurve przekazałem następujące 3 zestawy współrzędnych:
Użyłem funkcji ST_OffsetCurve do obliczenia przesunięcia - 1/10 długości oryginalnej linii w moim przykładzie.
Oto SQL, którego użyłem do wygenerowania linii krzywych z oryginalnych linii prostych:
źródło