# clamp Spherical coordinates to latitude/longitude

For usage in a shader I am looking for an efficient way to convert spherical coordinates to latitude/longitude values in $$[0,\pi]$$, $$[0,2\pi]$$ respectively. (Conversion to convential long/lat with these values would be trivial)

For the spherical coordinates I'm using the mathematical convention with $$\phi$$ corresponding to the latitude and $$\phi=0$$ at the north pole and $$\theta$$ corresponding to the longitude.

As a starting point one could write

$$lat = \phi$$ $$long = mod(\theta, 2\pi)$$

$$r$$ is left out as it is constant.

Now the difficulty I'm having is extending this to convert spherical coordinates with $$\phi$$ not in $$[0,\pi]$$. In this case spherical coordinates can be written as (again ignoring $$r$$)

$$\vec{r} = \phi\hat{\phi} + \theta\hat{\theta}$$

I am not sure how I should express the way in which the latitude $$\phi$$ influences the longitude if

$$\pi

If I'm not mistaken, one way would be to write it as a piecewise function like this:

$$\vec{r}_{longlat}=\begin{cases} mod(\phi, \pi)\hat{\phi} + mod(\theta, 2\pi)\hat{\theta} & mod(\phi, 2\pi)\in[0,\pi]\\ (\pi-mod(\phi, \pi))\hat{\phi} + mod(\theta+\pi, 2\pi)\hat{\theta} & mod(\phi, 2\pi)\notin[0,\pi] \\ \end{cases}$$

However, I'm wondering if there's a more elegant way to go about it.

Another way to do it would be to simplify the result of converting the spherical coordinates to carthesian coordinates and then getting the spherical coordinates back from that again. In that case one finds the carthesian coordinates,

$$\vec{p} = \begin{bmatrix} cos(\theta)sin(\phi) \\ sin(\theta)sin(\phi) \\ cos(\phi) \end{bmatrix}$$

which can be converted back to get

$$\vec{r}_{longlat} = \begin{bmatrix} arccos(cos(\phi)) \\ atan2(cos(\theta)sin(\phi), sin(\theta)sin(\phi)) \\ \end{bmatrix}$$

Then the $$arccos(cos(\phi))$$ gives the ping-pong behaviour and atan2 would handle the offset on $$\theta$$ based on $$\phi$$.

Which of these two makes more sense to use? Which would you expect to be more efficient? Are there any alternatives/well known formulae I'm not considering?

• "In this case spherical coordinates can be written as (again ignoring $r$) $\vec{r} = \phi\hat{\phi} + \theta\hat{\theta}$" - No. That works in cartesian coordinates, but in spherical coordinates $\hat\phi$ and $\hat\theta$ are not constants, and represent tangent directions at $\vec r$, These directions change as $\vec r$ changes, so you cannot use them to locate $\vec r$. Dec 13, 2021 at 17:49
• @PaulSinclair You're right, this description was not mathematically sound. But in this usecase where I try to define on a sphere of a known radius this point can be defined by the values of $\phi$ and $\theta$ only. I suppose a better way to describe it would be to use the vector $(r, \phi, \theta)$ leaving $r$. Dec 13, 2021 at 22:14

If you want efficiency, using $$\text{arccos}(\cos \phi)$$ is like driving 5 miles south to the ring-freeway, following it around to the north side of town, and driving another 5 miles south to visit the second house up the block from where you started. Similarly for $$\text{atan2}$$. You would be hard-pressed to come up with a more in-efficient solution.

Seriously - computers directly add, subtract, multiply, and divide. Anything else takes multiple steps to calculate - usually many such steps. It used to be that even multiplying and dividing required multiple steps, but then chip technology improved until the whole logic could be performed in one step. And yes, on the most advanced chips, some functions - square rooting in particular - are now incorporated into a single operation. But even if the trig functions were all incorporated, why would you bother when the problem has a much more simple computation?

A simple algorithm takes care of it:

ToLatitudeLongitude(phi, theta)
phi = mod(phi, 2*pi)
theta = mod(theta, 2*pi)
if (phi > pi)
phi = 2*pi - phi
if (theta < pi)
theta = theta + pi
else
theta = theta - pi

return (phi, theta)

• Very nice algorithm, thank you. I ended up writing this with the main difference adding pi before the modulo on theta (here frac) to avoid the second if: // add offset in fmod to ensure proper behaviour with negative input // safe considering that theta and phi do not change by more than 1 between frames // phi and theta stored divided by pi for convenience with UVs phi = fmod(2.0f + phi, 2.0f); theta = phi > 1.0f ? theta + 0.5f : theta; theta = frac(1.0f + theta); phi = phi > 1.0f ? 2.0f - phi : phi; (can't do multi line code in comments :( ) Dec 13, 2021 at 22:49
• That is an improvement. If looks like theta is divided by $2\pi$, not $\pi$. Dec 13, 2021 at 23:52