Масштабировать прямоугольник так, чтобы он помещался внутри повернутого прямоугольника

У меня есть 2 прямоугольника: красный и черный со своими размерами. Черный прямоугольник помещается внутрь красного прямоугольника (первое изображение). Я пытаюсь найти способ вычислить размер черного прямоугольника после поворота красного прямоугольника на любой градус (45 градусов здесь для простоты), чтобы он все еще помещался внутри красного прямоугольника (третье изображение). На втором изображении показан черный прямоугольник до изменения размера, чтобы он поместился внутри красного прямоугольника. Центр обоих прямоугольников находится в (0,0)

Я смотрел на это Вычислить самый большой вписанный прямоугольник в повернутый прямоугольник, но это решение работает, только если черный прямоугольник является квадратом.

Может ли кто-нибудь указать мне правильное направление? Спасибо.

Должен ли внутренний прямоугольник сохранять соотношение сторон? Внутренний прямоугольник будет касаться только двух сторон внешнего - это нормально? Ваш пример с квадратом и 45 градусами не раскрывает таких деталей.

MBo 01.04.2023 04:55

Внутренний прямоугольник должен сохранять пропорции и касаться 4-х сторон внешнего.

user16484677 01.04.2023 05:27

Не могли бы вы продемонстрировать это изображение? ;)

MBo 01.04.2023 05:59

Невозможно выполнить все требования вместе. Если приоритетом является аспект, мы должны ограничиться касанием двух сторон. Касание 4-х сторон возможно не во всех случаях (рассмотрите длинный внешний прямоугольник)

MBo 01.04.2023 15:48

@MBo, ты прав, моя ошибка, невозможно коснуться 4 сторон. Мне просто нужно, чтобы он касался как минимум 2 сторон. Я обновил свой пост другим изображением для демонстрации. Спасибо, что изучили это вместе со мной.

user16484677 01.04.2023 17:18
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
2
5
82
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Пусть центр прямоугольников является началом координат (и центром вращения).

Размеры большого прямоугольника 2W, 2H, маленького прямоугольника 2w, 2h.

Первая вершина (A) маленького прямоугольника имеет начальные координаты (w,h), после подгонки они становятся (k*w,k*h), вторая (B) : (-k*w,k*h), коэффициент k пока неизвестен (для расчетов нужны только две вершины))

Для угла поворота f в диапазоне 0..Pi/2Pi..3*Pi/2) сторона большого прямоугольника, которая может содержать A, имеет начальную точку (F)

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

и вектор направления

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

и эта сторона имеет параметрическое уравнение

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

Мы можем написать уравнение, сторона которого содержит A

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

и решить для неизвестных k, t

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

Точно так же сторона, которая может содержать B

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

и вектор направления

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)

Нам нужно выбрать меньшее допустимое значение из k1 и k2 (возможно, некоторые результаты просто недействительны - отрицательные и т. д.)

Аналогичные вычисления для угла f в диапазоне Pi/2..Pi3*Pi/2..2*Pi) с соответствующими сторонами.


Реализовано в Delphi для визуального контроля правильности. Формулы зависят от квадранта угла поворота: quad = 0,1,2,3 для угла поворота f в диапазоне 0..Pi/2, Pi/2..Pi и т.д. (На самом деле мы можем уменьшить диапазоны до 0..Pi из-за симметрии)

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 используется для масштабирования внутреннего прямоугольника

Результат работы:

Большое спасибо @MBo. Я смог получить тот же результат в php/javascript. Ценю вашу помощь!!

user16484677 03.04.2023 19:10

Другие вопросы по теме