I have a rectangle that has to be rotated always the same amount of degrees. Lets call this angle alpha (𝜶).
The width (w) and height (h) of this rectangle can vary. The rectangle has always to fit rotated inside the big rectangle. It must be scaled up or down to fit inside the gray rectangle.
NOTE: Alpha is the angle between w and the horizontal line.
So, there are 3 kinds of rectangles where
w > h
w < h or
w = h
See the picture below.
What I know:
what I need to know:
This is what I did so far, but this is not giving the correct values:
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));
}
any clues? Thanks.
The essence is this: (1) If c is the center point, then the corners are c + (L/2,W/2), +/- etc., where L and W are the length & width of the rectangle. (2) Translate the rectangle so that center c is at the origin, by subtracting c from all four corners. (3) Rotate the rectangle by 40 deg via the trig formulas cited.
The way I see it is like this... You work out the total width and total height of the rectangle. For that, you simply walk along two edges. Like this:
dx = w * cos(theta) + h * sin(theta)
dy = h * cos(theta) + w * sin(theta)
These could be negative, so special handling would apply if the rectangle is rotated into other quadrants. This will happen later.
You now just need the ratio between the width and height. This is where you decide whether to scale by the vertical amount or the horizontal amount. It's nothing to do with w
and h
-- it's actually about where the rectangle ends up as a result of rotation. That's what dx
and dy
are for.
rectratio = abs( dx / dy )
viewratio = R / K
If rectratio
comes out larger than viewratio
that means the rotated rectangle's horizontal footprint needs to be scaled. Otherwise you scale by the vertical footprint.
if rectratio > viewratio
scale = R / abs(dx)
else
scale = K / abs(dy)
end
And the scale itself is applied to the original width and height
sw = scale * w
sh = scale * h
So now you can compute the corners of your rectangle. It doesn't matter where you start.
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)
I've assumed image co-ordinates given that (0,0) is top-left, so increasing y
moves down. So, if I haven't made a mistake in my math, the above gives you the rectangle vertices (in clockwise order).
The last thing to do is normalise them... This means finding the min value of px
and py
. Call them pxmin
and pymin
. I don't need to show code for that. The idea is to calculate an offset for your rectangle such that the view area is defined by the rectangle (0,0)
to (R,K)
.
First we need to find the left and right value of the subview that completely contains our rotated rectangle... Remember the ratio before:
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
left
and top
are now the 'minimum' co-ordinate of our subview that exactly contains the rectangle (floating point rounding errors exempted). So:
left += pxmin
top += pymin
Now they are the offset required to shift the rectangle to where it's wanted. All you do is add left
and top
to all your rectangle co-ordinates, and you are done. The position of P
is px[0]
and py[0]
. If you rotated by 90 degrees or more, it won't be the top-left vertex.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With