tags:

views:

871

answers:

4
A: 

divide the rect into 4 smaller rectangles. cut this in half diagonally (before rotation, from a corner to a center point) and you will have 8 triangles. You only need 4 of them. After your rotation, the hypotenuse of these triangles are sticking out of the original bounds box.

determine a formula for the hypotenuse (you have the original angle, 45, -45, 135, -135, and the starting point, so that's mx+b), transform those lines (modify their slopes by adding the rotation), intersect those lines with the boundary walls (y = 0, y = w, x = 0, x = h, distance formula, test for infinite cases) & figure out which hypotenuse is shortest (center to wall, at the corner). Since all the hypotenuse were the same length to start with, just resize all of them to this new value, you have your new rectangle.

Am I doing it right?

ryansstack
i guess, it should have an easier way :)
Tolgahan Albayrak
i can't imagine how :) though I could have rephrased it "figure out how far the longest sticking-out-corner sticks out, and resize it"
ryansstack
A: 
function resize_factor()
{
    /* Find how far the upper-left corner sticks up beyond the top */
    overtop = gety(0, 0);
    /* Compute a vertical resize factor that would put that point at the top */
    /* (be sure to use floating point arithmetic) */
    vertical_resize = _cy / (_cy - overtop);

    /* Do the same for the lower-left corner sticking out beyond the left */
    /* (using 2*_cy for the height of the rectangle) */
    overleft = getx(0, 2*_cy);    
    horizontal_resize = _cx / (_cx - overleft);

    /* Return whichever resize constraint is stricter */
    return min(vertical_resize, horizontal_resize);
}

function resize_x(x)
{
    /* To get location of a point, after resize, before rotation... */
    /* ...multiply its resize factor by its distance from the center. */
    return resize_factor()*(x - _cx) + _cx;
}

function resize_y(y)
{
    return resize_factor()*(y - _cy) + _cy;
}

/* These resized coordinates can be used inside any other code you want: */
function getx_after_resize_and_rotate(x, y)
{
    return getx( resized_x(x), resized_y(y) );
}

Notes: This code assumes the angle is rotating clockwise by less than 90 degrees (because that's what your pictures show). If your angle is something else, you might have to check all 4 corners and determine which ones are the furthest overtop and overleft.

+3  A: 

If your original sizes where h and w, and you turned is by angle phi, try to calculate the new height

h1 = h*h / (w*sin(phi) + h*cos(phi))

and

h2 = h*w / (w*cos(phi) + h*sin(phi))

And pick the hew height h' as the smallest of h1 and h2.

Then, obviously, new width w' = h' * w / h.

Please try it - I didn't have time to test my math :)

Igor Krivokon
your formula is ok if angle a => 0 >= a <= 90, now i am trying other variations of this way
Tolgahan Albayrak
A: 
    fitRect: function( rw,rh,radians ){
            var x1 = -rw/2,
                x2 = rw/2,
                x3 = rw/2,
                x4 = -rw/2,
                y1 = rh/2,
                y2 = rh/2,
                y3 = -rh/2,
                y4 = -rh/2;

            var x11 = x1 * Math.cos(radians) + y1 * Math.sin(radians),
                y11 = -x1 * Math.sin(radians) + y1 * Math.cos(radians),
                x21 = x2 * Math.cos(radians) + y2 * Math.sin(radians),
                y21 = -x2 * Math.sin(radians) + y2 * Math.cos(radians), 
                x31 = x3 * Math.cos(radians) + y3 * Math.sin(radians),
                y31 = -x3 * Math.sin(radians) + y3 * Math.cos(radians),
                x41 = x4 * Math.cos(radians) + y4 * Math.sin(radians),
                y41 = -x4 * Math.sin(radians) + y4 * Math.cos(radians);

            var x_min = Math.min(x11,x21,x31,x41),
                x_max = Math.max(x11,x21,x31,x41);

            var y_min = Math.min(y11,y21,y31,y41);
                y_max = Math.max(y11,y21,y31,y41);

            return [x_max-x_min,y_max-y_min];
        }
bajie