使用ArcGIS Desktop在多边形内填充多边形?


25

我有一个布尔栅格。

在栅格的灰色区域,我想在一个连续范围内拟合给定大小的多边形。

基本上,我有一个不规则多边形,我想在不规则多边形的范围内尽可能多地“拟合”一个已知多边形。

多边形的方向无关紧要,它可以是正方形。我希望它适合图形显示,但是如果它只是将一个数字附加到多边形(适合的#号)上也可以。

我正在使用ArcGIS Desktop 10。


8
这是一个非常困难的问题。例如,要使尽可能多的圆适合一个正方形就需要大量的工作。当原始多边形很复杂时(如图所示),您需要一些强大的优化程序。我找到的解决此问题的最佳方法是模拟退火,但是在ArcGIS中将不可用,并且要花很多技巧才能编写脚本(ArcGIS太慢了)。也许你可以放松你的要求一点,比如装修更小的多边形足够的次数,而不是多次,可能吗?
ub

1
@whuber感谢您编辑我的帖子。是的,足够多次。或者,如何以给定的角度定向。例如 在上图中,在该方向上,我已尽可能多地拟合多边形,如果我将其旋转90度,则可以再拟合一次……
Thad

1
是的,但是也充满陷阱。有些是基本的。例如,由ESRI撰写并出版的文本“ Getting to Know ArcView GIS”(对于版本3)包括一个练习,其中将代表足球场的矩形交互式地放置在多边形内。问题是,练习的答案是错误的,因为作者无法投影数据,并且使用地理坐标的误差很大,足以影响结果。答案在GIS中看起来不错,但如果有人尝试建立该字段,他们会发现那里没有足够的空间:-)。
ub

6
@whuber我想他们认为一个“棒球场”数字就足够了。
Kirk Kuykendall 2012年

2
在不规则多边形内的不规则多边形的一般情况下,这是一个计算上棘手的问题:在所有情况下找到最佳解决方案都不是一个合理的目标,从技术角度来看很可能是NP完全的:哪些情况是无法预先确定的。如果您极大地限制了问题,则某些迭代随机拟合算法可能会为您提供较高的数字。我的感觉是,这不是他们在寻找正确的答案,而是在寻找创造性的方法。
MappingTomorrow 2012年

Answers:


22

有很多方法可以解决此问题。 数据的栅格格式建议使用基于栅格的方法。在回顾这些方法时,将问题表示为二进制整数线性程序看起来很有希望,因为它非常符合许多GIS站点选择分析的精神,并且可以轻松地适应它们。

在此公式中,我们列举了填充多边形的所有可能的位置和方向,我将它们称为“平铺”。与每个图块相关联的是其“优”的度量。目的是找到其总优度尽可能大的非重叠图块的集合。在这里,我们可以将每个图块的优势作为其覆盖的区域。(在数据更加丰富和复杂的决策环境中,我们可能会通过将每个图块中包含的单元格的属性,可能与可见性相关的属性,与其他事物的接近性等等的组合来计算优度。)

对这个问题的约束仅仅是解决方案中没有两个图块可以重叠。

可以通过枚举要填充的多边形(“区域”)1、2,...,M中的像元以一种有助于进行有效计算的方式将其抽象一些。可以使用零和一的指示符矢量对任何图块的位置进行编码,让它们对应于图块覆盖的单元格和其他位置的零。在这种编码中,可以通过它们的指示符向量求和(通常是逐个分量)求和来找到有关瓦片集合所需的所有信息:在至少一个瓦片覆盖一个单元的确切位置上,总和将为非零值,并且总和将更大。多于两个或多个图块重叠的位置。(总和有效地计算了重叠量。)

还有一点点抽象:可能会枚举一组可能的磁贴放置,例如1、2,...,N。任何一组瓦片放置的选择本身都对应于指示符矢量,其中指示符矢量指示要放置的瓦片。

这是解决想法的一个小例子。它与用于进行计算的Mathematica代码一起使用,因此编程困难(或缺乏编程困难)显而易见。

首先,我们描述一个要平铺的区域:

region =  {{0, 0, 1, 1}, {1, 1, 1, 1}, {1, 1, 1, 1}, {1, 1, 1, 1}};

图1:区域

如果从顶部开始从左到右对其单元格编号,则该区域的指标向量有16个条目:

Flatten[region]

{0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1}

让我们使用以下图块以及所有旋转90度的倍数:

tileSet = {{{1, 1}, {1, 0}}};

图2:平铺

生成旋转(和反射)的代码:

