Зростання геометрії PostGIS на відсоток


10

Я шукаю спосіб додати буфер навколо геометрії PostGIS, але розмір буфера повинен залежати від розміру геометрії. Тобто я хочу, щоб кожна геометрія була збільшена, скажімо, на 5%.

Ідея полягає в тому, що я шукаю пересічні геометрії, але може виникнути помилка до 5%, пов'язана з кожною з них, яку я хочу врахувати.

Хтось знає найкращий спосіб зробити це?

База даних має майже мільйон рядків, тому я вважаю за краще, щоб вона була досить швидкою.


2
5% чого? Припускаючи, що ви використовуєте багатокутники, це 5% найбільшої ширини, найвужчої ширини, обмежувального поля, відстані вершини від центральної ...? Якщо ви говорите про точки або лінії, то це має ще менше сенсу!
MerseyViking

Я думаю, що відстань у центрі вершин - або, можливо, збільшення на 5% площі також було б добре. Збільшення обмежувального поля добре, якщо геометрія масштабується, щоб потім заповнити цю обмежувальну скриньку. Усі геометрії - це замкнуті багатокутники (переважна більшість - чотирикутники).
Джеймс Бейкер

Відповіді:


8

У коментарях випливає, що 5% не потрібно отримувати з високою точністю. (Якщо це станеться, це займе довгий час , щоб амортизувати мільйон полігонів!) Тому ми можемо посилатися на Піці Принципі : лінійно перемасштабування функції 2D множник а перемасштабірует його площа на в ^ 2.

Ось як міркують:

  • Коли форма не надто звивиста - особливо якщо вона опукла - тоді буферизація дає результат, порівнянний з масштабуванням фігури навколо центральної точки. (Однак важливо розуміти, що буферизація ніколи не еквівалентна масштабуванню для будь-яких фігур, окрім дисків. Для деяких увігнутих фігур "буфер", обчислений за допомогою масштабування, насправді не може включати частини самої оригінальної форми! Тому в кінцевому підсумку ми будемо обчислювати справжній буфер форми, але тільки з допомогою цієї приблизної еквівалентності в якості евристики , щоб оцінити , скільки в буфер.)

  • Якщо забудована площа повинна бути на 5% більша, то розмір масштабування, таким чином, повинен бути sqrt (1 + 5/100), що наближається до 1,025: тобто ми повинні хотіти розширити форму на 2,5% у всіх напрямках .

  • Еквівалентно, якщо ми вважаємо, що форма має "діаметр" (рівний типовій відстані поперек), її радіус повинен збільшитися на 2,5%. Це дорівнює 2,5% / 2 = 1,25% діаметра.

  • Ми можемо оцінити типовий діаметр із обмежувальної коробки форми. Використовуйте, скажімо, середнє арифметичне або геометричне значення бічних довжин коробки.

Це говорить про наступний робочий процес:

  1. Отримайте обмежувальний ящик форми.

  2. Нехай e - середня довжина бічних коробок.

  3. Буферна форма на 1,25% е ; тобто за (5/100) / 4 * e .

Оскільки кроки 1 і 2 вимагають дуже мало обчислень, це пропонує себе як одне з найшвидших можливих рішень. Для перевірки точності ви можете (звичайно) обчислити площі буферизованих фігур і порівняти їх з початковими областями, щоб побачити, наскільки тісно вони підходять до бажаного 5% збільшення. Іноді забудовані площі будуть навіть більше ніж на 5% більшими, але рідко їх буває менше, і неможливо їх помітно менше.

Приклади

В якості перевірки та ілюстрації розглянемо кілька простих фігур.

  1. Диск радіусом r має обмежувальний ящик зі сторонами довжиною 2 r . Наша формула обчислює e = (5/100) / 4 * 2 * r = r / 40. Буферизована форма очевидно являє собою концентричний диск радіусом r + r / 40 = 1.025 r . Стара область була pi * r ^ 2, тоді як нова область pi * (1,025 r ) ^ 2 = pi * 1,0506 * r ^ 2, що на 5,06% більше.

  2. Прямокутник зі сторонами, паралельними осям координат довжин r і s, дає e = ( r + s ) / 2. Додаткова площа буферизації прямокутника виходить з чотирьох прямокутників шириною (5/100) / 4 e = e / 80 = ( r + s ) / 160, що межують із сторонами плюс чотири чверті кола радіуса e / 80 у кутах. Нехтуючи чверть колами, які будуть невеликими порівняно з іншими областями, Загальна нова площа дорівнює

    2 ( r + s ) * ( r + s ) / 160 = ( r ^ 2 + s ^ 2 + 2 r * s ) / 80.

    Коли r і s не надто різні, ми можемо зрозуміти, що r ^ 2 + s ^ 2 приблизно дорівнює 2 r * s . Це наближення спрощує загальну нову площу до 4 r * s / 80 = 5% від початкової площі r * s , за призначенням.


4

Ви хочете використовувати комбінацію ST_Scale ( http://postgis.net/docs/ST_Scale.html ) та ST_Translate ( http://postgis.net/docs/ST_Translate.html ). У нас є приклад цього в PostGIS в дії та подібний у главі 8. Якщо у вас немає книги, ви можете завантажити код для цієї глави тут:

http://www.postgis.us/chapter_08

Фрагмент із книги Подивіться приклад 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;

Працює. Зараз, здається, також є, ST_Transscaleале я якось не можу зрозуміти, як змусити цю роботу ...
n1000

0

Це дуже пізно для партії, але я нещодавно розробив власну функцію PostGIS, яка це робить, а також зменшивши її при необхідності:

ST_Dilate

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.