Увеличение геометрии 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. Пусть е будет средним из сторон длины коробки.

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

Поскольку шаги 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 , как и предполагалось.

Whuber
источник
4

Вы хотите использовать комбинацию ST_Scale ( http://postgis.net/docs/ST_Scale.html ) и ST_Translate ( http://postgis.net/docs/ST_Translate.html ), я думаю. У нас есть пример этого в PostGIS in Action и аналогичный в Главе 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;
LR1234567
источник
Работает. Теперь, кажется, также, ST_Transscaleно почему-то я не могу понять, как заставить это работать ...
n1000
0

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

ST_Dilate

wfgeo
источник