Який алгоритм використовується інструментом ArcGIS для забору води?


10

Хтось знає, який тип алгоритму використовується в інструменті ArcGIS Watertershed (в пакеті Spatial Analyst)?

Дуже мало інформації, що міститься на веб-сайті Есрі ... але я підозрюю, що це може бути якийсь пошук по глибині / широті.

Я переглянув ці сторінки Інтернет-довідки ArcGIS:

Так, так, він використовує растр напрямку потоку, але який алгоритм він використовує для обходу растру?

Зверніть увагу, я не шукаю відповідей у ​​рядках "він використовує D8 .." ... D8 насправді не алгоритм, а модель, яка допоможе визначити алгоритм, який ви використовували б. IE ви могли б реалізувати схему D8 в рамках алгоритму пошуку перших глибин та / або алгоритму пошуку на першому широті


Джеймс, я намагаюся зробити те ж саме, тобто створити додаток, який би визначив координацію і дав нам акваторію. Я використовую python. Поговоримо про наш прогрес.

Я також використовую Python. Я починаю з більш простої проблеми обчислення сітки напрямку потоку і рухаюся звідти.
Джеймс

Відповіді:


6

Метод, який я реалізував на декількох мовах і вважаю, що ESRI використовує (вибачте, жодних посилань, окрім Jenson та Domingue, цитованих в інших місцях на цій сторінці), - це запустити в надану користувачем клітинку "point-point" або клітинку на краю сітки напрямку потоку (fdr) вивчіть вісім його сусідів, щоб знайти, хто з цих прямих потоків в поточну комірку, і призначити ці комірки поточному "вододілу" у вихідній сітці. Потім функція рекурсивно викликає себе один раз для кожного з припливних сусідів. Цей процес повторюється до тих пір, поки всі осередки, що надходять, не будуть вичерпані для точки виливу, а потім повторяться для всіх точок виливу.

Дизайн рекурсивного алгоритму може бути досить дорогим, оскільки він може закінчитися спробою зберігати багато даних в пам'яті, потребуючи поміняти сторінку / сторінку на диск, а отже, загалом страждає повільний спад.

(див. коментар Ваубера нижче щодо різних методів рекурсії, якщо ви збираєтесь RYO)

_____________ РЕДАКЦІЯ _____________

Прикладіть мій старий код С як приклад (зауважте: Хоча більшість пітонерів, можливо, захоче бігти з кімнати, це не повинно бути дуже погано). Думав, що це може бути цікаво проілюструвати. Хоча я лише зараз поверхово знайомий з першою глибиною та глибиною першою рекурсією, я думаю, що моя рутина справді є глибиною першою (і що мій опис природної мови вище був оманливим) на основі цієї публікації stackoverflow (сподіваюсь @ whuber чи інша людина, розумніша за мене, може підтвердити / заперечити).

Код: пояснення: idirце растр значень напрямку потоку. offsetвідноситься до центральної комірки, яка в даний час аналізується, і offперевіряє кожного з сусідів цієї комірки. Це викликає іншу функцію, does_it_flow_into_meяка повертає булеве значення про те, чи вказує потоковий сигнал сусідньої комірки на поточну комірку. Якщо вірно для сусіда, то поверніться до цього місця.

void shed(int init_x, int init_y, int basin_id){

int i, j, offset, off, flow_dir;

offset = ((init_y - 1) * nc) + (init_x - 1);
*(basin + offset) = basin_id;


/* kernel analysis */
for (i = -1; i <  2; i++) {
    for (j = -1; j <  2; j++) {
        if ((i) || (j)) {

            off = offset + (j * nc +  i);
            flow_dir = *(idir + off);


            if (does_it_flow_into_me(i,j,flow_dir)){
                shed(init_x+i, init_y+j,basin_id);
            }
        } /*not center */
    } /* do - j */
} /* do - i */
}

Ви описуєте першу рекурсію вшир. За допомогою невеликого стека ви можете реалізувати ефективну первинну глибинну рекурсію, яка вимагає мало пам'яті. Основна проблема продуктивності стосуватиметься великих вододілів, де, можливо, доведеться міняти плитки мережі та виходити з оперативної пам’яті неодноразово. Як обговорюється в коментарях до інших відповідей, правда, справжнє питання стосується подолання комірок, де немає однозначно визначеного напрямку D8, особливо клітинок, що лежать у широких плоских горизонтальних патчах (таких, як створені попередніми процедурами заповнення раковини).
whuber

