How to correctly calculate X1 after the rectangle was rotated 30 degrees? The X point is 164,83 before the rotation. I used this code:
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;
}
But as you can see from the printed output when the mouse points at X1 the coords are 190,35 but the calculation gives 89 and 11.
Can someone share some light on this? Google didn't help sadly.
Calculate the original coordinate as polar coordinate, relative to the center of the rectangle (x+w/2
,y+h/2
), i.e. get its representation as an angle and magnitude. Then the updated position has the same magnitude, with an angle that's equal to the original angle plus the rotation you added.
Getting the Euclidean coordinate is then a matter of x=cos(a) and y=sin(a), rather than using the full rotation matrix:
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);
}
With an on-page example:
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>