У меня есть 2 прямоугольника: красный и черный со своими размерами. Черный прямоугольник помещается внутрь красного прямоугольника (первое изображение). Я пытаюсь найти способ вычислить размер черного прямоугольника после поворота красного прямоугольника на любой градус (45 градусов здесь для простоты), чтобы он все еще помещался внутри красного прямоугольника (третье изображение). На втором изображении показан черный прямоугольник до изменения размера, чтобы он поместился внутри красного прямоугольника. Центр обоих прямоугольников находится в (0,0)
Я смотрел на это Вычислить самый большой вписанный прямоугольник в повернутый прямоугольник, но это решение работает, только если черный прямоугольник является квадратом.
Может ли кто-нибудь указать мне правильное направление? Спасибо.
Внутренний прямоугольник должен сохранять пропорции и касаться 4-х сторон внешнего.
Не могли бы вы продемонстрировать это изображение? ;)
Невозможно выполнить все требования вместе. Если приоритетом является аспект, мы должны ограничиться касанием двух сторон. Касание 4-х сторон возможно не во всех случаях (рассмотрите длинный внешний прямоугольник)
@MBo, ты прав, моя ошибка, невозможно коснуться 4 сторон. Мне просто нужно, чтобы он касался как минимум 2 сторон. Я обновил свой пост другим изображением для демонстрации. Спасибо, что изучили это вместе со мной.
Пусть центр прямоугольников является началом координат (и центром вращения).
Размеры большого прямоугольника 2W
, 2H
, маленького прямоугольника 2w
, 2h
.
Первая вершина (A
) маленького прямоугольника имеет начальные координаты (w,h)
, после подгонки они становятся (k*w,k*h)
, вторая (B
) : (-k*w,k*h)
, коэффициент k
пока неизвестен (для расчетов нужны только две вершины))
Для угла поворота f
в диапазоне 0..Pi/2
(и Pi..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..Pi
(и 3*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. Ценю вашу помощь!!
Должен ли внутренний прямоугольник сохранять соотношение сторон? Внутренний прямоугольник будет касаться только двух сторон внешнего - это нормально? Ваш пример с квадратом и 45 градусами не раскрывает таких деталей.