使用最少的矩形覆盖一条多边形线,同时保持其连续性

时间:2018-08-21 09:53:40

标签: algorithm geometry

给出形成一条折线的点列表,以及矩形的高度宽度,如何找到数字和位置

矩形应该旋转并且可以重叠,但是必须遵循折线的路径(一个矩形可以包含该线的多个线段,但是每个矩形必须包含一个与上一个线段相邻的线段。)

在可能的情况下,最好在矩形的最小边上进行交点。

到目前为止,我发现的所有解决方案都不是干净的,这是我得到的结果:

Actual Render

您应该看到,在接近平坦的情况下,它可以提供良好的渲染效果,但在较大的路缘上,它们的重叠太多。如果前一个矩形已偏移,则可以清楚地删除一个矩形。

实际上,我沿线放置一个以 width / 2 为中心的矩形,并使用凸包和改进的旋转卡尺算法对其进行旋转,并从上一个矩形和直线的交点开始重复。

您可能会发现,我是从最小定向矩形边界框算法获得灵感的,但是它不包括切割方面,也不包括固定尺寸。

感谢您的帮助!

2 个答案:

答案 0 :(得分:2)

我修改了k-means来解决此问题。它不是很快,不是最优,不能保证,但是(恕我直言)这是一个好的开始。 有两个重要的修改:

1-距离度量

我使用了受Chebyshev-distance启发的度量来查看每个矩形的距离。为了找到点到每个矩形的距离,首先将所有点转换为新的坐标系,移至矩形的中心并旋转至其方向:

Transformation of original data to coordinate system of rectangle

然后我使用这些变换的点来计算距离:

d = max(2*abs(X)/w, 2*abs(Y)/h);

它将为与矩形的每一侧具有相同距离的所有点提供相等的值。对于位于矩形内的点,结果将小于1.0。现在我们可以将点分类到最接近的矩形。

2-更新集群中心的策略

每个群集中心是矩形中心C和旋转角a的组合。在每次迭代中,将新的点集分配给一个群集。在这里,我们必须找到Ca,以便矩形覆盖最大可能的点数。我现在是否有解决方案,但我使用了统计方法。我使用点的加权平均值更新了C,并使用了第一个点principal component的方向来更新a。我使用建议的距离(以500为单位)的结果作为加权平均中每个点的权重。它将矩形移向位于矩形外部的点。

如何找到K

以1初始化它,然后增加它直到点到其相应矩形的所有距离都小于1.0,这意味着所有点都在矩形内。

结果

更新聚类中心(矩形)的迭代0、10、20、30、40和50: Iterations

测试案例1的解决方案: enter image description here

尝试K:2、4、6、8、10和12,以实现完整覆盖: Different Ks

测试案例2的解决方案: enter image description here

下午::我使用Chalous Road的一部分作为数据。从Google Maps下载它很有趣。我使用here描述的技术来采样一组等距的点。

答案 1 :(得分:1)

太晚了,您可能已经想通了。但是,我今天有空,并致力于最后一次编辑(细分的连续性)中反映的约束。正如我之前在评论中所说,我建议使用贪婪算法。它由两部分组成:

  1. 一种搜索算法,该算法从初始点寻找最远的点(我使用binary search algorithm),因此它们之间的所有点都位于给定w和{{1} }。

  2. 一个重复的循环,可以在每个步骤中找到最佳矩形并推进初始点。

它们的伪代码分别如下:

h

测试案例1的解决方案: enter image description here

测试案例2的解决方案: enter image description here

请记住,这并不是要找到最佳解决方案,而是要在合理的时间内找到次优的解决方案。毕竟是greedy

另一点是,您可以对此进行一些改进以减少矩形的数量。正如您在标记为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; 的行中看到的那样,尽管您可以使用相同的(*)和{{ 1}}(如果您旋转矩形)。 (Minimum Bounding Rectangle)(1