瓦片地图坐标相关计算

在给定level下,把行号tileY和列号tileX转换为2进制,然后行列交叉存储,再转换为4进制,即得到了相应的quadkey。譬如Level 3的第6行第4列的Tile计算:tileY = 5 = 101 ,tileX = 3 = 011;quadkey = 100111 = 213(4进制) = “213”。
那么,下面我们给出C#的代码实现
/// <summary>
/// Converts tile XY coordinates into a QuadKey at a specified level of detail.
/// </summary>
/// <param name="tileX">Tile X coordinate.</param>
/// <param name="tileY">Tile Y coordinate.</param>
/// <param name="levelOfDetail">Level of detail, from 1 (lowest detail)
/// to 23 (highest detail).</param>
/// <returns>A string containing the QuadKey.</returns>
public static string TileXYToQuadKey(int tileX, int tileY, int levelOfDetail)
{
StringBuilder quadKey
= new StringBuilder();
for (int i = levelOfDetail; i > 0; i--)
{
char digit = '0';
int mask = 1 << (i - 1);
if ((tileX & mask) != 0)
{
digit
++;
}
if ((tileY & mask) != 0)
{
digit
++;
digit
++;
}
quadKey.Append(digit);
}
return quadKey.ToString();
}
接下来是反算代码
/// <summary>
/// Converts a QuadKey into tile XY coordinates.
/// </summary>
/// <param name="quadKey">QuadKey of the tile.</param>
/// <param name="tileX">Output parameter receiving the tile X coordinate.</param>
/// <param name="tileY">Output parameter receiving the tile Y coordinate.</param>
/// <param name="levelOfDetail">Output parameter receiving the level of detail.</param>
public static void QuadKeyToTileXY(string quadKey, out int tileX, out int tileY, out int levelOfDetail)
{
tileX
= tileY = 0;
levelOfDetail
= quadKey.Length;
for (int i = levelOfDetail; i > 0; i--)
{
int mask = 1 << (i - 1);
switch (quadKey[levelOfDetail - i])
{
case '0':
break;

case '1':
tileX
|= mask;
break;

case '2':
tileY
|= mask;
break;

case '3':
tileX
|= mask;
tileY
|= mask;
break;

default:
throw new ArgumentException("Invalid QuadKey digit sequence.");
}
}
}
上面所讲到的是针对bingmap的情况,googleearth采用QRTS编码,即Q、R、T、S分别代表0、1、2、3,运算方法类似,代码如下
        /// <summary>
        /// 由tileX、tileY和level求解quadkey
        /// </summary>
        /// <param name="tileX"></param>
        /// <param name="tileY"></param>
        /// <param name="levelOfDetail"></param>
        /// <returns></returns>
        private static string TileXYToQuadKey(int tileX, int tileY, int levelOfDetail)
        {
            var quadKey = new StringBuilder();
            for (int i = levelOfDetail; i > 0; i--)
            {
                char digit = '0';

                //掩码,最高位设为1,其他位设为0
                int mask = 1 << (i - 1);

                //与运算取得tileX的最高位,若为1,则加1
                if ((tileX & mask) != 0)
                {
                    digit++;
                }

                //与运算取得tileY的最高位,若为1,则加2
                if ((tileY & mask) != 0)
                {
                    digit++;
                    digit++;
                }

                //也即2*y+x
                quadKey.Append(digit);
            }
            return quadKey.ToString();
        }
 protected static string QuadKeyNumberToAlpha(string base4)
        {
            return base4.Replace('0', 'q').Replace('1', 'r').Replace('2', 't').Replace('3', 's');
        }
private static string QuadKeyNumberToAlphaUrl(string url, int tilePositionX, int tilePositionY, int zoom)
        {
            string quadKey = TileXYToQuadKey(tilePositionX, tilePositionY, zoom);
            //获取最后一位,选择4个服务器中的一台
            string str3 = quadKey.Substring(quadKey.Length - 1, 1);
            string str4 = QuadKeyNumberToAlpha(quadKey);

            url = string.Format(url, str4, str3);
            return url;
        }
Google卫星地图是由256x256大小的jpg图片拼接而成,每块图片的URL格式为“http://kh.google.com/kh?v=3&t=trstrq”样。参数v选择4台服务器中的一台,起到均衡负载的作用,参数t是“qrst”4个字符排列而成的字符串。为获取某经纬度的URL,就需要把经纬度转化为“qrst”字符串。 Google卫星地图在zoom=1时,全球就为一个256x256的图片,它的中心经纬度为(0,0),URL为“http://kh.google.com/kh?v=3&t=t”。zoom=2时裂化为4块,每块的编号为:左上”t=tq”,右上”t=tr”,右下“t=ts”,左下”t=tt”。依此类推,每放大一倍,每一小块都裂分为四,从左上到右下顺时针按qrst编号,裂分后的编码为裂分前的编号上小块的编号。
代码如下:
function GetQuadtreeAddress(long, lat)
{
var PI = 3.1415926535897;
var digits = 18; // how many digits precision
// now convert to normalized square coordinates
// use standard equations to map into mercator projection
var x = (180.0 + parseFloat(long)) / 360.0;
var y = -parseFloat(lat) * PI / 180; // convert to radians
y = 0.5 * Math.log((1+Math.sin(y)) / (1 - Math.sin(y)));
y *= 1.0/(2 * PI); // scale factor from radians to normalized
y += 0.5; // and make y range from 0 - 1
var quad = "t"; // google addresses start with t
var lookup = "qrts"; // tl tr bl br
while (digits–)
{
// make sure we only look at fractional part
x -= Math.floor(x);
y -= Math.floor(y);
quad = quad + lookup.substr((x >= 0.5 ? 1 : 0) + (y >= 0.5 ? 2 : 0), 1);
// now descend into that square
x *= 2;
y *= 2;
}
return quad;
}
原文地址:https://www.cnblogs.com/junyuz/p/2021035.html