Jump to content
  • Advertisement
Sign in to follow this  
Suen

Cartesian to spherical coordinates

This topic is 2318 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

I have two functions, one that converts spherical coordinates to cartesian coordinates and one that converts cartesian coordinates to spherical coordinates. The spherical to cartesian function works fine as far as I am concerned. But my cartesian to spherical function is acting really weird.

I describe my spherical coordinates as following: (r, theta, phi) where theta [0, 2*PI) and phi [0, PI]

I noticed the problem with my function as I was accumulating values to my theta. Basically I get locked to a theta value of 89-91. If I convert the following spherical coordinate (3.0f, 91.0f, 0.0f) to cartesian coordinates I get (-2.99954, 0, 0.0523535). If I now convert THIS cartesian coordinate back to spherical coordinates I get (3, 89.0001, 0) which is clearly wrong. It then just continues in an endless cycle...goes up to 91 and goes back to 89 from there. To summarize the problem:

Spherical coord. (3.0f, 91.0f, 0.0f) -> Cartesian coord. (-2.99954, 0, 0.0523535)
Cartesian coord. (-2.99954, 0, 0.0523535) -> Spherical coord. (3, 89.0001, 0)

I've taken a look at both functions but I can't really figure out where the problem lies. Here is the code to both functions:

Spherical to cartesian


glm::vec3 Camera::sphericalToCartesian(glm::vec3 sphericalCoordinate)
{
GLfloat theta = degToRad(sphericalCoordinate.y);
GLfloat phi = degToRad(sphericalCoordinate.z);

glm::vec3 cartesianCoordinate(-cosf(phi)*sinf(theta), sinf(phi), -cosf(phi)*cos(theta));

return cartesianCoordinate * sphericalCoordinate.x;
}


Cartesian to spherical


glm::vec3 Camera::cartesianToSpherical(glm::vec3 cartesianCoordinate)
{
GLfloat r = (sqrt(pow(cartesianCoordinate.x, 2) + pow(cartesianCoordinate.y, 2) + pow(cartesianCoordinate.z, 2)));

GLfloat phi = (asinf(cartesianCoordinate.y/r)*180.0f)/PI;
//GLfloat radPhi = degToRad(phi); //Necessary?
GLfloat theta = (asinf(-cartesianCoordinate.x/(r*cosf(phi)))*180.0f)/PI;

glm::vec3 sphericalCoordinate(r, theta, phi);

return sphericalCoordinate;
}
Edited by Suen

Share this post


Link to post
Share on other sites
Advertisement
What's the purpose of the degrees-to-radians conversions? All of the standard library trig functions operate in radians, so I'm not sure where your numbers in degrees are coming from in the first place?

Share this post


Link to post
Share on other sites

What's the purpose of the degrees-to-radians conversions? All of the standard library trig functions operate in radians, so I'm not sure where your numbers in degrees are coming from in the first place?


I'm not sure how to answer your question. I specify theta and phi in degrees and as you said the standard library trig. functions operate in radians so I need to convert these to radians before performing my calculations. If, say (r, 0, 0), would mean you are looking in the negative z-axis and the user change phi from 0 to 90 I would expect a rotation of 90 degrees, looking straight up.

Share this post


Link to post
Share on other sites

[quote name='ApochPiQ' timestamp='1336841328' post='4939592']
What's the purpose of the degrees-to-radians conversions? All of the standard library trig functions operate in radians, so I'm not sure where your numbers in degrees are coming from in the first place?


I'm not sure how to answer your question. I specify theta and phi in degrees and as you said the standard library trig. functions operate in radians so I need to convert these to radians before performing my calculations. If, say (r, 0, 0), would mean you are looking in the negative z-axis and the user change phi from 0 to 90 I would expect a rotation of 90 degrees, looking straight up.
[/quote]
I think ApochPiQ is asking why you're using degrees in the first place, not why you are converting them. Why not just use radians always?

