Faster way to go from cartesian to polar in C? - math

My C code for discrete Fourier transform needs to output polar values, amplitude and angle. I have a fast algorithm that outputs cartesian values, x and y.
Is there a faster way of converting (f.e. 1024) cartesian values to polar than just:
int x, y;
float amplitude, angle;
...
amplitude = sqrt( x*x + y*y);
angle = atan2( y, x );
?

There are two approaches:
(1) Perform the common 2D FFT, and then complete the cartesian to polar conversion by yourself.
(2) Use the so called "polar FFT" directly. Actually, the "polar FFT" is also based on the interpolation.

I suggest that you read about CORDIC, check out this article.

Related

How to convert Cartesian coordinates epitrochoid graph into polar coordinates in pascalABC?

For my student project I need to create pascalABC.NET program that makes Epitrochoid graph in Cartesian and Polar coordinate systems. I made some simple code for Cartesian system and it seems to work pretty well, how can i convert it to polar system now? Is there any math equations for epitrochoid in polar system that i can use for this program? Hope someone can help me :)
Code i made for Cartesian system:
uses graphABC;
var c,x,y:integer;
r1,r2,m,h,t,ms:real;
begin
setwindowsize(500,500);
centerwindow;
c:=250;
r1:=1;
r2:=0.2;
m:=r2/r1;//m=0.2
h:=0.3;
ms:=(c-50)/(r1+2*r2);
setpenwidth(2);
setpencolor(clGreen);
circle(c,c,round(r1*ms));
setpencolor(clRed);
t:=0;
while t<=360 do
begin
x:=c+round((r1*(m+1)*cos(m*t)-h*cos((m+1)*t))*ms);
y:=c-round((r1*(m+1)*sin(m*t)-h*sin((m+1)*t))*ms);
if t=0 then moveto(x,y) else lineto(x,y);
t:=t+0.1;
end;
end.
You cannot build explicit function ro(theta) for epitrochoid.
It is possible to make ro(t) and theta(t) for t parameter:
ro = sqrt(x^2 + y^2)
theta = arctan2(y, x)
where x, y are expressions like your r1*(m+1)*cos(m*t)-h*cos((m+1)*t))*ms
Example of formula derivation for epicycloid
and result for epitrochoid
Seems a bit unnatural, in my mind...
Problems - it is hard to get equal-spaced points by theta, also note that one theta value might correspond to two ro values (loops at your picture).

From line in cartesian coordinates to polar coordinates with youth style

I have line like in 2D defined by ax+by+c = 0 so (a,b,c).
I need to compute a polar representation of this line like Hough approach with rho an theta.
How to do this?
A line in cartesian coordinates is not as easily represented in polar coordinates.
You can simply substitute x,y with their respective polar equivalents, r*cos(theta), r*sin(theta), giving you
a*r*cos(theta) + b*r*sin(theta) + c = 0
This implicit equation is not as easy to figure out, however. But, if you first convert your implicit line equation to a parametric vector equation of the form (x,y) = R(t) = R0 + t*V, where R0,V are cartesian vectors which you can derive from a,b,c, you can then write
(r*cos(theta), r*sin(theta)) = R0 + t*V
and solve this system of equations for r and theta in terms of t.
However, polar coordinates are not the same as the Hough transform.
In the Hough system, the line is defined by the length rho of a perpendicular line that crosses (0,0) , which is theta = atan(b/a). Figuring out rho seems more difficult at first, but this tutorial explains it.

Given a 2D transformation matrix, how to calculate the scalings, skews, rotations and translations?

