在矩形内部计算最大旋转矩形的顶点和尺寸

7

我有一个矩形,必须始终旋转相同的角度。我们将这个角度称为α()。

这个矩形的宽度(w)和高度(h)可能会变化。该矩形必须始终旋转以适合大矩形内部。它必须被缩放以适应灰色矩形内部。

注意:α是w和水平线之间的角度。

因此,有三种类型的矩形:

w > h
w < h  or
w = h

请看下图:

enter image description here

已知:
  1. 大矩形的宽度为R,高度为K,两个值都已知;
  2. w和h未知;
  3. 矩形总是旋转角度度数;
  4. 我知道w/h的值。我将其称为“ratioWH”;
  5. 红色矩形总是水平和垂直居中于灰色矩形上。
需要了解:
  1. 每个w和h情况下适合灰色矩形的最大w和h值;
  2. 点P的坐标,假设0,0在灰色矩形的左上角。
这是我目前所做的,但这并没有给出正确的值:
CGPoint P = CGPointZero;

if (ratioWH > 0) { // means w > h

    maxH = R / (ratioWH * fabsf(cosf(theta)) + fabsf(sinf(theta)));
    maxW = maxH * ratioWH;

    // P.x = 0.0f;  // P.x is already zero
    CGFloat marginY = (K - maxW * fabsf(sinf(theta)) - maxH * fabsf(cosf(theta))) / 2.0f;
    P.y = marginY +  maxW * fabsf(sinf(theta));

} else { // w <= h

    maxW  = K / (fabsf(cosf(theta) / ratioImagemXY) + fabsf(sinf(theta)));
    maxH = maxW / ratioWH;


    P.x = (R - maxW * fabsf(cosf(theta)) - maxH * fabsf(sinf(theta))) / 2.0f;
    P.y = maxW * fabsf(sinf(theta));

} 

有什么线索吗?谢谢。

“the maximum values of w and h that will fit the gray rectangle for each case of w and h” 的意思是什么?您绘图中的角度 alpha 是多少? - High Performance Mark
我的意思是:红色矩形必须适合灰色矩形内部。我已经更改了那个短语。Alpha是w和水平线之间的角度。 - Duck
1个回答

4
我认为可以这样理解...您需要计算矩形的总宽度和总高度。 为此,您只需沿着两条边行走。 就像这样:
dx = w * cos(theta) + h * sin(theta)
dy = h * cos(theta) + w * sin(theta)

这些值可以是负数,因此如果矩形旋转到其他象限,则需要进行特殊处理。这将在稍后发生。

现在您只需要计算宽度和高度之间的比率。这就是您决定是按垂直量还是水平量进行缩放的地方。与wh无关-实际上,它与矩形由于旋转而最终停放的位置有关。这就是dxdy的作用。

rectratio = abs( dx / dy )
viewratio = R / K

如果rectratioviewratio大,这意味着旋转矩形的水平占地面积需要缩放。否则,您需要按垂直占地面积进行缩放。
if rectratio > viewratio
    scale = R / abs(dx)
else
    scale = K / abs(dy)
end

而比例本身是应用于原始宽度和高度的

sw = scale * w
sh = scale * h

现在,您可以计算矩形的四个角。起点并不重要。

x[0] = 0
x[1] = x[0] + sw * cos(theta)
x[2] = x[1] + sh * sin(theta)
x[3] = x[2] - sw * cos(theta)

y[0] = 0
y[1] = y[0] - sw * sin(theta)
y[2] = y[1] + sh * cos(theta)
y[3] = y[2] + sw * sin(theta)

我假设图像坐标的原点(0,0)在左上角,因此增加 y 值会向下移动。所以,如果我的数学没有错误的话,以上内容将为您提供矩形顶点(按顺时针顺序)。
最后一件事是对它们进行规范化… 这意味着找到 pxpy 的最小值。称它们为 pxminpymin。我不需要展示代码。想法是计算一个矩形的偏移量,使视图区域由矩形 (0,0) 到 (R,K) 定义。
首先,我们需要找到完全包含旋转矩形的子视图的左右值。记住之前的比率:
if( rectratio > viewratio )
    // view is too tall, so centre vertically:
    left = 0
    top = (K - scale * abs(dy)) / 2.0
else
    // view is too wide, so centre horizontally:
    left = (R - scale * abs(dx)) / 2.0
    top = 0
end

lefttop现在是包含矩形的子视图的“最小”坐标(浮点舍入误差除外)。因此:

left += pxmin
top += pymin

现在它们是需要偏移的量,以将矩形移动到所需位置。您只需将lefttop添加到所有矩形坐标中,就完成了。 P的位置是px [0]py [0]。如果旋转了90度或更多,则它将不再是左上角顶点。


数学是今天的胜利者 =)如果我是你,我会写一个简单的测试程序来验证这一点。将一个矩形旋转360度进行动画显示。展示视图矩形并显示P。尝试几个不同的w和h值。 - paddy
顺便提一下...关于舍入误差的注释。请注意,我按顺时针顺序计算了顶点。这意味着你的最后一个顶点将受到最大的误差影响。对于你的应用程序可能不是非常重要,但通常你可能希望通过从起始位置逆时针移动来计算最后一个顶点,然后对于最远的顶点,你可以通过两种可能的路径之一平均到达该顶点的值。你还可能需要夹住你的顶点,以确保它们实际上位于视图矩形内。修复舍入误差是一件痛苦的事情。 - paddy

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接