我有一个布尔栅格。
在栅格的灰色区域,我想在一个连续范围内拟合给定大小的多边形。
基本上,我有一个不规则多边形,我想在不规则多边形的范围内尽可能多地“拟合”一个已知多边形。
多边形的方向无关紧要,它可以是正方形。我希望它适合图形显示,但是如果它只是将一个数字附加到多边形(适合的#号)上也可以。
我正在使用ArcGIS Desktop 10。
我有一个布尔栅格。
在栅格的灰色区域,我想在一个连续范围内拟合给定大小的多边形。
基本上,我有一个不规则多边形,我想在不规则多边形的范围内尽可能多地“拟合”一个已知多边形。
多边形的方向无关紧要,它可以是正方形。我希望它适合图形显示,但是如果它只是将一个数字附加到多边形(适合的#号)上也可以。
我正在使用ArcGIS Desktop 10。
Answers:
有很多方法可以解决此问题。 数据的栅格格式建议使用基于栅格的方法。在回顾这些方法时,将问题表示为二进制整数线性程序看起来很有希望,因为它非常符合许多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}};
如果从顶部开始从左到右对其单元格编号,则该区域的指标向量有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}}};
生成旋转(和反射)的代码:
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、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];
(前两个指标向量在左侧的前两列中显示。)敏锐的读者可能已经注意到了进行并行处理的几种机会:这些计算可能需要几秒钟的时间。
所有上述内容都可以使用矩阵表示法紧凑地重述:
F是此选项数组,具有M行和N列。
X是长度为N的一组瓷砖放置的指示器。
b是1的N向量。
R是该地区的指标;它是M向量。
与任何可能的解决方案X相关联的总“优度” 等于RFX,因为FX是X覆盖的像元的指标,而R的乘积将这些值相加。(如果希望解决方案偏爱或避开该地区的某些区域,可以对R进行加权。) 这将被最大化。 因为我们可以将其写为(RF)。X,它是一个线性的功能X:这是很重要的。(在下面的代码中,变量c
包含RF。)
约束条件是该
X的所有元素必须为非负数;
X的所有元素必须小于1(这是b中的对应项);
X的所有元素必须是整数。
约束(1)和(2)使它成为线性程序,而第三个要求使它成为整数线性程序。
存在许多用于解决以这种形式表示的整数线性程序的软件包。它们能够处理成千上万的M和N值。对于某些实际应用而言,这可能已经足够了。
作为我们的第一个插图,我使用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 &]]];
灰色单元格根本不在该区域中。白细胞未被该溶液覆盖。
您可以(手动)计算出许多其他与该瓷砖一样好的瓷砖-但您找不到更好的瓷砖。这是这种方法的一个潜在的局限性:它给你一个最佳的解决方案,即使有不止一个。(有一些解决方法:如果我们对X的列进行重新排序,问题仍然没有改变,但是结果是软件经常选择其他解决方案。但是,这种行为是无法预测的。)
作为第二个说明,为了更加现实,让我们考虑问题中的区域。通过导入图像并重新采样,我用69 x 81网格表示它:
该区域包含此网格的2156个单元。
为了使事情有趣,并说明线性编程设置的一般性,让我们尝试用两种矩形覆盖尽可能多的区域:
一个是17 x 9(153个单元),另一个是15 x 11(165个单元)。我们可能更喜欢使用第二个,因为它更大,但是第一个更紧身并且可以放在更狭窄的地方。让我们来看看!
该程序现在涉及N = 5589个可能的图块放置。相当大!经过6.3秒的计算,Mathematica提出了以下10位数解决方案:
由于有些松弛(例如,我们可以将底部的左图块向左移动四列),因此显然还有一些其他解决方案与该解决方案略有不同。
我对“ 寻找算法”中的一个类似问题的回答中提供了“ 关于用于多边形填充的遗传算法 ”的链接,以最小间距将约束区域内的最大点数放置?,可能会很有用。看来该方法可以通用化以处理任意容器形状(而不仅仅是矩形)。
对于您提到的高度受限的子集(坑洞中的正方形/三角形平铺),假设上面有显式优化,则此伪代码应通过简单地带您解决高分辨率问题,蛮力解决问题的方式得出近似答案。在单个磁贴旋转可以看到收益的情况下,例如矩形磁贴或高度不规则的容器,它无法正常工作。这是一百万次迭代,如有必要,您可以尝试更多。
假设边长为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翻译棋盘格
选择完全在容器内的正方形
出口广场