I wrote a program (like this) that generate and apply a transformation matrix to an object thanks to user's input on scalings, skews, rotations and translations.
Now I want to do it inversely: given the transformation matrix, how to calculate the these values? The matrix is 2D (a, b, c, d, tx, ty).
I know this is a pure math problem but I was not concentrated enough in high school...
I found a lot of useful info on this tutorial which solved the problem for me. Here is the formula for those who cares:
Translation (pixel)
x := tx
y := ty
Scale (time)
scale_x := sqrt(a^2 + b^2)
scale_y := sqrt(c^2 + d^2)
Skew (degree)
skew_x := 180/pi * atan2(d, c) - 90
skew_y := 180/pi * atan2(b, a)
Rotation (degree)
This is the tricky part: rotation is not a basic transform function; in fact it is the result of the combination of skew and scale. You can skew an object by its x and y axis and then scale it to make it look like it has been rotated. The angle of x skew is usually regarded as the rotation angle:
rotation := skew_x
Sometimes:
rotation := skew_y
Assuming a translate/rotate/scale&skew order of operations, the easiest thing to do is to snip them off one at a time.
Extract the last column; it is the translation. discard it and the last row.
Find the QR decomposition of the resultant 3x3 matrix. The orthogonal component is the rotation; discard it and keep the upper triangular component.
The diagonal of the upper triangular component is the scaling. Reverse it by left-multiplying the upper triangular matrix by the scaling's inverse.
The result is the skew matrix.

Rotate quaternion on all 3 axis from axis angle in GLM

I use quaternions for rotations in OpenGL engine.Currently , in order to create rotation matrix for x ,y and z rotations I create a quaternion per axis rotation.Then I multiply these to get the final quaternion:
void RotateTo3(const float xr ,const float yr ,const float zr){
quat qRotX=angleAxis(xr, X_AXIS);
quat qRotY=angleAxis(yr, Y_AXIS);
quat qRotZ=angleAxis(zr, Z_AXIS);
quat resQuat=normalize(qRotX * qRotY * qRotZ);
resQuat=normalize(resQuat);
_rotMatrix= mat4_cast(resQuat);
}
Now it's all good but I want to create only one quaternion from all 3 axis angles and skip the final multiplication.One of the quat constructors has params for euler angles vector which goes like this:
quat resQuat(vec3(yr,xr,zr))
So if I try this the final rotation is wrong.(Also tried quat(vec3(xr,yr,zr)) ) .Isn't there a way in GLM to fill the final quaternion from all 3 axis in one instance ?
Now , one more thing:
As Nicol Bolas suggested , I could use glm::eulerAngleYXZ() to fill a rotation matrix right away as by his opinion it is pointless to do the intermediate quaternion step.. But what I found is that the function doesn't work properly , at least for me .For example :
This :
mat4 ex= eulerAngleX(radians(xr));
mat4 ey= eulerAngleY(radians(yr));
mat4 ez= eulerAngleZ(radians(zr));
rotMatrix= ex * ey * ez;
Doesn't return the same as this :
rotMatrix= eulerAngleYXZ(radians(yr),radians(xr),radians(zr));
And from my comparisons to the correct rotation state ,the first way gives the correct rotations while the second wrong .
Contrary to popular belief, quaternions are not magical "solve the Gimbal lock" devices, such that any uses of quaternions make Euler angles somehow not Euler angles.
Your RotateTo3 function takes 3 Euler angles and converts them into a rotation matrix. It doesn't matter how you perform this process; whether you use 3 matrices, 3 quaternions or glm::eulerAngleYXZ. The result will still be a matrix composed from 3 axial rotations. It will have all of the properties and failings of Euler angles. Because it is Euler angles.
Using quaternions as intermediaries here is pointless. It gains you nothing; you may as well just use matrices built from successive glm::rotate calls.
If you want to do orientation without Gimbal lock or the other Euler angle problems, then you need to stop representing your orientation as Euler angles.
In answer to the question you actually asked, you can use glm::eulerAngleYXZ to compute
Do you mean something like this:
quat formQuaternion(double x, double y, double z, double angle){
quat out;
//x, y, and z form a normalized vector which is now the axis of rotation.
out.w = cosf( fAngle/2)
out.x = x * sinf( fAngle/2 )
out.y = y * sinf( fAngle/2 )
out.z = z * sinf( fAngle/2 )
return out;
}
Sorry I don't actually know the quat class you are using, but it should still have some way to set the 4 dimensions. Source: Quaternion tutorial
eulerAngleYXZ gives one possible set of euler angles which, if recombined in the order indicated by the api name, will yield the same orientation as the given quaternion.
It's not a wrong result - it's one of several correct results.
Use a quaternion to store your orientation internally - to rotate it, multiply your orientation quat by another quat representing the amount to rotate by, which can be built from angle/axis to achieve what you want.

