Disclaimer:
This article is for educational purpose only, it is purely demonstrating how google map works.
Hi Guys,
If you are reading this article, you should know about google maps. It’s an awesome service, and the API provided can help you to do lots stuff, ie inputting your GPS coordinates and pin point where you are. HOWEVER, google maps only works when you have an internet connection, which is not feasible for most of us to have wireless internet card.
So I started to think, what if I can store google map on to my harddrive??
Then I searched and searched and searched on google… finally I found 2 links that helped me achieve this.
The first link which helped me how to retrieve the map:
The second link which helped me to find out where I am exactly:
Let me briefly put them together
- You need to find out the GPS boundaries for your city, left upper bound and bottom right bound.
- Use the c# function getTileXY(double lat, double lon, int zoom) provided below to calculate the X,Y tile coordinates to help you “retrieve” the maps from google map. Eg. left upper bound tile is x=10, y=10 and bottom right bound tile is x=100, y=100, then you use a for loop to download the tiles in between those 2 bounds, x=11, y=10……x=99, y=98….
- Now, assume you have “retrieved” all the map tiles for your city, use the same c# function getTileXY(double lat, double lon, int zoom) which work out the x,y tile to find out which tile you are currently at.
- After finding the tile you are currently at, ie. x=55, y=67 tile, you need to work out the pixel coordinate inside a tile to pin point where you are inside a tile, use C# function getXYPixelFromTile(double lat, double lon, int zoom)
A Map Tile looks like this:
OK, thats the theory, you should be able to build up an application hooks up to a GPS device:
C# Functions:
public static Point getTileXY(double lat, double lon, int zoom) { /* Per se earth coordinates are -90?<= lat <= +90?and -180?<= lon <= 180?*/ /* Mercator is NOT applicable for abs(lat) > 85.0511287798066 degrees */ if (System.Math.Abs(lat) > 85.0511287798066) return new Point(0, 0); /* latitude (deg) -> latitude (rad) */ double sin_phi = System.Math.Sin(lat * System.Math.PI / 180); /* * Use Mercator to calculate x and normalize this to -1 <= x <= +1 by division by 180. * The center of the map is lambda_0 = 0, hence x = lat. */ double norm_x = lon / 180; /* * Use Mercator to calculate y and normalize this to -1 <= y <= +1 by division by PI. * According to Mercator y is defined in the range of -PI <= y <= PI only */ double norm_y = (0.5 * System.Math.Log((1 + sin_phi) / (1 - sin_phi))) / System.Math.PI; /* * Apply the normalized point coordinations to any application, here the coordinates of * a 256*256 image holding that point in a thought grid with origin 0,0 top/left */ double tileRow = System.Math.Pow(2, 17 - zoom) * ((1 - norm_y) / 2); double tileColumn = System.Math.Pow(2, 17 - zoom) * ((norm_x + 1) / 2); return new Point((int)tileColumn, (int)tileRow); } public static Point getXYPixelFromTile(double lat, double lon, int zoom) { /* Per se earth coordinates are -90?<= lat <= +90?and -180?<= lon <= 180?*/ /* Mercator is NOT applicable for abs(lat) > 85.0511287798066 degrees */ if (System.Math.Abs(lat) > 85.0511287798066) return new Point(0, 0); /* latitude (deg) -> latitude (rad) */ double sin_phi = System.Math.Sin(lat * System.Math.PI / 180); /* * Use Mercator to calculate x and normalize this to -1 <= x <= +1 by division by 180. * The center of the map is lambda_0 = 0, hence x = lat. */ double norm_x = lon / 180; /* * Use Mercator to calculate y and normalize this to -1 <= y <= +1 by division by PI. * According to Mercator y is defined in the range of -PI <= y <= PI only */ double norm_y = (0.5 * System.Math.Log((1 + sin_phi) / (1 - sin_phi))) / System.Math.PI; /* * Apply the normalized point coordinations to any application, here the coordinates of * a 256*256 image holding that point in a thought grid with origin 0,0 top/left */ double tileRow = System.Math.Pow(2, 17 - zoom) * ((1 - norm_y) / 2); double tileColumn = System.Math.Pow(2, 17 - zoom) * ((norm_x + 1) / 2); int y = (int)((tileColumn - (int)tileColumn) * 256); int x = (int)((tileRow - (int)tileRow) * 256); Console.Out.WriteLine(x +" " + y); return new Point(y,x); }