I am using a VI in the LV 2014 distribution called "NI_AALPro.lvlib:3D Coordinate Conversion (Scalar).vi". This uses DBL inputs and outputs, and has several Build Array functions in it as well as a Call Library Function. I need to perform a massive number of Cartesian to Spherical conversions with SGL values, and so I would like to re-write this VI using LV primitives in the most efficiant manner possible.
The math appears to be quite simple, and I have attached a VI that does this. However, there is an issue with calculating the polar angle. From what I read online, it is just arctan (y/x), yet I get incorrect values when x is negative (but not when y is negative).
From what I read on the Wolfram site, "the inverse tangent must be suitably defined to take the correct quadrant of (x/y) into account". I have searched online for more detail on the calculation, but I am lost. Any trig whizzes out there who can help me?
Solved! Go to Solution.
Definitions are extremely important in defining coordinate systems. The documents that you include with your Cart_to_Sph VI contain numerous mistakes and inconsistencies.
Here is a convention that I use and that seems to have a reasonably wide acceptance (I'm not sure that this is the Wolfram convention, however).
Let X, Y, and Z be a right-hand coordinate system. Let P be a point whose X, Y, Z coordinates we know. Define a Spherical Polar Coordinate (SPC) system as follows:
Under this coordinate system, the following code (very similar to Altenbach's, which uses a slightly different coordinate system) maps X, Y, Z into Rho, Theta, Phi:
Let's check some "known quantities". Start with the Unit X axis, [1, 0, 0]. This clearly has length, Rho = 1. The X axis lies in the XY plane, so the angle between it and the Z axis is 90°, so Phi should be pi/2. Finally, the projection of the X axis in the XY plane lies along the X axis, so the angle between the two X axes is 0, so Theta should be 0. The first Re/Im to Polar will give 1, 0, so Theta = 0. The second will give 1, pi/2, so Rho = 1 and Phi = pi/2.
How about Unit Z, [0, 0, 1]? Again, the length, Rho, is 1. Technically, since the Z axis projects onto the origin, the azimuthal angle cannot be properly defined (as both X and Y coordinates are 0), so we'll do a "math cop-out" and just say it's zero. The Polar angle is easy -- the angle between the Z axis and the pole, the Z axis, is 0, so Phi = 0. Now "do the math". Putting [0, 0] into the first Re/Im to Polar gives [0, 0], so Theta = 0. The second Re/Im to Polar takes [1, 0] into [1, 0], so Rho = 1 and Phi = 0.
It is easy to show (especially by coding this up and putting in test numbers) that negative quantities work properly. Rho is always non-negative, Phi is always in the range 0 .. pi, and Theta is always -pi .. pi, with the sign dependent on the sign of Y (as it should be).
Bob "Just Do the Math" Schor
P.S. -- if you think this is fun, just try 3-D rotation matrices ...
Defining (and understanding the definition of) the coordinate system is definitely key here. However, it is so easy to make silly mistakes (just check out the printed material the OP included with the Cart_to_Sph VI, and the mixing of names and Greek letters). I'd say we are in complete agreement ...
Use atan2(y,x) instead
Of course "atan2" and "RE/IM to Polar" give you the identical result for the angle, but with the complex primitive we also get r for free, which we need here anyway.
Some quick benchmarking shows that the complex version is only a few % slower* (but it also caclulates r!). If we use atan2 and calculate r seperately, we are slower than the complex version.
Complex also wastes less diagram space. 😄
* note that these speed differences are irrelevant and many other code changes have similar subtle effects. Unless we get at least a factor of two, I don't worry and go with the cleaner code. 🙂
Continuing on with this discussion, I found some unexpected behavior while comparing the efficiency of the algorithms. See attached VIs (LV-2014).
The first one, SpeedTest1.vi, allows you to compare three different Cartesian-to-Spherical conversion methods. It behaves as expected, with the Real/Imag algorithm running the fastest. All well and good. Then I decided to see what effect using SGL vs DBL would have, so I put a case structure in to try these, SpeedTest2.vi.
Strangely, despite both VIs using the same algorithm, Real/Imag, and both with SGL inputs, the efficiency is vastly different. The only code difference is the presence of the SGL/DBL case structure, which seems to slows things down by a factor of 20x
Any ideas on why there would be such a huge slowdown just from the presence of the case structure?
Hmmm, on a little further investigation, I see that turning off debugging in SpeedTest2.vi greatly improves the efficiency.