## 2d rotation gives unexpected results.

### 2d rotation gives unexpected results.

Hello!
This is my first post, nice to meet you all!
I`m biology student from Russia, trying to learn python to perform some simple simulations.

Here`s my first problem.
I`m trying to perform some simple 2d vector rotations in pygame, in order to learn the basics of linear algebra and 2d transformations. So far i understand matrix multiplication pretty well, and probably all my math is right. Eventually i`m planning to write Poly class, and use it to rotate and translate some simple shapes. But when i try and write it in the program, i get very weird results, like all points of rectangle with coordinates [0,0],[0,100],[100,0],[100,100] start to go spiral and eventually shrink to the center instead of rotating right. Although even Excel calculations with this formulas give me right result.
What is wrong with my code?

Code: Select all
import pygame
import math as m

black = ( 0, 0, 0)
white = ( 255, 255, 255)
green = ( 0, 255, 0)
red = ( 255, 0, 0)

class Poly():
pos = [100,100] #x and y coordinates of a point
rot = m.radians(1) #rotation in degrees
def draw(self): #draw point
pygame.draw.circle(screen,white,self.pos,10,0)
def rotate(self): # rotation method
sin = m.sin(self.rot) #calculationg sin and cos
cos = m.cos(self.rot)
x_rot = int(self.pos[0]*cos-self.pos[1]*sin) #mulpitplicating vector to rotation matrix
y_rot = int(self.pos[0]*sin+self.pos[1]*cos)

self.pos[0] = x_rot #set new coordinates to a point
self.pos[1] = y_rot

a = Poly() #Some simple sample points giving rectangle
b = Poly()
c = Poly()
d = Poly()

b.pos = [0,100]
c.pos = [100,0]
d.pos = [0,0]

pygame.init()
size = [700,500]
screen = pygame.display.set_mode(size)
done = False
clock = pygame.time.Clock()
while done == False:
for event in pygame.event.get():
if event.type == pygame.QUIT:
done = True

a.rotate() #perform rotation
b.rotate()
c.rotate()
d.rotate()

screen.fill(black)

a.draw() #draw point
b.draw()
c.draw()
d.draw()
pygame.display.flip()
clock.tick(30)

pygame.quit()

P.S. I use Python 3.3. Sorry for my english, bit rusty in that department.
Zirgon

Posts: 3
Joined: Tue Jul 23, 2013 11:48 am

### Re: 2d rotation gives unexpected results.

Well, with some help, i did it.
The main problem was with float to integer coordinate conversion in this code:
Code: Select all
x_rot = int(self.pos[0]*cos-self.pos[1]*sin) #mulpitplicating vector to rotation matrix
y_rot = int(self.pos[0]*sin+self.pos[1]*cos)

For each cycle we get more and more error with conversion.
Instead, it should be like this:
Code: Select all
x_rot = self.pos[0]*cos-self.pos[1]*sin #mulpitplicating vector to rotation matrix
y_rot = self.pos[0]*sin+self.pos[1]*cos

And coordinate conversion should happen when point calls a draw method:
Code: Select all
def draw(self): #draw point
pygame.draw.circle(screen,white,[int(self.pos[0]),int(self.pos[1])],10,0)

Hope this helps someone.
Zirgon

Posts: 3
Joined: Tue Jul 23, 2013 11:48 am

### Re: 2d rotation gives unexpected results.

Zirgon wrote:Well, with some help, i did it.
The main problem was with float to integer coordinate conversion in this code.

Lol. I was mid-writing this post when you posted saying you solved it. So I'll say this instead.

You should really properly __init__ your Point class. And you should try to resist the urge to use class wide variables that should be instance specific.
Code: Select all
import math,sys
import pygame

class Point(object):
def __init__(self,x,y):
self.x,self.y = x,y

def rotate(self,axis,angle):
sin_of_angle = math.sin(angle)
cos_of_angle = math.cos(angle)
self.x = x_new+axis[0]
self.y = y_new+axis[1]

def draw(self,surface):
draw_location = int(self.x),int(self.y)
pygame.draw.circle(surface,(255,255,255),draw_location,10,0)

class Control(object):
def __init__(self):
pygame.init()
self.size = [700,500]
self.screen = pygame.display.set_mode(self.size)
self.screen_rect = self.screen.get_rect()
self.done = False
self.clock = pygame.time.Clock()
self.make_some_points()

def make_some_points(self):
rect = pygame.Rect(0,0,100,100)
rect.center = (200,self.screen_rect.centery)
self.points = []
for (x,y) in (rect.topleft,rect.topright,rect.bottomleft,rect.bottomright):
self.points.append(Point(x,y))

def event_loop(self):
for event in pygame.event.get():
if event.type == pygame.QUIT:
self.done = True

def main_loop(self):
while not self.done:
self.event_loop()
self.screen.fill(0)
for point in self.points:
point.rotate(self.screen_rect.center,3)
point.draw(self.screen)
pygame.display.update()
self.clock.tick(60)

if __name__ == "__main__":
run_it = Control()
run_it.main_loop()
pygame.quit();sys.exit()

-Mek
• Use code tags when posting code.
• Include any errors with your post (in code tags).
• Make examples the minimum length to demonstrate your issue.

Mekire

Posts: 1600
Joined: Thu Feb 07, 2013 11:33 pm
Location: Tucson, Arizona

### Re: 2d rotation gives unexpected results.

It`s helpful example of good structured code, thanks!
Zirgon

Posts: 3
Joined: Tue Jul 23, 2013 11:48 am