## Introduction

In this article, I will discuss a problem about how we can calculate the latitude and longitude information for a particular location, without using any online service such as Microsoft, or Google map service. Although I have taken the image data from Google, all the background processing for calculating the latitude and longitude is done by me using Mercator projection method. I have included the code files to demonstrate how you can convert the mouse position on the map to real world latitude and longitude values, which is demonstrated in the figure below:

In the upper left corner of the window above X, Y shows the screen co-coordinates for the Yellow pointer and latitude and longitude shows the real world latitude and longitude of the Yellow pointer on to the screen. If you run the application file included with this article, you will see that mouse coordinates (X,Y) will be shown on the screen and their real world latitude and longitude values as soon as you move the mouse in the application window. In this way, you can use Google maps offline in Windows.

## What is the Problem?

The things such as XNA framework, Winforms API, and Mercator projection formulas are easily available. The main problem is to convert Latitude and longitude values to screen coordinates. It was the requirement in one of my projects.

You can easily understand the Mercator projection, but to apply that to Google images and to program that in the computer is a slightly difficult problem. In order to apply Mercator projection, you need to calculate different parameters such as radius, circumference, and others. I have addressed all these difficulties and implemented the Mercator projection using C#.NET. Similar to Mercator projection, there are more advanced projections available which are more accurate, but for the sake of simplicity, I chose the Mercator projection. You can utilize the information present in this article to apply to different projections methodologies.

## What is Mercator Projection?

To define it simply, a projection in the field of cartography is a field in which you draw the map of the whole world which is 3D onto a 2-dimensional surface. Mercator projection is a kind of projection. In Mercator projection, each and every individual point on the earth is first projected to inside surface of a cylinder and then that cylinder expanded to view the whole globe. Mercator projection model can be found on the internet easily and there is a good description of Mercator projection on Wikipedia.

There are some limitations to Mercator projection. One is that the formula is not defined for 90-degree values, another is values obtain from these formulas contain some error which is very tiny.

## How Google Arranges their Maps?

Google people also use the Mercator projection. They organize images at different zoom levels. Zoom level ranges from 1 to 19. At each zoom level, they have divided the map into tiles. Each tile consists of 256*256 pixels. There are different number of tiles for each zoom level. The number of tiles per zoom level is given by:

Total number of tiles = 2 ^ (2*zoom Level)

Hence, it shows that more zoom level means a greater number of tiles and more detail is present. Since Google has arranged their maps in tiles, it is easier to work with them because the smallest unit of the map is not meter or centimeter but it is a pixel which is easier to work when working with graphics and computer programming.

## How to View Google Maps Offline in Windows

### Step 1

The very first step is to define zoom level.

this.zoomLevel = zoomLevel;

### Step 2

In this, we have to calculate the circumference, radius, and Centre of the projected map. First, we calculate the circumference. In order to calculate, we should know the zoom level and then we calculate the number of horizontal tiles of the projection.

Math.Pow(2, zoomLevel);

After that, we multiply it by 256, which is the horizontal length of the projection, therefore:

this.circumference = 256 * Math.Pow(2, zoomLevel);

Once we know the circumference, it is easier to find the radius and center of the projection.

Circumference = 2 * Pi * radius

Therefore:

this.radius = (this.circumference) / (2 * Math.PI);

Similarly for calculating the center:

this.centre = new RTPoint(this.circumference / 2, this.circumference / 2);

Where `RTPoint `

is a class used to define any 2-dimensional point in x, y plane.

### Step 3

In step 3, we will calculate the x from Longitude and y from latitude.

Calculating the x from longitude is much easier. You simply have to multiply the longitude value with the radius.

