Я пытаюсь улучшить в настоящее время чрезвычайно громоздкий процесс вектор / питон для модели естественной опасности. На данный момент у нас есть длинный скрипт, который генерирует линии расстояния / пеленга из заданной точки, чтобы определить:
- тип полигона, который он пересекает (например, лес, трава, болото и т. д.)
- расстояние до этого многоугольника
- сколько из этих линий пересекают многоугольники, чтобы определить, насколько они «окружены».
Там гораздо больше, но это суть. Я пытаюсь найти способ улучшить это, и в настоящее время нахожусь в тупике в части 3. Идея состоит в том, чтобы определить, полностью ли точка окружена полигонами, скажем, в 200 м.
Поэтому на моем прикрепленном изображении я бы хотел, чтобы точка A была отмечена как находящаяся под более высоким риском, чем точка B, поскольку она полностью окружена моими полигонами. Это повторяется примерно для 13 миллионов точек, так что это не маленькая задача, и я бы предпочел иметь поверхность для получения значений, а не запускать наш скрипт. Я думаю, что для этого должен быть вариант гидрологических инструментов или затрат, но я никак не могу обойти это.
Как я мог пойти об этом?
Ответы:
Существует решение с использованием затратного пути, но вам придется кодировать его самостоятельно. Вот как это может выглядеть применительно к каждой точке изображения в вопросе (немного увеличено, чтобы ускорить вычисления):
Черные клетки являются частями окружающих многоугольников. Цвета, от светло-оранжевого (короткий) до синего (длинный), показывают максимальное расстояние (максимум до 50 ячеек), которое может быть достигнуто путем прохождения линии прямой видимости без перехвата многоугольных ячеек. (Любая ячейка за пределами этого изображения рассматривается как часть многоугольников.)
Давайте обсудим эффективный способ сделать это, используя растровое представление данных. В этом представлении все «окружающие» многоугольные ячейки будут иметь, скажем, ненулевые значения, а любая ячейка, которая может быть «просвечена», будет иметь нулевое значение.
Шаг 1: Предварительный расчет структуры данных окрестности
Сначала вы должны решить, что значит для одной клетки блокировать другую. Одно из самых справедливых правил, которые я могу найти, заключается в следующем: используя интегральные координаты для строк и столбцов (и предполагая, что квадратные ячейки), давайте рассмотрим, какие ячейки могут блокировать ячейку (i, j) из представления в начале координат (0,0). Я назначаю ячейку (i ', j'), которая находится ближе всего к отрезку, соединяющему (i, j) с (0,0) среди всех ячеек, координаты которых отличаются от i и j не более чем на 1. Поскольку это не всегда дать уникальное решение (например, при (i, j) = (1,2) оба (0,1) и (1,1) будут работать одинаково хорошо), необходимы некоторые средства для устранения связей. Было бы хорошо, если бы это разрешение связей учитывало симметрию круговых окрестностей в сетках: отрицание либо координаты, либо переключение координат сохраняют эти окрестности. Поэтому мы можем решить, какие клетки блокировать (я,
Это правило иллюстрирует следующий код прототипа, написанный на
R
. Этот код возвращает структуру данных, которая будет удобна для определения «окруженности» произвольных ячеек в сетке.Значение
screen(12)
было использовано для создания этого отношения скрининга: стрелки указывают от ячеек к тем, которые немедленно их экранируют. Оттенки пропорциональны расстоянию до начала координат, которое находится в середине этого района:Это вычисление быстрое и должно быть сделано только один раз для данной окрестности. Например, при поиске 200 м на сетке с 5-метровыми ячейками размер окрестности будет 200/5 = 40 единиц.
Шаг 2. Применение вычислений к выбранным точкам
Все остальное просто: чтобы определить, окружена ли ячейка, расположенная в точке (x, y) (в координатах строки и столбца) относительно этой структуры данных окрестности, выполнить тест рекурсивно, начиная со смещения (i, j) = (0,0) (окрестность происхождения). Если значение в многоугольной сетке в точке (x, y) + (i, j) отлично от нуля, тогда видимость там блокируется. В противном случае нам нужно будет рассмотреть все смещения, которые могли быть заблокированы по смещению (i, j) (которое найдено за время O (1) с использованием возвращаемой структуры данных
screen
). Если нет ни одного заблокированного объекта, мы достигли периметра и пришли к выводу, что (x, y) не окружен, поэтому мы прекращаем вычисление (и не пытаемся осмотреть оставшиеся точки в окрестности).Мы можем собрать еще больше полезной информации, отслеживая самое дальнее расстояние прямой видимости, достигнутое в течение алгоритма. Если это меньше, чем желаемый радиус, ячейка окружена; в противном случае это не так.
Вот
R
прототип этого алгоритма. Это длиннее, чем кажется, потомуR
что изначально не поддерживает (простую) структуру стека, необходимую для реализации рекурсии, поэтому стек также должен быть закодирован. Реальный алгоритм начинается примерно через две трети пути и требует всего около десятка строк или около того. (А половина из них просто обрабатывает ситуацию по краю сетки, проверяя наличие индексов вне диапазона в окрестности. Это можно сделать более эффективным, просто расширив сетку многоугольникаk
строками и столбцами по ее периметру, исключив любые необходимость проверки диапазона индекса за счет увеличения объема оперативной памяти для удержания сетки многоугольника.)В этом примере многоугольные ячейки черные. Цвета дают максимальное расстояние прямой видимости (до 50 ячеек) для неполигональных ячеек: от светло-оранжевого для коротких расстояний до темно-синего для самых длинных расстояний. (Ячейки имеют ширину и высоту в одну единицу.) Видимые полосы создаются маленькими многоугольными «островками» в середине «реки»: каждая из них блокирует длинную линию других ячеек.
Анализ алгоритма
Структура стека реализует поиск в графе видимости окрестности в первую очередь для подтверждения того, что ячейка не окружена. В тех случаях, когда ячейки находятся далеко от любого многоугольника, этот поиск потребует проверки только O (k) ячеек для круговой окрестности радиуса-k. Наихудшие случаи возникают, когда в окрестности имеется небольшое количество рассеянных многоугольных ячеек, но даже при этом граница соседства не может быть полностью достигнута: для этого требуется осмотреть почти все ячейки в каждой окрестности, что является O (k ^ 2) операция.
Следующее поведение типично для того, что будет встречаться. Для малых значений k, если многоугольники не заполняют большую часть сетки, большинство неполигональных ячеек будут явно необоснованными, и алгоритм масштабируется как O (k). Для промежуточных значений масштабирование начинает выглядеть как O (k ^ 2). Поскольку k становится действительно большим, большинство ячеек будут окружены, и этот факт можно будет определить задолго до проверки всей окрестности: тем самым вычислительные усилия алгоритма достигают практического предела. Этот предел достигается, когда радиус окрестности приближается к диаметру самых больших соединенных неполигональных областей в сетке.
В качестве примера я использовал
counting
опцию, закодированную в прототипеscreen
для возврата количества операций стека, используемых в каждом вызове. Это измеряет вычислительные усилия. На следующем графике показано среднее число операций стека в зависимости от радиуса окрестности. Это демонстрирует предсказанное поведение.Мы можем использовать это для оценки вычислений, необходимых для оценки 13 миллионов точек на сетке. Предположим, что используется окрестность k = 200/5 = 40. Тогда в среднем потребуется несколько сотен операций стека (в зависимости от сложности сетки многоугольников и от того, где расположены 13 миллионов точек относительно многоугольников), что означает, что в эффективном скомпилированном языке не более нескольких тысяч простых числовых операций потребуется (сложение, умножение, чтение, запись, смещение и т. д.). Большинство компьютеров смогут оценить окружение примерно в миллион очков с такой скоростью. (The
R
реализация намного, намного медленнее, чем это, потому что это плохо в алгоритме такого рода, поэтому его можно рассматривать только как прототип.) Соответственно, мы могли бы надеяться, что эффективная реализация на достаточно эффективном и соответствующем языке - C ++ и Python приходит на ум - может завершить оценку 13 миллионов точек в минуту или меньше, при условии, что вся многоугольная сетка находится в оперативной памяти.Когда сетка слишком велика для размещения в ОЗУ, эту процедуру можно применить к мозаичным частям сетки. Они должны перекрываться только
k
строками и столбцами; возьмите максимумы в перекрытиях при составлении мозаики результатов.Другие приложения
«Извлечь» из тела воды тесно связана с «surroundedness» его точек. Фактически, если мы используем радиус окрестности, равный или превышающий диаметр водоема, мы создадим сетку (ненаправленного) извлечения в каждой точке водоема. Используя меньший радиус окрестности, мы, по крайней мере, получим нижнюю границу для выборки во всех точках самой высокой выборки, что в некоторых приложениях может быть достаточно хорошим (и может существенно уменьшить вычислительные усилия). Вариант этого алгоритма, который ограничивает отношение «экранированный» определенными направлениями, будет одним из способов эффективного вычисления выборки в этих направлениях. Обратите внимание, что такие варианты требуют модификации кода для
screen
; код дляpanvisibility
не меняется вообще.источник
Я определенно вижу, как можно сделать это с помощью растрового решения, но, учитывая даже уменьшенное количество точек, я ожидал бы очень большое / высокое разрешение и, следовательно, сложную обработку сетки или набора сеток. Учитывая это, мне интересно, может ли использование топологии в GDB быть более эффективным. Вы можете найти все внутренние пустоты с чем-то вроде:
затем вы можете работать
topoErrorsVoidPolys
в обычном порядкеIntersect_analysis()
или как угодно. Возможно, вам придется возиться с извлечением интересующих вас политикtopoErrorsVoidPolys
. У @whuber есть много отличных постов о подобных вещах в других местах здесь, на gis.stackexchange.com.источник
Если вы действительно хотите сделать растр ... я бы сделал что-то в духе этого псевдокода (не смущайтесь, потому что очевидно, что я возвращаю AML!: P)
Просто придумал, так что, возможно, потребуется доработка.
источник
Expand()
, но в этот момент я думаю, что ответ @radouxju будет функционально эквивалентным и, вероятно, быстрее. (ничего против видимости, просто не пользуйтесь им много).Expand()
чтобы сказать, сделать это наpts_g
и просто использовать,Con()
чтобы пересечь сpolys_g
.Если вы используете пороговое значение расстояния (здесь вы говорите о 200 м), то лучшим решением будет использовать векторный анализ:
1) создайте 200-метровый буфер вокруг каждой точки (черным на иллюстрации)
2) использовать инструмент пересечения (анализ) между буфером и полигонами (синим цветом на иллюстрации). Это будет выглядеть лучше, если вы сделаете это между границами окружающих полигонов и буфера, но конечный результат тот же.
3) использовать функцию полигона (управление) для создания полигонов, где ваши точки полностью окружены (красным на иллюстрации)
4) выберите слои по местоположению (управление) или пространственному объединению (анализ), чтобы определить точки, которые окружены. Использование пространственного соединения позволяет получить информацию о многоугольнике внедрения (площадь многоугольника, зональная статистика ...), которая может быть полезна для дальнейшей обработки.
Варианты 2b) В зависимости от ваших потребностей, вы можете выбрать расположение окружающих полигонов на расстоянии 200 м, затем вы можете определить некоторые виды «вложения», но не так строго, как в 2).
Рассматривая «случай лабиринта», это могло бы помочь: оценить, сколько времени нужно «убежать» из локации.
Вы уже можете исключить из анализа баллы, которые полностью включены или полностью свободны
затем вы преобразуете свои препятствия в растр и устанавливаете значения для NoData, где у вас есть многоугольник, и для размера ячейки в метрах, где вы этого не делаете (это сделает ваш растр стоимости).
в-третьих, вы можете вычислить расстояние затрат, используя только что созданный растр затрат
наконец, вы используете зональную статистику в качестве таблицы, основанной на границах буфера, преобразованных в растр (образуя кольцо). Если вы можете убежать во всех направлениях, минимум должен быть примерно 200 (в зависимости от размера ячейки вашего анализа). Но если вы находитесь в лабиринте, максимум будет больше 200. Таким образом, максимум зональной статистики минус 200 будет непрерывным значением, указывающим, насколько трудно «сбежать».
источник