GoogleMaps
Example using GoogleMaps static API to display the map of given location
Description
The examples show how to obtain map content from GoogleMaps and display it within U++ application.
Result
GoogleMaps.h
#ifndef _GoogleMaps_GoogleMaps_h
#define _GoogleMaps_GoogleMaps_h
#include <CtrlLib/CtrlLib.h>
using namespace Upp;
#define LAYOUTFILE <GoogleMaps/GoogleMaps.lay>
#include <CtrlCore/lay.h>
#define IMAGECLASS GoogleMapsImg
#define IMAGEFILE <GoogleMaps/GoogleMaps.iml>
#include <Draw/iml_header.h>
void SetGoogleMapsKey(const char *key);
String GetGoogleMap(double center_x, double center_y, int zoom, int cx, int cy,
const char *format = "png", String *error = NULL);
Image GetGoogleMapImage(double center_x, double center_y, int zoom, int cx, int cy,
const char *format = "png", String *error = NULL);
double CvDeg(double deg, double minutes, double seconds);
Pointf GoogleMapsPixelToGps(Pointf center, int zoom, Point diff);
Pointf GoogleMapsPixelToGps(Pointf center, int zoom, Size sz, Point p);
Pointf GoogleMapsGpsToPixelDiff(Pointf center, int zoom, Pointf gps);
Pointf GoogleMapsGpsToPixel(Pointf center, int zoom, Size sz, Pointf gps);
Pointf ScanGPS(const char *s);
String FormatGPSX(double x);
String FormatGPSY(double y);
String FormatGPS(Pointf p);
bool MapDlg(Pointf& p);
#endif
Main.cpp
#include "GoogleMaps.h"
GUI_APP_MAIN {
Pointf p(0, 51.477222);
if(MapDlg(p))
Exclamation("Marker position " + FormatGPS(p));
}
MapDlg.cpp
#include "GoogleMaps.h"
#define IMAGECLASS GoogleMapsImg
#define IMAGEFILE <GoogleMaps/GoogleMaps.iml>
#include <Draw/iml_source.h>
struct MapImage : public Ctrl {
Image map;
String error;
Point home;
Callback1<Point> WhenLeftClick;
virtual void LeftDown(Point p, dword)
{
WhenLeftClick(p);
}
virtual void Paint(Draw& w) {
Size sz = GetSize();
w.DrawRect(sz, SColorPaper());
if(IsNull(map))
w.DrawText(0, 0, error);
else {
w.DrawImage(0, 0, map);
Point p = GoogleMapsImg::Pin().GetHotSpot();
w.DrawImage(home.x - p.x, home.y - p.y, GoogleMapsImg::Pin());
}
}
MapImage() { SetFrame(ViewFrame()); BackPaint(); }
};
struct MapDlgDlg : public WithMapDlgLayout<TopWindow> {
typedef MapDlgDlg CLASSNAME;
Pointf home;
Pointf center;
MapImage map;
void LoadMap();
void SetHome();
void MapClick(Point p);
void ZoomIn();
void ZoomOut();
void Move(int x, int y);
void Set(Pointf p);
Pointf Get() { return home; }
MapDlgDlg();
};
void MapDlgDlg::SetHome()
{
map.home = GoogleMapsGpsToPixel(center, ~zoom, Size(640, 640), home);
gpsy.SetLabel(" " + FormatGPSY(home.y));
gpsx.SetLabel(" " + FormatGPSX(home.x));
map.Refresh();
}
void MapDlgDlg::LoadMap()
{
map.map = GetGoogleMapImage(center.x, center.y, ~zoom, 640, 640, "png", &map.error);
SetHome();
}
void MapDlgDlg::Move(int x, int y)
{
center = GoogleMapsPixelToGps(center, ~zoom, Point(250 * x, 250 * y));
LoadMap();
}
void MapDlgDlg::MapClick(Point p)
{
home = GoogleMapsPixelToGps(center, ~zoom, Size(640, 640), p);
SetHome();
}
void MapDlgDlg::Set(Pointf p)
{
home = center = p;
LoadMap();
}
void MapDlgDlg::ZoomIn()
{
zoom <<= min((int)~zoom + 1, 21);
LoadMap();
}
void MapDlgDlg::ZoomOut()
{
zoom <<= max((int)~zoom - 1, 0);
LoadMap();
}
MapDlgDlg::MapDlgDlg()
{
CtrlLayoutOKCancel(*this, "");
Size sz = GetSize();
Size msz = map.GetSize();
sz += Size(640 - msz.cx, 640 - msz.cy);
SetRect(sz);
for(int i = 0; i < 22; i++)
zoom.Add(i);
zoom <<= 17;
zoom <<= THISBACK(LoadMap);
zoomin <<= THISBACK(ZoomIn);
zoomout <<= THISBACK(ZoomOut);
left <<= THISBACK2(Move, -1, 0);
left.SetImage(CtrlImg::SmallLeft());
right <<= THISBACK2(Move, 1, 0);
right.SetImage(CtrlImg::SmallRight());
up <<= THISBACK2(Move, 0, -1);
up.SetImage(CtrlImg::SmallUp());
down <<= THISBACK2(Move, 0, 1);
down.SetImage(CtrlImg::SmallDown());
map.WhenLeftClick = THISBACK(MapClick);
}
bool MapDlg(Pointf& p)
{
MapDlgDlg dlg;
dlg.Set(p);
if(dlg.Run() == IDOK) {
p = dlg.Get();
return true;
}
return false;
}
GoogleMaps.cpp
#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.0 - GoogleMapsGpsToPixelDiff(center, zoom, gps);
}
GoogleMaps.lay
LAYOUT(MapDlgLayout, 428, 340)
UNTYPED(map, HSizePosZ(8, 136).VSizePosZ(8, 8))
ITEM(Button, zoomout, SetLabel(t_("-")).RightPosZ(104, 24).TopPosZ(8, 20))
ITEM(DropList, zoom, RightPosZ(40, 60).TopPosZ(8, 19))
ITEM(Button, zoomin, SetLabel(t_("+")).RightPosZ(8, 24).TopPosZ(8, 20))
ITEM(Button, up, RightPosZ(56, 24).TopPosZ(40, 40))
ITEM(Button, left, RightPosZ(88, 40).TopPosZ(80, 24))
ITEM(Button, right, RightPosZ(8, 40).TopPosZ(80, 24))
ITEM(Button, down, RightPosZ(56, 24).TopPosZ(104, 40))
ITEM(Button, cancel, SetLabel(t_("Cancel")).RightPosZ(72, 56).BottomPosZ(8, 24))
ITEM(Button, ok, SetLabel(t_("OK")).RightPosZ(8, 56).BottomPosZ(8, 24))
ITEM(Label, gpsy, SetFrame(BlackFrame()).RightPosZ(8, 120).TopPosZ(164, 24))
ITEM(Label, gpsx, SetFrame(BlackFrame()).RightPosZ(8, 120).TopPosZ(192, 24))
END_LAYOUT
|