Я ищу способ добавить буфер вокруг геометрии PostGIS, но размер буфера должен зависеть от размера геометрии. То есть я хочу, чтобы каждая геометрия была увеличена, скажем, на 5%.
Идея в том, что я ищу пересекающиеся геометрии, но может быть ошибка до 5%, связанная с каждой, которую я хочу принять во внимание.
Кто-нибудь знает лучший способ обойти это?
В базе данных почти миллион строк, поэтому я бы предпочел, чтобы она была достаточно быстрой.
Ответы:
Комментарии предполагают, что 5% не должны быть достигнуты с высокой точностью. (Если это произойдет, это займет долгое время , чтобы амортизировать миллион полигонов!) Поэтому мы можем ссылаться на Пицце Принципе : линейно перемасштабирование функции 2D множитель а перемасштабирует его площадь на в ^ 2.
Вот как идет рассуждение:
Когда форма не слишком запутанная - особенно если она выпуклая - тогда буферизация дает результат, сравнимый с масштабированием формы вокруг центральной точки. (Тем не менее, важно понимать, что буферизация никогда не эквивалентна масштабированию для любых форм, кроме дисков. Для некоторых вогнутых фигур «буфер», вычисляемый с помощью масштабирования, может фактически не включать части самой исходной формы! мы вычислим настоящий буфер формы, но будем использовать эту приблизительную эквивалентность как эвристику, чтобы оценить, сколько буферизировать.)
Если буферная область должна быть на 5% больше, то величина масштабирования должна быть равна sqrt (1 + 5/100), что близко к 1,025: то есть мы должны расширить форму на 2,5% во всех направлениях. ,
Эквивалентно, если мы думаем о форме как имеющей «диаметр» (равный типичному расстоянию поперек), ее радиус должен увеличиться на 2,5%. Это равно 2,5% / 2 = 1,25% диаметра.
Мы можем оценить типичный диаметр из ограничительной рамки формы. Используйте, скажем, среднее арифметическое или длину сторон бокса.
Это предполагает следующий рабочий процесс:
Получите ограничивающий прямоугольник формы.
Пусть е будет средним из сторон длины коробки.
Буфер формы на 1,25% е ; то есть на (5/100) / 4 * е .
Поскольку шаги 1 и 2 требуют очень мало вычислений, это предлагает себя как одно из наиболее быстрых возможных решений. В качестве проверки точности вы можете (конечно) вычислить области буферизованных фигур и сравнить их с исходными областями, чтобы увидеть, насколько близко они достигают желаемого 5% увеличения. Иногда буферизованные области будут даже более чем на 5% больше, но они редко бывают меньше, и для них невозможно быть заметно меньше.
Примеры
В качестве проверки и иллюстрации давайте рассмотрим несколько простых фигур.
Диск радиуса 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% больше.
Прямоугольник со сторонами, параллельными осям координат длин 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 , как и предполагалось.
источник
Вы хотите использовать комбинацию 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:
источник
ST_Transscale
но почему-то я не могу понять, как заставить это работать ...Это очень поздно для вечеринки, но я недавно разработал пользовательскую функцию PostGIS, которая делает это, а также сокращает ее при необходимости:
ST_Dilate
источник