# Key Concepts

This section provides insights into the key concepts used throughout the HERE Venue Maps API.

## The Mercator Projection

The Venue Maps API serves map tiles obtained by mapping points on the surface of a sphere (the globe) to points on a plane, using the *normalized Mercator projection*.

The basic Mercator projection formula is this:

{λ, φ} -> x[-1, 1] y [-1, 1]

In this formula:

λ | = | longitude |

φ | = | latitude |

x | = | λ / π |

y | = | ln(tan(π/4 + φ/2)) / π |

The plane represents the globe as a square grid of map tiles. The size of the grid depends on the map zoom level. At the lowest zoom level, the world is contained in one map tile. At the next higher zoom level, the world is two tiles wide and two tiles high (2x2), at the next level above that, the grid is 4x4, then 8x8, 16x16, and so on up to the maximum zoom for a particular region. In other words, at each zoom level the tiles that make up the complete map of the world form a grid in which the number of tiles is equal to two to the power of two multiplied by the zoom level (2^{(2*zoom)}).

The relationship between tiles at two consecutive zoom levels can be expressed as follows:

col_{1,z+1} = (2*col_{z}) + 1row_{1,z+1} = (2*row_{z}) + 1

In this formula:

col | = | column number in the tile grid |

row | = | row number in the tile grid |

z | = | zoom level |

The diagram below demonstrates this graphically:

```
--- javascript ---
var lat = 52.525439, // Latitude
lon = 13.38727, // Longitude
z = 12, // Zoom level
latRad,
n,
xTile,
yTile;
latRad = lat * Math.PI / 180;
n = Math.pow(2, z);
xTile = n * ((lon + 180) / 360);
yTile = n * (1-(Math.log(Math.tan(latRad) + 1/Math.cos(latRad)) /
Math.PI)) / 2;
--- output ---
lat_rad = 0.916
n = 4096
xTile = 2200.31 // Column
yTile = 1343.20 // Row
```

The zoom level and tile row and column can be used as URL variables separated by the '/' character in map tile requests. Note that they must be provided in this order: `zoom/column/row`

. This is the *[Z]/[X]/[Y] addressing scheme*.

The map tile specification is typically preceded by other path variables and may be followed either by further path variables and/or query parameters.

## Quadkeys

Specifying the grid location of a map tile in terms of zoom level, column and row as described under The Mercator Projection is easy to understand and intuitive in practise. However, the grid is a two-dimensional array and as such does not offer efficient storage and retrieval. A better solution is a one-dimensional array, where each item is uniquely addressable by a single value. This is made possible by quadkeys, which combine the zoom level, column and row information for a tile in a one value.

In fact, a quadkey is a string containing a numeric value. The value is obtained by interleaving the bits of the row and column coordinates of a tile in the grid at the given zoom level, then converting the result to a base-4 number (the leading zeros are retained). The length of a quadkey string (the number of digits/characters) equals the zoom level of the tile.

For example, we can obtain the quadkey for a map tile in column 3 and row 5 at zoom level 5 as follows:

```
// Convert the column (x) and row (y) values
// to their binary (b) equivalents:
x = 3 -> 011b
y = 5 -> 101b
// Interleave the binary values (b), convert the
// combined result to a base-4 (q) number and
// finally convert that to a string:
quadkey = 100111b -> 213q -> "213"
```

The code below shows a JavaScript implementation of the algorithm that calculates quadkeys. The inputs are the coordinates of the a map tile and the zoom level. The return value is a string containing the quadkey. The lower part of the code block shows the function called to calculate a quadkey for zoom level 16, which is also the length of the output string shown on the last line.

```
--- input ---
xTile: 35210 // Column
yTile: 21493 // Row
z: 16 // Zoom Level
--- JavaScript ---
function tileXYToQuadKey(xTile, yTile, z) {
var quadKey = "";
for (var i = z; i > 0; i--) {
var digit = "0",
mask = 1 << (i - 1);
if ((xTile & mask) != 0) {
digit++;
}
if ((yTile & mask) != 0) {
digit = digit + 2;
}
quadKey += digit;
} // for i return quadKey;
return quadKey;
}
quadKey = tileXYToQuadKey(35210, 21493, 16);
--- output ---
quadKey = "1202102332221212"
```

Note that when using a quadkey address, you cannot specify the size or format of the map tile image. The response always includes an image that measures 256 x 256 pixels and the format is `png32`

.

## Example Calculate Tile Address

```
--- JavaScript ---
var latRad, n, xTile, yTile,
PI = Math.PI,
lat = 52.519067, //latitude
lon = 13.415851, //longitude
z = 16; //zoom level
latRad = lat * PI/180;
n = Math.pow(2, z);
xTile = n * ((lon + 180)/360);
yTile = n * (1-(Math.log(Math.tan(latRad) + 1/Math.cos(latRad))/PI))/2;
--- Output ---
latRad = 0.9166306392255008
n = 65536
xTile = 35210.28114204445
yTile = 21493.148547728106
```

xTile and yTile are used as an input for the following step to generate their corresponding quadkey.

## Tile Coordinates To Quadkeys

Venue Maps API uses Bing Maps Tile System to encode xTile, yTile and Zoom Level into a quadkey. Each quadkey is prefixed with floor level.

### Example Calculate QuadKey

We continue with the tile coordinates we calculated in Example Calculate Tile Address

```
--- Input ---
xTile: 35210
yTile: 21493
zoom level: 16
--- JavaScript ---
function tileXYToQuadKey(xTile, yTile, z) {
var quadKey = "";
for (var i = z; i > 0; i--) {
var digit = "0",
mask = 1 << (i - 1);
if ((xTile & mask) != 0) {
digit++;
}
if ((yTile & mask) != 0) {
digit++;
digit++;
}
quadKey += digit;
} //for i return quadKey;
return quadKey;
}
quadKey = tileXYToQuadKey(35210, 21493, 16);
--- Output ---
quadKey = 1202102332221212
```

Example of Venue Maps API URL using the calculated QuadKey:

```
http://static-3.venue.maps.api.here.com
/0/tiles-png
/L0/1202102332221212.png?
Policy=<Policy-value>
&Signature=<Signature-value>
&Key-Pair-Id=<Key-Pair-Id-value>
&app_id={YOUR_APP_ID}
&app_code={YOUR_APP_CODE}
```

Resulting Venue Maps API tile: