# Will This Work?

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

## Recommended Posts

I got someone on a math forum to come up with a formula to convert a normal to a spherical coordinate from there I made it into c++ but I'm not sure it will work or if this is the best way so tell me how I can make it better or at least work?
void Normal2Spherical(float x,float y,float z)
{
radius = sqrt((x*x) + (y*y) + (z*z));
latitude = arctan(y/x);
if(y<0 && x<0)
{
latitude += 180;
}
if(y>0 && x<0)
{
latitude += 180;
}
longitude = arccos(z/sqrt((x*x) + (y*y) + (z*z)))
}


[Edited by - EmptyVoid on July 26, 2007 4:54:34 PM]

##### Share on other sites
Ok; let's go through it line by line. I'm assuming you haven't actually tested it, since this code wouldn't compile. Additionally, this doesn't look like you want spherical coordinates, it looks like you want geographic coordinates. Which is it?

void Normal2Spherical(float x,float y,float z) {  // No semicolon  float radius, latitude, longitude;  // This line is unnecessary. If it's a normal, the radius will be 1.  radius = sqrt((x*x) + (y*y) + (z*z));  // arctan does not return degrees, it returns radians  latitude = arctan(y/x) * 180.0f / M_PI;  // What range are you trying to keep the latitude in? arctan is in the range  // [-π,π], so I'm guessing that you want to keep it in [0,2π]? Either way,  // adding π isn't the answer. If you want to keep a correct translation, add  // 2π. That and you don't need to test against x and y, just test for latitude.  if( latitude < 0.0f ) {     latitude += 360.0f;   }  // You've already calculated the radius, so why do it again?  // Even still, it's unnecessary, since the radius will be 1.  longitude = arccos(z) * 180.0f / M_PI;}

That being said, I didn't actually check your math - just your code.

##### Share on other sites
OK is this right?

void Normal2Spherical(float x,float y,float z){float latitude, longitude;latitude = arctan(y/x) * 180.0f / 3.14159f;if(latitude < 0.0f) { latitude += 360.0f; } longitude = arccos(z) * 180.0f / 3.14159f;}

And as I said I don't really know how it works I didn't make the formula. I just made it into c++.

##### Share on other sites
Err.. that code doesnt really do anything
It may as well be

void Normal2Spherical(float x,float y,float z){}

Whether latitude and longitude were calculated correctly however I dont really know, sorry. Although it doesnt look like calculating spherical coordinates to me.

That said, the point remains you still need to return whatever output you calculate.

spherical polar coordinates are calculated using a radius, theta and phi:

radius = sqrt(x*x + y*y + z*z)
theta = arctan(y/x)
phi = arccos(z/r)

I think the point you're missing is that in your first example you forgot the quotient z/r within the arccos. << Edit: Actually I was looking at erissians version where the division is missing, in your original version EmptyVoid you calculate the radius twice for some reason.

I'd also rename your function to CartesianToSpherical which makes much more sense.

Edit:
Quote:
 arctan is in the range // [-π,π], so I'm guessing that you want to keep it in [0,2π]? Either way, // adding π isn't the answer. If you want to keep a correct translation, add // 2π.

Am i miss-understanding? I think adding Pi is correct?:
-π + π = 0
π + π = 2π

[Edited by - dmatter on July 26, 2007 7:55:33 PM]

##### Share on other sites
Quote:
Original post by dmatter
Edit:
Quote:
 arctan is in the range // [-π,π], so I'm guessing that you want to keep it in [0,2π]? Either way, // adding π isn't the answer. If you want to keep a correct translation, add // 2π.

Am i miss-understanding? I think adding Pi is correct?:
-π + π = 0
π + π = 2π

Angles in the range [0,PI] are correct. You will have only to translate negative angles to the equivalent positive value (keeping it smaller than 2*PI), which is done by adding 2*PI. You keep your [0,PI] and replace [-PI,0) with [PI,2*PI), resulting in an interval of [0,2*PI).

##### Share on other sites
OK I have added all your ideas to the code but made some changes I need the values in the range of 0-1. I also tested it and it works. this is what I have:

#include "math.h"struct SPHCOORD{float theta, phi;};SPHCOORD CartesianToSpherical(float x,float y,float z){SPHCOORD SphericalPos;SphericalPos.theta = atan(x/z)/6.28318f;if(SphericalPos.theta < 0.0f) SphericalPos.theta += 0.5f;//Fix for problem #1if(z== -1.0f) SphericalPos.theta += 0.5f;//Fix for problem #2if(x<0)SphericalPos.theta += 0.5f;SphericalPos.phi = acos(y)/3.14159f;return SphericalPos;}

But there are 2 problems with it.

1. When it's exactly 0, 0, -1 it returns 0.0, 0.5 but it needs to be 0.5, 0.5 so I added this code:

if(z== -1.0f) SphericalPos.theta += 0.5f;

2. When x less then 0 it starts back at 0 like when it's set to -0.1, 0, -0.9 it returns 0.017612, 0.5 so I added this code:

if(x<0)SphericalPos.theta += 0.5f;

So how can I make this more mathematically perfect?

[Edited by - EmptyVoid on July 27, 2007 6:38:45 PM]

##### Share on other sites
Well, this time around I'm going to assume that you want spherical coordinates. They are subtly different from geographic coordinates.

Geographic coordinates have only two values, longitude and latitude. Latitude is measured in degrees north or south of the equator, giving it a range of [-90,90]. Longitude is measured in degrees east or west of the meridian, giving it a range of [-180,180]. The radius is non-existent because it is assumed to be whatever the radius of the surface of the object is at that point, but you could implement it anyways for a more abstract system, but it's much easier to deal with genuine spherical coordinates.

Spherical coordinates are defined by three values, θ (theta), φ (phi), and ρ (radius). Theta denotes the angle from the top of the sphere (or Z axis) in radians, so it has a range of [0,π]. Phi denotes the angle from the X axis (typically) giving it a range of [0,2π]. The radius denotes the distance from the center of the sphere to the point being described. It has a range of [0,∞).

You are converting a rectilinear normal to spherical coordinates in this function. Because it's a normal, it has a radius of 1 by definition, so we can skip anything that deals with it. I'll still mention it where appropriate, but I won't put it in the resulting code. dmatter is correct that your code doesn't return anything, but I'm assuming that this is example code anyways.

The first thing we'll do it figure out phi, or the angle between the vector and the X axis. This is done by projecting the vector onto the XY plane (assuming your "up" is Z. If it isn't, then just mentally switch all my Ys and Zs). This projection is pretty easy, just ignore the Z component of the vector. Now if you remember what a tangent is (if not, look it up now), then we can use two parts of a triangle to find the angle using the arctangent (atan2f). In this case the opposite angle will be the Y component, and the adjacent angle will be the X component, therefore:

phi = atan2f(y,x);

After that, we need to find theta. This is done is the same manner, but on the plane between the Z axis and our vector. Also, we'll need not the length of our vector, but the vector we projected onto the XY plane earlier.

theta = atan2f(sqrtf(x*x+y*y),z);

##### Share on other sites
lol erissian you posted like 1 secound after me ok I put all of your ideas into one perfect function and here it is:

[source c++]#include "math.h"struct SPHCOORD{float theta, phi;};SPHCOORD CartesianToSpherical(float x, float y, float z){SPHCOORD SphericalPos;SphericalPos.phi = atan2f(x,z)/6.28318f;if(SphericalPos.phi < 0.0f) SphericalPos.phi += 1.0f;SphericalPos.theta = atan2f(sqrtf(x*x+z*z),y)/3.14159f;return SphericalPos;}

So it works perfect. I can't see how it could be any better but if anyone else has an idea please tell me.

[Edited by - EmptyVoid on July 28, 2007 5:37:35 AM]

• ### What is your GameDev Story?

In 2019 we are celebrating 20 years of GameDev.net! Share your GameDev Story with us.

• 11
• 15
• 14
• 46
• 22
• ### Forum Statistics

• Total Topics
634054
• Total Posts
3015274
×