As for your formulae, why not use the conversions from Wikipedia? Be sure to use atan2 instead of atan so you don't have to worry about divide by zero stuff.

Share this post


Link to post
Share on other sites

[quote name='Suen' timestamp='1336845526' post='4939601']
[quote name='ApochPiQ' timestamp='1336841328' post='4939592']
What's the purpose of the degrees-to-radians conversions? All of the standard library trig functions operate in radians, so I'm not sure where your numbers in degrees are coming from in the first place?


I'm not sure how to answer your question. I specify theta and phi in degrees and as you said the standard library trig. functions operate in radians so I need to convert these to radians before performing my calculations. If, say (r, 0, 0), would mean you are looking in the negative z-axis and the user change phi from 0 to 90 I would expect a rotation of 90 degrees, looking straight up.
[/quote]
I think ApochPiQ is asking why you're using degrees in the first place, not why you are converting them. Why not just use radians always?

As for your formulae, why not use the conversions from Wikipedia? Be sure to use atan2 instead of atan so you don't have to worry about divide by zero stuff.
[/quote]

Alright that was just to simplify it for myself. Two other tutorials I've followed a few weeks ago also made the same and since I used them as a starting point for what I wanted to do I just went with degrees. I could probably just use radians though yes.

As for your question, the thing is that I used another convention to have it in a specific way. What I have is the following:

x = -cos(phi)*sin(theta)*r
y = sin(phi)*r
z = -cos(phi)*cos(theta)*r

and again it is (r, theta, phi) with the interval for theta and phi as described in my first post.

If I defined a spherical coord. (1, 0, 0) I want it to correspond to the negative z-axis which is exactly what I would get from the above: (0, 0, -1).
If I have spherical coord. (1, 0, 90) I would visualize that as my point moving up to the north pole on the sphere thus I would expect to look straight up in the positive y-axis and again with the above it gives me (0, 1, 0). Having spherical coord (1, 90, 0) would give me (1, 0, 0) and so on

The convention used in wikipedia would not give me this. For example (1, 90, 0) would give me (0, 0, 1) from the wikipedia page.

Share this post


Link to post
Share on other sites
The convention used in wikipedia would not give me this. For example (1, 90, 0) would give me (0, 0, 1) from the wikipedia page.[/quote]
It's perfectly valid to shuffle around which formula corresponds to which coordinate, so that it matches the coordinate system you are interested in. Just make sure you don't turn a cos into a sin by accident or something like that.

Share this post


Link to post
Share on other sites

The convention used in wikipedia would not give me this. For example (1, 90, 0) would give me (0, 0, 1) from the wikipedia page.

It's perfectly valid to shuffle around which formula corresponds to which coordinate, so that it matches the coordinate system you are interested in. Just make sure you don't turn a cos into a sin by accident or something like that.
[/quote]

This is what confused me quite a bit at first. However I got some excellent help with it twice (second time was more of an explanation here on gamedev) so the formula I use now should be fine. I've tried it and it worked as I wanted it. In fact I already have a working solution for what I want to do but I didn't use a cartesian to spherical conversion there. Anyway I thought it would be good (someday in the future) to have a properly working function.

Does it have something to do perhaps with arcsin returning a limit between PI/2 and -PI/2?

Share this post


Link to post
Share on other sites
Does it have something to do perhaps with arcsin returning a limit between PI/2 and -PI/2?[/quote]
? No, there are just many coordinate systems in use, for instance XY horizontal plane and Z vertical axis, XZ horizontal plane and Y vertical axis, sometimes the Z axis goes in the negative direction, etc... these are all conventions and you just need to transform the formula from the coordinate system used by Wikipedia into the coordinate system you are using, otherwise it doesn't make sense. The formula is equivalent, it is just in a different (no less valid) coordinate system.