Однозначно випуск сміття в сміття. Те, що я і більшість GIss роблю, не очистить вхід! Здається, що мені потрібно піти на глибину першої рекурсії, щоб нанести трохи лаку на мій злом.
Роланд

Я не думаю, що це сміття - пам'ятайте, незалежно від того, як розбита реалізація, оригінальним вводом є саме DEM, а не чиєсь кодування D8 - але це, безумовно, проблема. У реальному світі є багато таких рівних місць, що напрямок потоку важко визначити: будь-який статичний водогін - хороший приклад. Насправді вам потрібно знайти відводи озер та інших рівнинних ділянок, і вам потрібно впоратися з плоскими ділянками, які мають декілька розеток. Для цього потрібні не локальні пошукові запити, які важко зробити.
whuber

Я, мабуть, тоді заплутався. Я думаю, ми обговорюємо help.arcgis.com/en/arcgisdesktop/10.0/help../index.html#//… , який приймає flowdir як вхід. Не хочете затягувати нас у бур’яни, якщо я не прочитав решту досить уважно!
Роланд

Ні, я думаю, що ви праві: коли я перечитував питання, я бачу, що він зосереджений конкретно на обробці растру потоку як вхід, а не на більш загальну ситуацію, яку я передбачав. Тож +1 до вашої відповіді, щоб звернутися до неї безпосередньо, з розумінням та корисними вказівками.
whuber

4

ArcGIS допомогу говорить:

Вододільні ділянки можуть бути відмежовані від DEM шляхом обчислення напрямку потоку та використання його в інструменті вододілу. Для визначення площі, що вносить свій внесок, слід спочатку створити растр, що представляє напрямок потоку за допомогою інструмента «Напрямок потоку».

Напрямок потоку обчислюється з DEM за допомогою методу D8 , де потік абстрагується шляхом обчислення для кожної комірки, кому з 8 сусідів, вода з цієї клітини буде надходити.

Існує багато альтернатив D8, таких як Rho8, Froh8 & Stream Tubes, але більшість програм GIS, включаючи ArcGIS, як правило, використовують D8, оскільки він простіший і менш обчислювально інтенсивний, ніж інші.


Кілька років тому я працював над проектом розмежування водорозділу, і ми зіткнулися з кількома проблемами завдяки ArcGIS, використовуючи метод D8. Дві головні проблеми були

  • D8 дозволяє здійснювати тільки Універсальний потік. Вода може стікати лише в одному напрямку з однієї клітини.
  • Створені потокові потоки мали величезний зміщення по осі діагоналі. Це породило дивні погляди.

З наших даних ми знали, що ці дві проблеми є великими проблемами, тому я розробив кілька інструментів для генерації напрямків потоку за допомогою гібридних методів.

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

Для цієї клітинки ви знайдете всі клітини в околицях, які сприяють їй. Для кожної з цих сусідніх комірок ви знаходите клітини, які сприяють їм тощо. Ви продовжуєте цей ітераційний процес, поки не знайдете нових комірок. Ось тоді ви досягли лінії хребта або межі вододілу.

Я виявив, що мій простий код, який зробив це для растер ASCII, дав майже аналогічний вихід у порівнянні з інструментом ArcGIS для забору води. Іноді на кордоні була різниця декількох комірок, тому я переконаний, що ArcGIS дотримується немодифікованого алгоритму D8.


Дякую за розроблення. Але який алгоритм використання напрямків D8 для пошуку вододілів? Будь ласка, дивіться коментарі після відповіді dmahr .
whuber

Привіт, дякую, але це насправді не відповідає на питання. Ви натискаєте на нього реченням "Для цієї клітинки ви знайдете всі клітини в околицях, які сприяють їй. Для кожної з цих клітинок сусідства ви знайдете клітини, що сприяють їм тощо". Для здійснення цього пошуку існує багато різних алгоритмів. Питання, яке саме
Джеймс

