rotation of 2d shape clockwise direction - Python

TAGS :
Viewed: 4 - Published at: a few seconds ago

[ rotation of 2d shape clockwise direction ]

I am new to python and graphics but have programmed before. According to http://en.wikipedia.org/wiki/Transformation_matrix#Rotation ,

For rotation by an angle θ anticlockwise about the origin, the functional form is x' = xcosθ − ysinθ and y' = xsinθ + ycosθ

But the following python code rotates it in the clockwise direction. Could somebody explain this?. Also translating the rectangle to the origin and back to the center seems to be an overhead. Is there any way to avoid this?. Thanks in advance.

PS: I have looked at `pygame.transform.rotate` which does this but I would like to start from scratch to get better idea about the graphics. Is there a way to see the source of this method from python interpreter?

``````import pygame, sys, time
from math import *
from pygame.locals import *
co_ordinates =((200,200),(400,200),(400,300),(200,300))

window_surface = pygame.display.set_mode((500,500),0,32)
BLACK=(0,0,0)
GREEN=(0,255,0)
RED=(255,0,0)
window_surface.fill(BLACK)
"""orig=pygame.draw.polygon(window_surface,GREEN,co_ordinates)
n_co_ordinates = tuple([(((x[0])*cos(ang)-(x[1])*sin(ang)),((x[0])*sin(ang)+(x[1])*cos(ang))) for x in n_co_ordinates])
n_co_ordinates = tuple([((x[0]+300),(x[1]+250)) for x in n_co_ordinates])
print(n_co_ordinates)
pygame.draw.polygon(window_surface,RED,n_co_ordinates)"""

pygame.display.update()
while True:
for event in pygame.event.get():
if event.type == QUIT:
pygame.quit()
sys.exit()
for i in range(360):
if i&gt;=360:
i=0
n_co_ordinates = tuple([((x[0]-300),(x[1]-250)) for x in co_ordinates])
n_co_ordinates = tuple([((x[0]*cos(ang)-x[1]*sin(ang)),(x[0]*sin(ang)+x[1]*cos(ang))) for x in n_co_ordinates])
n_co_ordinates = tuple([((x[0]+300),(x[1]+250)) for x in n_co_ordinates])
window_surface.fill(BLACK)
pygame.draw.polygon(window_surface,RED,n_co_ordinates)
pygame.display.update()
time.sleep(0.02)
``````

Pygame uses a coordinate system where [0,0] is the top left corner. Your rotation would work fine in a coordinate system where the higher the point is, the higher the y coordinate, but pygame is the opposite: the lower the point is, the higher the y coordinate. This makes everything "flipped," and so the angle that your object will appear to have rotated will be opposite the angle you rotated it. Probably the easiest way to fix this would be to just input the opposite of the angle you want rotated.

To rotate in the opposite direction change `ang` to `-ang`. I suspect you have got a sign wrong in the rotation matrix, but I can never remember. (EDIT: This is equivalent to changing the sign of the `sin` terms, because `sin(-x)==-sin(x)` and `cos(-x)==cos(x)`.)

You can't avoid the translation to the centre. The reason is that your transformation fixes the origin `(0,0)` (since `0*cos(...)==0`), so you are always rotating about the origin. Thus, to rotate about anywhere else, you have to translate that point to the origin first.

Here is the source of `rotate`, from `transform.c` in the pygame source. It's written in C.

``````static void
rotate (SDL_Surface *src, SDL_Surface *dst, Uint32 bgcolor, double sangle,
double cangle)
{
int x, y, dx, dy;

Uint8 *srcpix = (Uint8*) src->pixels;
Uint8 *dstrow = (Uint8*) dst->pixels;
int srcpitch = src->pitch;
int dstpitch = dst->pitch;

int cy = dst->h / 2;
int xd = ((src->w - dst->w) << 15);
int yd = ((src->h - dst->h) << 15);

int isin = (int)(sangle * 65536);
int icos = (int)(cangle * 65536);

int ax = ((dst->w) << 15) - (int)(cangle * ((dst->w - 1) << 15));
int ay = ((dst->h) << 15) - (int)(sangle * ((dst->w - 1) << 15));

int xmaxval = ((src->w) << 16) - 1;
int ymaxval = ((src->h) << 16) - 1;

switch (src->format->BytesPerPixel)
{
case 1:
for (y = 0; y < dst->h; y++)
{
Uint8 *dstpos = (Uint8*)dstrow;
dx = (ax + (isin * (cy - y))) + xd;
dy = (ay - (icos * (cy - y))) + yd;
for (x = 0; x < dst->w; x++)
{
if(dx < 0 || dy < 0 || dx > xmaxval || dy > ymaxval)
*dstpos++ = bgcolor;
else
*dstpos++ = *(Uint8*)
(srcpix + ((dy >> 16) * srcpitch) + (dx >> 16));
dx += icos;
dy += isin;
}
dstrow += dstpitch;
}
break;
case 2:
for (y = 0; y < dst->h; y++)
{
Uint16 *dstpos = (Uint16*)dstrow;
dx = (ax + (isin * (cy - y))) + xd;
dy = (ay - (icos * (cy - y))) + yd;
for (x = 0; x < dst->w; x++)
{
if (dx < 0 || dy < 0 || dx > xmaxval || dy > ymaxval)
*dstpos++ = bgcolor;
else
*dstpos++ = *(Uint16*)
(srcpix + ((dy >> 16) * srcpitch) + (dx >> 16 << 1));
dx += icos;
dy += isin;
}
dstrow += dstpitch;
}
break;
case 4:
for (y = 0; y < dst->h; y++)
{
Uint32 *dstpos = (Uint32*)dstrow;
dx = (ax + (isin * (cy - y))) + xd;
dy = (ay - (icos * (cy - y))) + yd;
for (x = 0; x < dst->w; x++)
{
if (dx < 0 || dy < 0 || dx > xmaxval || dy > ymaxval)
*dstpos++ = bgcolor;
else
*dstpos++ = *(Uint32*)
(srcpix + ((dy >> 16) * srcpitch) + (dx >> 16 << 2));
dx += icos;
dy += isin;
}
dstrow += dstpitch;
}
break;
default: /*case 3:*/
for (y = 0; y < dst->h; y++)
{
Uint8 *dstpos = (Uint8*)dstrow;
dx = (ax + (isin * (cy - y))) + xd;
dy = (ay - (icos * (cy - y))) + yd;
for (x = 0; x < dst->w; x++)
{
if (dx < 0 || dy < 0 || dx > xmaxval || dy > ymaxval)
{
dstpos[0] = ((Uint8*) &bgcolor)[0];
dstpos[1] = ((Uint8*) &bgcolor)[1];
dstpos[2] = ((Uint8*) &bgcolor)[2];
dstpos += 3;
}
else
{
Uint8* srcpos = (Uint8*)
(srcpix + ((dy >> 16) * srcpitch) + ((dx >> 16) * 3));
dstpos[0] = srcpos[0];
dstpos[1] = srcpos[1];
dstpos[2] = srcpos[2];
dstpos += 3;
}
dx += icos; dy += isin;
}
dstrow += dstpitch;
}
break;
}
}
``````

``````n_co_ordinates = tuple([(((x[0])*cos(ang)+(x[1])*sin(ang)),((-x[0])*sin(ang)+(x[1])*cos(ang))) for x in n_co_ordinates])