For instance the conventional "up" vector would be (0, 1, 0) in a coordinate system where Y is the vertical axis, if you were to import a model containing such vectors in an application which uses a coordinate system where Z is the vertical axis, you would need to transform the vector to one coordinate system to the other so that it still correctly points upwards, in this case it would involve swapping the Y and Z coordinates, so the new vector would be (0, 0, 1) which is correct.

Share this post


Link to post
Share on other sites
My point is you're converting degrees to radians, then feeding the resulting numbers (which are in radians) back into the degree-to-radian conversion functions. I'm not sure how you expect this to work, but it will always produce incorrect results, because you never convert back to degrees anywhere.

[edit] Don't mind me, I can't read. You are indeed converting back to degrees. It just seems really wasteful to go back and forth all the time and it's going to complicate your math and lead to incorrect conversions like this if you happen to make a mistake. Edited by ApochPiQ

Share this post


Link to post
Share on other sites

Does it have something to do perhaps with arcsin returning a limit between PI/2 and -PI/2?

? No, there are just many coordinate systems in use, for instance XY horizontal plane and Z vertical axis, XZ horizontal plane and Y vertical axis, sometimes the Z axis goes in the negative direction, etc... these are all conventions and you just need to transform the formula from the coordinate system used by Wikipedia into the coordinate system you are using, otherwise it doesn't make sense. The formula is equivalent, it is just in a different (no less valid) coordinate system.

For instance the conventional "up" vector would be (0, 1, 0) in a coordinate system where Y is the vertical axis, if you were to import a model containing such vectors in an application which uses a coordinate system where Z is the vertical axis, you would need to transform the vector to one coordinate system to the other so that it still correctly points upwards, in this case it would involve swapping the Y and Z coordinates, so the new vector would be (0, 0, 1) which is correct.
[/quote]

Alright, this is how I understood it as well. Well basically that's what I've been doing, transforming the formula in wiki (and many other materials) to one suited for my need. I had a hard time understanding first though how all of these can be equivalent and still get confused by it from time to time biggrin.png


My point is you're converting degrees to radians, then feeding the resulting numbers (which are in radians) back into the degree-to-radian conversion functions. I'm not sure how you expect this to work, but it will always produce incorrect results, because you never convert back to degrees anywhere.

[edit] Don't mind me, I can't read. You are indeed converting back to degrees. It just seems really wasteful to go back and forth all the time and it's going to complicate your math and lead to incorrect conversions like this if you happen to make a mistake.


As you said it's most likely wasteful and it will eventually lead to incorrect conversions (as can be seen in the data below). But I don't see how this is keeping it locked at 90-91 degrees.

This is a wild guess but while I checked the data printed out by the conversion the problem seem to be when my z-coordinate gets to really low values..that and it never goes below zero. It gets really weird, I'll print out some values to show. First two lines show the current stored coordinate in both cartesian and spherical form. The two following ones shows the stored coordinate after adding one to theta.

Cartesian coord: (-2.89778, 0, -0.776461)
Spherical coord: (3, 75, 0)

Spherical coord.(after adding 1 to theta): (3, 76, 0)
Cartesian coord.(after adding 1 to theta): (-2.91089, 0, -0.72577)

Cartesian coord: (-2.91089, 0, -0.72577)
Spherical coord: (3, 76, 0)

Spherical coord.(after adding 1 to theta): (3, 77, 0)
Cartesian coord.(after adding 1 to theta): (-2.92311, 0, -0.674858)

Cartesian coord: (-2.92311, 0, -0.674858)
Spherical coord: (3, 77, 0)

Spherical coord.(after adding 1 to theta): (3, 78, 0)
Cartesian coord.(after adding 1 to theta): (-2.93444, 0, -0.62374)

Cartesian coord: (-2.93444, 0, -0.62374)
Spherical coord: (3, 78, 0)

Spherical coord.(after adding 1 to theta): (3, 79, 0)
Cartesian coord.(after adding 1 to theta): (-2.94488, 0, -0.572432)