public double getXFromLongitude(double longInDegrees)
{
double x = 0;
double longInRadians = longInDegrees * Math.PI / 180;
x = this.radius *
longInRadians;

After this, you will have to calculate the false easting. False easting is calculated for X, since it is the horizontal shift of the origin. For calculating false easting sometime, you have to add with x component of the center and sometimes you have to subtract from the component. This will depend upon the part of the image you are considering or depend up the values of x. For example, if you are taking the image in India or Pakistan, you will have to add to the center if you are considering the image of U.S you will have to subtract from the center.

x = this.centre.getPointX()+ x;
return x;

Now, for calculating y from latitude, you will have to apply the formula for Mercator projection whose implementation in the programming language is as follows:

public double getYFromLatitude(double latInDegrees)
double y;
double latInRadians = latInDegrees * Math.PI / 180;
double logVal = Math.Log(((1 + Math.Sin(latInRadians)) / (1 - Math.Sin(latInRadians))),
Math.E);
y = this.radius * 0.5 * logVal;

One thing to note in the above statement is that the base for the logarithm used is the natural base (E).

Similarly, in calculating the y from latitude, we have to calculate the false northing. Again for false northing is specific to image area or y values.

y = this.centre.getPointY() - y;
return y;

Up to this step, we now have the x and y values, but these x, y values are for the complete Mercator projection. These values are projection x, y values. For converting them to our specific map on the screen, we have to perform some translations which are described in the next step.

### Step 4

In this step, we have to convert the above-calculated x, y values to screen coordinates. At higher zoom level, we can only display the map for a particular area. The limits of the size of the map are bounded by the screen resolution. Therefore, in order to work with a portion of the image first, we must know the center of that portion of an image. While taking images from Google map service, you can specify the center of the map and resolution of the map, hence this center is the center of that particular portion of the map. In the above figure, the map is center at `latitude = 24.846605`

and `longitude = 67.028379`

, and the resolution for the image is 800 by 800 pixels.

Hence we find the x, y values at this center.

double x = projection.getXFromLongitude(67.028379);
double y = projection.getYFromLatitude(24.846605);
screenMapCentre = new RTPoint (x, y);

After that, I will shift the center to the upper left corner of the screen, since in computer screen the x, y is set to (0,0) in the upper left corner. And the value of x increases if you move to right and value of y increases if you move downward. Therefore, we have to shift the center to upper left corner. Note that this shift is different from the shift that we have done while false easting and false northing, this shift is just for working on the computer screen. Because the resolution of the complete map image is 800 by 800 therefore for shifting the center you have to subtract 400 from both x, y.

x = x - 400;
y = y - 400;
shiftedCentre = new RTPoint(x, y);

Hence for getting screen coordinates, you will have to subtract the projection coordinates values from the shifted center.

aDot.X = (float)(projection.getXFromLongitude(longitudeInRadian)
- shiftedCentre.getPointX());
aDot.Y = (float)(projection.getYFromLatitude(latitudeInRadian)
- shiftedCentre.getPointY());

In this way, you can obtain the value of any position in latitude and longitude to in x, y format, and you can show a marker, dot, arrow or anything on that x, y value of computer screen. Note that all these screen values are particular to your application only, not to the complete screen.

## Steps to Translate from 2 Dimensional Co-ordinates to Latitude and Longitude

In this article, the code example which I provided contains the working functionality for converting mouse position to latitude and longitude. In my application, when pointing any location on the map, it will display the latitude and longitude on the screen. For testing, you can put this latitude and longitude in Google earth and it will show the same position as shown by my application.

The method for converting 2D co-ordinate to latitude and longitude is simply the reverse procedure of the above method. Step 1 and Step 2 are similar since they are initialization steps.

### Step 3

First, we have to convert from screen x, y coordinate to Mercator projection x, y values and it is the reverse procedure for the step-5 above.

X = xMousePos +
shiftedCentre.getPointX()
Y = yMousePos + shiftedCentre.getPointY()

### Step 4

In this step, I will convert X to longitude and Y to latitude. For converting X to longitude, we will execute the following lines of code:

double longitude = 0;
xValue = xValue - this.centre.getPointX();
longitude = xValue / this.radius;
longitude = longitude * 180 / Math.PI;

Note that this time, we also perform the False easting exactly opposite as we were doing when converting from longitude to X.

Then we convert the Y value to latitude with the following code:

double latitude =0;
yValue = this.centre.getPointY()- yValue;
double InvLog = yValue / (this.radius * 0.5);
InvLog = Math.Pow(Math.E, InvLog);
latitude = Math.Asin( (InvLog - 1) / (InvLog + 1) );
latitude = latitude * 180 / Math.PI;
return latitude;

The whole method is just the reverse of the above work which we have already done.

Hence in this way, we have converted the X, Y values to longitude and latitude values.

## How Microsoft XNA/WinformsFramework Helped Me?

Previously, I wrote this code in XNA Framework but XNA framework is obsolete and my readers were complaining that they were unable to compile the code in latest Visual Studio versions. Therefore, for my readers, I updated the code and re-wrote the example source code in WinForms. Now you can just download it and use it in your projects.

Microsoft XNA is a fantastic framework for creating games for hobbyists and for nonprofessional game developers. It is easier as compared to DirectX API. I picked up an easier gaming API and show the values of latitude, longitude, X and Y values as soon as the user moves the mouse cursor on the computer screen.

## How to Save Google Maps Offline on Windows

You can obtain register with Google maps API service and can work with them utilizing the key provided by Google, but I use the Google code playground tool. Code playground is a tool provided by Google maps API website, where you can run, test and debug your code. There is a very good documentation for Google maps API on that website from where you can read about the different service methods. For taking images, I utilize the service method as follows:

var map;
functioninitialize() {
if(GBrowserIsCompatible()) {
map = new GMap2(document.getElementById("map_canvas"));
map.setMapType(G_SATELLITE_MAP);
map.setCenter(new GLatLng(24.846605, 67.028379),17);

The above JavaScript code utilizes the Google map service class `GMAP2 `

for creating a map and then calling the relevant methods.

The complete map will be displayed in the `div `

area of an HTML page. On the HTML page, you can define the number of pixels for the map by defining the width and height of the `div `

element as shown in the following code:

<body onload="initialize()" onunload="GUnload()">
<div id="map_canvas" style="width: 800px; height: 800px"></div>

After the image is loaded, you can print screen and then with the help of an image editor such as Microsoft paint, paint.net or Photoshop, you can extract the image and then you can use that image in your application. This is how I take images for the software Google maps offline windows.

## What Interesting Things Can Others Do?

Well, there are a lot of things which you can play around with such as accessing the GPS coordinate from GPS card or any other GPS device and show it on the GOOGLE map. I developed it in 2D, but you can also convert it into 3D. Other people can also calculate a proper method for calculating the false easting and false northing. One method is that they can define either to add or subtract depending upon the x and y values.

With the help of this simple programming model, you can develop the real-time GPS system, which displays the position of a particular object onto the Google Map. You can also use this programming model with the accelerometers to show the real-time positions with little error because commercial GPSs are slow and do not provide much accuracy when placed on a fast moving vehicle hence you can build your own using 3 axis accelerometers.

## Conclusion

One question asked by many colleagues is why I have not used Google maps API. First of all, Google maps API is online and cannot be accessed offline. In my application, I have completely implemented the Mercator projection hence you can modify and customize it for any application especially where a very fast response is required. You can implement it to any application from mobiles, GPS navigation and inertial navigation system for real-time position display. Well, there are a lot of things which you can play around such as accessing the GPS coordinate from GPS card or any other GPS device and show it on the Google map.

## History

- 8
^{th} June, 2010: Initial post - 2018: Updated the code from XNA framework to WinForms