The X angle between two 3D vectors?

I have two 3D vectors called A and B that both only have a 3D position. I know how to find the angle along the unit circle ranging from 0-360 degrees with the atan2 function by doing:
EDIT: (my atan2 function made no sense, now it should find the "y-angle" between 2 vectors):
toDegrees(atan2(A.x-B.x,A.z-B.z))+180
But that gives me the Y angle between the 2 vectors.
I need to find the X angle between them. It has to do with using the x, y and z position values. Not the x and z only, because that gives the Y angle between the two vectors.
I need the X angle, I know it sounds vague but I don't know how to explain. Maybe for example you have a camera in 3D space, if you look up or down than you rotate the x-axis. But now I need to get the "up/down" angle between the 2 vectors. If I rotate that 3D camera along the y-axis, the x-axis doens't change. So with the 2 vectors, no matter what the "y-angle" is between them, the x-angle between the 2 vectors wil stay the same if y-angle changes because it's the "up/down" angle, like in the camara.
Please help? I just need a line of math/pseudocode, or explanation. :)
atan2(crossproduct.length,scalarproduct)
The reason for using atan2 instead of arccos or arcsin is accuracy. arccos behaves very badly close to 0 degrees. Small computation errors in argument will lead to disproportionally big errors in result. arcsin has same problem close to 90 degrees.
Computing the altitude angle
OK, it might be I finally understood your comment below about the result being independent of the y angle, and about how it relates to the two vectors. It seems you are not really interested in two vectors and the angle between these two, but instead you're interested in the difference vector and the angle that one forms against the horizontal plane. In a horizontal coordinate system (often used in astronomy), that angle would be called “altitude” or “elevation”, as opposed to the “azimuth” you compute with the formula in your (edited) question. “altitude” closely relates to the “tilt” of your camera, whereas “azimuth” relates to “panning”.
We still have a 2D problem. One coordinate of the 2D vector is the y coordinate of the difference vector. The other coordinate is the length of the vector after projecting it on the horizontal plane, i.e. sqrt(x*x + z*z). The final solution would be
x = A.x - B.x
y = A.y - B.y
z = A.z - B.z
alt = toDegrees(atan2(y, sqrt(x*x + z*z)))
az = toDegrees(atan2(-x, -z))
The order (A - B as opposed to B - A) was chosen such that “A above B” yields a positive y and therefore a positive altitude, in accordance with your comment below. The minus signs in the azimuth computation above should replace the + 180 in the code from your question, except that the range now is [-180, 180] instead of your [0, 360]. Just to give you an alternative, choose whichever you prefer. In effect you compute the azimuth of B - A either way. The fact that you use a different order for these two angles might be somewhat confusing, so think about whether this really is what you want, or whether you want to reverse the sign of the altitude or change the azimuth by 180°.
Orthogonal projection
For reference, I'll include my original answer below, for those who are actually looking for the angle of rotation around some fixed x axis, the way the original question suggested.
If this x angle you mention in your question is indeed the angle of rotation around the x axis, as the camera example suggests, then you might want to think about it this way: set the x coordinate to zero, and you will end up with 2D vectors in the y-z plane. You can think of this as an orthogonal projection onto said plain. Now you are back to a 2D problem and can tackle it there.
Personally I'd simply call atan2 twice, once for each vector, and subtract the resulting angles:
toDegrees(atan2(A.z, A.y) - atan2(B.z, B.y))
The x=0 is implicit in the above formula simply because I only operate on y and z.
I haven't fully understood the logic behind your single atan2 call yet, but the fact that I have to think about it this long indicates that I wouldn't want to maintain it, at least not without a good explanatory comment.
I hope I understood your question correctly, and this is the thing you're looking for.
Just like 2D Vectors , you calculate their angle by solving cos of their Dot Product
You don't need atan, you always go for the dot product since its a fundamental operation of vectors and then use acos to get the angle.
double angleInDegrees = acos ( cos(theta) ) * 180.0 / PI;

Resources