public static void Main()
var minTileX = LongitudeToX(minLon, z);
var maxTileX = LongitudeToX(maxLon, z);
var minTileY = LatitudeToY(minLat, z);
var maxTileY = LatitudeToY(maxLat, z);
Console.WriteLine(string.Format("Min:Max LON= {0}:{1}. Min:Max LAT={2}:{3}", minLon, maxLon, minLat, maxLat));
Console.WriteLine(string.Format("Min:Max X={0}:{1} - Number of Tiles Per Row {2}", minTileX, maxTileX, (maxTileX-minTileX)+1));
Console.WriteLine(string.Format("Min:Max Y={0}:{1} - Number of Tiles Per Column {2}", minTileY, maxTileY, (maxTileY-minTileY)+1));
var minTile = LatLongToTile(minLon, minLat, z);
Console.WriteLine(string.Format("{0}, {1}", minTile.X, minTile.Y));
static (int X, int Y) LatLongToTile(float longitude, float latitude, int level)
var longRadians = DegreesToRadians(longitude);
var latRadians = DegreesToRadians(latitude);
var tileNums = MathF.Pow(2, level);
var x = ((1+(longRadians/MathF.PI))/2)*tileNums;
var y = ((1-(MathF.Asinh((MathF.Tan((latRadians))))/MathF.PI))/2)*tileNums;
return new ((int)MathF.Floor(x), (int)MathF.Floor(y));
public static float DegreesToRadians(float degrees){ return degrees*MathF.PI/180;}
public static int LongitudeToX(float longitude, int level){return (int)MathF.Floor(((longitude+180)/360)*MathF.Pow(2, level));}
public static int LatitudeToY(float latitude, int level){return (int)MathF.Floor((1-MathF.Log(MathF.Tan(DegreesToRadians(latitude))+1/MathF.Cos(DegreesToRadians(latitude)))/MathF.PI)/2*MathF.Pow(2, level));}