2

I have 2 rectangles: red and black with their dimensions. Black rectangle is fitted inside red rectangle (first image). I'm trying to find the way to calculate black rectangle dimension after rotating red rectangle any degrees (45deg here for simplicity) so that it is still fitted inside the red rectangle (third image). Second image shows the black rectangle before resize to fit inside the red rectangle. Center of both rectangles are at (0,0)

I've been looking at this Calculate largest inscribed rectangle in a rotated rectangle but this solution only works if the black rectangle is a square.

Can someone point me to the right direction? Thank you.

enter image description here

enter image description here

enter image description here

enter image description here

user16484677
  • 95
  • 1
  • 1
  • 7
  • 1
    Should inner rectangel preserve it's aspect ratio? Inner rectangle will touch only two sides of outer one - is it OK? Your example with square and 45 degrees does not reveal such details. – MBo Apr 01 '23 at 02:55
  • 1
    Inner rectangle has to preserve its ratio and it should touch 4 sides of the outer one – user16484677 Apr 01 '23 at 03:27
  • 1
    Could you demonstrate a picture of this? ;) – MBo Apr 01 '23 at 03:59
  • 1
    It is impossible to fulfill all requirements together. If priority is aspect, we have to limit us with touching of two sides. Touching 4 sides is not possible in all cases (conside long outer rectangle) – MBo Apr 01 '23 at 13:48
  • 1
    @MBo you are right, my mistake, it's impossible to touch 4 sides. I just need it to touch at least 2 sides. I updated my post with another image to demonstrate. Thanks for looking into this with me. – user16484677 Apr 01 '23 at 15:18

1 Answers1

1

Let rectangles center is coordinate origin (and center of rotation).

Large rect dimensions are 2W, 2H, small rect 2w, 2h.

First vertex (A) of small rect has initial coordinates (w,h), they become (k*w,k*h) after fitting, second one (B) : (-k*w,k*h), k is unknown yet coefficient (we need only two vertices for calculations)) enter image description here

For rotation angle f in range 0..Pi/2 (and Pi..3*Pi/2) side of large rect which can contain A, has starting point (F)

px = W*cos(f)-H*sin(f)
py = W*sin(f)+H*cos(f)

and direction vector

dx = sin(f)
dy = -cos(f) 

and this side has parametric equation

x = px + t * dx
y = py + t * dy

We can write equation that side contains A

k*w = px + t * dx
k*h = py + t * dy

and solve it for unknowns k, t

k1 = (px * dy - py * dx) / (w * dy - h * dx)

Similarly side that might contain B

px = W*cos(f)-H*sin(f)   //same point
py = W*sin(f)+H*cos(f)

and direction vector

d2x = -cos(f)
d2y = -sin(f) 

-k*w = px + t * d2x
k*h = py + t * d2y

k2 = (px * d2y - py * d2x) / (-w * d2y - h * d2x)

We need to choose smaller valid value from k1 and k2 (perhaps some results are just invalid - negative etc)

Similar calculations for angle f in range Pi/2..Pi (and 3*Pi/2..2*Pi) with corresponding sides.


Implemented in Delphi to visually control correctness. Formulas depend on rotation angle quadrant: quad = 0,1,2,3 for rotation angle f in range 0..Pi/2, Pi/2..Pi and so on. (Really we can diminish ranges to 0..Pi due to the symmetry)

procedure TForm1.RectInRotRect(hw, hh, hWW, hHH: Integer; f: Double);
var
  px, py, dx, dy, k, kmin: Double;
  pts: array [0 .. 3] of TPoint;
  quad: Integer;
begin
  kmin := 999999;
  quad := Floor(2 * f / Pi);
  if Odd(quad) then
  begin
    px := hWW * cos(f) + hHH * sin(f);
    py := hWW * sin(f) - hHH * cos(f);
    dx := -cos(f);
    dy := -sin(f);
    if (hw * dy - hh * dx) <> 0 then
    begin
      k := (px * dy - py * dx) / (hw * dy - hh * dx);
      if quad >= 2 then
        k := -k;
      if k > 0 then
        kmin := Min(kmin, k);
    end;
    if (-hw * dx + hh * dy) <> 0 then
    begin
      k := (px * dx + py * dy) / (-hw * dx + hh * dy);
      if quad >= 2 then
        k := -k;
      if k > 0 then
        kmin := Min(kmin, k);
    end
  end
  else
  begin
    px := hWW * cos(f) - hHH * sin(f);
    py := hWW * sin(f) + hHH * cos(f);
    dx := sin(f);
    dy := -cos(f);
    if (hw * dy - hh * dx) <> 0 then
    begin
      k := (px * dy - py * dx) / (hw * dy - hh * dx);
      if quad >= 2 then
        k := -k;
      if k > 0 then
        kmin := Min(kmin, k);
    end;
    if (-hw * dx + hh * dy) <> 0 then
    begin
      k := (px * dx + py * dy) / (-hw * dx + hh * dy);
      if quad >= 2 then
        k := -k;
      if k > 0 then
        kmin := Min(kmin, k);
    end;
  end;

kmin is used to scale inner rectangle

Result of work:

enter image description here

MBo
  • 77,366
  • 5
  • 53
  • 86