ArcGIS Watershed 도구는 어떤 알고리즘을 사용합니까?


10

ArcGIS Watershed 도구 (Spatial Analyst 패키지)에서 어떤 유형의 알고리즘이 사용되는지 알고 있습니까?

Esri 웹 사이트에 제공된 정보는 거의 없지만 ... 어딘가 깊이 / 폭 검색 일 수 있습니다.

다음 ArcGIS Online Help 페이지를 살펴 보았습니다.

예, 흐름 방향 래스터를 사용하지만 래스터를 통과하기 위해 어떤 알고리즘을 사용합니까?

'D8을 사용합니다.'라는 행을 따라 답을 찾지는 않습니다. D8은 실제로 알고리즘이 아니라 사용하는 알고리즘을 정의하는 데 도움이되는 모델입니다. IE는 깊이 우선 검색 알고리즘 및 / 또는 너비 우선 검색 알고리즘 내에서 D8 체계를 구현할 수 있습니다.


James, 내가하려고하는 것 같은 일, 즉 결정된 좌표를 취하고 유역을 묘사하는 앱을 만듭니다. 나는 파이썬을 사용하고 있습니다. 진행 상황에 대해 이야기합시다.

나는 또한 파이썬을 사용하고 있습니다. 흐름 방향 그리드를 계산하고 거기에서 나아가는 간단한 문제로 시작합니다.
James

답변:


6

내가 두 가지 언어로 구현했고 ESRI가 사용한다고 믿는 방법 (죄송합니다,이 페이지의 다른 곳에서 인용 된 Jenson 및 Domingue 이외의 다른 참고 문헌은 없음)은 사용자 제공 "푸어 포인트"셀 또는 셀에서 시작하는 것입니다 흐름 방향 그리드 (fdr)의 가장자리에서 8 개의 이웃을 검사하여 전류 셀로 직접 유입되는 흐름을 찾은 다음 해당 셀을 출력 그리드의 현재 "유역"에 할당합니다. 그런 다음 함수는 유입되는 각 이웃에 대해 한 번씩 재귀 적으로 자신을 호출합니다. 이 프로세스는 모든 유입 셀이 유동점에 대해 소진 될 때까지 반복 된 다음 모든 유동점에 대해 반복됩니다.

재귀 알고리즘 설계는 많은 양의 데이터를 메모리에 저장하려고 시도하고 디스크로 스왑 / 페이징해야하기 때문에 일반적으로 I / O 속도 저하가 발생하기 때문에 상당히 비쌀 수 있습니다.

(RYO를 할 경우 다른 재귀 방법에 대해서는 아래 whuber의 의견을 참조하십시오)

_____________ 수정 _____________

예를 들어 이전 C 코드를 파헤 쳤습니다 (참고 : 대부분의 Pythoners는 방에서 도망 가고 싶지만 너무 나쁘지 않아야합니다). 설명하는 것이 흥미로울 수 있다고 생각했습니다. 난 단지 지금 w / 폭 우선 깊이 우선 재귀 대 표면적으로 잘 알고 있지만, 나는 나의 일상은 참으로 깊이 우선 (내 자연 언어의 설명은 위의 오해였습니다)를 기반이라고 생각하고 이 유래 게시 희망 (@ whuber 또는 나보다 똑똑한 사람은 확인 / 거부 할 수 있습니다).

코드 : 설명 : idir흐름 방향 값의 래스터입니다. offset는 현재 분석되고있는 중앙 셀을 참조하고 off해당 셀의 각 이웃을 확인합니다. 이것은 다른 함수를 호출 does_it_flow_into_me하는데,이 함수 는 인접 셀의 flowdir이 현재 셀을 가리키는 지 여부에 대한 부울을 리턴합니다. 이웃에 해당하는 경우 해당 위치로 재귀하십시오.

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 */
}

너비 우선 재귀를 설명합니다. 작은 스택을 사용하면 메모리를 거의 요구하지 않는 효율적인 깊이 우선 재귀를 구현할 수 있습니다. 주요 성능 문제는 그리드 타일을 RAM에 반복적으로 교체해야하는 대규모 유역과 관련이 있습니다. 그러나 다른 답변들에 대한 의견에서 논의 된 바와 같이, 실제 문제는 독특하게 결정된 D8 방향이없는 셀들, 특히 광범위한 평평한 수평 패치들 (예를 들어 예비 싱크-충전 루틴들에 의해 생성 된 것들) 내에 놓인 셀들에 대처하는 것에 관한 것이다.
whuber

