Rotación de coordenadas
La vía fácil
Si conocemos
las coordenadas del centro de rotación var c = {x:cx, y:cy}
,
el radio
de la trayectoria circular,
el angulo
inicial del elemento que queremos girar, y
el ángulo de rotacion
lo tenemos muy fácil. Las nuevas coordenadas del elemento son:
var p1 = { x: c.x + radio * Math.cos(angulo + rotacion), y: c.y + radio * Math.sin(angulo + rotacion) }
En los siguientes ejemplos el punto rojo es la posición que toma el punto azul después de un giro de 30 grados.
See the Pen rotación 2D TEST simple* by Gabi (@enxaneta) on CodePen.
Un poco más complicado
Pero ¿que pasa si conocemos solo:
las coordenadas del centro de rotación var c = {x:cx, y:cy}
,
las coordenadas del punto p
que queremos girar y
el ángulo de rotacion
?
En este caso tenemos que calcular el radio
de la trayectoria circular:
// la distancia en x entre el punto p y el centro c de la trayectoria var dx = p.x - c.x; // la distancia en y entre el punto p y el centro c de la trayectoria var dy = p.y - c.y; // el radio de la trayectoria var radio = Math.sqrt(dx * dx + dy * dy);
También tenemos que calcular el ángulo inicial del elemento que queremos girar.
var angulo = Math.atan2(dy, dx);
Finalmente podemos calcular las nuevas coordenadas del elemento utilizando las mismas fórmulas de antes:
var p1 = { x: c.x + radio * Math.cos(angulo + rotacion), y: c.y + radio * Math.sin(angulo + rotacion) }
See the Pen rotación 2D TEST #0 by Gabi (@enxaneta) on CodePen.
Este método va muy bien si tenemos que girar un solo punto o muy pocos. Sin embargo es muy ineficiente si tenemos que calcular las trayectorias de un gran número de puntos.
Un método avanzado
Hay unas fórmulas que nos permiten calcular fácilmente el seno y el coseno de la suma de dos ángulos:
cos(a + b) = cos(a)*cos(b) - sin(a)*sin(b); sin(a + b) = sin(a)*cos(b) + cos(a)*sin(b);
Por lo cual si queremos calcular las coordenadas de un punto después de la rotación podemos escribir ( traducido al javascript ):
x1 = r * (Math.cos(a)*Math.cos(rot)) – r*(Math.sin(a)*Math.sin(rot)); y1 = r * (Math.sin(a)*Math.cos(rot)) + r*(Math.cos(a)*Math.sin(rot));
Donde a
es el ángulo inicial, rot
es el ángulo de rotación y r es el radio de la trayectoria. Sabemos que podemos calcular el el radio de la trayectoria utilizando estas fórmulas:
r = x / Math.cos(a) o r = y / Math.sin(a);
O sea:
x1 = (x / Math.cos(a)) * (Math.cos(a)*Math.cos(rot)) – (y / Math.sin(a)) * (Math.sin(a)*Math.sin(rot)); y1 = (y / Math.sin(a)) * (Math.sin(a)*Math.cos(rot)) + (x / Math.cos(a)) * (Math.cos(a)*Math.sin(rot));
Simplificando podemos escribir:
x1 = x * Math.cos(rot) - y * Math.sin(rot); y1 = y * Math.cos(rot) + x * Math.sin(rot);
Y lo podemos poner en una fórmula:
var cos = Math.cos(rotacion);
var sin = Math.sin(rotacion);
function girarPunto(p){
return {
x : p.x * cos - p.y * sin,
y : p.x * sin + p.y * cos
}
}
OJO: Esta fórmula considera que el centro de rotación es origen del canvas, por lo cual, en el siguiente ejemplo, necesitamos trasladar el contexto en el centro del canvas ( ctx.translate(cx, cy);
):
See the Pen rotación 2D TEST #2 by Gabi (@enxaneta) on CodePen.
Teniendo en cuenta el centro de rotación
En este otro ejemplo el punto p
gira alrededor del centro del canvas, así que hemos vuelto a escribir la función girarPunto()
para que tenga en cuenta el centro de rotación.
var cos = Math.cos(rotacion);
var sin = Math.sin(rotacion);
function girarPunto(p,centro){
return {
x: centro.x + (p.x - centro.x) * cos - (p.y - centro.y) * sin,
y: centro.y + (p.x - centro.x) * sin + (p.y - centro.y) * cos
}
}
See the Pen rotación 2D TEST #3* by Gabi (@enxaneta) on CodePen.