【问题标题】:Calculating point and dimensions of maximum rotated rectangle inside rectangle计算矩形内最大旋转矩形的点和尺寸
【发布时间】:2012-10-29 20:08:48
【问题描述】:

我有一个矩形,它必须始终旋转相同的度数。让我们称这个角度为 alpha (????)。

此矩形的宽度 (w) 和高度 (h) 可以变化。矩形必须始终适合在大矩形内旋转。它必须按比例放大或缩小以适合灰色矩形。

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

所以,有3种矩形

w > h
w < h  or
w = h

见下图。

我知道的:

  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));

} 

有什么线索吗?谢谢。

【问题讨论】:

  • 你是什么意思 w 和 h 的最大值将适合 w 和 h 的每种情况的灰色矩形?你的绘图中哪个是角度 alpha?
  • 我的意思是:红色矩形必须适合灰色矩形。我已经改变了那句话。 Alpha 是 w 与水平线的夹角。

标签: objective-c math


【解决方案1】:

我看到它的方式是这样的......你计算出矩形的总宽度和总高度。为此,您只需沿着两条边走。像这样:

dx = w * cos(theta) + h * sin(theta)
dy = h * cos(theta) + w * sin(theta)

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

您现在只需要宽度和高度之间的比率。这是您决定是按垂直量还是水平量进行缩放的地方。这与wh 无关——它实际上是关于矩形因旋转而结束的位置。这就是 dxdy 的用途。

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

如果rectratio 大于viewratio,则意味着需要缩放旋转矩形的水平足迹。否则,您将按垂直足迹进行缩放。

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。尝试使用 wh 的几个不同值。
  • 顺便说一句...只是关于舍入误差的说明。请注意我是如何按顺时针顺序计算顶点的。这意味着您的最后一个顶点将受到最大错误的影响。它可能对您的应用程序根本不重要,但通常您可能希望通过从起始位置逆时针移动来计算最后一个顶点,然后对于最远的顶点,您可以平均到达该顶点的值两种可能的路径之一。您可能还需要夹住顶点以确保它们实际上位于视图矩形内。修复舍入误差很痛苦。
猜你喜欢
  • 2011-08-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-01-09
  • 1970-01-01
  • 2013-03-05
  • 1970-01-01
相关资源
最近更新 更多