apply[s_List, alpha] := Reverse /@ s;
apply[s_List, beta] := Transpose[s];
apply[s_List, g_List] := Fold[apply, s, g];
group = FoldList[Append, {}, Riffle[ConstantArray[alpha, 4], beta]];
tiles = Union[Flatten[Outer[apply[#1, #2] &, tileSet, group, 1], 1]];

(在/math//a/159159的回复中解释了这种有点不透明的计算,该计算表明该计算仅会产生图块的所有可能的旋转和反射,然后删除所有重复的结果。)

假设我们将瓷砖放置如下所示:

图3:瓷砖放置

单元3、6和7在此放置中。由指标向量指定

{0,0,1,0,0,1,1,0,0,0,0,0,0,0,0,0}

如果我们将此图块向右移动一列,则该指标向量将改为

{0,0,0,1,0,0,1,1,0,0,0,0,0,0,0,0}

尝试同时在两个位置放置图块的组合取决于这些指标的总和,

{0,0,1,1,0,1,2,1,0,0,0,0,0,0,0,0}

第七位置的2表示这些重叠在一个单元格中(向下第二行,左起第三列)。因为我们不希望重叠,所以我们将要求任何有效解中向量的总和不得超过1。

事实证明,对于这个问题,瓷砖可能有29种方向和位置组合。(这是通过一些涉及穷举搜索的简单编码而发现的。)我们可以通过将它们的指示符绘制为向量来描述所有29种可能性。(通常使用列而不是行。)这是结果数组的图片,它将包含16行(矩形中每个可能的单元格一个)和29列:

makeAllTiles[tile_, {n_Integer, m_Integer}] := 
  With[{ m0 = Length[tile], n0 = Length[First[tile]]},
   Flatten[
    Table[ArrayPad[tile, {{i, m - m0 - i}, {j, n - n0 - j}}],  {i, 0, m - m0}, {j, 0, n - n0}], 1]];
allTiles = Flatten[ParallelMap[makeAllTiles[#, ImageDimensions[regionImage]] & , tiles], 1];
allTiles = Parallelize[
   Select[allTiles, (regionVector . Flatten[#]) >= (Plus @@ (Flatten[#])) &]];
options = Transpose[Flatten /@ allTiles];

图4:选项数组

(前两个指标向量在左侧的前两列中显示。)敏锐的读者可能已经注意到了进行并行处理的几种机会:这些计算可能需要几秒钟的时间。

所有上述内容都可以使用矩阵表示法紧凑地重述:

  • F是此选项数组,具有M行和N列。

  • X是长度为N的一组瓷砖放置的指示器。

  • b是1的N向量。

  • R是该地区的指标;它是M向量。

与任何可能的解决方案X相关联的总“优度” 等于RFX,因为FXX覆盖的像元的指标,而R的乘积将这些值相加。(如果希望解决方案偏爱或避开该地区的某些区域,可以对R进行加权。) 这将被最大化。 因为我们可以将其写为(RF)。X,它是一个线性的功能X:这是很重要的。(在下面的代码中,变量c包含RF。)

约束条件是

  1. X的所有元素必须为非负数;

  2. X的所有元素必须小于1(这是b中的对应项);

  3. X的所有元素必须是整数。

约束(1)和(2)使它成为线性程序,而第三个要求使它成为整数线性程序。

存在许多用于解决以这种形式表示的整数线性程序的软件包。它们能够处理成千上万的MN值。对于某些实际应用而言,这可能已经足够了。


作为我们的第一个插图,我使用Mathematica 8的LinearProgramming命令为上述示例计算了一个解决方案。(这将最小化通过否定目标函数的线性目标函数最小化,容易变成最大化。)。它返回的溶液(如瓷砖和它们的位置的列表)中0.011秒:

b = ConstantArray[-1, Length[options]];
c = -Flatten[region].options;
lu = ConstantArray[{0, 1}, Length[First[options]]];
x = LinearProgramming[c, -options, b, lu, Integers, Tolerance -> 0.05];
If[! ListQ[x] || Max[options.x] > 1, x = {}];
solution = allTiles[[Select[x Range[Length[x]], # > 0 &]]];

图5:解决方案

灰色单元格根本不在该区域中。白细胞未被该溶液覆盖。

您可以(手动)计算出许多其他与该瓷砖一样好的瓷砖-但您找不到更好的瓷砖。这是这种方法的一个潜在的局限性:它给你一个最佳的解决方案,即使有不止一个。(有一些解决方法:如果我们对X的列进行重新排序,问题仍然没有改变,但是结果是软件经常选择其他解决方案。但是,这种行为是无法预测的。)

作为第二个说明,为了更加现实,让我们考虑问题中的区域。通过导入图像并重新采样,我用69 x 81网格表示它:

图6:区域

该区域包含此网格的2156个单元。

为了使事情有趣,并说明线性编程设置的一般性,让我们尝试用两种矩形覆盖尽可能多的区域:

图7:瓷砖

一个是17 x 9(153个单元),另一个是15 x 11(165个单元)。我们可能更喜欢使用第二个,因为它更大,但是第一个更紧身并且可以放在更狭窄的地方。让我们来看看!

该程序现在涉及N = 5589个可能的图块放置。相当大!经过6.3秒的计算,Mathematica提出了以下10位数解决方案:

图8:解决方案

由于有些松弛(例如我们可以将底部的左图块向左移动四列),因此显然还有一些其他解决方案与该解决方案略有不同。


1
此解决方案的较早版本(但效果不太好)出现在Mathematica网站mathematica.stackexchange.com/a/6888上。同样可能值得注意的是,可以使用较小的配方变化来解决用尽可能少的瓷砖完全覆盖区域的问题(当然,允许一些重叠):这将解决“坑洞修补”问题问题。
ub

1
为了节省空间,此答案未描述某些可能有用的改进。例如,在找到所有可能的图块位置(作为指示符向量)之后,可以将它们全部加起来,以找出哪些图块实际上可以覆盖哪些单元格。在第二个示例中,此类单元格的集合分为两个独立的连接组件。这意味着可以在两个组件中独立解决该问题,从而大大减少了它的大小(从而减少了计算时间)。这种最初的简化对于解决现实世界中的问题往往很重要。
ub

很大的努力和答案。克里斯的回答也很有帮助。谢谢大家的帮助!有效,让我再次朝着正确的方向前进。
塔德

哇!我对类似的问题感兴趣,这篇文章给了我新的观点。谢谢。如果R较大(例如140x140≈20000)怎么办,有什么方法可以降低计算成本?您知道与此问题有关的论文吗?我的搜索关键字没有以正确的方式引导我(直到现在)。
nimcap

@nimcap这是一类重要的问题,因此需要进行大量研究。要搜索的关键字将从“混合整数线性程序”开始,然后根据您发现的内容从那里分支出来。
whuber

5

对“ 寻找算法”中的一个类似问题的回答中提供了“ 关于用于多边形填充的遗传算法 ”的链接,以最小间距将约束区域内的最大点数放置?,可能会很有用。看来该方法可以通用化以处理任意容器形状(而不仅仅是矩形)。


该论文有一些不错的主意(+1),但其所有算法从根本上着眼于在矩形区域内填充多边形。这是因为它代表用代表一组,其中所述多边形程序的离散数据结构(多边形与它们的取向沿着序列)填料滑动,平行于所述正方形的边,朝向指定角落。看起来,这种简单的离散编码对于较复杂的区域将不太有效。也许最初简化网格中的区域会有所帮助。
whuber

2

对于您提到的高度受限的子集(坑洞中的正方形/三角形平铺),假设上面有显式优化,则此伪代码应通过简单地带您解决高分辨率问题,蛮力解决问题的方式得出近似答案。在单个磁贴旋转可以看到收益的情况下,例如矩形磁贴或高度不规则的容器,它无法正常工作。这是一百万次迭代,如有必要,您可以尝试更多。

假设边长为L的正方形

创建正方形的棋盘格图案,该图案至少是容器范围的尺寸,并且每个方向至少要有1L。

N = 0

DX = 0

DY = 0

DR = 0

将棋盘位置重置为原始质心

对于(R = 1:100)

对于(Y = 1:100)

对于(X = 1:100)

M =完全在容器中计数的平方数

如果(M> N)

DR = R

DY = Y

DX = X

N = M

向西移动棋盘L / 100

重置棋盘东

将棋盘向北移动L / 100

重置棋盘北

将棋盘绕其质心旋转3.6度

DY = DY * L

DX = DX *长

将棋盘重置为原始位置并旋转

打印DR&“,”&DX&“和”&DY&“是最终的平移/旋转矩阵”

通过DR旋转棋盘格

由DX,DY翻译棋盘格

选择完全在容器内的正方形

出口广场


如果在2 x 5区域上尝试此过程,并且在一个长边的中间缺少一个像元,则会发现您只能在其中放置2 x 2平方的一个。但是,两个这样的正方形很容易匹配。问题在于它们不是常规“棋盘”模式的一部分。这个困难是使这个问题相当困难的原因之一。
ub

1
对。如果您的容器形状不规则,足以支持多个不连续的规则模式(每个单元只有几个单元格),那么最终结果将远非最佳。在可能性空间中添加类似的内容会非常迅速地增加处理时间,并且需要针对您要针对的特定案例进行一定程度的计划。
MappingTomorrow 2012年
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.