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

В настоящее время я пытаюсь рекурсивно нарисовать квадрат внутри квадрата, который будет соответствовать соответствующему квадрату. Пользователь введет, сколько раз квадрат будет масштабироваться и вращаться, и выберет угол.

Например, при вводе 5 делений с углом 45 градусов будет получено:

Изображение масштабировано с помощью sin(45) и повернуто на угол 45 градусов 5 раз

Теперь это хорошо, но это работает только для угла 45 градусов. Как мне получить масштаб другого угла? Скажем, деление на 5 вводится под углом 19 градусов?

Ниже приведен мой код прямо сейчас (он в OpenGL, но все еще вопрос триггера/математики):

glm::vec3 vector = transformObject(1.0f, Z_AXIS, 0.0f, glm::vec3(0.0f, 0.0f, 0.0f));
glDrawArrays(GL_LINE_LOOP, 0, 4);
float scale = 1.0f;
float SinOfAngle = glm::sin(glm::degrees(inputtedAngle));
for (int i = 0; i < userInputTimes; i++)
{
    scale *= SinOfAngle;
    vector = transformObject(scale , Z_AXIS, inputtedAngle, glm::vec3(0.0f, 0.0f, 0.0f));
    glDrawArrays(GL_LINE_LOOP, 0, 4);
    inputtedAngle += inputtedAngle;
}

person John Cannatoid    schedule 23.09.2020    source источник


Ответы (1)


Поскольку это все еще вопрос триггера/математики, я отвечу математически.

введите здесь описание изображения

Независимо от того, как квадраты повернуты, их центральная точка всегда будет одной и той же. Это вопрос аффинного преобразования,

предположим, что пользователь указал угол θ, повторенный k раз.

зафиксируйте вектор n, который является единичным вектором, направленным вверх.

  1. зафиксируйте вектор v1 из центра в один угол.
  2. поверните вектор v1 на θ градусов, и вы получите v1`
  3. коэффициент масштабирования будет следующим: float factor = glm::dot(v1, n) / glm::dot(v1`, n)
  4. масштабируйте и поворачивайте исходный квадрат и n на (коэффициент, θ), вы получите красный квадрат на рис. 2 // сначала запомните масштаб, затем поверните, порядок здесь очень важен.

Повторите 1, 2, 3 по k раз, и вы сможете получить эти k повернутых квадратов.


ps 1. Доказательство означает, что если мы проецируем v1 и v1` на вектор n, коэффициент для вертикальной стороны и гипотенузы будет одинаковым из-за подобных треугольников. поэтому glm::dot(v1, n) / glm::dot(v1`, n) является допустимым фактором.

ps 2. Только первая итерация зависит от глобального фрейма, все остальные операции зависят от локального фрейма, сгенерированного предыдущими итерациями.

person Zhou Zhi Hua    schedule 25.09.2020
comment
Я немного смущен, когда пытаюсь понять это. Скажем, vector.x - это длина (1) сторон квадратов. У меня есть стороны длины, у меня есть гипотенуза (sqrt ((1 * 1 + 1 * 1)), и у меня есть углы (90, 45, 45). Не уверен, как я должен подключить эти числа, чтобы получить масштаб. Я понял, что как только вы получите первый масштаб, он просто рекурсивно уменьшится настолько сильно. Таким образом, для поворота на 45 градусов масштаб равен масштабу * = 0,707107 на каждой итерации. Для поворота на 19 градусов это масштаб * = ~ 0,785 на каждой итерации. - person John Cannatoid; 26.09.2020
comment
@JohnCannatoid в этом случае v1 будет (-0,5, 0,5), а повернутый v1’ будет (0, sqrt (2)/2), n будет (0,1). Подставив числа, вы получите точка (v1, n) / точка (v1’, n) = 0,5 / (sqrt (2)/2) => 0,707107. - person Zhou Zhi Hua; 26.09.2020
comment
Где угол, введенный пользователем, играет роль в этом уравнении? Итак, для поворота на 19 градусов? Кажется, что уравнение всегда будет выводить шкалу, которая работает только для поворота на 45 градусов. - person John Cannatoid; 27.09.2020
comment
@JohnCannatoid угол ввода пользователя равен тета - person Zhou Zhi Hua; 27.09.2020
comment
Я попробовал формулу, которую вы мне дали, мне интересно, куда в нее вложить тета? Я пытался сделать два вектора. Один (-0,5, 0,5), а другой (тета, sqrt (2)/2) и n (0, 1). Затем я разделил значения двух точек. При любом введенном угле ответ был 0,707107, что не будет работать для поворота на 19 градусов. Если пользователь вводит 19 в качестве угла поворота, он должен дать мне приблизительный масштаб 0,785, хотя при любом введенном угле я получаю 0,707107. - person John Cannatoid; 27.09.2020
comment
Это мой код прямо сейчас: pastebin.com/V6YP5s7F При введенном пользователем угле 19,0f вывод VAL по-прежнему 0,707107. - person John Cannatoid; 27.09.2020
comment
@JohnCannatoid значение тета должно использоваться для создания матрицы вращения. Rot = [(cos(theta), -sin(theta)),(sin(theta), cos(theta))], матрица поворота повернет вектор v1 на v1', поэтому вы можете использовать эти два вектора для вычисления масштаб. Если у вас нет опыта работы с этими матрицами, я бы посоветовал вам прочитать mathworld.wolfram.com/RotationMatrix.html< /а> - person Zhou Zhi Hua; 27.09.2020
comment
@JohnCannatoid, если у меня есть вектор v1 = (-0,5, 0,5), а значение тета равно 19 градусам, моя матрица вращения будет [(cos (-19), -sin (-19)), (sin (-19) ),cos(-19))], используя эту матрицу для поворота v1, вы получите (-0,30997, 0,63554), используя формулу для значения масштабирования, вы получите dot((-0,5,0,5), (0, 1))/точка((-0,30997, 0,63554), (0, 1)) = 0,78673 - person Zhou Zhi Hua; 27.09.2020
comment
Отрицательный угол, потому что вы вращаетесь по часовой стрелке - person Zhou Zhi Hua; 27.09.2020
comment
Я понял! Изучение матриц вращения плюс математика, которую вы мне дали, отлично сработали. Большое спасибо! - person John Cannatoid; 27.09.2020