Principal | Gráficos 3D | Gráficos 2D | Fractales | Math | Códigos | Tutoriales | Links

Roatación en 2D

Primero un poco de trigonometria básica

donde tenemos las siguientes relaciones:
x = r cos a
y = r sin a
r = sqrt(x*x + y*y) (hipotenusa)

algunas relaciones trigonometricas utiles

sin(a-b) sin a cos b - cos a sin b
sin(a+b) sin a cos b + cos a sin b
cos(a-b) cos a cos b + sin a sin b
cos(a+b) cos a cos b - sin a sin b

Formulas para la rotación en 2D

Rotación de un punto P(x,y), en torno al origen y en sentido antihorario, donde c es el ángulo de rotación y P'(x',y'), es el punto despues de aplicarle la rotación.

x = r cos a
y = r sin a

x' = r cos b
y' = r sin b

b = a + c

x' = r cos(a+c)
y' = r sin(a+c)

sustituyendo cos(a+c) y sin(a+c)

x' = r (cos a cos c - sin a sin c)
y' = r (sin a cos c + cos a sin c)

x' = r cos a cos c - r sin a sin c
y' = r sin a cos c + r cos a sin c

reemplazando por r cos a = x y r sin a = y, obtenemos finalmente las ecuaciones de rotación de un punto en el plano.

x' = x cos c - y sin c
y' = y cos c + x sin c

Codificación en C, esta función toma los siguientes parametros:

void rotacion(float x, float y, float *rx, float *ry, float angulo)
{
 angulo = (PI*angulo)/180.0;
 *rx = x*cos(angulo) - y*sin(angulo);
 *ry = x*sin(angulo) + y*cos(angulo);
}

tambien se puede expresar todo esto en forma de una matriz de 2x2 Rot(c):

|  cos(c)  sin(c) |
| -sin(c)  cos(c) |

aplicando Rot(c) a un punto |x, y|, se obtiene el punto transformado |x', y'|

|x', y'| = |x, y| * |  cos(c)  sin(c) |
                    | -sin(c)  cos(c) |

|x', y'| = |x*cos(c) - y*sin(c), x*sin(c) + y*cos(c)|

donde

x' = x*cos(c) - y*sin(c)
y' = x*sin(c) + y*cos(c)

Código de ejemplo

Salida del programa a 640x480, en blanco el objeto original, en amarillo luego de aplicarle una rotación de 45 grados.

rotacion.gif

El código lo compile con BorlandC++ 3.1, utilizando las librerias BGI.

#include <graphics.h>
#include <stdlib.h>
#include <stdio.h>
#include <conio.h>
#include <math.h>

#define PI	3.141592654

struct punto_f {
	float x;
	float y;
	};

struct punto_d {
	int x;
	int y;
	};

float  xmin = -2.0, ymin=-2.0, xmax=2.0, ymax=2.0;
int MaxX, MaxY, right, left;

void escala(float x, float y, int *px, int*py)
{
 float deltax, deltay;

 deltax = MaxY/(xmax - xmin);
 deltay = MaxY/(ymax - ymin);
 *px = (int)(deltax*(x-xmin) + right);
 *py = MaxY - (int)(deltay*(y-ymin));
}

void rotacion(float x, float y, float *rx, float *ry, float angulo)
{
 angulo = (PI*angulo)/180.0;
 *rx = x*cos(angulo) - y*sin(angulo);
 *ry = x*sin(angulo) + y*cos(angulo);
}

void dibujar_ejes(void)
{
 int sx1, sy1, sx2, sy2;

 setcolor(GREEN);
 escala(xmin, 0.0, &sx1, &sy1);
 escala(xmax, 0.0, &sx2, &sy2);
 line(sx1, sy1, sx2, sy2);
 escala(0.0, ymin, &sx1, &sy1);
 escala(0.0, ymax, &sx2, &sy2);
 line(sx1, sy1, sx2, sy2);
}

int main(void)
{
 punto_f pts[4], rot_pts[4];
 punto_d tmp_pts[4];
 int i;

 /* request auto detection */
 int gdriver = DETECT, gmode, errorcode;
 /* inicializa el modo grafico */
 initgraph(&gdriver, &gmode, "");
 /* lee el resultado de la inicializacion */
 errorcode = graphresult();
 if (errorcode != grOk)  /* si ocurrio un error */
   {
   printf("Graphics error: %s\n", grapherrormsg(errorcode));
   printf("Press any key to halt:");
   getch();
   exit(1);             /* retorna el codigo de error */
   };
 MaxX=getmaxx();
 MaxY=getmaxy();
 right=(MaxX-MaxY)/2;
 left=MaxX-right;

 dibujar_ejes();

 //puntos originales del poligono
 pts[0].x=-1.0; pts[0].y=-1.0;
 pts[1].x= 0.0; pts[1].y= 1.4142;
 pts[2].x= 1.0; pts[2].y=-1.0;
 pts[3].x=-1.0; pts[3].y=-1.0;

 setcolor(WHITE);
 //dibujo un poligono de tres lados
 for (i=0; i<4; i++)
	escala(pts[i].x, pts[i].y, &tmp_pts[i].x, &tmp_pts[i].y);
 moveto(tmp_pts[0].x, tmp_pts[0].y);
 lineto(tmp_pts[1].x, tmp_pts[1].y);
 lineto(tmp_pts[2].x, tmp_pts[2].y);
 lineto(tmp_pts[3].x, tmp_pts[3].y);

 setcolor(YELLOW);
 //lo roto 45 grados
 for (i=0; i<4; i++)
	{
	rotacion(pts[i].x, pts[i].y, &rot_pts[i].x, &rot_pts[i].y, 45 .0);
	escala(rot_pts[i].x, rot_pts[i].y, &tmp_pts[i].x, &tmp_pts[i].y);
	}
 moveto(tmp_pts[0].x, tmp_pts[0].y);
 lineto(tmp_pts[1].x, tmp_pts[1].y);
 lineto(tmp_pts[2].x, tmp_pts[2].y);
 lineto(tmp_pts[3].x, tmp_pts[3].y);

 getch();
 closegraph();
 return 0;
}


valcoey@hotmail.com

Ramiro Alcocer, 2001

Principal | Gráficos 3D | Gráficos 2D | Fractales | Math | Códigos | Tutoriales | Links