web-dev-qa-db-fra.com

Comment calculer la rotation en 2D en Javascript

Je ne suis pas si familier de la trigonométrie, mais je n'ai que deux points à faire pivoter en 2D:

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

cx, cy = centre de rotation
x, y = courant x, y
nx, ny = nouvelles coordonnées

Comment calculer de nouveaux points dans un certain angle?

32
Digerkam
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];
}

Les deux premiers paramètres sont les coordonnées X et Y du point central (l'origine autour de laquelle le deuxième point sera tourné). Les deux paramètres suivants sont les coordonnées du point que nous allons tourner. Le dernier paramètre est l'angle, en degrés.

Par exemple, nous prendrons le point (2, 1) et le tournerons autour du point (1, 1) de 90 degrés dans le sens des aiguilles d'une montre.

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

Trois notes sur cette fonction:

  1. Pour une rotation dans le sens horaire, le dernier paramètre angle doit être positif. Pour une rotation dans le sens antihoraire (comme dans le diagramme que vous avez fourni), il doit être négatif.

  2. Notez que même si vous fournissez des arguments qui devraient produire un point dont les coordonnées sont des nombres entiers - c'est-à-dire en faisant pivoter le point (5, 0) de 90 degrés par rapport à l'origine (0, 0), ce qui devrait donner (0, -5) - - Le comportement d'arrondi de JavaScript signifie que l'une ou l'autre coordonnée pourrait toujours être une valeur qui est frustrante proche du nombre entier attendu, mais est toujours un flottant. Par exemple:

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

    Pour cette raison, les deux éléments du tableau résultant doivent être attendus comme un flottant. Vous pouvez les convertir en nombres entiers à l'aide de Math.round(), Math.ceil() ou Math.floor() selon vos besoins.

  3. Enfin, notez que cette fonction suppose un système de coordonnées cartésiennes , ce qui signifie que les valeurs sur l'axe Y deviennent plus élevées lorsque vous montez "dans le plan de coordonnées". En HTML/CSS, l'axe Y est inversé - les valeurs sur l'axe Y augmentent lorsque vous vous déplacez vers le bas de la page .

82
theftprevention
  1. Tout d'abord, traduisez le centre de rotation en origine
  2. Calculer les nouvelles coordonnées (nx, ny)
  3. Retour au centre de rotation d'origine

Étape 1

Vos nouveaux points sont

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

Étape 2

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

Étape 3

Revenez au centre de rotation d'origine:

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

Pour une explication plus approfondie, avec quelques diagrammes fantaisistes, je recommande de regarder --- (this .

6
jh314

la réponse acceptée ci-dessus ne fonctionne pas correctement pour moi, la rotation est inversée, voici la fonction de travail

/*
 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:parseInt(x), y:parseInt(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};
 }
1
user889030