97 lines
2.1 KiB
C++
97 lines
2.1 KiB
C++
#ifndef GOOGLEPROJECTION_H
|
|
#define GOOGLEPROJECTION_H
|
|
|
|
#include <vector>
|
|
using std::vector;
|
|
#include <cmath>
|
|
|
|
#define max(a,b) (((a)>(b))?(a):(b))
|
|
#define min(a,b) (((a)<(b))?(a):(b))
|
|
|
|
struct ScreenPos
|
|
{
|
|
int x,y;
|
|
ScreenPos() { x=y=0; }
|
|
ScreenPos(int x,int y) { this->x=x; this->y=y; }
|
|
};
|
|
|
|
struct EarthPoint
|
|
{
|
|
double x,y;
|
|
EarthPoint() { x=y=0.0; }
|
|
EarthPoint(double x,double y) { this->x=x; this->y=y; }
|
|
};
|
|
|
|
class GoogleProjection
|
|
{
|
|
private:
|
|
|
|
vector<double> Bc,Cc,zc,Ac;
|
|
int levels;
|
|
|
|
double minmax (double a,double b, double c)
|
|
{
|
|
a = max(a,b);
|
|
a = min(a,c);
|
|
return a;
|
|
}
|
|
|
|
public:
|
|
GoogleProjection(int levels=18)
|
|
{
|
|
this->levels=levels;
|
|
double c = 256;
|
|
double e;
|
|
for (int d=0; d<levels; d++)
|
|
{
|
|
e = c/2;
|
|
Bc.push_back(c/360.0);
|
|
Cc.push_back(c/(2 * M_PI));
|
|
zc.push_back(e);
|
|
Ac.push_back(c);
|
|
c *= 2;
|
|
}
|
|
}
|
|
|
|
ScreenPos fromLLToPixel(double lon,double lat,int zoom)
|
|
{
|
|
double d = zc[zoom];
|
|
double e = round(d + lon * Bc[zoom]);
|
|
double f = minmax(sin((M_PI/180.0) * lat),-0.9999,0.9999);
|
|
double g = round(d + 0.5*log((1+f)/(1-f))*-Cc[zoom]);
|
|
return ScreenPos(e,g);
|
|
}
|
|
|
|
EarthPoint fromPixelToLL(int x,int y,int zoom)
|
|
{
|
|
double e = zc[zoom];
|
|
double f = (x - e)/Bc[zoom];
|
|
double g = (y - e)/-Cc[zoom];
|
|
double h = (180.0/M_PI) * ( 2 * atan(exp(g)) - 0.5 * M_PI);
|
|
return EarthPoint(f,h);
|
|
}
|
|
|
|
// convert to the zoom independent Google system; TBH I don't really
|
|
// understand what it represents....
|
|
static EarthPoint fromLLToGoog(double lon,double lat)
|
|
{
|
|
double a = log(tan((90+lat)*M_PI / 360))/(M_PI / 180);
|
|
double custLat = a * 20037508.34 / 180;
|
|
double custLon=lon;
|
|
custLon = custLon * 20037508.34 / 180;
|
|
return EarthPoint(custLon,custLat);
|
|
}
|
|
|
|
// other way round
|
|
static EarthPoint fromGoogToLL(double x,double y)
|
|
{
|
|
double lat_deg,lon_deg;
|
|
lat_deg = (y / 20037508.34) * 180;
|
|
lon_deg = (x / 20037508.34) * 180;
|
|
lat_deg = 180/M_PI *
|
|
(2 * atan(exp(lat_deg * M_PI / 180)) - M_PI / 2);
|
|
return EarthPoint(lon_deg,lat_deg);
|
|
}
|
|
};
|
|
|
|
#endif // GOOGLEPROJECTION_H
|