Re: Beginner. 2d rotation gives unexpected results.
On 23 July 2013 13:34, en...@yandex.ru wrote: 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. Although even Excel calculations with this formulas give me right result. I use Python 3.3 on Windows Xp. What is wrong with my code? [code]import pygame import math as m GAH! Why on earth would you do such a thing? Just import math, there's no need to obfuscate your code. black = ( 0, 0, 0) white = ( 255, 255, 255) green = ( 0, 255, 0) red = ( 255, 0, 0) It's probably better to do: black = pygame.Color(Black) white = pygame.Color(white) green = pygame.Color(green) red = pygame.Color(red) class Poly(): pos = [100,100] #x and y coordinates of a point rot = m.radians(1) #rotation in degrees *Do not do this* This is because classes have shared values -- these pos and rot values are shared within the class. class P: ... n = [] ... def more_n(self): ... self.n.append(len(self.n)) ... ... ... one_P = P() two_P = P() one_P.more_n() one_P.more_n() one_P.more_n() two_P.n [0, 1, 2] Normally you want to set these at initialisation: class Poly(): def __init__(self, pos=None, rot=math.radians(1)): self.pos = [100, 100] if pos is None else pos self.rot = rot super().__init__(self) def draw(self): #draw point pygame.draw.circle(screen,white,self.pos,10,0) Add some spaces, dude. I was going to say: Also, use keyword arguments instead of throwing around 10 and 0 with no context: def draw(self): pygame.draw.circle(screen, white, self.pos, radius=10, width=0) Pygame-ists will know that width means border_width, by now. Pygame isn't known for it's clean design ;). But pygame, being brilliant (not) decided that it won't let you. 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 lot of your comments are ridiculous. This one is particularly so: #mulpitplicating vector to rotation matrix. Don't add comments that talk about lines. Here is a quick guide for when to use comments: 1) API usage, when docstrings aren't usable 2) When something funny or unexpected occurs in the code, such as: # Goes down to 0 (does not include end-point) for i in range(foo, -1, -1): ... 3) To explain large-scale methodologies and algorithms Other than this, are you trying to obfuscate this line? HINT: ADD SPACES ;). A big problem here (this solves your problem) is your int(...) conversions. Do *not* store important information less accurately than it deserves. This is one very important instance. Only convert to int when you need to. Another thing: sin = m.sin(self.rot)??? Really? Write sin_1deg = ... instead, at least. 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] Use: a = Poly() b = Poly([0, 100]) c = Poly([100, 0]) d = Poly([0, 0]) pygame.init() size = [700,500] screen = pygame.display.set_mode(size) done = False clock = pygame.time.Clock() while done == False: while not done Also, just use while True and a break. I know some C-people or what not think this is evil or something, but they're wrong. Personally, I actually like using: while rotating the squares: ... instead of while True. It's no slower and it's free documentation. 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()[/code] You don't need pygame.quit(). You *only* want pygame.quit() if you're quitting Pygame *before* the program is finished. -- http://mail.python.org/mailman/listinfo/python-list
Re: Beginner. 2d rotation gives unexpected results.
On 7/24/2013 5:17 PM, Joshua Landau wrote: import math as m GAH! Why on earth would you do such a thing? for the same reason people do 'import tkinter as tk': to minimize typing and maximize clarity. In this case, from math import sin, cos, radians also works well -- Terry Jan Reedy -- http://mail.python.org/mailman/listinfo/python-list
Re: Beginner. 2d rotation gives unexpected results.
On Tue, 23 Jul 2013 15:11:43 +0200, Peter Otten wrote: The conversion to int introduces a rounding error that accumulates over time. Most floating point calculations introduce a rounding error. If the calculations are iterated, the error will accumulate. In general, you want to avoid accumulating entire transformations. E.g. if you want a spinning object, maintain the cumulative rotation angle and rotate the original points each frame. If you must accumulate transformations, you need to actively work to maintain any desired invariants. E.g. if a transformation is supposed to be orthonormal (all axes perpendicular and of unit length), you should renormalise it periodically, otherwise the lengths and angles will change over time. -- http://mail.python.org/mailman/listinfo/python-list
Beginner. 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. Although even Excel calculations with this formulas give me right result. I use Python 3.3 on Windows Xp. What is wrong with my code? [code]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()[/code] P.S. Sorry for my english, bit rusty in that department. -- http://mail.python.org/mailman/listinfo/python-list
Re: Beginner. 2d rotation gives unexpected results.
haven't used pygame that much, but it sounds like you drew Z. You have [0,0],[0,100],[100,0],[100, 100] 0,0 is the top left, if I recall 0, 100 would be the lower left, then you move to100, 0 which would go diagonal to the top right, and then 100,100 to the lower right, this is assuming 0,0 is the upper left. for a square you would go,[0,0],[0,100],[100,100],[100,0]then back to [0,0] to complete the square. This is assuming that 0,0 is the upper left, the coords are x,y in the brackets, and the increase in x takes you the right, and the increase in y takes you down. If that doesn't work,I'll download it later, and try it out. On Tue, Jul 23, 2013 at 8:34 AM, en...@yandex.ru wrote: 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. Although even Excel calculations with this formulas give me right result. I use Python 3.3 on Windows Xp. What is wrong with my code? [code]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()[/code] P.S. Sorry for my english, bit rusty in that department. -- http://mail.python.org/mailman/listinfo/python-list -- Best Regards, David Hutto *CEO:* *http://www.hitwebdevelopment.com* -- http://mail.python.org/mailman/listinfo/python-list
Re: Beginner. 2d rotation gives unexpected results.
en...@yandex.ru wrote: This is my first post, nice to meet you all! Welcome! 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. Although even Excel calculations with this formulas give me right result. I use Python 3.3 on Windows Xp. What is wrong with my code? 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 The conversion to int introduces a rounding error that accumulates over time. 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 One way to keep the error low is to keep the float values in self.pos and do the rounding on the fly when you display the point: class Poly(): def __init__(self, color, pos, rot=m.radians(1)): self.color = color self.pos = pos self.rot = rot def draw(self): x, y = self.pos pygame.draw.circle(screen, self.color, [350+int(x), 250+int(y)], 10, 0) def rotate(self): sin = m.sin(self.rot) cos = m.cos(self.rot) x_rot = self.pos[0]*cos-self.pos[1]*sin y_rot = self.pos[0]*sin+self.pos[1]*cos self.pos = [x_rot, y_rot] a = Poly(white, [100, 100]) b = Poly(green, [0, 100]) c = Poly(blue, [100, 0]) d = Poly(red, [0, 0]) -- http://mail.python.org/mailman/listinfo/python-list