# Tile Index Scheme

Scenery in FlightGear is composed of tiles, each associated with a tile index. The tiles are cut so that none of them is excessively large or small compared to other tiles regarding their actual size on the earth surface.

Each tile is defined by the geodetic coordinates of its southwest corner and it extends in degrees of geodetic latitude and longitude. We will refer to the latitude, longitude of the southwest corner as lat, lon. However, the index calculations should also work with any other position inside the tile.

The authoritative source for the tile index scheme is the definition of the class `SGBucket` in SimGear (`simgear/bucket/newbucket.{hxx, cxx}`).

## Calculating the Tile Index

The tile index is composed of four parts

• base longitude index (-180...179)
• base latitude index (-90...89),
• longitude offset (0...7), and
• latitude offset (0...7).

Each degree of latitude is split up into 8 rows of tiles. Each tile spans 1/8th degree (0.125 degrees of latitude). Therefore the base latitude index and offset are directly derived from lat using the `floor` and `trunc` functions:

``` base_y = floor(lat)
y = trunc((lat - base_y) * 8)
```

floor & trunc explained: http://www.cplusplus.com/reference/cmath/trunc/

The tiling in east-west direction is more complex. As the meridians converge towards the pole, the width of tile columns must be adapted based on latitude, as the following table shows (taken from `sg_bucket_span` in `simgear/bucket/newbucket.hxx`):

Latitude Range Tile Width (deg)
89 ≤ lat < 90 12
86 ≤ lat < 89 4
83 ≤ lat < 86 2
76 ≤ lat < 83 1
62 ≤ lat < 76 0.5
22 ≤ lat < 62 0.25
-22 ≤ lat < 22 0.125
-62 ≤ lat < -22 0.25
-76 ≤ lat < -62 0.5
-83 ≤ lat < -76 1
-86 ≤ lat < -83 2
-89 ≤ lat < -86 4
-90 ≤ lat < -89 12

Note that in latitudes north of N83 or south of S83 tiles span more than a single degree of latitude. The naive code for determining the base longitude index is therefore

``` base_x=floor(floor(lon / tile_width) * tile_width)
x=floor((lon - base_x) / tile_width)
```

The final tile index is found by composing the base offsets and indices into a bit-field:

``` index=((lon + 180) << 14) + ((lat + 90) << 6) + (y << 3) + x
```

So here is the final code for calculating the index (using the width from the table above for `tile_width`)

``` base_y = floor(lat)
y = trunc((lat - base_y) * 8)
base_x = floor(floor(lon / tile_width) * tile_width)
x = floor((lon - base_x) / tile_width)
```