Вычислить новые координаты прямоугольника X, Y после вращения

Как правильно рассчитать X1 после поворота прямоугольника на 30 градусов? Точка X равна 164,83 перед вращением. Я использовал этот код:

void rotate_rectangle(double x, double y, double angle, double* new_x, double* new_y) {
  // Convert angle to radians
  double angle_rad = angle * M_PI / 180.0;

  // Calculate coordinates of top-left corner relative to center
  double rel_x = -w / 2;
  double rel_y = -h / 2;

  // Rotate top-left corner around center
  double new_rel_x = rel_x * cos(angle_rad) - rel_y * sin(angle_rad);
  double new_rel_y = rel_x * sin(angle_rad) + rel_y * cos(angle_rad);

  // Calculate new coordinates of top-left corner
  *new_x = x + new_rel_x;
  *new_y = y + new_rel_y;
}

Но, как вы можете видеть из распечатанного вывода, когда мышь указывает на X1, координаты равны 190,35, но расчет дает 89 и 11.

Может ли кто-нибудь поделиться светом по этому поводу? Гугл, к сожалению, не помог.

Да, вы правы, они связаны с верхним левым углом. Я изменил последние строки следующим образом: *new_x = x + w/2 + new_rel_x; *new_y = y + y/2 + new_rel_y; Но все же я не получаю тех же результатов. Где подвох?

GiuTor 27.07.2024 07:03

Не забудьте вычислить исходную координату как полярную координату относительно (x+w/2) и (y+h/2). И.Э. вам нужно получить его угол и радиус относительно вашего прямоугольного центра. Затем обновленная позиция использует тот же радиус, но угол, равный (исходный угол + угол поворота).

Mike 'Pomax' Kamermans 27.07.2024 16:15
Стоит ли изучать 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 называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
1
2
56
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

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

Вычислите исходную координату как полярную координату относительно центра прямоугольника (x+w/2,y+h/2), т. е. получите ее представление в виде угла и величины. Тогда обновленная позиция будет иметь ту же величину, а угол будет равен исходному углу плюс добавленный вами поворот.

Тогда получение евклидовой координаты зависит от x=cos(a) и y=sin(a), а не от использования полной матрицы вращения:

void rotate_rectangle(double x, double y, double angle, double* new_x, double* new_y) {
  double dx = -w/2;
  double dy = -h/2;

  // Get the center offset
  double cx = x - dx;
  double cy = y - dy;

  // Get (x,y) as polar coordinate
  double a = atan2(dy, dx);
  double m = sqrt(dx*dx + dy*dy);

  // Then all we need to do is update that angle
  angle = a + angle * M_PI / 180.0;

  // And then we convert back to euclidean
  *new_x = cx + m * cos(angle);
  *new_y = cy + m * sin(angle);
}

С примером на странице:

const d = gfx.width;
const ctx = gfx.getContext(`2d`);
const { atan2, cos, sin, sqrt, PI } = Math;
const rad = (v) => (v / 180) * PI;
let angle = 0;

function rotateCoordinate(x, y, w, h, angle) {
  const dx = -w/2;
  const dy = -h/2;

  // Get the center offset
  const cx = x - dx;
  const cy = y - dy;

  // Get (x,y) as polar coordinate
  const a = atan2(dy, dx);
  const m = sqrt(dx * dx + dy * dy);

  // Then all we need to do is update that angle
  angle = a + rad(angle);

  // And then we convert back to euclidean
  return {
    x: cx + m * cos(angle),
    y: cy + m * sin(angle),
  };
}

function drawRectAndPoint(x, y, w, h) {
  ctx.beginPath();
  ctx.rect(x, y, w, h);
  ctx.stroke();
}

function drawNextFrame() {
  ctx.clearRect(0,0,d,d);

  // first the normal rect
  ctx.strokeStyle = `grey`;
  drawRectAndPoint(10, 50, 130, 50);

  // then rotated about the center
  ctx.translate(d / 2, d / 2);
  ctx.rotate(rad(angle));
  ctx.translate(-d / 2, -d / 2);
  ctx.strokeStyle = `red`;
  drawRectAndPoint(10, 50, 130, 50);
  ctx.resetTransform();

  // And then we draw our "own" rotated point
  const { x, y } = rotateCoordinate(10, 50, 130, 50, angle);
  ctx.strokeStyle = `purple`;
  ctx.beginPath();
  ctx.rect(x - 1, y - 1, 3, 3);
  ctx.stroke();

  angle = (angle + 0.25) % 360;
  requestAnimationFrame(drawNextFrame);
}

drawNextFrame();
<canvas id = "gfx" width = "150" height = "150"></canvas>

Спасибо за код. Однако я получаю новые значения x и y с этими значениями: 287 и 195, которые довольно далеки от координат x, y мыши, когда она наводит курсор на верхний левый угол повернутого прямоугольника: 191,37

GiuTor 28.07.2024 08:15

Довольно глупая ошибка: dx и dy были ошибкой при копипасте. Исправлено это и добавлен код, работающий в JS, на странице, чтобы вы могли видеть, как он работает.

Mike 'Pomax' Kamermans 28.07.2024 18:16

Ты ГЕНИЙ, чувак! Наконец-то это УРА! Вы не представляете, сколько страниц я прочитал в Google и сколько видео посмотрел на YouTube, чтобы найти решение! НИ ОДИН из них не сообщил о расчетах, которые вы написали! Не могли бы вы сказать мне, где учиться/какую книгу купить, чтобы изучить эти концепции?

GiuTor 28.07.2024 18:35

По сути, это линейная алгебра, связанная с графикой. Я не тот человек, чтобы просить книги или что-то в этом роде, но если вы ищете этот конкретный вариант линейной алгебры, вы сможете найти приличное количество ресурсов. Важными частями являются понимание аффинных преобразований (т. е. перемещения, вращения, масштабирования и сдвига), а также однородной проекции (когда вы выполняете 2D-работу в 3D, а 3D-работу в 4D, поэтому вместо этого вы можете выполнять все свои аффинные преобразования одновременно. необходимости запускать их как последовательность операций. Чего мы не делаем в этом коде, но могли бы сделать, если бы действительно захотели).

Mike 'Pomax' Kamermans 28.07.2024 19:19

Это текстовое поле является частью более крупного проекта, который я начал еще в 2009 году. Я пытаюсь модернизировать его, добавляя современные части графического интерфейса. Хотите помочь? Вы можете найти проект здесь: воображение.sourceforge.net Я заменил создание команды ffmpeg на libav и запустил проект временной шкалы, который, надеюсь, будет добавлен сюда: github.com/colossus73/gtk_timeline

GiuTor 28.07.2024 19:35

Мне придется отказаться.

Mike 'Pomax' Kamermans 28.07.2024 20:09

Хорошо, не волнуйтесь. Еще раз спасибо за вашу любезную помощь.

GiuTor 28.07.2024 20:09

Но помните, что вы разместили сообщение на Stackoverflow: задавая вопрос, вы должны проголосовать за полезные ответы и принять ответ, который решил вашу проблему. Без этого сайт был бы бесполезен =)

Mike 'Pomax' Kamermans 28.07.2024 20:15

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

GiuTor 28.07.2024 20:27

Не от меня конкретно, нет. Если у вас есть еще проблемы, с которыми вам нужна помощь, это будет новый пост.

Mike 'Pomax' Kamermans 28.07.2024 20:34

Это новый пост: stackoverflow.com/questions/78784823/…

GiuTor 28.07.2024 20:45

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