Cartesian coord: (-2.94488, 0, -0.572432)
Spherical coord: (3, 79, 0)

Spherical coord.(after adding 1 to theta): (3, 80, 0)
Cartesian coord.(after adding 1 to theta): (-2.95442, 0, -0.52095)

Cartesian coord: (-2.95442, 0, -0.52095)
Spherical coord: (3, 80, 0)

Spherical coord.(after adding 1 to theta): (3, 81, 0)
Cartesian coord.(after adding 1 to theta): (-2.96306, 0, -0.469309)

Cartesian coord: (-2.96306, 0, -0.469309)
Spherical coord: (3, 81, 0)

Spherical coord.(after adding 1 to theta): (3, 82, 0)
Cartesian coord.(after adding 1 to theta): (-2.9708, 0, -0.417525)

Cartesian coord: (-2.9708, 0, -0.417525)
Spherical coord: (3, 82, 0)

Spherical coord.(after adding 1 to theta): (3, 83, 0)
Cartesian coord.(after adding 1 to theta): (-2.97764, 0, -0.365614)

Cartesian coord: (-2.97764, 0, -0.365614)
Spherical coord: (3, 83, 0)

Spherical coord.(after adding 1 to theta): (3, 84, 0)
Cartesian coord.(after adding 1 to theta): (-2.98357, 0, -0.313591)

Cartesian coord: (-2.98357, 0, -0.313591)
Spherical coord: (3, 83.9999, 0)

Spherical coord.(after adding 1 to theta): (3, 84.9999, 0)
Cartesian coord.(after adding 1 to theta): (-2.98858, 0, -0.261474)

Cartesian coord: (-2.98858, 0, -0.261474)
Spherical coord: (3, 85, 0)

Spherical coord.(after adding 1 to theta): (3, 86, 0)
Cartesian coord.(after adding 1 to theta): (-2.99269, 0, -0.209275)

Cartesian coord: (-2.99269, 0, -0.209275)
Spherical coord: (3, 85.9999, 0)

Spherical coord.(after adding 1 to theta): (3, 86.9999, 0)
Cartesian coord.(after adding 1 to theta): (-2.99589, 0, -0.157014)

Cartesian coord: (-2.99589, 0, -0.157014)
Spherical coord: (3, 86.9999, 0)

Spherical coord.(after adding 1 to theta): (3, 87.9999, 0)
Cartesian coord.(after adding 1 to theta): (-2.99817, 0, -0.104707)

Cartesian coord: (-2.99817, 0, -0.104707)
Spherical coord: (3, 87.9998, 0)

Spherical coord.(after adding 1 to theta): (3, 88.9998, 0)
Cartesian coord.(after adding 1 to theta): (-2.99954, 0, -0.0523715)

Cartesian coord: (-2.99954, 0, -0.0523715)
Spherical coord: (3, 88.9997, 0)

Spherical coord.(after adding 1 to theta): (3, 89.9997, 0)
Cartesian coord.(after adding 1 to theta): (-3, 0, -1.77503e-005)

Cartesian coord: (-3, 0, -1.77503e-005)
Spherical coord: (3, 90.0001, 0)

Spherical coord.(after adding 1 to theta): (3, 91.0001, 0)
Cartesian coord.(after adding 1 to theta): (-2.99954, 0, 0.0523574)

Cartesian coord: (-2.99954, 0, 0.0523574)
Spherical coord: (3, 89.0001, 0)

Spherical coord.(after adding 1 to theta): (3, 90.0001, 0)
Cartesian coord.(after adding 1 to theta): (-3, 0, 2.63453e-006)

Cartesian coord: (-3, 0, 2.63453e-006)
Spherical coord: (3, 90.0001, 0)

Spherical coord.(after adding 1 to theta): (3, 91.0001, 0)
Cartesian coord.(after adding 1 to theta): (-2.99954, 0, 0.0523574) Edited by Suen

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!