what do you think r is? With the coord pair r is the distance
This is a discussion on Inverse Tangent within the C++ Programming forums, part of the General Programming Boards category; what do you think r is? With the coord pair r is the distance...
what do you think r is? With the coord pair r is the distance
Dood if you want an EASY way to calculate inverse tan, all you have to do is incorporate sequences and series from Calculus.
Okay because the derivative of inverse tan is 1/(1+x^2)
transforming this into an infinite series you get 1+X^2+X^4+X^6... to x^infinity.
Integrate this and you get
X+(X^3)/3 + (X^5)/5 + (X^7)/7
So thats your function. Make it recurse as many times as you want and make it so that the more times you recurse the function the more accurate it is.
Hey Knee I'm willing to bet Quantrizi isn't in calculas yet
>>you need to convert the sin and cos to from radians to degress first. sorry about that
Maybe this works, and I'm not totally sure why it would, but from my understanding... it's the angle that needs to be converted to radians, not the trig'ed result (and besides which, you're 'converting' the result to degrees from radians...).Code:x = cos(theta) * (180/pi) y = sin(theta) * (180/pi)
Code:theta *= (pi / 180); x = r * cos(theta); y = r * sin(theta);Hold it right there... That whole r * sin(theta) bit WAS converting from polar to rectangular. Rectangular means using (x,y) to represent the vector. Polar is using an angle and magnitude.That works perfectly for what I need on converting rectangular to polar.
I am still having trouble though trying to change polar into rectangular. Do you have any ideas on howto fix it?
Anyhoo, to convert to polar, you need to:
a) atan(y / x) to give you the reference angle (in radians - so convert to degrees)
b) If x > 0 and y > 0, leave it; if x < 0 and y > 0, add 180; if x < 0 and y < 0, add 180; if x > 0 and y < 0, add 360.
c) Magnitude can be found with Pythagoras: mag = sqrt((x * x) + (y * y));
And there you have polar.
**EDIT**
@ KneeGrow:
If you mean easy as in 'simple', I disagree. If you mean it as in 'requires little math knowledge', I disagree. If you mean it as 'Easy for the computer, i.e. is fast', I disagree. The atan() function finds the result exactly, as far as a double can be precise. I don't know how accurate your function is either; if you need to recurse very far though, I can imagine that it will be VERY slow with the accumulated stack-building/destroying etc. that you'll end up with, besides which you're doing power and division operations for each recursive call - and, if you recurse too far (unlikely, I suppose, unless you have an overenthusiastic coder), you'll run into stack overflows.Dood if you want an EASY way to calculate inverse tan, all you have to do is incorporate sequences and series from Calculus.
...
So thats your function. Make it recurse as many times as you want and make it so that the more times you recurse the function the more accurate it is.
It is highly unlikely that your homemade function will be any faster than the function provided with the compiler. Chances are, the compiler-writers either used that implementation themselves, or else they found a better way of doing it. Why reinvent the wheel, when you're just going to end up with something worse?
Last edited by Hunter2; 05-08-2004 at 04:12 PM.
Just Google It. √
(\ /)
( . .)
c(")(") This is bunny. Copy and paste bunny into your signature to help him gain world domination.
dang it you got me. Serves me right for not actually testing it. You are correct, theta needs to be converted from degress to radians and then put into the functions. I'm gotten so used to using radians since we've been told to get used to them.
>>I'm gotten so used to using radians since we've been told to get used to them.
Lucky you. I still can't stand the darned things!
Just Google It. √
(\ /)
( . .)
c(")(") This is bunny. Copy and paste bunny into your signature to help him gain world domination.
Major difference between getting used to and liking.
I threw together my own program for this. It seems to work. The hardest part is dealing with the limited domain of atan and having to check to make sure that x isn't zero (don't want those pesky floating point errors)
Oh and no I didn't type out pi, I copied and paste from the windows calculatorCode:#include <iostream> #include <math.h> using namespace std; void polar2rect(double &, double &, double &, double &); void rect2polar(double &, double &, double &, double &); int main(void) { double x, y, r, theta; polar2rect((r=5), (theta=45), x, y); cout<<"Number 1: "<<"\tRad: "<<r<<"\tTheta: "<<theta<<"\tx: "<<x<<"\ty: "<<y<<endl; x = y= r = theta = 0.0; rect2polar((x=0), (y=4), r, theta); cout<<"Number 2: "<<"\tRad: "<<r<<"\tTheta: "<<theta<<"\tx: "<<x<<"\ty: "<<y<<endl; } void polar2rect(double &r, double &theta, double &x, double &y) { double rtheta = theta * (3.1415926535897932384626433832795/180); x = r * cos(rtheta); y = r * sin(rtheta); } void rect2polar(double &x, double &y, double &r, double &theta) { double ref; if ( x != 0.0 ) { ref = atan(y/x); ref *= (180/3.1415926535897932384626433832795); if (x < 0.0) { if ( y > 0.0 ) theta = 180 - ref; else theta = 180 + ref; } else theta = ref; } else { if ( y > 0.0) theta = 90; else if ( y < 0.0) theta = 270; else theta = 0; } r = pow(x*x + y*y, .5); }
>>Oh and no I didn't type out pi, I copied and paste from the windows calculator
Hehehe, call me a nerd but I can recite pi to 3 more decimal places than you typed out
I actually have a function here that I wrote a little while ago, to find the angle from one point to another. I used it for my NetMaggotz game I actually included another parameter, specifying if it was in screen coordinates or 'normal' coordinates, and if it was screen then it would reverse the y coordinates, but in this case that isn't useful.
radiansToDegrees basically does the " *= pi/180", except that the constant multiplier is defined as a static constant, so the division operation doesn't get run every time the function is called. I love the ternary operatorCode:float angleTo(POINTFLOAT pos, POINTFLOAT dest) { //Check for special cases if(dest.x == pos.x) return (dest.y >= pos.y)? 90.f : 270.f; else if(dest.y == pos.y) return (dest.x >= pos.x)? 0.f : 180.f; //If no special cases, continue... float result = radiansToDegrees((float)atan((dest.y - pos.y) / (dest.x - pos.x))); //Get positive angles, in proper quadrants if(dest.x < pos.x) //Quad II, III result += 180.f; else if(dest.y < pos.y) //Quad IV result += 360.f; return result; }
P.S. Say, why are you using pow() instead of sqrt()? lol...
Just Google It. √
(\ /)
( . .)
c(")(") This is bunny. Copy and paste bunny into your signature to help him gain world domination.
Personal preference. Since I'm often using math that requires finding other roots and other powers besides 2, I prefer to use pow() rather then sqrt() so that I can more easily change my roots around if need be. Also since I think of roots as just fractional exponents it makes since to meP.S. Say, why are you using pow() instead of sqrt()? lol...
Also, wouldn't it just be easier to use M_PI?
Naturally I didn't feel inspired enough to read all the links for you, since I already slaved away for long hours under a blistering sun pressing the search button after typing four whole words! - Quzah
You. Fetch me my copy of the Wall Street Journal. You two, fight to the death - Stewie
Using a series expansion will give a varied range of inaccuracies. For example when using a series to get the distance between 2 points in 2D the error range is +/- 3% and for 3D it is +/- 6%. If you are looking for accurate values...use sqrt(). If you are looking for speedy math functions...use the FPU in assembly.
Floating point operations are extremely fast...in some instance faster than integer operations on modern CPUs so I wouldn't worry too much about using them.
Knee: Thantos is correct. I'm not in calculus yet. I'm in year 3 integrated math (it's like medium-advanced math).
Hunter: Thanks. Polar coordinates use (radius, theta) though. But still, thanks I'll try out what you've given me.
Thantos: Thanks I'm using atan2 though, but I'll try out atan again.
Thanks all for your help. I'll see how it goes.
Here's my code now (thanks to Thantos I believe it was for the rect2polar and polar2rect functions. if it wasn't thantos, sorry):
Really, my only problem is that I still can't theta to display correctly. Does anyone have any ideas on why?Code:static void Polar2Rect(double r, double theta){ double rtheta = theta * (pi/180); x = r * cos(rtheta); y = r * sin(rtheta); cout << "x = r * cos(theta)\n"; cout << "x = " << r << " * cos(" << theta << ")\n"; cout << "x = " << x << "\n\n"; cout << "y = r * sin(theta)\n"; cout << "y = " << r << " * sin(" << theta << ")\n"; cout << "y = " << y << "\n\n"; cout << "Rect: (" << x << " , " << y << ")\n\n"; } static void Rect2Polar(double x, double y){ double ref, x2, y2, r2 = 0; ref = atan(y/x); ref *= (180/pi); if((x < 0) || (x > 0)){ if((ref >= 0) || (ref < 90)){ theta = ref; } if(ref == 90){ theta = ref; } if((ref > 90) || (ref < 180)){ theta = 180 - ref; } if(ref == 180){ theta = ref; } if((ref > 180) || (ref < 270)){ theta = 180 + ref; } if(ref == 270){ theta = ref; } if((ref > 270) || (ref < 360)){ theta = 360 - ref; } if(ref == 360){ theta = 0; } } x2 = x * x; y2 = y * y; r2 = x2 + y2; r = sqrt(r2); cout << "NOTICE: sqrt(...) means square root.\n"; cout << " itan(...) means inverse tangent.\n\n"; cout << "r = sqrt(x^2 + y^2)\n"; cout << "r = sqrt(" << x << "^2 + " << y << "^2)\n"; cout << "r = " << r << "\n\n"; cout << "theta = itan(y/x)\n"; cout << "theta = itan(" << y << "/" << x << ")\n"; cout << "theta = " << theta << "\n\n"; cout << "Polar: (" << r << " , " << theta << ")\n\n"; }
It is really interesting how you can complicate such simple thing
I would suggest this:
Note that I only changed second function which is much simpler now.Code:#include <iostream> #include <cmath> using namespace std; const double pi=3.14159; static void Polar2Rect(double r, double theta){ double rtheta = theta * (pi/180),x,y; x = r * cos(rtheta); y = r * sin(rtheta); cout << "x = r * cos(theta)\n"; cout << "x = " << r << " * cos(" << theta << ")\n"; cout << "x = " << x << "\n\n"; cout << "y = r * sin(theta)\n"; cout << "y = " << r << " * sin(" << theta << ")\n"; cout << "y = " << y << "\n\n"; cout << "Rect: (" << x << " , " << y << ")\n\n"; } static void Rect2Polar(double x, double y){ double r,theta; r=sqrt(pow(x,2)+pow(y,2)); if(x==0 && y>0) theta=90; else if(x==0 && y<0) theta=270; else { theta=atan(y/x); theta=theta*180/pi; if(x<0 && y>0) theta=180-theta; else if(x<0 && y<0) theta=180+theta; else if(x>0 && y<0) theta=360+theta; } cout << "NOTICE: sqrt(...) means square root.\n"; cout << " itan(...) means inverse tangent.\n\n"; cout << "r = sqrt(x^2 + y^2)\n"; cout << "r = sqrt(" << x << "^2 + " << y << "^2)\n"; cout << "r = " << r << "\n\n"; cout << "theta = itan(y/x)\n"; cout << "theta = itan(" << y << "/" << x << ")\n"; cout << "theta = " << theta << "\n\n"; cout << "Polar: (" << r << " , " << theta << ")\n\n"; } int main() { double x=3,y=4; Rect2Polar (2,3); return 0; }
I leave simplification of the first one to you.
This is ok if you want theta in range [0 360] degrees.
You could also use theta [-180 180] degrees.