考虑到2D多边形的顶点,我必须在X
轴上找到多边形的最小可能投影。
我被允许以任意角度旋转多边形。
首先我想到了最小的情况,至少有一个多边形的边将与X
轴对齐,但事实并非如此。
多边形可以是凹面或凸面。
答案 0 :(得分:6)
您正在寻找的是“旋转卡尺算法”。
https://en.wikipedia.org/wiki/Rotating_calipers
关于此算法的维基百科页面甚至为您的问题提供了伪代码。
https://en.wikipedia.org/wiki/Rotating_calipers#Minimum_width_of_a_convex_polygon
答案 1 :(得分:2)
如评论中所述,如果用凸包替换多边形,答案将不会发生变化。所以我们认为多边形已经是凸的。现在假设我们找到了最小角度。这意味着我们有一条平行于Y的条带限制身体。很容易看出多边形边之一可以位于条带边界上(如果不是,我们可以稍微旋转主体而不增加条带宽度)。
总结一下,我们得到一个算法:计算凸包,然后为船体的每一侧选择一个角度,使其与Y平行并测试宽度。拿分钟。 0
答案 2 :(得分:0)
设X(i,alpha)为旋转角度α后的顶点i的X- coodrinate。
我们总是假设-PI< = alpha< = PI。
如果X(i,alpha)> = X(j,alpha),则对于所有j,令i =最右边(alpha)。如果除了一个之外的所有j,则i = second_rightmost(alpha),如果X(i,alpha)> = X(j,alpha)。类似地定义leftmost()和second_leftmost()。
让我们证明以下内容:如果X(i,α)> = X(j,α),并且X(i,β)> = X(j,β),并且β-α<1。对于[α,β]中的所有γ,PI,然后X(i,γ)> = X(j,γ)。实际上,X(i,alpha)= x [i] * cos(alpha)-y [i] * sin(alpha),其中(x [i],y [i])是顶点i的初始位置。因此,X(i,a)-X(j,a)= c1 * cos(a)-c2 * sin(a),其中c1 = x [i] -x [j],c2 = y [i] - Y [j]的。设f(a)= X(i,a)-Y(i,a)。函数f是连续的,并且当tan(a)= c1 / c2时改变其符号,即a = atan2(c1,c2)+ PI * n。如果是beta-alpha
现在我们有:
这足以通过二进制搜索获得哪个点是最右边的间隔。通过角度的符号反转,我们得到最左边的点间隔。由于我们知道每个点最左边的哪个间隔,并且每个点都是最右边的,我们可以计算间隔之间边界处的值,并选择最小值。