diff --git a/examples/GoogleMaps/GoogleMaps.cpp b/examples/GoogleMaps/GoogleMaps.cpp index cf915d8f4..840bc2b29 100644 --- a/examples/GoogleMaps/GoogleMaps.cpp +++ b/examples/GoogleMaps/GoogleMaps.cpp @@ -1,181 +1,181 @@ -#include "GoogleMaps.h" - -using namespace Upp; - -#define LLOG(x) // LOG(x) - -String apikey = ""; - -void SetGoogleMapsKey(const char *key) -{ - apikey = key; -} - -String GetGoogleMap(double center_x, double center_y, int zoom, int cx, int cy, - const char *format, String *error) -{ - String request; - request << "http://maps.google.com/maps/api/staticmap?center=" << - AsString(center_y) << ',' << AsString(center_x) << - "&zoom=" << zoom << - "&size=" << cx << 'x' << cy << - "&format=" << format << - "&sensor=false&key=" << apikey; - HttpRequest r(request); - String h = r.Execute(); - if(r.IsFailure()) - *error = r.GetErrorDesc(); - return h; -} - -Image GetGoogleMapImage(double center_x, double center_y, int zoom, int cx, int cy, - const char *format, String *error) -{ - return StreamRaster::LoadStringAny(GetGoogleMap(center_x, center_y, zoom, cx, cy, format, error)); -} - -double CvDeg(double deg, double minutes, double seconds) -{ - return deg + (double)minutes / 60 + seconds / 3600; -} - -static void sFetch(double& a, double *x, int& ii) -{ - a = CvDeg(x[0], x[1], x[2]); - ii = 0; -} - -int CharFilterH(int c) -{ - return c == 'e' || c == 'E' ? 'r' : c == '\'' || c == '\"' ? '@' : c; -} - -Pointf ScanGPS(const char *s) -{ - String h = Filter(s, CharFilterH); - Pointf r = Null; - double x[3]; - CParser p(h); - x[0] = x[1] = x[2] = 0; - int ii = 0; - while(!p.IsEof()) { - if(p.IsDouble()) { - if(ii < 3) - x[ii++] = p.ReadDouble(); - else { - if(IsNull(r.y)) - sFetch(r.y, x, ii); - else { - sFetch(r.x, x, ii); - break; - } - x[ii++] = p.ReadDouble(); - } - } - else - if(p.Char('W') || p.Char('w')) { - if(x[0] > 0) - x[0] = -x[0]; - sFetch(r.x, x, ii); - } - else - if(p.Char('r')) - sFetch(r.x, x, ii); - else - if(p.Char('S') || p.Char('s')) { - if(x[0] > 0) - x[0] = -x[0]; - sFetch(r.y, x, ii); - } - else - if(p.Char('N') || p.Char('n')) - sFetch(r.y, x, ii); - else - p.SkipTerm(); - } - if(!IsNull(r.y) && IsNull(r.x)) - sFetch(r.x, x, ii); - return r; -} - -String FormatDegree(double d, int decimals) -{ - if(IsNull(d)) - return Null; - d = modulo(d + 180, 360) - 180; - char sign = (d < 0 ? '-' : '+'); - if(d < 0) d = -d; - int deg = ffloor(d); - String cd = ToCharset(CHARSET_DEFAULT, "%c%d°", CHARSET_UTF8); - if(decimals <= -2) - return NFormat(cd, sign, deg); - d = (d - deg) * 60; - int min = ffloor(d); - if(decimals <= -1) - return NFormat(cd + " %02d\'", sign, deg, min); - d = (d - min) * 60; - String sec = FormatDoubleFix(d, decimals); - if(!IsDigit(sec[1])) - sec.Insert(0, '0'); - return NFormat(cd + " %02d\' %s\"", sign, deg, min, sec); -} - -String FormatGPSX(double x) -{ - return IsNull(x) ? String() : FormatDegree(x, 2) + (x < 0 ? "W" : "E"); -} - -String FormatGPSY(double y) -{ - return IsNull(y) ? String() : FormatDegree(y, 2) + (y < 0 ? "S" : "N"); -} - -String FormatGPS(Pointf p) -{ - return FormatGPSY(p.y) + ' ' + FormatGPSX(p.x); -} - -static const double sOffset = 268435456; -static const double sRadius = sOffset / M_PI; - -static int LToX_(double x) -{ - return int(sOffset + sRadius * x * M_PI / 180); -} - -static int LToY_(double y) -{ - return int(sOffset - sRadius * log((1 + sin(y * M_PI / 180))/(1 - sin( y * M_PI / 180))) / 2); -} - -static double XToL_(int x) -{ - return ((x - sOffset) / sRadius) * 180 / M_PI; -} - -static double YToL_(int y) -{ - return (M_PI / 2 - 2 * atan(exp((y - sOffset) / sRadius))) * 180 / M_PI; -} - -Pointf GoogleMapsPixelToGps(Pointf center, int zoom, Point diff) -{ - return Pointf(XToL_(LToX_(center.x) + (diff.x << (21 - zoom))), - YToL_(LToY_(center.y) + (diff.y << (21 - zoom)))); -} - -Pointf GoogleMapsPixelToGps(Pointf center, int zoom, Size sz, Point p) -{ - return GoogleMapsPixelToGps(center, zoom, p - sz / 2); -} - -Pointf GoogleMapsGpsToPixelDiff(Pointf center, int zoom, Pointf gps) -{ - return Pointf((LToX_(center.x) - LToX_(gps.x)) >> (21 - zoom), - (LToY_(center.y) - LToY_(gps.y)) >> (21 - zoom)); -} - -Pointf GoogleMapsGpsToPixel(Pointf center, int zoom, Size sz, Pointf gps) -{ - return sz / 2 - GoogleMapsGpsToPixelDiff(center, zoom, gps); -} +#include "GoogleMaps.h" + +using namespace Upp; + +#define LLOG(x) // LOG(x) + +String apikey = ""; + +void SetGoogleMapsKey(const char *key) +{ + apikey = key; +} + +String GetGoogleMap(double center_x, double center_y, int zoom, int cx, int cy, + const char *format, String *error) +{ + String request; + request << "http://maps.google.com/maps/api/staticmap?center=" << + AsString(center_y) << ',' << AsString(center_x) << + "&zoom=" << zoom << + "&size=" << cx << 'x' << cy << + "&format=" << format << + "&sensor=false&key=" << apikey; + HttpRequest r(request); + String h = r.Execute(); + if(r.IsFailure()) + *error = r.GetErrorDesc(); + return h; +} + +Image GetGoogleMapImage(double center_x, double center_y, int zoom, int cx, int cy, + const char *format, String *error) +{ + return StreamRaster::LoadStringAny(GetGoogleMap(center_x, center_y, zoom, cx, cy, format, error)); +} + +double CvDeg(double deg, double minutes, double seconds) +{ + return deg + (double)minutes / 60 + seconds / 3600; +} + +static void sFetch(double& a, double *x, int& ii) +{ + a = CvDeg(x[0], x[1], x[2]); + ii = 0; +} + +int CharFilterH(int c) +{ + return c == 'e' || c == 'E' ? 'r' : c == '\'' || c == '\"' ? '@' : c; +} + +Pointf ScanGPS(const char *s) +{ + String h = Filter(s, CharFilterH); + Pointf r = Null; + double x[3]; + CParser p(h); + x[0] = x[1] = x[2] = 0; + int ii = 0; + while(!p.IsEof()) { + if(p.IsDouble()) { + if(ii < 3) + x[ii++] = p.ReadDouble(); + else { + if(IsNull(r.y)) + sFetch(r.y, x, ii); + else { + sFetch(r.x, x, ii); + break; + } + x[ii++] = p.ReadDouble(); + } + } + else + if(p.Char('W') || p.Char('w')) { + if(x[0] > 0) + x[0] = -x[0]; + sFetch(r.x, x, ii); + } + else + if(p.Char('r')) + sFetch(r.x, x, ii); + else + if(p.Char('S') || p.Char('s')) { + if(x[0] > 0) + x[0] = -x[0]; + sFetch(r.y, x, ii); + } + else + if(p.Char('N') || p.Char('n')) + sFetch(r.y, x, ii); + else + p.SkipTerm(); + } + if(!IsNull(r.y) && IsNull(r.x)) + sFetch(r.x, x, ii); + return r; +} + +String FormatDegree(double d, int decimals) +{ + if(IsNull(d)) + return Null; + d = modulo(d + 180, 360) - 180; + char sign = (d < 0 ? '-' : '+'); + if(d < 0) d = -d; + int deg = ffloor(d); + String cd = ToCharset(CHARSET_DEFAULT, "%c%d°", CHARSET_UTF8); + if(decimals <= -2) + return NFormat(cd, sign, deg); + d = (d - deg) * 60; + int min = ffloor(d); + if(decimals <= -1) + return NFormat(cd + " %02d\'", sign, deg, min); + d = (d - min) * 60; + String sec = FormatDoubleFix(d, decimals); + if(!IsDigit(sec[1])) + sec.Insert(0, '0'); + return NFormat(cd + " %02d\' %s\"", sign, deg, min, sec); +} + +String FormatGPSX(double x) +{ + return IsNull(x) ? String() : FormatDegree(x, 2) + (x < 0 ? "W" : "E"); +} + +String FormatGPSY(double y) +{ + return IsNull(y) ? String() : FormatDegree(y, 2) + (y < 0 ? "S" : "N"); +} + +String FormatGPS(Pointf p) +{ + return FormatGPSY(p.y) + ' ' + FormatGPSX(p.x); +} + +static const double sOffset = 268435456; +static const double sRadius = sOffset / M_PI; + +static int LToX_(double x) +{ + return int(sOffset + sRadius * x * M_PI / 180); +} + +static int LToY_(double y) +{ + return int(sOffset - sRadius * log((1 + sin(y * M_PI / 180))/(1 - sin( y * M_PI / 180))) / 2); +} + +static double XToL_(int x) +{ + return ((x - sOffset) / sRadius) * 180 / M_PI; +} + +static double YToL_(int y) +{ + return (M_PI / 2 - 2 * atan(exp((y - sOffset) / sRadius))) * 180 / M_PI; +} + +Pointf GoogleMapsPixelToGps(Pointf center, int zoom, Point diff) +{ + return Pointf(XToL_(LToX_(center.x) + (diff.x << (21 - zoom))), + YToL_(LToY_(center.y) + (diff.y << (21 - zoom)))); +} + +Pointf GoogleMapsPixelToGps(Pointf center, int zoom, Size sz, Point p) +{ + return GoogleMapsPixelToGps(center, zoom, p - sz / 2); +} + +Pointf GoogleMapsGpsToPixelDiff(Pointf center, int zoom, Pointf gps) +{ + return Pointf((LToX_(center.x) - LToX_(gps.x)) >> (21 - zoom), + (LToY_(center.y) - LToY_(gps.y)) >> (21 - zoom)); +} + +Pointf GoogleMapsGpsToPixel(Pointf center, int zoom, Size sz, Pointf gps) +{ + return (Sizef)sz / 2 - GoogleMapsGpsToPixelDiff(center, zoom, gps); +}