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 eastwest 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 bitfield:
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)