쓰레기 인 쓰레기 문제. 저와 대부분의 GI는 입력을 정리하지 않습니다! 내 핵을 연마하기 위해 깊이 우선 재귀를 찾아야하는 것처럼 들립니다.
Roland

나는 이것이 쓰레기라고 생각하지 않습니다. 구현 방법에 관계없이 원래 입력은 누군가의 D8 코딩이 아니라 DEM 자체입니다. 그러나 그것은 확실히 도전입니다. 현실 세계에는 유동 방향이 결정하기 어려운 평평한 장소가 많이 있습니다. 정적 수역이 좋은 예입니다. 실제로 호수와 다른 평평한 지역의 출구 를 찾아야 하고 여러 개의 배출구 가있는 평평한 지역에 대처해야합니다 . 이를 위해서는 로컬 검색 이외의 검색 이 필요합니다 .
whuber

아마 혼란 스러울 것입니다. flowdir을 입력으로 사용하는 help.arcgis.com/en/arcgisdesktop/10.0/help../index.html#//… 에 대해 논의하고 있다고 생각 합니다. 나머지를 충분히 읽지 않았다면 잡초로 우리를 끌어 들이고 싶지 않습니다!
Roland

아니오, 나는 당신이 옳다고 생각합니다. 질문을 다시 읽으면서, 내가 생각하고있는보다 일반적인 상황보다는 흐름 방향 래스터를 입력으로 처리하는 데 특히 중점을 둡니다. 따라서 직접적이고 통찰력 있고 유용한 정보를 제공하여 답변을 +1하십시오.
whuber

4

는 ArcGIS 도움이 말한다 :

유역은 흐름 방향을 계산하고 유역 도구에서 사용하여 DEM에서 묘사 할 수 있습니다. 기고 영역을 결정하려면 먼저 흐름 방향 도구를 사용하여 흐름 방향을 나타내는 래스터를 만들어야합니다.

흐름 방향은 D8 방법을 사용 하여 DEM 에서 계산됩니다. 여기서 8 개의 이웃 중 각 셀에 대해 계산하여 흐름을 추상화하면이 셀의 물이 흐릅니다.

Rho8, Froh8 및 Stream Tubes와 같은 D8에 대한 많은 대안이 있지만 ArcGIS를 포함한 대부분의 GIS 소프트웨어는 D8을 사용하는 경향이 있습니다. 다른 것보다 간단하고 계산 집약성이 낮기 때문입니다.


몇 년 전에 저는 유역 묘사 프로젝트를 수행하고 있었고 D8 방법을 사용하는 ArcGIS로 인해 몇 가지 문제에 직면했습니다. 두 가지 주요 문제는

  • D8은 단방향 흐름 만 허용합니다. 물은 하나의 세포에서 한 방향으로 만 흐를 수 있습니다.
  • 생성 된 스트림 흐름은 대각선 축을 따라 큰 편향을 가졌습니다. 이로 인해 이상한 시냇물이 생겼습니다.

우리 데이터에서이 두 가지 문제가 큰 문제라는 것을 알았으므로 하이브리드 방법을 사용하여 흐름 방향을 생성하는 도구를 개발했습니다.

가장 빠른 작업 중 하나는 Catchment 계산 도구를 리버스 엔지니어링하는 것이 었습니다. 논리적으로 매우 간단하다는 것을 알았습니다. 주어진 지점 (타설 지점이라고도 함)에 대한 집수를 찾으려면 먼저 해당 지점이 속한 셀을 찾으십시오. 종종 주어진 공차에서 가장 높은 유량으로 포인트에 스냅하려고 시도합니다.

이 셀의 경우 이웃에 기여하는 모든 셀을 찾을 수 있습니다. 이러한 각 인접 셀에 대해 해당 셀 등에 기여하는 셀을 찾습니다. 새 셀을 찾을 때까지이 반복 프로세스를 계속합니다. 그 때 능선이나 유역 경계에 도달했을 때입니다.

ASCII 래스터 에서이 작업을 수행 한 간단한 코드는 ArcGIS의 Watershed 도구와 비교할 때 거의 비슷한 결과를 얻었습니다. 때로는 경계에 몇 개의 셀 차이가 있었으므로 ArcGIS는 수정되지 않은 D8 알고리즘을 따르는 것으로 확신합니다.


