3D rotations in python (slowly decreasing radius)

Question:

I’ve recently been tasked with writing a Python based app that generates an STL file (a stereolithography file format – basically a list of triangles). I’m new to python, and I’m trying to avoid using overly complicated libraries. The issue that I’m having is with 3D rotations in a vector class that I’ve created.

My rotation function in the vector class looks like the following:

def rotateY(self, amount):
    '''Rotates a vertex on the Y axis around the origin by a given amount (in radians)'''       
    self.x = self.x * math.cos(amount) + self.z * math.sin(amount)
    self.y = self.y
    self.z = self.x * (-math.sin(amount)) + self.z * math.cos(amount)

As you may have guessed, the vector class has an x, y, and z component. I’m reasonably familiar with 3D transformations and math, and the code looks correct, as far as I can tell. I’d rather not have to pull in some other matrix library for the sake of keeping things simple.

The problem arises when I attempt to do something like this:

v = vector(50.0, 0.0, 0.0)
rotationAmount = math.radians(10.0)
for i in range(0, 36):
    v.rotateY(rotationAmount)
    #Draw something at (v.x, v.y, v.z), 
    #...or in my case, create a list of triangles to export to an STL file

As I rotate around the y axis, the distance from the origin to the point being rotated slowly decreases. Here’s an example, where I’m creating a 3D sphere at the location of the vector after each rotation, and exporting it all as an STL (as show in Maya):
As seen in Maya

As you can see, the distance from the origin to the vector being rotated is definitely decreasing the more times the vector is rotated. This is also backed up by printing out the length of the vector after each rotation, as shown (the initial vector is set to a position of (50.0, 0.0, 0.0):

Length decreases the more the vector is rotated

Just as s temporary hack, I tried finding the length of the vector, normalizing it, rotating it, normalizing it again, then scaling back by the original size, and this seemed to have worked, but it seems like a very dirty hack to get something as simple as this to work.

My question is: what is causing the length of the vector to slowly decrease?

EDIT: I should have been a little more clear. The vector class only supports rotations around the origin.

Asked By: Joel B

||

Answers:

There is a problem in your rotateY function. You are modifying x then using that modified x to calculate your modified z. This is causing your spiraling doom. One way to fix it would be to store your x in a temp variable so you can calculate your modified z off the original x. This will maintain your magnitude.

def rotateY(self, amount):
    '''Rotates a vertex on the Y axis around the origin by a given amount (in radians)'''
    temp_x = self.x
    self.x = self.x * math.cos(amount) + self.z * math.sin(amount)
    self.z = temp_x * (-math.sin(amount)) + self.z * math.cos(amount)
Answered By: cmd
Categories: questions Tags: ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.