Hallo,
der “atan”-Ersatz von
http://www.forum.nokia.com/forum/showthread.php?t=72840
ist anscheinend ziemlich gut…
Hab mir mal schnell einen Vergleich quick’n dirty in C zusammengehackt:
#include <stdio.h>
#include <math.h>
// taken from
//
// http://svn.bbtracker.org/bbtracker_common/trunk/src/org/bbtracker/MMath.java
//
// resp.
//
// http://www.forum.nokia.com/forum/showthread.php?t=72840
double sq2p1 = 2.414213562373095048802e0;
double sq2m1 = .414213562373095048802e0;
double p4 = .161536412982230228262e2;
double p3 = .26842548195503973794141e3;
double p2 = .11530293515404850115428136e4;
double p1 = .178040631643319697105464587e4;
double p0 = .89678597403663861959987488e3;
double q4 = .5895697050844462222791e2;
double q3 = .536265374031215315104235e3;
double q2 = .16667838148816337184521798e4;
double q1 = .207933497444540981287275926e4;
double q0 = .89678597403663861962481162e3;
double PIO2 = 1.5707963267948966135E0;
//double nan = (0.0/0.0);
double mxatan(double arg)
{
double argsq, value;
argsq = arg*arg;
value = ((((p4*argsq + p3)*argsq + p2)*argsq + p1)*argsq + p0);
value = value/(((((argsq + q4)*argsq + q3)*argsq + q2)*argsq + q1)*argsq + q0);
return value*arg;
}
double msatan(double arg)
{
if(arg < sq2m1)
return mxatan(arg);
if(arg > sq2p1)
return PIO2 - mxatan(1/arg);
return PIO2/2 + mxatan((arg-1)/(arg+1));
}
double atan_approx(double arg)
{
if(arg > 0)
return msatan(arg);
return -msatan(-arg);
}
double PI= 3.14159265358979323846;
double tile2lat_approx(int y, int zoom)
{
double n = PI - ((2.0 * PI * y) / (1 << zoom));
return 180.0 / PI * atan_approx(0.5 * (exp(n) - exp(-n)));
}
double tile2lat(int y, int zoom)
{
double n = PI - ((2.0 * PI * y) / (1 << zoom));
return 180.0 / PI * atan(0.5 * (exp(n) - exp(-n)));
}
// gcc -c -Wall atan_tst.c
//
// gcc -o atan_tst atan_tst.o -lm
int main(void)
{
int i;
double delta, min= 1, max= -1;
for(i=23314; i<=23316; i++)
printf("tile2lat(%5d)=%22.18lf %22.18lf %.18lf\n", i, tile2lat(i, 16) , tile2lat_approx(i, 16), tile2lat(i, 16)-tile2lat_approx(i, 16));
printf("\n");
for(i=0; i<=2; i++)
printf("tile2lat(%5d)=%22.18lf %22.18lf %.18lf\n", i, tile2lat(i, 16) , tile2lat_approx(i, 16), tile2lat(i, 16)-tile2lat_approx(i, 16));
for(i=16383; i<=16385; i++)
printf("tile2lat(%5d)=%22.18lf %22.18lf %.18lf\n", i, tile2lat(i, 16) , tile2lat_approx(i, 16), tile2lat(i, 16)-tile2lat_approx(i, 16));
for(i=32767; i<=32769; i++)
printf("tile2lat(%5d)=%22.18lf %22.18lf %.18lf\n", i, tile2lat(i, 16) , tile2lat_approx(i, 16), tile2lat(i, 16)-tile2lat_approx(i, 16));
for(i=65534; i<=65536; i++)
printf("tile2lat(%5d)=%22.18lf %22.18lf %.18lf\n", i, tile2lat(i, 16) , tile2lat_approx(i, 16), tile2lat(i, 16)-tile2lat_approx(i, 16));
for(i=0; i<=65536; i++)
{
delta= tile2lat(i, 16)-tile2lat_approx(i, 16);
if (delta < min) min= delta;
if (delta > max) max= delta;
}
printf("\nmin=%.18lf max=%.18lf\n", min, max);
return 0;
}
Es liefert:
tile2lat(23314)= 46.004593255744815000 46.004593255744815000 -0.000000000000000836
tile2lat(23315)= 46.000777568556607000 46.000777568556600000 0.000000000000005742
tile2lat(23316)= 45.996961618203812000 45.996961618203805000 0.000000000000004382
tile2lat( 0)= 85.051128779806604000 85.051128779806589000 0.000000000000011907
tile2lat( 1)= 85.050654879827547000 85.050654879827547000 0.000000000000002193
tile2lat( 2)= 85.050180934581164000 85.050180934581149000 0.000000000000012206
tile2lat(16383)= 66.515449574975378000 66.515449574975378000 0.000000000000006689
tile2lat(16384)= 66.513260443111861000 66.513260443111861000 0.000000000000002227
tile2lat(16385)= 66.511071118747594000 66.511071118747594000 0.000000000000004975
tile2lat(32767)= 0.005493164054085968 0.005493164054085968 0.000000000000000001
tile2lat(32768)= 0.000000000000000000 0.000000000000000000 0.000000000000000000
tile2lat(32769)= -0.005493164054084375 -0.005493164054084374 -0.000000000000000001
tile2lat(65534)=-85.050180934581164000 -85.050180934581149000 -0.000000000000012206
tile2lat(65535)=-85.050654879827547000 -85.050654879827547000 -0.000000000000002193
tile2lat(65536)=-85.051128779806604000 -85.051128779806589000 -0.000000000000012691
min=-0.000000000000018617 max=0.000000000000018020
Schöne Grüße
PA94