给定二维多边形的顶点,我必须找到多边形在X
轴上的最小可能投影。
我可以以任意角度旋转多边形。
起初我认为对于最小的情况,多边形的至少一个边将与X
轴对齐,这是不正确的。
多边形可以是凹的或凸的。
给定二维多边形的顶点,我必须找到多边形在X
轴上的最小可能投影。
我可以以任意角度旋转多边形。
起初我认为对于最小的情况,多边形的至少一个边将与X
轴对齐,这是不正确的。
多边形可以是凹的或凸的。
您正在寻找的是所谓的“旋转卡尺算法”。
https://en.wikipedia.org/wiki/Rotating_calipers
关于这个算法的维基百科页面甚至有你的问题的伪代码。
https://en.wikipedia.org/wiki/Rotating_calipers#Minimum_width_of_a_convex_polygon
如评论中所述,如果您用凸包替换多边形,答案将不会改变。所以让我们认为多边形已经是凸的。现在假设我们找到了最小角度。这意味着我们有一条平行于 Y 的条带包围身体。很容易看出,多边形边之一可以位于条带边界上(如果不是,我们可以稍微旋转主体而不增加条带宽度)。
总而言之,我们得到一个算法:计算凸包,然后为包的每一侧选择一个使其平行于 Y 的角度并测试宽度。采取分钟。0
令 X(i, alpha) 为顶点 i 在旋转角度 alpha 后的 X 坐标。
我们总是假设 -PI <= alpha <= PI 。
如果所有 j 的 X(i, alpha)>=X(j, alpha),则令 i=rightmost(alpha)。令 i=second_rightmost(alpha) 如果 X(i, alpha)>=X(j,alpha) 对于除一个之外的所有 j 。类似地定义 leftmost() 和 second_leftmost()。
让我们证明以下内容:如果 X(i, alpha) >= X(j, alpha),并且 X(i, beta) >= X(j, beta),并且 beta-alpha < PI,那么 X(i, gamma) >= X(j, gamma) 对于所有 gamma 中的 alpha, beta]。实际上,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
现在我们有:
这足以通过二分查找在哪个间隔获得最右边的点。通过角度的符号反转,我们得到最左边的点间隔。由于我们知道每个点在哪个区间最左边,每个点在最右边,我们可以计算区间边界处的值,并选择最小的那个。