Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to calculate rotation in 2D in Javascript

I am not so familiar trigonometry, but I have only two points to rotate in 2D:

                    *nx, ny
               .     -
          .           -
     .  angle          -
*cx,cy.................*x,y

cx, cy = rotation center
x,y = current x,y
nx, ny = new coordinates

How to calculate new points in a certain angle?

like image 727
Digerkam Avatar asked Jul 01 '13 18:07

Digerkam


People also ask

How do you calculate 2d rotation?

The distance from the origin can be found using the Pythagorean Theorem: r2 = x2+y2. If you plug in (4,3) for (x,y), you find that r = 5. The angle can be found using trigonometry: θ = tan-1(y/x). If you plug in (4,3) for (x,y), you find that θ=36.87°.

How do you rotate in JavaScript?

Introduction to JavaScript rotate() canvas API The rotate() method accepts a rotation angle in radians. If the angle is positive, the rotation is clockwise. In case the angle is negative, the rotation is counterclockwise. When adding a rotation, the rotate() method uses the canvas origin as the rotation center point.

How do you calculate a rotation?

The angle of rotation between the two points or vertices is the number of central angles times the measure of a single central angle: angle of rotation =m×α = m × α .


5 Answers

function rotate(cx, cy, x, y, angle) {
    var radians = (Math.PI / 180) * angle,
        cos = Math.cos(radians),
        sin = Math.sin(radians),
        nx = (cos * (x - cx)) + (sin * (y - cy)) + cx,
        ny = (cos * (y - cy)) - (sin * (x - cx)) + cy;
    return [nx, ny];
}

The first two parameters are the X and Y coordinates of the central point (the origin around which the second point will be rotated). The next two parameters are the coordinates of the point that we'll be rotating. The last parameter is the angle, in degrees.

As an example, we'll take the point (2, 1) and rotate it around the point (1, 1) by 90 degrees clockwise.

rotate(1, 1, 2, 1, 90);
// > [1, 0]

Three notes about this function:

  1. For clockwise rotation, the last parameter angle should be positive. For counterclockwise rotation (like in the diagram you provided), it should be negative.

  2. Note that even if you provide arguments that should yield a point whose coordinates are whole numbers -- i.e. rotating the point (5, 0) by 90 degrees about the origin (0, 0), which should yield (0, -5) -- JavaScript's rounding behavior means that either coordinate could still be a value that's frustratingly close to the expected whole number, but is still a float. For example:

    rotate(0, 0, 5, 0, 90);
    // > [3.061616997868383e-16, -5]
    

    For this reason, both elements of the resulting array should be expected as a float. You can convert them to integers using Math.round(), Math.ceil(), or Math.floor() as needed.

  3. Finally, note that this function assumes a Cartesian coordinate system, meaning that values on the Y axis become higher as you go "up" in the coordinate plane. In HTML / CSS, the Y axis is inverted -- values on the Y axis become higher as you move down the page.

like image 101
theftprevention Avatar answered Oct 11 '22 14:10

theftprevention


  1. First, translate the rotation center to the origin
  2. Calculate the new coordinates (nx, ny)
  3. Translate back to the original rotation center

Step 1

Your new points are

  1. center: (0,0)
  2. point: (x-cx, y-cy)

Step 2

  1. nx = (x-cx)*cos(theta) - (y-cy)*sin(theta)
  2. ny = (y-cy)*cos(theta) + (x-cx)*sin(theta)

Step 3

Translate back to original rotation center:

  1. nx = (x-cx)*cos(theta) - (y-cy)*sin(theta) + cx
  2. ny = (y-cy)*cos(theta) + (x-cx)*sin(theta) + cy

For deeper explanation, with some fancy diagrams, I recommend looking at this.

like image 34
jh314 Avatar answered Oct 11 '22 15:10

jh314


above accepted answer not work for me correctly, rotation are reversed , here is working function

/*
 CX @ Origin X  
 CY @ Origin Y
 X  @ Point X to be rotated
 Y  @ Point Y to be rotated  
 anticlock_wise @ to rotate point in clockwise direction or anticlockwise , default clockwise 
 return @ {x,y}  
*/
function rotate(cx, cy, x, y, angle,anticlock_wise = false) {
    if(angle == 0){
        return {x:parseFloat(x), y:parseFloat(y)};
    }if(anticlock_wise){
        var radians = (Math.PI / 180) * angle;
    }else{
        var radians = (Math.PI / -180) * angle;
    }
    var cos = Math.cos(radians);
    var sin = Math.sin(radians);
    var nx = (cos * (x - cx)) + (sin * (y - cy)) + cx;
    var ny = (cos * (y - cy)) - (sin * (x - cx)) + cy;
    return {x:nx, y:ny};
 }
like image 34
user889030 Avatar answered Oct 11 '22 15:10

user889030


According to Polar coordinate system artycle on Wikipedia:

x = r * cos(deg)
y = r * sin(deg)
  • r (radius) is equal to distance between Rotation Centre and Rotated Point
  • deg (degrees) is angle measured in degrees
like image 33
Octoturge Avatar answered Oct 11 '22 14:10

Octoturge


I think it is better to use matrices for such operations.

Here is the example with gl-matrix (but you can use something like THREEJS as well).

import * as glm from 'gl-matrix';
const rotateVector = (() => {
  
  const q = glm.quat.create();  
  // const m = glm.mat4.create(); // 2nd way

  return (v: glm.vec3, point: glm.vec3, axis: glm.vec3, angle: number) => {

      glm.quat.setAxisAngle(q, axis, angle);
      // glm.mat4.fromRotation(m, angle, axis); // 2nd way
      glm.vec3.sub(v, v, point);
      glm.vec3.transformQuat(v, v, q);
      // glm.vec3.transformMat4(v, v, m); // 2nd way
      glm.vec3.add(v, v, point);
      return v;
  }
})();

In 2D case you need to rotate around z-axis:

rotateVector([x, y, 0], [cX, cY, 0], [0, 0, 1], angleInRadians);
like image 30
SalientBrain Avatar answered Oct 11 '22 15:10

SalientBrain