GIS理论(墨卡托投影、地理坐标系、地面分辨率、地图比例尺、Bing Maps Tile System)
2013-07-24 22:16
483 查看
墨卡托投影(MercatorProjection),又名“等角正轴圆柱投影”,荷兰地图学家墨卡托(Mercator)在1569年拟定,假设地球被围在一个中空的圆柱里,其赤道与圆柱相接触,然后再假想地球中心有一盏灯,把球面上的图形投影到圆柱体上,再把圆柱体展开,这就是一幅标准纬线为零度(即赤道)的“墨卡托投影”绘制出的世界地图。
一、墨卡托投影坐标系(MercatorProjection)
墨卡托投影以整个世界范围,赤道作为标准纬线,本初子午线作为中央经线,两者交点为坐标原点,向东向北为正,向西向南为负。南北极在地图的正下、上方,而东西方向处于地图的正右、左。
由于MercatorProjection在两极附近是趋于无限值得,因此它并没完整展现了整个世界,地图上最高纬度是85.05度。为了简化计算,我们采用球形映射,而不是椭球体形状。虽然采用MercatorProjection只是为了方便展示地图,需要知道的是,这种映射会给Y轴方向带来0.33%的误差。
由于赤道半径为6378137米,则赤道周长为2*PI*r=20037508.3427892,因此X轴的取值范围:[-20037508.3427892,20037508.3427892]。当纬度φ接近两极,即90°时,Y值趋向于无穷。因此通常把Y轴的取值范围也限定在[-20037508.3427892,20037508.3427892]之间。因此在墨卡托投影坐标系(米)下的坐标范围是:最小为(-20037508.3427892,-20037508.3427892)到最大坐标为(20037508.3427892,20037508.3427892)。
二、地理坐标系(Geographicalcoordinates)
地理经度的取值范围是[-180,180],纬度不可能到达90°,通过纬度取值范围为[20037508.3427892,20037508.3427892]反计算可得到纬度值为85.05112877980659。因此纬度取值范围是[-85.05112877980659,85.05112877980659]。因此,地理坐标系(经纬度)对应的范围是:最小地理坐标(-180,-85.05112877980659),最大地理坐标(180,85.05112877980659)。
三、地面分辨率(GroundResolution)
地面分辨率是以一个像素(pixel)代表的地面尺寸(米)。以微软BingMaps为例,当Level为1时,图片大小为512*512(4个Tile),那么赤道空间分辨率为:赤道周长/512。其他纬度的空间分辨率则为纬度圈长度/512,极端的北极则为0。Level为2时,赤道的空间分辨率为赤道周长/1024,其他纬度为纬度圈长度1024。很明显,GroundResolution取决于两个参数,缩放级别Level和纬度latitude,Level决定像素的多少,latitude决定地面距离的长短。
地面分辨率的公式为,单位:米/像素:
groundresolution=(cos(latitude*pi/180)*2*pi*6378137meters)/(256*2levelpixels)
最低地图放大级别(1级),地图是512x512像素。每下一个放大级别,地图的高度和宽度分别乘于2:2级是1024x1024像素,3级是2048x2048像素,4级是4096x4096像素,等等。通常而言,地图的宽度和高度可以由以下式子计算得到:mapwidth=mapheight=256*2^level
四、地图比例尺(MapScale)
地图比例尺是指测量相同目标时,地图上距离与实际距离的比例。通过地图分辨率在计算可知由Level可得到图片的像素大小,那么需要把其转换为以米为单位的距离,涉及到DPI(dotperinch),暂时可理解为类似的PPI(pixelperinch),即每英寸代表多少个像素。256*2level/DPI即得到相应的英寸inch,再把英寸inch除以0.0254转换为米。实地距离仍旧是:cos(latitude*pi/180)*2*pi*6378137meters;因此比例尺的公式为:
mapscale=256*2level/screendpi/0.0254/(cos(latitude*pi/180)*2*pi*6378137)
比例尺=1:(cos(latitude*pi/180)*2*pi*6378137*screendpi)/(256*2level*0.0254)
地面分辨率和地图比例尺之间的关系:
mapscale=1:groundresolution*screendpi/0.0254meters/inch
五、BingMaps像素坐标系和地图图片编码
为了优化地图系统性能,提高地图下载和显示速度,所有地图都被分割成256x256像素大小的正方形小块。由于在每个放大级别下的像素数量都不一样,因此地图图片(Tile)的数量也不一样。每个tile都有一个XY坐标值,从左上角的(0,0)至右下角的(2^level–1,2^level–1)。例如在3级放大级别下,所有tile的坐标值范围为(0,0)至(7,7),如下图:
已知一个像素的XY坐标值时,我们很容易得到这个像素所在的Tile的XY坐标值:
Quadkey还有其他一些有意思的特性。第一,quadkey的长度等于该tile所对应的放大级别;第二,每个tile的quadkey的前几位和其父tile(上一放大级别所对应的tile)的quadkey相同,下图中,tile2是tile20至23的父tile,tile13是tile130至133的父级:
最后,quadkey提供的一维索引值通常显示了两个tile在XY坐标系中的相似性。换句话说,两个相邻的tile对应的quadkey非常接近。这对于优化数据库的性能非常重要,因为相邻的tile通常被同时请求显示,因此可以将这些tile存放在相同的磁盘区域中,以减少磁盘的读取次数。
下面是微软BingMaps的TileSystem相关算法:
usingSystem;
usingSystem.Text;
namespaceMicrosoft.MapPoint
{
staticclassTileSystem
{
privateconstdoubleEarthRadius=6378137;
privateconstdoubleMinLatitude=-85.05112878;
privateconstdoubleMaxLatitude=85.05112878;
privateconstdoubleMinLongitude=-180;
privateconstdoubleMaxLongitude=180;
///<summary>
///Clipsanumbertothespecifiedminimumandmaximumvalues.
///</summary>
///<paramname="n">Thenumbertoclip.</param>
///<paramname="minValue">Minimumallowablevalue.</param>
///<paramname="maxValue">Maximumallowablevalue.</param>
///<returns>Theclippedvalue.</returns>
privatestaticdoubleClip(doublen,doubleminValue,doublemaxValue)
{
returnMath.Min(Math.Max(n,minValue),maxValue);
}
///<summary>
///Determinesthemapwidthandheight(inpixels)ataspecifiedlevel
///ofdetail.
///</summary>
///<paramname="levelOfDetail">Levelofdetail,from1(lowestdetail)
///to23(highestdetail).</param>
///<returns>Themapwidthandheightinpixels.</returns>
publicstaticuintMapSize(intlevelOfDetail)
{
return(uint)256<<levelOfDetail;
}
///<summary>
///Determinesthegroundresolution(inmetersperpixel)ataspecified
///latitudeandlevelofdetail.
///</summary>
///<paramname="latitude">Latitude(indegrees)atwhichtomeasurethe
///groundresolution.</param>
///<paramname="levelOfDetail">Levelofdetail,from1(lowestdetail)
///to23(highestdetail).</param>
///<returns>Thegroundresolution,inmetersperpixel.</returns>
publicstaticdoubleGroundResolution(doublelatitude,intlevelOfDetail)
{
latitude=Clip(latitude,MinLatitude,MaxLatitude);
returnMath.Cos(latitude*Math.PI/180)*2*Math.PI*EarthRadius/MapSize(levelOfDetail);
}
///<summary>
///Determinesthemapscaleataspecifiedlatitude,levelofdetail,
///andscreenresolution.
///</summary>
///<paramname="latitude">Latitude(indegrees)atwhichtomeasurethe
///mapscale.</param>
///<paramname="levelOfDetail">Levelofdetail,from1(lowestdetail)
///to23(highestdetail).</param>
///<paramname="screenDpi">Resolutionofthescreen,indotsperinch.</param>
///<returns>Themapscale,expressedasthedenominatorNoftheratio1:N.</returns>
publicstaticdoubleMapScale(doublelatitude,intlevelOfDetail,intscreenDpi)
{
returnGroundResolution(latitude,levelOfDetail)*screenDpi/0.0254;
}
///<summary>
///Convertsapointfromlatitude/longitudeWGS-84coordinates(indegrees)
///intopixelXYcoordinatesataspecifiedlevelofdetail.
///</summary>
///<paramname="latitude">Latitudeofthepoint,indegrees.</param>
///<paramname="longitude">Longitudeofthepoint,indegrees.</param>
///<paramname="levelOfDetail">Levelofdetail,from1(lowestdetail)
///to23(highestdetail).</param>
///<paramname="pixelX">OutputparameterreceivingtheXcoordinateinpixels.</param>
///<paramname="pixelY">OutputparameterreceivingtheYcoordinateinpixels.</param>
publicstaticvoidLatLongToPixelXY(doublelatitude,doublelongitude,intlevelOfDetail,outintpixelX,outintpixelY)
{
latitude=Clip(latitude,MinLatitude,MaxLatitude);
longitude=Clip(longitude,MinLongitude,MaxLongitude);
doublex=(longitude+180)/360;
doublesinLatitude=Math.Sin(latitude*Math.PI/180);
doubley=0.5-Math.Log((1+sinLatitude)/(1-sinLatitude))/(4*Math.PI);
uintmapSize=MapSize(levelOfDetail);
pixelX=(int)Clip(x*mapSize+0.5,0,mapSize-1);
pixelY=(int)Clip(y*mapSize+0.5,0,mapSize-1);
}
///<summary>
///ConvertsapixelfrompixelXYcoordinatesataspecifiedlevelofdetail
///intolatitude/longitudeWGS-84coordinates(indegrees).
///</summary>
///<paramname="pixelX">Xcoordinateofthepoint,inpixels.</param>
///<paramname="pixelY">Ycoordinatesofthepoint,inpixels.</param>
///<paramname="levelOfDetail">Levelofdetail,from1(lowestdetail)
///to23(highestdetail).</param>
///<paramname="latitude">Outputparameterreceivingthelatitudeindegrees.</param>
///<paramname="longitude">Outputparameterreceivingthelongitudeindegrees.</param>
publicstaticvoidPixelXYToLatLong(intpixelX,intpixelY,intlevelOfDetail,outdoublelatitude,outdoublelongitude)
{
doublemapSize=MapSize(levelOfDetail);
doublex=(Clip(pixelX,0,mapSize-1)/mapSize)-0.5;
doubley=0.5-(Clip(pixelY,0,mapSize-1)/mapSize);
latitude=90-360*Math.Atan(Math.Exp(-y*2*Math.PI))/Math.PI;
longitude=360*x;
}
///<summary>
///ConvertspixelXYcoordinatesintotileXYcoordinatesofthetilecontaining
///thespecifiedpixel.
///</summary>
///<paramname="pixelX">PixelXcoordinate.</param>
///<paramname="pixelY">PixelYcoordinate.</param>
///<paramname="tileX">OutputparameterreceivingthetileXcoordinate.</param>
///<paramname="tileY">OutputparameterreceivingthetileYcoordinate.</param>
publicstaticvoidPixelXYToTileXY(intpixelX,intpixelY,outinttileX,outinttileY)
{
tileX=pixelX/256;
tileY=pixelY/256;
}
///<summary>
///ConvertstileXYcoordinatesintopixelXYcoordinatesoftheupper-leftpixel
///ofthespecifiedtile.
///</summary>
///<paramname="tileX">TileXcoordinate.</param>
///<paramname="tileY">TileYcoordinate.</param>
///<paramname="pixelX">OutputparameterreceivingthepixelXcoordinate.</param>
///<paramname="pixelY">OutputparameterreceivingthepixelYcoordinate.</param>
publicstaticvoidTileXYToPixelXY(inttileX,inttileY,outintpixelX,outintpixelY)
{
pixelX=tileX*256;
pixelY=tileY*256;
}
///<summary>
///ConvertstileXYcoordinatesintoaQuadKeyataspecifiedlevelofdetail.
///</summary>
///<paramname="tileX">TileXcoordinate.</param>
///<paramname="tileY">TileYcoordinate.</param>
///<paramname="levelOfDetail">Levelofdetail,from1(lowestdetail)
///to23(highestdetail).</param>
///<returns>AstringcontainingtheQuadKey.</returns>
publicstaticstringTileXYToQuadKey(inttileX,inttileY,intlevelOfDetail)
{
StringBuilderquadKey=newStringBuilder();
for(inti=levelOfDetail;i>0;i--)
{
chardigit='0';
intmask=1<<(i-1);
if((tileX&mask)!=0)
{
digit++;
}
if((tileY&mask)!=0)
{
digit++;
digit++;
}
quadKey.Append(digit);
}
returnquadKey.ToString();
}
///<summary>
///ConvertsaQuadKeyintotileXYcoordinates.
///</summary>
///<paramname="quadKey">QuadKeyofthetile.</param>
///<paramname="tileX">OutputparameterreceivingthetileXcoordinate.</param>
///<paramname="tileY">OutputparameterreceivingthetileYcoordinate.</param>
///<paramname="levelOfDetail">Outputparameterreceivingthelevelofdetail.</param>
publicstaticvoidQuadKeyToTileXY(stringquadKey,outinttileX,outinttileY,outintlevelOfDetail)
{
tileX=tileY=0;
levelOfDetail=quadKey.Length;
for(inti=levelOfDetail;i>0;i--)
{
intmask=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:
thrownewArgumentException("InvalidQuadKeydigitsequence.");
}
}
}
}
}
注:本文中内容来源于互联网整理而成,如涉及到任何侵权等行为请联系本人。
推荐资源:
《BingMapsTileSystem》
转载自/article/4658542.html
一、墨卡托投影坐标系(MercatorProjection)
墨卡托投影以整个世界范围,赤道作为标准纬线,本初子午线作为中央经线,两者交点为坐标原点,向东向北为正,向西向南为负。南北极在地图的正下、上方,而东西方向处于地图的正右、左。
由于MercatorProjection在两极附近是趋于无限值得,因此它并没完整展现了整个世界,地图上最高纬度是85.05度。为了简化计算,我们采用球形映射,而不是椭球体形状。虽然采用MercatorProjection只是为了方便展示地图,需要知道的是,这种映射会给Y轴方向带来0.33%的误差。
由于赤道半径为6378137米,则赤道周长为2*PI*r=20037508.3427892,因此X轴的取值范围:[-20037508.3427892,20037508.3427892]。当纬度φ接近两极,即90°时,Y值趋向于无穷。因此通常把Y轴的取值范围也限定在[-20037508.3427892,20037508.3427892]之间。因此在墨卡托投影坐标系(米)下的坐标范围是:最小为(-20037508.3427892,-20037508.3427892)到最大坐标为(20037508.3427892,20037508.3427892)。
二、地理坐标系(Geographicalcoordinates)
地理经度的取值范围是[-180,180],纬度不可能到达90°,通过纬度取值范围为[20037508.3427892,20037508.3427892]反计算可得到纬度值为85.05112877980659。因此纬度取值范围是[-85.05112877980659,85.05112877980659]。因此,地理坐标系(经纬度)对应的范围是:最小地理坐标(-180,-85.05112877980659),最大地理坐标(180,85.05112877980659)。
三、地面分辨率(GroundResolution)
地面分辨率是以一个像素(pixel)代表的地面尺寸(米)。以微软BingMaps为例,当Level为1时,图片大小为512*512(4个Tile),那么赤道空间分辨率为:赤道周长/512。其他纬度的空间分辨率则为纬度圈长度/512,极端的北极则为0。Level为2时,赤道的空间分辨率为赤道周长/1024,其他纬度为纬度圈长度1024。很明显,GroundResolution取决于两个参数,缩放级别Level和纬度latitude,Level决定像素的多少,latitude决定地面距离的长短。
地面分辨率的公式为,单位:米/像素:
groundresolution=(cos(latitude*pi/180)*2*pi*6378137meters)/(256*2levelpixels)
最低地图放大级别(1级),地图是512x512像素。每下一个放大级别,地图的高度和宽度分别乘于2:2级是1024x1024像素,3级是2048x2048像素,4级是4096x4096像素,等等。通常而言,地图的宽度和高度可以由以下式子计算得到:mapwidth=mapheight=256*2^level
pixels
四、地图比例尺(MapScale)
地图比例尺是指测量相同目标时,地图上距离与实际距离的比例。通过地图分辨率在计算可知由Level可得到图片的像素大小,那么需要把其转换为以米为单位的距离,涉及到DPI(dotperinch),暂时可理解为类似的PPI(pixelperinch),即每英寸代表多少个像素。256*2level/DPI即得到相应的英寸inch,再把英寸inch除以0.0254转换为米。实地距离仍旧是:cos(latitude*pi/180)*2*pi*6378137meters;因此比例尺的公式为:
mapscale=256*2level/screendpi/0.0254/(cos(latitude*pi/180)*2*pi*6378137)
比例尺=1:(cos(latitude*pi/180)*2*pi*6378137*screendpi)/(256*2level*0.0254)
地面分辨率和地图比例尺之间的关系:
mapscale=1:groundresolution*screendpi/0.0254meters/inch
缩放级别 | 地图宽度、高度(像素) | 地面分辨率(米/像素) | 地图比例尺(以96dpi为例) |
1 | 512 | 78,271.5170 | 1:295,829,355.45 |
2 | 1,024 | 39,135.7585 | 1:147,914,677.73 |
3 | 2,048 | 19,567.8792 | 1:73,957,338.86 |
4 | 4,096 | 9,783.9396 | 1:36,978,669.43 |
5 | 8,192 | 4,891.9698 | 1:18,489,334.72 |
6 | 16,384 | 2,445.9849 | 1:9,244,667.36 |
7 | 32,768 | 1,222.9925 | 1:4,622,333.68 |
8 | 65,536 | 611.4962 | 1:2,311,166.84 |
9 | 131,072 | 305.7481 | 1:1,155,583.42 |
10 | 262,144 | 152.8741 | 1:577,791.71 |
11 | 524,288 | 76.4370 | 1:288,895.85 |
12 | 1,048,576 | 38.2185 | 1:144,447.93 |
13 | 2,097,152 | 19.1093 | 1:72,223.96 |
14 | 4,194,304 | 9.5546 | 1:36,111.98 |
15 | 8,388,608 | 4.7773 | 1:18,055.99 |
16 | 16,777,216 | 2.3887 | 1:9,028.00 |
17 | 33,554,432 | 1.1943 | 1:4,514.00 |
18 | 67,108,864 | 0.5972 | 1:2,257.00 |
19 | 134,217,728 | 0.2986 | 1:1,128.50 |
20 | 268,435,456 | 0.1493 | 1:564.25 |
21 | 536,870,912 | 0.0746 | 1:282.12 |
22 | 1,073,741,824 | 0.0373 | 1:141.06 |
23 | 2,147,483,648 | 0.0187 | 1:70.53 |
为了优化地图系统性能,提高地图下载和显示速度,所有地图都被分割成256x256像素大小的正方形小块。由于在每个放大级别下的像素数量都不一样,因此地图图片(Tile)的数量也不一样。每个tile都有一个XY坐标值,从左上角的(0,0)至右下角的(2^level–1,2^level–1)。例如在3级放大级别下,所有tile的坐标值范围为(0,0)至(7,7),如下图:
已知一个像素的XY坐标值时,我们很容易得到这个像素所在的Tile的XY坐标值:
tileX=floor(pixelX/256)
tileY=floor(pixelY/256)
为了简化索引和存储地图图片,每个tile的二维XY值被转换成一维字串,即四叉树键值(quardtreekey,简称quadkey)。每个quadkey独立对应某个放大级别下的一个tile,并且它可以被用作数据库中B-tree索引值。为了将坐标值转换成quadkey,需要将Y和X坐标二进制值交错组合,并转换成4进制值及对应的字符串。例如,假设在放大级别为3时,tile的XY坐标值为(3,5),quadkey计算如下:
tileX=3=011(二进制)
tileY=5=101(二进制)
quadkey=100111(二进制)
=213(四进制)
=“213”
Quadkey还有其他一些有意思的特性。第一,quadkey的长度等于该tile所对应的放大级别;第二,每个tile的quadkey的前几位和其父tile(上一放大级别所对应的tile)的quadkey相同,下图中,tile2是tile20至23的父tile,tile13是tile130至133的父级:
最后,quadkey提供的一维索引值通常显示了两个tile在XY坐标系中的相似性。换句话说,两个相邻的tile对应的quadkey非常接近。这对于优化数据库的性能非常重要,因为相邻的tile通常被同时请求显示,因此可以将这些tile存放在相同的磁盘区域中,以减少磁盘的读取次数。
下面是微软BingMaps的TileSystem相关算法:
usingSystem;
usingSystem.Text;
namespaceMicrosoft.MapPoint
{
staticclassTileSystem
{
privateconstdoubleEarthRadius=6378137;
privateconstdoubleMinLatitude=-85.05112878;
privateconstdoubleMaxLatitude=85.05112878;
privateconstdoubleMinLongitude=-180;
privateconstdoubleMaxLongitude=180;
///<summary>
///Clipsanumbertothespecifiedminimumandmaximumvalues.
///</summary>
///<paramname="n">Thenumbertoclip.</param>
///<paramname="minValue">Minimumallowablevalue.</param>
///<paramname="maxValue">Maximumallowablevalue.</param>
///<returns>Theclippedvalue.</returns>
privatestaticdoubleClip(doublen,doubleminValue,doublemaxValue)
{
returnMath.Min(Math.Max(n,minValue),maxValue);
}
///<summary>
///Determinesthemapwidthandheight(inpixels)ataspecifiedlevel
///ofdetail.
///</summary>
///<paramname="levelOfDetail">Levelofdetail,from1(lowestdetail)
///to23(highestdetail).</param>
///<returns>Themapwidthandheightinpixels.</returns>
publicstaticuintMapSize(intlevelOfDetail)
{
return(uint)256<<levelOfDetail;
}
///<summary>
///Determinesthegroundresolution(inmetersperpixel)ataspecified
///latitudeandlevelofdetail.
///</summary>
///<paramname="latitude">Latitude(indegrees)atwhichtomeasurethe
///groundresolution.</param>
///<paramname="levelOfDetail">Levelofdetail,from1(lowestdetail)
///to23(highestdetail).</param>
///<returns>Thegroundresolution,inmetersperpixel.</returns>
publicstaticdoubleGroundResolution(doublelatitude,intlevelOfDetail)
{
latitude=Clip(latitude,MinLatitude,MaxLatitude);
returnMath.Cos(latitude*Math.PI/180)*2*Math.PI*EarthRadius/MapSize(levelOfDetail);
}
///<summary>
///Determinesthemapscaleataspecifiedlatitude,levelofdetail,
///andscreenresolution.
///</summary>
///<paramname="latitude">Latitude(indegrees)atwhichtomeasurethe
///mapscale.</param>
///<paramname="levelOfDetail">Levelofdetail,from1(lowestdetail)
///to23(highestdetail).</param>
///<paramname="screenDpi">Resolutionofthescreen,indotsperinch.</param>
///<returns>Themapscale,expressedasthedenominatorNoftheratio1:N.</returns>
publicstaticdoubleMapScale(doublelatitude,intlevelOfDetail,intscreenDpi)
{
returnGroundResolution(latitude,levelOfDetail)*screenDpi/0.0254;
}
///<summary>
///Convertsapointfromlatitude/longitudeWGS-84coordinates(indegrees)
///intopixelXYcoordinatesataspecifiedlevelofdetail.
///</summary>
///<paramname="latitude">Latitudeofthepoint,indegrees.</param>
///<paramname="longitude">Longitudeofthepoint,indegrees.</param>
///<paramname="levelOfDetail">Levelofdetail,from1(lowestdetail)
///to23(highestdetail).</param>
///<paramname="pixelX">OutputparameterreceivingtheXcoordinateinpixels.</param>
///<paramname="pixelY">OutputparameterreceivingtheYcoordinateinpixels.</param>
publicstaticvoidLatLongToPixelXY(doublelatitude,doublelongitude,intlevelOfDetail,outintpixelX,outintpixelY)
{
latitude=Clip(latitude,MinLatitude,MaxLatitude);
longitude=Clip(longitude,MinLongitude,MaxLongitude);
doublex=(longitude+180)/360;
doublesinLatitude=Math.Sin(latitude*Math.PI/180);
doubley=0.5-Math.Log((1+sinLatitude)/(1-sinLatitude))/(4*Math.PI);
uintmapSize=MapSize(levelOfDetail);
pixelX=(int)Clip(x*mapSize+0.5,0,mapSize-1);
pixelY=(int)Clip(y*mapSize+0.5,0,mapSize-1);
}
///<summary>
///ConvertsapixelfrompixelXYcoordinatesataspecifiedlevelofdetail
///intolatitude/longitudeWGS-84coordinates(indegrees).
///</summary>
///<paramname="pixelX">Xcoordinateofthepoint,inpixels.</param>
///<paramname="pixelY">Ycoordinatesofthepoint,inpixels.</param>
///<paramname="levelOfDetail">Levelofdetail,from1(lowestdetail)
///to23(highestdetail).</param>
///<paramname="latitude">Outputparameterreceivingthelatitudeindegrees.</param>
///<paramname="longitude">Outputparameterreceivingthelongitudeindegrees.</param>
publicstaticvoidPixelXYToLatLong(intpixelX,intpixelY,intlevelOfDetail,outdoublelatitude,outdoublelongitude)
{
doublemapSize=MapSize(levelOfDetail);
doublex=(Clip(pixelX,0,mapSize-1)/mapSize)-0.5;
doubley=0.5-(Clip(pixelY,0,mapSize-1)/mapSize);
latitude=90-360*Math.Atan(Math.Exp(-y*2*Math.PI))/Math.PI;
longitude=360*x;
}
///<summary>
///ConvertspixelXYcoordinatesintotileXYcoordinatesofthetilecontaining
///thespecifiedpixel.
///</summary>
///<paramname="pixelX">PixelXcoordinate.</param>
///<paramname="pixelY">PixelYcoordinate.</param>
///<paramname="tileX">OutputparameterreceivingthetileXcoordinate.</param>
///<paramname="tileY">OutputparameterreceivingthetileYcoordinate.</param>
publicstaticvoidPixelXYToTileXY(intpixelX,intpixelY,outinttileX,outinttileY)
{
tileX=pixelX/256;
tileY=pixelY/256;
}
///<summary>
///ConvertstileXYcoordinatesintopixelXYcoordinatesoftheupper-leftpixel
///ofthespecifiedtile.
///</summary>
///<paramname="tileX">TileXcoordinate.</param>
///<paramname="tileY">TileYcoordinate.</param>
///<paramname="pixelX">OutputparameterreceivingthepixelXcoordinate.</param>
///<paramname="pixelY">OutputparameterreceivingthepixelYcoordinate.</param>
publicstaticvoidTileXYToPixelXY(inttileX,inttileY,outintpixelX,outintpixelY)
{
pixelX=tileX*256;
pixelY=tileY*256;
}
///<summary>
///ConvertstileXYcoordinatesintoaQuadKeyataspecifiedlevelofdetail.
///</summary>
///<paramname="tileX">TileXcoordinate.</param>
///<paramname="tileY">TileYcoordinate.</param>
///<paramname="levelOfDetail">Levelofdetail,from1(lowestdetail)
///to23(highestdetail).</param>
///<returns>AstringcontainingtheQuadKey.</returns>
publicstaticstringTileXYToQuadKey(inttileX,inttileY,intlevelOfDetail)
{
StringBuilderquadKey=newStringBuilder();
for(inti=levelOfDetail;i>0;i--)
{
chardigit='0';
intmask=1<<(i-1);
if((tileX&mask)!=0)
{
digit++;
}
if((tileY&mask)!=0)
{
digit++;
digit++;
}
quadKey.Append(digit);
}
returnquadKey.ToString();
}
///<summary>
///ConvertsaQuadKeyintotileXYcoordinates.
///</summary>
///<paramname="quadKey">QuadKeyofthetile.</param>
///<paramname="tileX">OutputparameterreceivingthetileXcoordinate.</param>
///<paramname="tileY">OutputparameterreceivingthetileYcoordinate.</param>
///<paramname="levelOfDetail">Outputparameterreceivingthelevelofdetail.</param>
publicstaticvoidQuadKeyToTileXY(stringquadKey,outinttileX,outinttileY,outintlevelOfDetail)
{
tileX=tileY=0;
levelOfDetail=quadKey.Length;
for(inti=levelOfDetail;i>0;i--)
{
intmask=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:
thrownewArgumentException("InvalidQuadKeydigitsequence.");
}
}
}
}
}
注:本文中内容来源于互联网整理而成,如涉及到任何侵权等行为请联系本人。
推荐资源:
转载自
相关文章推荐
- GIS理论(墨卡托投影、地理坐标系、地面分辨率、地图比例尺、Bing Maps Tile System)
- GIS理论(墨卡托投影、地理坐标系、地面分辨率、地图比例尺、Bing Maps Tile System)
- GIS理论(墨卡托投影、地理坐标系、地面分辨率、地图比例尺、Bing Maps Tile System)
- GIS理论(墨卡托投影、地理坐标系、地面分辨率、地图比例尺、Bing Maps Tile System)【转载】
- GIS理论(墨卡托投影、地理坐标系、地面分辨率、地图比例尺、Bing Maps Tile System)
- GIS理论(墨卡托投影、地理坐标系、地面分辨率、地图比例尺、Bing Maps Tile System)
- GIS理论(墨卡托投影、地理坐标系、地面分辨率、地图比例尺、Bing Maps Tile System)
- GIS理论(墨卡托投影、地理坐标系、地面分辨率、地图比例尺、Bing Maps Tile System)
- GIS理论(墨卡托投影、地理坐标系、地面分辨率、地图比例尺、Bing Maps Tile System)
- GIS理论(墨卡托投影、地理坐标系、地面分辨率、地图比例尺、Bing Maps Tile System)
- GIS理论(墨卡托投影、地理坐标系、地面分辨率、地图比例尺、Bing Maps Tile System)【转载】
- GIS理论(墨卡托投影、地理坐标系、地面分辨率、地图比例尺、Bing Maps Tile System)【转载】
- GIS理论(墨卡托投影、地理坐标系、地面分辨率、地图比例尺、Bing Maps Tile System)
- GIS理论(墨卡托投影、地理坐标系、地面分辨率、地图比例尺、Bing Maps Tile System)
- GIS理论(墨卡托投影、地理坐标系、地面分辨率、地图比例尺、Bing Maps Tile System)
- GIS理论(墨卡托投影、地理坐标系、地面分辨率、地图比例尺、Bing Maps Tile System)
- GIS理论(墨卡托投影、地理坐标系、地面分辨率、地图比例尺、Bing Maps Tile System)转载
- GIS理论(墨卡托投影、地理坐标系、地面分辨率、地图比例尺、Bing Maps Tile System)
- GIS理论(墨卡托投影、地理坐标系、地面分辨率、地图比例尺、Bing Maps Tile System)
- (转)GIS理论(墨卡托投影、地理坐标系、地面分辨率、地图比例尺、Bing Maps Tile System)