给出形成一条折线的点列表,以及矩形的高度和宽度,如何找到数字和位置?
矩形应该旋转并且可以重叠,但是必须遵循折线的路径(一个矩形可以包含该线的多个线段,但是每个矩形必须包含一个与上一个线段相邻的线段。)
在可能的情况下,最好在矩形的最小边上进行交点。
到目前为止,我发现的所有解决方案都不是干净的,这是我得到的结果:
您应该看到,在接近平坦的情况下,它可以提供良好的渲染效果,但在较大的路缘上,它们的重叠太多。如果前一个矩形已偏移,则可以清楚地删除一个矩形。
实际上,我沿线放置一个以 width / 2 为中心的矩形,并使用凸包和改进的旋转卡尺算法对其进行旋转,并从上一个矩形和直线的交点开始重复。
您可能会发现,我是从最小定向矩形边界框算法获得灵感的,但是它不包括切割方面,也不包括固定尺寸。
感谢您的帮助!
答案 0 :(得分: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:
下午::我使用Chalous Road的一部分作为数据。从Google Maps下载它很有趣。我使用here描述的技术来采样一组等距的点。
答案 1 :(得分:1)
太晚了,您可能已经想通了。但是,我今天有空,并致力于最后一次编辑(细分的连续性)中反映的约束。正如我之前在评论中所说,我建议使用贪婪算法。它由两部分组成:
一种搜索算法,该算法从初始点寻找最远的点(我使用binary search algorithm),因此它们之间的所有点都位于给定w
和{{1} }。
一个重复的循环,可以在每个步骤中找到最佳矩形并推进初始点。
它们的伪代码分别如下:
h
请记住,这并不是要找到最佳解决方案,而是要在合理的时间内找到次优的解决方案。毕竟是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)