정교 해 주셔서 감사합니다. 그러나 유역을 찾기 위해 D8 방향을 사용 하는 알고리즘은 무엇 입니까? dmahr 's answer 다음의 의견을 참조하십시오 .
whuber

안녕하세요, 감사하지만 이것은 실제로 질문에 대답하지 않습니다. "이 셀의 경우 이웃에 기여하는 모든 셀을 찾을 수 있습니다. 이러한 각 인접 셀에 대해 해당 셀 등에 기여하는 셀을 찾을 수 있습니다"라는 문장을 사용했습니다. 해당 검색을 구현하는 여러 가지 알고리즘이 있습니다. 문제는 어느 것입니다
James

4

이것은 약간 다른 맥락에서 전에 요청 되었습니다 . Spatial Analyst의 Hydrological 툴셋의 모든 지오 프로세싱 툴은 흐름 방향 작동 방식 페이지에 설명 된대로 D8 흐름 방향 모델을 사용합니다 .

흐름이 이동할 수있는 8 개의 인접한 셀과 관련된 8 개의 유효한 출력 방향이 있습니다. 이 접근 방식은 일반적으로 8 방향 (D8) 흐름 모델이라고하며 Jenson and Domingue (1988)에서 제시된 접근 방식을 따릅니다.

Jenson and Domingue (1988) 논문의 사본은 여기에서 구할 수 있습니다 .

흐름 방향 래스터를 입력으로 사용하는 모든 도구는이 흐름 방향 모델을 연결하여 사용합니다. 여기에는 유역, 유량 누적, 유량 길이, 채우기 등이 포함됩니다.


그래서 질문에 대한 후속 조치가 될 것이라고 생각합니다. 어떻게 알고리즘을 수정하여 집수를 반환합니까?
제임스

유역 도구는 유동점에서 유동 방향 래스터를 탐색합니다. 셀 수를 설명하는 출력 래스터 대신 유동점의 ID를보고한다는 점을 제외하고는 Flow Accumulation 도구의 반대입니다.
dmahr

1
좋아, 좀 더 구체적이어야 할 것 같아. 나는 그것이하는 일의 개념을 안다. 어떤 알고리즘이 구현되는지 모르겠습니다. 즉, 일종의 검색 알고리즘이라고 가정하지만 여전히 가능합니다. 너비 우선, 깊이 우선, 반복 심화 깊이 우선 등 ...
James

1
고마워요 dmahr. @ whuber : 내가 아는 한, 다른 검색 알고리즘이 약간 다른 결과를 줄 수 있습니까? 물론 일반적인 알고리즘을 찾는 것은 문제가되지 않지만 ESRI가 유역 관련 영역 (예 : DTM의 평평한 부분)을 처리하는 방법을 배우는 것이 유용합니다.
제임스

1
James 마지막 스레드를 명확히하기 위해 질문을 편집하여이 스레드가 쓸모없는 "D8"답변을 수집하지 않도록하십시오. ( D8 주석에 도움 되는 것은 D8이 고유 한 흐름 방향 그래프를 가져온다는 사실을 인정 하면 유역이 그래프 자체의 속성이기 때문에 유역 묘사 문제에 대한 고유 한 올바른 솔루션이 있다는 것입니다. (a) "유역"의 정의, (b) D8 방향을 계산하는 방법 또는 (c) 수평 셀 (예 : 고유 한 D8 방향이없는)을 처리하는 방법에 대한
모호성

0

이 질문에 대한 더 많은 생각을하기 위해 나는 유역 분석을 원호로 실행했습니다. 나는 (채워진) DEM을 가져 와서 흐름 방향을 계산하고 이전에 계산 된 스트림 네트워크의 위치에 해당하는 몇 가지 점을 배치했습니다. 나는 '유역'도구를 사용했고 나에게 나머지 유역 '상류'의 대부분을 덮는 멋진 분지 몇 개를 주었다.

유역 이미지

그런 다음 파이썬에서 빠른 검색 알고리즘을 코딩했습니다 (위의 답변과 같이). 흐름 방향 그리드를 검사하고 흐름 경로를 '따릅니다'. 각 노드에 대해 8 개의 이웃을 검사하고 이웃이 현재 노드로 유입되면 이웃 노드를 입력으로 사용하여 동일한 기능을 재귀 적으로 호출합니다.

의사 (ish) 코드 :

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 셀을 반환합니다.

내가 뭘 잘못하고 있는지 아는 사람 있습니까?

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.