user162097
user162097

Reputation: 1258

Rotate points on canvas without calling native transform functions

I have a square whose vertex positions (when the origin is the center of the canvas) are given below:

let canvasCenter = [canvas.width / 2, canvas.height / 2],
    halfSize = this.size / 2,
    vertexPositions = [
        [halfSize, halfSize],
        [-halfSize, halfSize],
        [halfSize, -halfSize],
        [-halfSize, -halfSize],
    ];

Of course, it's trivial for me to draw, for example, a circle at each of the vertices when the coordinate system is rotated. I just call the native transform functions:

context.translate(canvasCenter[0], canvasCenter[1]);
context.rotate(this.rotation);

for (let i = 0; i < 4; ++i) {
    let v = vertexPositions[i];

    context.beginPath();
    context.arc(v[0], v[1], 10, 0, 2 * Math.PI);
    context.fill();
}

context.rotate(-this.rotation);
context.translate(-canvasCenter[0], -canvasCenter[1]);

However, I don't just want to draw the vertices. I also want to calculate the new positions of the vertices on the canvas when each is rotated and translated (for example, to tell whether they are within the bounds of the canvas). I've tried using the standard formula, as below, but when I draw those vertices, it gives me a skewed shape, not a rotated square, so there is obviously something wrong with my calculation:

let cos = Math.cos(this.rotation),
    sin = Math.sin(this.rotation);

for (let i = 0; i < 4; ++i) {
    let v = vertexPositions[i];

    v[1] = v[1] * cos - v[0] * sin;
    v[0] = v[1] * sin + v[0] * cos;

    v[0] += canvasCenter[0];
    v[1] += canvasCenter[1];
}

Please can you help me to calculate the correct vertices (after rotation and translation).

Upvotes: 0

Views: 79

Answers (1)

Blindman67
Blindman67

Reputation: 54041

Cause

v[1] = v[1] * cos - v[0] * sin;
v[0] = v[1] * sin + v[0] * cos;

You change v[1] on the first line and then using it on the second line. Thus you use the transformed V[1] to find the transformed v[0] which is incorrect.

Solution is separate the variables.

const a = v[1] * cos - v[0] * sin;
const b = v[1] * sin + v[0] * cos;
v[0] = b + canvasCenter[0];
v[1] = a + canvasCenter[1];

I called them a,b as I am unsure why you have v[1] in the x coordinate and v[0] in the y. The standard transform is

const x1 = x * cos - y * sin;
const y1 = x * sin + y * cos;
x = x1 + canvasCenter[0];
y = y1 + canvasCenter[1];

Upvotes: 3

Related Questions