有谁知道ArcGIS分水岭工具(在Spatial Analyst软件包中)使用哪种算法?
Esri网站上提供的信息很少...但是我怀疑这可能是某种深度/广度搜索。
我查看了以下ArcGIS Online帮助页面:
是的,它使用流向栅格,但是遍历栅格使用什么算法?
请注意,我并不是在寻找“它使用D8 ..”的答案。...D8并不是真正的算法,而是可以帮助定义您将要使用的算法的模型。IE,您可以在深度优先搜索算法和/或广度优先搜索算法中实施D8方案
有谁知道ArcGIS分水岭工具(在Spatial Analyst软件包中)使用哪种算法?
Esri网站上提供的信息很少...但是我怀疑这可能是某种深度/广度搜索。
我查看了以下ArcGIS Online帮助页面:
是的,它使用流向栅格,但是遍历栅格使用什么算法?
请注意,我并不是在寻找“它使用D8 ..”的答案。...D8并不是真正的算法,而是可以帮助定义您将要使用的算法的模型。IE,您可以在深度优先搜索算法和/或广度优先搜索算法中实施D8方案
Answers:
我已经用几种语言实现并相信ESRI使用的方法(对不起,除此页其他地方引用的Jenson和Domingue之外,没有其他参考)是从用户提供的“倾点”单元或一个单元开始的在流向网格(fdr)的边缘,检查其八个邻居,以找出哪些直接流进当前单元格,并将这些单元格分配到输出网格中的当前“分水岭”。然后,该函数为每个流入的邻居递归调用一次。重复此过程,直到所有流入的池都用完了一个倾点为止,然后对所有倾点重复一次。
递归算法设计可能会非常昂贵,因为它最终可能会试图在内存中保存大量数据,不得不交换/分页到磁盘,因此通常会遭受I / O速度降低的麻烦。
(如果要使用RYO,请参见下面关于不同的递归方法的wuber的评论)
_____________ 编辑 _____________
挖出我的旧C代码作为示例(注意:尽管大多数pythoner可能想从房间运行,但应该不会太糟)。认为可能需要说明。尽管我现在才刚刚肤浅地熟悉w / breadth-first vs depth-first递归,但基于此stackoverflow发布(希望@或比我聪明的人可以确认/拒绝)。
代码:说明:idir
是流向值的栅格。offset
指当前正在分析的中心单元,并off
检查该单元的每个邻居。这将调用另一个函数,does_it_flow_into_me
该函数返回有关相邻单元格的flowdir是否指向当前单元格的布尔值。如果对邻居为true,则递归到该位置。
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 */
}
在ArcGIS的帮助说:
通过计算流向并在分水岭工具中使用它,可以从DEM划定分水岭。为了确定贡献区域,必须首先使用“流向”工具创建代表流向的栅格。
流动方向是使用D8方法从DEM计算得出的,其中,通过计算每个单元的水量来抽象流,该单元是8个邻居中的哪个,该单元中的水将流向该单元。
D8有许多替代方案,例如Rho8,Froh8和Stream Tubes,但是大多数GIS软件(包括ArcGIS)都倾向于使用D8,因为它比其他方法更简单且计算量更少。
几年前,我正在进行“分水岭划界”项目,由于ArcGIS使用D8方法,我们遇到了一些问题。两个主要问题是
根据我们的数据,我们知道这两个问题是大问题,因此我开发了一些工具来使用混合方法生成流向。
我最早的任务之一是对流域计算工具进行逆向工程。我发现从逻辑上讲它很简单。如果要查找给定点(也称为倾泻点)的汇水面积,首先要找到其所属的单元。通常,您将尝试在给定的公差范围内将其捕捉到具有最高流量累积的点。
对于此单元格,您将找到附近所有对其有贡献的单元格。对于这些邻近单元中的每一个,您都会找到对它们有贡献的单元,依此类推。您将继续执行此迭代过程,直到找不到新的单元格为止。那是当您到达山脊线或分水岭边界时。
我发现,与ASCII分水岭工具相比,我的简单代码(对ASCII栅格执行此操作)提供了几乎相似的输出。有时边界上的几个像元之间存在差异,因此我确信ArcGIS遵循的是未经修改的D8算法。
之前曾有人问过这个问题,尽管可能情况略有不同。Spatial Analyst的水文工具集中的所有地理处理工具都使用D8流向模型,如“流向如何工作”页面中所述:
有八个有效的输出方向与流可能进入的八个相邻单元有关。这种方法通常称为八向(D8)流动模型,并且遵循Jenson和Domingue(1988)中提出的方法。
詹森和多明格(Jenson and Domingue,1988)论文的副本可在此处获得。
所有使用“流向”栅格作为输入的工具都可以通过关联使用此流向模型。这包括分水岭,流量累积,流量长度,填充等。
为了进一步思考这个问题,我在弧线中进行了分水岭分析:我采用了(填充的)DEM,计算了流向,并放置了一些与先前计算的流网络上的位置相对应的点。我运行了“分水岭”工具,它给了我一些不错的盆地,几乎覆盖了上游其余大部分区域(正如您所期望的那样):
然后,我用Python编写了一种快速搜索算法(如上述答案),该算法检查流向网格并“遵循”流路。对于每个节点,我检查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)
我使用相同的流向输入网格和相同的点之一来运行该函数。问题是,在该点上,arc返回的集水量约为40000个像元,而我的算法仅返回72个像元。
有人知道我在做什么错吗?