4

Це було задано раніше , хоча можливо у дещо іншому контексті. Усі інструменти геообробки в наборі інструментів гідрологічного просторового аналітика використовують модель напрямку потоку D8 , як зазначено на сторінці « Як працює напрямок роботи» :

Існує вісім дійсних вихідних напрямків, що стосуються восьми сусідніх комірок, в які може проходити потік. Цей підхід зазвичай називають моделлю потоку у восьми напрямках (D8) і слідкує за підходом, представленим у Jenson and Domingue (1988).

Копія документа Jenson and Domingue (1988) доступна тут .

Всі інструменти, які використовують растри потоку потоку як вхідні, використовують цю модель напрямку потоку асоціативно. Сюди входить включення вододілу, накопичення потоку, довжина потоку, заливка тощо.


Отже, я вважаю, що наступним питанням буде, як цей алгоритм буде змінено для повернення водозбору?
Джеймс

Інструмент «Водоспад» переміщується вгору по растру напрямку потоку від точок заливки. Це зворотний бік інструменту накопичення потоку, за винятком того, що замість вихідного растру, що описує кількість комірок, він повідомляє ідентифікатор точки заливки.
dmahr

1
Гаразд, я думаю, я повинен бути трохи більш конкретним. Я знаю поняття, що це робить. Я не знаю, який алгоритм реалізований. Тобто я припускаю, що це якийсь алгоритм пошуку, але це все-таки може бути; широта-перша, глибина-перша, ітеративне-поглиблення-глибина-перше і т.д. ...
Джеймс

1
дякую dmahr. @whuber: Наскільки я знаю, різні алгоритми пошуку можуть дати дещо різні результати? І так, знайти загальний алгоритм не є проблемою, але навчитися, як ESRI обробляє конкретні ділянки вододілу (наприклад, плоскі частини DTM), є корисним.
Джеймс

1
Джеймс Будь ласка, відредагуйте своє запитання, щоб уточнити цей останній пункт, щоб ця нитка перестала збирати інакше марні відповіді "це D8". (Що це корисно про коментарі D8 в тому , що якщо ви згодні , що D8 призводить до своєрідного напрямку потоку графа, тобто унікальне правильне рішення водозбору проблеми розмежування, оскільки вододіли властивості самого графа. Таким чином , якщо є будь-які неоднозначності, які вони повинні полягати в (а) визначенні "вододілу", (б) як обчислюються напрямки D8, або (в) як обробляються горизонтальні осередки (тобто без унікального напрямку D8).
whuber

0

Щоб детальніше замислитися над цим питанням, я провів аналіз вододілу в дузі: я взяв (заповнений) DEM, обчислив напрямок потоку і розмістив кілька точок, які відповідали місцям раніше розрахованої потокової мережі. Я запустив «вододільний» інструмент, і він дав мені кілька приємних басейнів, в значній мірі охоплюючи більшу частину області, що залишилася «вгору за течією» (як можна було очікувати):

зображення вододілу

Тоді я зашифрував алгоритм швидкого пошуку в Python (на зразок відповіді вище), який перевіряє сітку напрямку потоку та 'слідкує' за шляхами потоку. Для кожного вузла я перевіряю 8 сусідів, і якщо сусід впадає в поточний вузол, я викликаю ту ж функцію рекурсивно з сусіднім вузлом, що і вхід.

Псевдо (іш) код:

class d8():
    def __init__(self, arr):
       self.catchment = set()
       self.arr = arr

    def search(self, node):
        """ Searches all neighbouring nodes to find flow paths """ 

        # add the current node to the catchment
        self.catchment.add(node)

        # search the neighbours, ignore ones we already visited
        for each_neighbour:
            if neighbour is in self.catchment:
               do nothing

            # if the neighbour flows into the current node, visit that neighbour
            elif neighbour_flows_into_me:
               self.search(neighbour)

Я виконував цю функцію, використовуючи ту саму сітку введення напрямку руху та одну і ту ж точку. Проблема полягає в тому, що дуга повертає в цей момент близько 40000 комірок, мій алгоритм повертає 72 комірки.

Хтось знає, що я роблю неправильно?

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