Zwiększenie geometrii PostGIS o wartość procentową

10

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.

James Baker
źródło
2
5% czego? Zakładając, że używasz wielokątów, czy jest to 5% największej szerokości, najwęższej szerokości, obwiedni, odległości wierzchołka od środka ciężkości ...? Jeśli mówisz o punktach lub liniach, ma to jeszcze mniej sensu!
MerseyViking
Sądzę, że odległość wierzchołek-środek ciężkości - a może wzrost powierzchni o 5% również byłby w porządku. Zwiększenie obwiedni jest w porządku, jeśli geometria jest skalowana w celu wypełnienia tego obwiedni. Wszystkie geometrie są zamkniętymi wielokątami (zdecydowana większość to kwadraty).
James Baker,

Odpowiedzi:

8

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:

  1. Uzyskaj obwiednię kształtu.

  2. Niech e będzie średnią długości boków pudełka.

  3. 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.

  1. 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.

  2. 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.

Whuber
źródło
4

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:

    -- Listing 8.26 Combining Scale and Translation to maintain centroid
    SELECT xfactor, yfactor, 
       ST_Translate(ST_Scale(hex.the_geom, xfactor, yfactor), 
       ST_X(ST_Centroid(the_geom))*(1 - xfactor), 
       ST_Y(ST_Centroid(the_geom))*(1 - yfactor) ) As scaled_geometry
    FROM 
 ( SELECT ST_GeomFromText('POLYGON((0 0,64 64,64 128,0 192,-64 128,-64 64,0 0))') As the_geom)  As hex
    CROSS JOIN (SELECT x*0.5 As xfactor 
        FROM generate_series(1,4) As x) As xf
    CROSS JOIN (SELECT y*0.5 As yfactor
        FROM generate_series(1,4) As y) As yf;
LR1234567
źródło
Pracuje. Teraz wydaje się, że jest, ST_Transscaleale jakoś nie potrafię
wymyślić,
0

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

wfgeo
źródło