Как правильно рассчитать 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.
Может ли кто-нибудь поделиться светом по этому поводу? Гугл, к сожалению, не помог.
Не забудьте вычислить исходную координату как полярную координату относительно (x+w/2) и (y+h/2). И.Э. вам нужно получить его угол и радиус относительно вашего прямоугольного центра. Затем обновленная позиция использует тот же радиус, но угол, равный (исходный угол + угол поворота).
Вычислите исходную координату как полярную координату относительно центра прямоугольника (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
Довольно глупая ошибка: dx
и dy
были ошибкой при копипасте. Исправлено это и добавлен код, работающий в JS, на странице, чтобы вы могли видеть, как он работает.
Ты ГЕНИЙ, чувак! Наконец-то это УРА! Вы не представляете, сколько страниц я прочитал в Google и сколько видео посмотрел на YouTube, чтобы найти решение! НИ ОДИН из них не сообщил о расчетах, которые вы написали! Не могли бы вы сказать мне, где учиться/какую книгу купить, чтобы изучить эти концепции?
По сути, это линейная алгебра, связанная с графикой. Я не тот человек, чтобы просить книги или что-то в этом роде, но если вы ищете этот конкретный вариант линейной алгебры, вы сможете найти приличное количество ресурсов. Важными частями являются понимание аффинных преобразований (т. е. перемещения, вращения, масштабирования и сдвига), а также однородной проекции (когда вы выполняете 2D-работу в 3D, а 3D-работу в 4D, поэтому вместо этого вы можете выполнять все свои аффинные преобразования одновременно. необходимости запускать их как последовательность операций. Чего мы не делаем в этом коде, но могли бы сделать, если бы действительно захотели).
Это текстовое поле является частью более крупного проекта, который я начал еще в 2009 году. Я пытаюсь модернизировать его, добавляя современные части графического интерфейса. Хотите помочь? Вы можете найти проект здесь: воображение.sourceforge.net Я заменил создание команды ffmpeg на libav и запустил проект временной шкалы, который, надеюсь, будет добавлен сюда: github.com/colossus73/gtk_timeline
Мне придется отказаться.
Хорошо, не волнуйтесь. Еще раз спасибо за вашу любезную помощь.
Но помните, что вы разместили сообщение на Stackoverflow: задавая вопрос, вы должны проголосовать за полезные ответы и принять ответ, который решил вашу проблему. Без этого сайт был бы бесполезен =)
Я только что это сделал, извините, я не привык писать здесь. Могу ли я попросить вас еще об одной небольшой помощи?
Не от меня конкретно, нет. Если у вас есть еще проблемы, с которыми вам нужна помощь, это будет новый пост.
Это новый пост: stackoverflow.com/questions/78784823/…
Да, вы правы, они связаны с верхним левым углом. Я изменил последние строки следующим образом: *new_x = x + w/2 + new_rel_x; *new_y = y + y/2 + new_rel_y; Но все же я не получаю тех же результатов. Где подвох?