Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > comp.lang.python > #51082 > unrolled thread

Beginner. 2d rotation gives unexpected results.

Started byenmce@yandex.ru
First post2013-07-23 05:34 -0700
Last post2013-07-24 19:55 -0400
Articles 6 — 6 participants

Back to article view | Back to comp.lang.python


Contents

  Beginner. 2d rotation gives unexpected results. enmce@yandex.ru - 2013-07-23 05:34 -0700
    Re: Beginner. 2d rotation gives unexpected results. Peter Otten <__peter__@web.de> - 2013-07-23 15:11 +0200
      Re: Beginner. 2d rotation gives unexpected results. Nobody <nobody@nowhere.com> - 2013-07-23 16:20 +0100
    Re: Beginner. 2d rotation gives unexpected results. David Hutto <dwightdhutto@gmail.com> - 2013-07-23 09:04 -0400
    Re: Beginner. 2d rotation gives unexpected results. Joshua Landau <joshua@landau.ws> - 2013-07-24 22:17 +0100
    Re: Beginner. 2d rotation gives unexpected results. Terry Reedy <tjreedy@udel.edu> - 2013-07-24 19:55 -0400

#51082 — Beginner. 2d rotation gives unexpected results.

Fromenmce@yandex.ru
Date2013-07-23 05:34 -0700
SubjectBeginner. 2d rotation gives unexpected results.
Message-ID<0a905ff1-199c-4900-81e6-d9b7bb63bb44@googlegroups.com>
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.

[toc] | [next] | [standalone]


#51084

FromPeter Otten <__peter__@web.de>
Date2013-07-23 15:11 +0200
Message-ID<mailman.5004.1374585095.3114.python-list@python.org>
In reply to#51082
enmce@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])


[toc] | [prev] | [next] | [standalone]


#51091

FromNobody <nobody@nowhere.com>
Date2013-07-23 16:20 +0100
Message-ID<pan.2013.07.23.15.20.35.67000@nowhere.com>
In reply to#51084
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.

[toc] | [prev] | [next] | [standalone]


#51085

FromDavid Hutto <dwightdhutto@gmail.com>
Date2013-07-23 09:04 -0400
Message-ID<mailman.5003.1374585070.3114.python-list@python.org>
In reply to#51082

[Multipart message — attachments visible in raw view] — view raw

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, <enmce@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*

[toc] | [prev] | [next] | [standalone]


#51168

FromJoshua Landau <joshua@landau.ws>
Date2013-07-24 22:17 +0100
Message-ID<mailman.5066.1374700684.3114.python-list@python.org>
In reply to#51082

[Multipart message — attachments visible in raw view] — view raw

On 23 July 2013 13:34, <enmce@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.

[toc] | [prev] | [next] | [standalone]


#51176

FromTerry Reedy <tjreedy@udel.edu>
Date2013-07-24 19:55 -0400
Message-ID<mailman.5073.1374710157.3114.python-list@python.org>
In reply to#51082
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

[toc] | [prev] | [standalone]


Back to top | Article view | comp.lang.python


csiph-web