使用最少的矩形覆盖折线,同时保持其连续性
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了使用最少的矩形覆盖折线,同时保持其连续性相关的知识,希望对你有一定的参考价值。
给定形成折线的点列表,以及矩形的高度和宽度,如何找到覆盖所有点所需的所有矩形的数量和位置?
矩形应该旋转并且可以重叠,但必须遵循折线的路径(矩形可以包含线的多个线段,但每个矩形必须包含与前一个矩阵相邻的线段。)
在可能的情况下,在矩形的最小边上进行交叉是非常值得赞赏的。
到目前为止我找到的所有解决方案都不干净,这是我得到的结果:
您应该看到它在接近平坦的情况下提供良好的渲染,但在大的路缘中重叠太多。如果前一个矩形被偏移,则可以清楚地移除一个矩形。
实际上,我沿着直线放置一个以宽度/ 2为中心的矩形,并使用凸包和改进的旋转卡尺算法旋转它,并重复从前一个矩形和直线的交点开始。
您可能会发现我从最小化的矩形边界框算法中获取灵感,用于方向,但它不包括切割方面,也不包括固定大小。
谢谢你的帮助!
这有点晚了,你可能已经想到了这一点。但是,我今天有空,并且研究了上次编辑中反映的约束(段的连续性)。正如我在评论中所说,我建议使用贪心算法。它由两部分组成:
- 搜索算法从初始点(我使用binary search algorithm)查找最远点,以便它们之间的所有点位于给定
w
和h
的矩形内。 - 一个重复的循环,在每一步找到最佳矩形并提升初始点。
它们的伪代码分别如下:
function getBestMBR( P, iFirst, w, h )
nP = length(P);
iStart = iFirst;
iEnd = nP;
while iStart <= iEnd
m = floor((iStart + iEnd) / 2);
MBR = getMBR(P[iFirst->m]);
if (MBR.w < w) & (MBR.h < h) {*}
iStart = m + 1;
iLast = m;
bestMBR = MBR;
else
iEnd = m - 1;
end
end
return bestMBR, iLast;
end
function getRectList( P, w, h )
nP = length(P);
rects = [];
iFirst = 1;
iLast = iFirst;
while iLast < nP
[bestMBR, iLast] = getBestMBR(P, iFirst, w, h);
rects.add(bestMBR.x, bestMBR.y, bestMBR.a];
iFirst = iLast;
end
return rects;
请记住,它并不是要找到最佳解决方案,而是在合理的时间内找到次优解决方案。毕竟这是greedy。
另一点是,您可以稍微改进一下,以减少矩形的数量。正如您在标有(*)
的行中看到的那样,我在MBR(Minimum Bounding Rectangle)的方向上保持得到矩形,即使您可以覆盖具有相同w
和h
的矩形的较大MBR,如果旋转矩形。 (1)(2)
我修改了k-means来解决这个问题。它并不快,它不是最佳的,它不能保证,但(恕我直言)这是一个良好的开端。有两个重要的修改:
1-距离测量
我使用Chebyshev-distance启发的测量来查看每个矩形的点数。为了找到从点到每个矩形的距离,首先我将所有点转换为新的坐标系,移动到矩形的中心并旋转到它的方向:
然后我使用这些变换点来计算距离:
d = max(2*abs(X)/w, 2*abs(Y)/h);
对于距矩形每边具有相同距离的所有点,它将给出相等的值。对于位于矩形内的点,结果将小于1.0
。现在我们可以将点分类为最近的矩形。
2-更新集群中心的策略
每个聚类中心都是C
,矩形中心和a
的组合,它的旋转角度。在每次迭代时,将新的点集分配给集群。在这里,我们必须找到C
和a
,以便矩形覆盖最大可能的点数。如果有解决方案,我现在不用,但我采用了统计方法。我使用点的加权平均值更新了C
,并使用点的第一个principal component的方向来更新a
。我使用了由500提供的建议距离的结果作为加权平均值中每个点的权重。它将矩形移向位于其外部的点。
如何找到K.
用1开始并增加它直到从点到它们相应的矩形的所有距离变得小于1.0,这意味着所有点都在矩形内。
结果
更新聚类中心(矩形)的迭代0,10,20,30,40和50:
P.M:我使用了部分Chalous Road作为数据。从Google Maps下载它很有趣。我使用的技术描述了here来采样一组等间距点。
以上是关于使用最少的矩形覆盖折线,同时保持其连续性的主要内容,如果未能解决你的问题,请参考以下文章