Numerical precision of arctan function I'm trying to convert points into spherical coordinates, do some filtering/manipulation of the points and convert them back into the Cartesian coordinate frame. These are my transformation equations into spherical coordinates:
$$
\begin{align}
r &= \sqrt{x^2 + y^2 + z^2}\\
\theta &= \arccos\left(\frac{z}{x^2+y^2+z^2}\right)\\
\phi &= \arctan\left(\frac{y}{x}\right)
\end{align}
$$
And to convert back to Cartesian coordinates:
$$
\begin{align}
x &= r\sin{\theta}\cos{\phi}\\
y &= r\sin{\theta}\sin{\phi}\\
z &= r \cos{\theta}
\end{align}
$$
However, after converting back to Cartesian coordinates, I notice a hole in my points along the $z$-axis (both in the positive $z$-axis and negataive $z$-axis directions). I suspect this is due to the imprecision of the $arctan$ function (I'm using the std version of atan2 in C++). Can anyone confirm my this? If so, does anyone know a way around it?
 A: If anything, I would suspect the acos function since you need to compute its argument very precisely near the z-axis to ensure that you remain within the domain $[-1,1]$. Due to the sensitivity of acos near the endpoints of its domain to small numerical errors (the slope approaches vertical), I would suggest computing $\theta$ using the asin function when you detect that the $z$ coordinate dominates the $x$ and $y$ coordinates.
Currently, you are essentially taking a dot product of your normalized vector $(x,y,z)/|(x,y,z)|$ with the unit $z$ vector $(0,0,1)$, which gets you $\cos\theta$. Instead, compute the magnitude of the cross product of your normalized vector with the unit $z$ vector, which gets you $\sin\theta$. The slope of asin is around $1$ near $0$, leading to much improved numerical sensitivity.
A: A good rule of thumb is: don't ever use acos or asin on arguments whose magnitudes may be greater than $\sqrt 2/2$.
Since you're using atan2 which is a solid tool, you can get the two angles robustly as:
$$
\begin{align}
\theta &= \mathrm{atan2}\left({z},\sqrt{x^2+y^2}\right)\\
\phi &= \mathrm{atan2}\left({y},{x}\right)
\end{align}
$$
The rest of your formulas look good.
