PDA

Click to See Complete Forum and Search --> : Rearrange Formula


SLH
Oct 26th, 2009, 08:08 AM
I have the following code which implements a formula:double xtile = (Coordinate.Long + 180) / 360 * (1 << ZoomLevel);
double ytile = (1 - Math.Log(Math.Tan(Coordinate.Lat * Math.PI / 180) + 1 / Math.Cos(Coordinate.Lat * Math.PI / 180)) / Math.PI) / 2 * (1 << ZoomLevel);

It converts map lat/long coordinates (degrees) into X/Y coordinates (on an image).
ZoomLevel is a constant.

I need to go the other way round i.e. from x,y coords on the image, to a lat,long coord on earth.
I'm thinking that to do this i just need to rearrange the formula(s?) in terms of coordinate.lat/long.
I'm ok with the X => Long conversion, but am having trouble rearranging the Y => Lat one.

Any help would be greatly appreciated.

jemidiah
Oct 27th, 2009, 03:33 AM
You seem to be somewhat lucky--your question actually has an answer (using well-known mathematical functions, at least).

I'll write Lat for Coordinate.Lat, L for Coordinate.Lat * Math.PI / 180, z for (1 << ZoomLevel), pi for Math.PI, and y for ytile. I'll also use log for Math.Log, tan for Math.Tan, sec for 1/Math.Cos, exp for Math.exp, and arctan for Math.atan, using the standard C++ math library. Your formula is then

y = (1-log(tan(L) + sec(L))/pi)/2*z
=>
2y/z = 1-log(tan(L) + sec(L))/pi
=>
log(tan(L) + sec(L))/pi = 1 - 2y/z
=>
log(tan(L) + sec(L)) = pi*(1 - 2y/z)
=>
tan(L) + sec(L) = exp(pi*(1 - 2y/z))

Here's where magic happens. As it turns out, adding tangent and secant gives a single trig function (http://en.wikipedia.org/wiki/List_of_trigonometric_identities#Other_sums_of_trigonometric_functions). So we have...

tan(L) + sec(L) = tan(L/2 + pi/4) = exp(pi*(1 - 2y/z))
=>
L/2 + pi/4 = arctan(exp(pi*(1 - 2y/z)))
=>
L = 2*(arctan(exp(pi*(1 - 2y/z))) - pi/4)


Since L = Lat * pi / 180, we have in all that Lat = 360/pi*(arctan(exp(pi*(1 - 2y/z))) - pi/4).


I can see why you had trouble. I had to look up the tan + sec formula. I haven't rederived it (no proof is given on the page I linked), but I did graph it to make sure it works (it does).