Szukam sposobu na dodanie bufora wokół geometrii PostGIS, ale rozmiar bufora powinien zależeć od wielkości geometrii. To znaczy, chcę, aby każda geometria została powiększona o, powiedzmy, 5%.
Chodzi o to, że szukam przecinających się geometrii, ale może występować błąd do 5% związany z każdą z nich, którą chcę wziąć pod uwagę.
Czy ktoś wie, jak to zrobić?
Baza danych ma prawie milion wierszy, więc wolałbym, żeby była dość szybka.
Odpowiedzi:
Komentarze sugerują, że 5% nie musi być osiągane z wysoką dokładnością. (Jeśli tak, to zajmie dużo czasu, aby bufor A milionów wielokątów!) Możemy zatem powołać się na Pizza Zasada : liniowo przeskalowania funkcji 2D za pomocą czynnika A przeskalowanie swój obszar przez a ^ 2.
Oto jak brzmi uzasadnienie:
Kiedy kształt nie jest zbyt skomplikowany - szczególnie jeśli jest wypukły - wówczas buforowanie daje wynik porównywalny do przeskalowania kształtu wokół centralnego punktu. (Ważne jest jednak, aby zrozumieć, że buforowanie nigdy nie jest równoważne przeskalowaniu dla jakichkolwiek kształtów innych niż dyski. W przypadku niektórych kształtów wklęsłych „bufor” obliczony przez przeskalowanie może w rzeczywistości nie zawierać części samego kształtu! Dlatego ostatecznie my będzie obliczyć rzeczywisty bufor kształtu, ale tylko za pomocą tej równoważności jako heurystyki do oszacowania , ile do buforowania przez).
Jeśli buforowany obszar ma być o 5% większy, wówczas wartość przeskalowania powinna wynosić sqrt (1 + 5/100), co jest bliskie 1,025: to znaczy, powinniśmy chcieć rozszerzyć kształt o 2,5% we wszystkich kierunkach .
Odpowiednio, jeśli uważamy, że kształt ma „średnicę” (równą typowej odległości w poprzek), jego promień powinien wzrosnąć o 2,5%. Jest to równe 2,5% / 2 = 1,25% średnicy.
Typową średnicę możemy oszacować na podstawie obwiedni kształtu. Użyj, powiedzmy, arytmetycznej lub geometrycznej średniej długości boków pudełka.
Sugeruje to następujący przepływ pracy:
Uzyskaj obwiednię kształtu.
Niech e będzie średnią długości boków pudełka.
Buforuj kształt o 1,25% e ; to znaczy przez (5/100) / 4 * e .
Ponieważ kroki 1 i 2 wymagają bardzo mało obliczeń, oferuje się to jako jedno z najszybszych możliwych rozwiązań. Aby sprawdzić dokładność, możesz (oczywiście) obliczyć obszary zbuforowanych kształtów i porównać je z obszarami oryginalnymi, aby zobaczyć, jak bardzo zbliżają się one do pożądanego wzrostu o 5%. Czasami buforowane obszary będą nawet większe o ponad 5%, ale rzadkie jest, że są mniejsze i nie jest możliwe, aby były znacznie mniejsze.
Przykłady
Jako czek i ilustrację rozważmy kilka prostych kształtów.
Tarcza o promieniu r ma obwiednię z bokami o długości 2 r . Nasza formuła oblicza e = (5/100) / 4 * 2 * r = r / 40. Buforowany kształt jest oczywiście koncentrycznym dyskiem o promieniu r + r / 40 = 1,025 r . Stary obszar to pi * r ^ 2, podczas gdy nowy obszar to pi * (1.025 r ) ^ 2 = pi * 1.0506 * r ^ 2, czyli o 5,06% więcej.
Prostokąt o bokach równoległych do osi współrzędnych o długości r i s daje e = ( r + s ) / 2. Dodatkowy obszar buforowania prostokąta pochodzi z czterech prostokątów o szerokości (5/100) / 4 e = e / 80 = ( r + s ) / 160 graniczących z bokami plus cztery ćwierć koła o promieniu e / 80 w rogach. Z pominięciem ćwiartek, które będą małe w porównaniu z innymi obszarami, Całkowity nowy obszar jest równy
2 ( r + s ) * ( r + s ) / 160 = ( r ^ 2 + s ^ 2 + 2 r * s ) / 80.
Gdy R i y nie są zbyt różne, można ustalić r ^ 2 + s ^ 2 wynosi około 2 r * s . To przybliżenie upraszcza całkowity nowy obszar do 4 r * s / 80 = 5% pierwotnego obszaru r * s , zgodnie z przeznaczeniem.
źródło
Chcesz użyć kombinacji ST_Scale ( http://postgis.net/docs/ST_Scale.html ) i ST_Translate ( http://postgis.net/docs/ST_Translate.html ) Myślę, że. Mamy taki przykład w PostGIS w akcji i podobnie w rozdziale 8. Jeśli nie masz książki, możesz pobrać kod dla tego rozdziału tutaj:
http://www.postgis.us/chapter_08
Fragment z książki Spójrz na przykład 8.26:
źródło
ST_Transscale
ale jakoś nie potrafięJest już późno na imprezę, ale niedawno opracowałem niestandardową funkcję PostGIS, która to robi, a także zmniejszam ją w razie potrzeby:
ST_Dilate
źródło