精华内容
下载资源
问答
  • 瓦片地图是什么

    千次阅读 2019-04-30 10:01:54
    瓦片地图的诞生 地图数据通常体量较大,需要充足的带宽和数据渲染能力。瓦片地图诞生以前,地图多在局域网的桌面软件中使用...WMS的设计,在服务器端把地图渲染成图片,浏览器端显示地图图片。地图图片大小根据浏...

    瓦片地图的诞生

     地图数据通常体量较大,需要充足的带宽和数据渲染能力。瓦片地图诞生以前,地图多在局域网的桌面软件中使用。互联网的发展,催生了通过浏览器使用地图的需求,于是在1999年,出现了WMS(Web Map Service)这样的解决方案。在浏览器这一端,没有地图的概念,但浏览器天生就是为了显示文本和图片。WMS的设计是,在服务器端把地图渲染成图片,浏览器端显示地图图片。地图图片大小根据浏览器视窗大小来定。

    WMS大大推进了互联网地图的进程。 问题是,WMS根据浏览器视窗大小每次生成一大张图片,对于后端渲染和网络传输都是挑战,效率低下。紧接着就有了WMS-C(Cached)的思想,通过缓存地图瓦片提高效率。在工程实践方面更胜一筹的Google成为这一思想的最佳实践者。2005年,Google地图上线,通过高效的瓦片地图技术,让全球用户轻而易举的享受到了地图的福利。

     

    Google地图采用的Web Mecator投影和瓦片分级切割方案,也成为目前互联网地图事实上的标准。紧接着,Google地图又新增了路网服务、实时路况、街景地图和Google地球,互联网地图的蓬勃发展就此开始。

     

    瓦片地图的原理

    使用互联网地图时,我们看到的是一张铺满整个屏幕的大的地图图片。实际上,这张大的图片是多个尺寸相同(通常是256*256像素)的小图片按照既定规则无缝拼接而成的,这些小图片就是瓦片。瓦片按照如下图所示的金字塔结构组织,每张瓦片都可通过级别、行列号唯一标记。在平移地图、缩放地图时,浏览器根据金字塔规则,计算出所需的瓦片,从瓦片服务器获取并拼接。

     

    由于瓦片是静态的图片,可预先生成,通过缓存和CDN技术,瓦片服务器可提供高效的瓦片读取服务。此外,浏览器并行获取和显示多张小图片,比获取和显示一张大图片要高效的多。显示地图变成和显示图片一样简单,这也是互联网地图能够承载亿级规模用户的原因。

     

    瓦片地图金字塔模型

    瓦片地图金字塔模型是一种多分辨率层次模型,从瓦片金字塔的底层到顶层,分辨率越来越低,但表示的地理范围不变。首先确定地图服务平台所要提供的缩放级别的数量N,把缩放级别最高、地图比例尺最大的地图图片作为金字塔的底层,即第0层,并对其进行分块,从地图图片的左上角开始,从左至右、从上到下进行切割,分割成相同大小(比如256x256像素)的正方形地图瓦片,形成第0层瓦片矩阵;在第0层地图图片的基础上,按每2x2像素合成为一个像素的方法生成第1层地图图片,并对其进行分块,分割成与下一层相同大小的正方形地图瓦片,形成第1层瓦片矩阵;采用同样的方法生成第2层瓦片矩阵;…;如此下去,直到第N一1层,构成整个瓦片金字塔。

    首先用(如ArcGIS软件等)对地图数据进行处理,配成需要的图层方案,并保存方案。

    再用软件自带功能进行切片,切片过程中选择切片方案,根据所选方案不同,例如金字塔级别不同,地图切片范围不同等,都会影响到切片的速度。切片之后的数据称为瓦片。

     

    瓦片地图的进化

    以图片为介质的瓦片(栅格瓦片)打开了互联网地图的大门,互联网地图得以迅速普及。但是,随着地图的移动化和应用的逐渐深入,栅格瓦片至少遇到了两个问题:

    • 图片占用带宽和存储都较大,不利于地图在移动设备的应用;

    • 图片无法交互。

    受网络带宽开销和存储空间的限制,栅格瓦片地图在移动端一开始就显现出先天不足。这促使在移动端,使用矢量瓦片替代栅格瓦片。矢量瓦片采用和栅格瓦片相同的分级切割方案,所不同的是,瓦片数据以矢量形式存在。矢量瓦片体积小,可高度压缩,占用的存储空间比栅格瓦片要小上千倍。一方面减小网络带宽消耗,另一方面使地图离线成为可能。

     

    目前,在浏览器端,矢量瓦片也在逐渐成为互联网地图的主流技术。但这并不是说栅格瓦片将退出历史舞台。 互联网地图数据更新不频繁,单个瓦片内需要显示的地物数量和种类有限,矢量瓦片可预先生成,进行局部更新的代价也很小。矢量瓦片并不适合数据更新频繁,数据量大,渲染方式复杂多样的场景。

     

    可交互的栅格瓦片

    在GeoHey数据可视化服务中,就是根据输入配置参数,把用户数据在服务器端渲染成图片。在很多应用场景中,需要查看空间数据的属性信息。由于栅格瓦片无法保留数据的空间特征,瓦片中的点、线、面失去了交互能力。那么,如何显示百万量级的地块数据,又能让地块具有交互能力呢?

    [鼠标在地图上随意移动即可 全屏体验]

    在本周更新中,GeoHey数据可视化服务,增加了UTF-Grid能力,用以为栅格瓦片提供交互能力。 

    多任务切图原理

    随着测绘技术的发展,地图数据的体量越来越大,一般情况下,电子地图生成地图瓦片(以下简称切图)少则需要几天,多则一个月乃至更长时间。如何才能高效地生成地图瓦片,是众多技术人员共同关心的问题。

    多任务切图是将地图切图任务拆分成多个子任务,同时开启多个进程,每个进程自动领取并执行切图子任务。切图结果支持保存为本地瓦片,也支持保存到MongoDB数据库。多任务切图支持在一台计算机上开启多个进程执行切图任务,也支持在多个计算机分别开启多个进程,获取子任务执行切图任务。

     

    在线地图及参数

    Arcgis online上的瓦片地图为例,服务中有几个比较关键的使用到的参数。

    Height、Weight:每个瓦片的宽度和高度

    Resolution:每一个缩放级别下1像素代表的地图单位(投影坐标)

    Initial Extent:瓦片地图的范围

     

    展开全文
  • 百度地图瓦片的下载其实很容易,拿到下载链接然后批量下载就行了。不过由于需要按照规则来存储,最好自己写个程序去下载这些链接。否则就要使用人家已经做好的程序去下载了,这些很多都需要收费的,或者有水印什么...

    续上篇《Web版百度地图加载离线瓦片》,本文贴出下载瓦片的简易程序。

    百度地图瓦片的下载其实很容易,拿到下载链接然后批量下载就行了。不过由于需要按照规则来存储,最好自己写个程序去下载这些链接。否则就要使用人家已经做好的程序去下载了,这些很多都是需要收费的,或者有水印什么的。

    其实直接拿到地图窗口内的所有瓦片并非难事,跟踪一下脚本中的代码就行了。不过脚本是压缩混淆过的,读起来比较难。

    本文直接贴出来整理好的代码,然后就可以调用下载了。

    function downloadBaiduTiles(){

    var EARTHRADIUS = 6370996.81;

    var MCBAND = [ 12890594.86, 8362377.87, 5591021, 3481989.83,

    1678043.12, 0 ];

    var LLBAND = [ 75, 60, 45, 30, 15, 0 ];

    var MC2LL = [

    [ 1.410526172116255e-8, 0.00000898305509648872,

    -1.9939833816331, 200.9824383106796,

    -187.2403703815547, 91.6087516669843,

    -23.38765649603339, 2.57121317296198,

    -0.03801003308653, 17337981.2 ],

    [ -7.435856389565537e-9, 0.000008983055097726239,

    -0.78625201886289, 96.32687599759846,

    -1.85204757529826, -59.36935905485877,

    47.40033549296737, -16.50741931063887,

    2.28786674699375, 10260144.86 ],

    [ -3.030883460898826e-8, 0.00000898305509983578,

    0.30071316287616, 59.74293618442277,

    7.357984074871, -25.38371002664745,

    13.45380521110908, -3.29883767235584,

    0.32710905363475, 6856817.37 ],

    [ -1.981981304930552e-8, 0.000008983055099779535,

    0.03278182852591, 40.31678527705744,

    0.65659298677277, -4.44255534477492,

    0.85341911805263, 0.12923347998204,

    -0.04625736007561, 4482777.06 ],

    [ 3.09191371068437e-9, 0.000008983055096812155,

    0.00006995724062, 23.10934304144901,

    -0.00023663490511, -0.6321817810242,

    -0.00663494467273, 0.03430082397953,

    -0.00466043876332, 2555164.4 ],

    [ 2.890871144776878e-9, 0.000008983055095805407,

    -3.068298e-8, 7.47137025468032,

    -0.00000353937994, -0.02145144861037,

    -0.00001234426596, 0.00010322952773,

    -0.00000323890364, 826088.5 ] ];

    var LL2MC = [

    [ -0.0015702102444, 111320.7020616939,

    1704480524535203, -10338987376042340,

    26112667856603880, -35149669176653700,

    26595700718403920, -10725012454188240,

    1800819912950474, 82.5 ],

    [ 0.0008277824516172526, 111320.7020463578,

    647795574.6671607, -4082003173.641316,

    10774905663.51142, -15171875531.51559,

    12053065338.62167, -5124939663.577472,

    913311935.9512032, 67.5 ],

    [ 0.00337398766765, 111320.7020202162,

    4481351.045890365, -23393751.19931662,

    79682215.47186455, -115964993.2797253,

    97236711.15602145, -43661946.33752821,

    8477230.501135234, 52.5 ],

    [ 0.00220636496208, 111320.7020209128,

    51751.86112841131, 3796837.749470245,

    992013.7397791013, -1221952.21711287,

    1340652.697009075, -620943.6990984312,

    144416.9293806241, 37.5 ],

    [ -0.0003441963504368392, 111320.7020576856,

    278.2353980772752, 2485758.690035394,

    6070.750963243378, 54821.18345352118,

    9540.606633304236, -2710.55326746645,

    1405.483844121726, 22.5 ],

    [ -0.0003218135878613132, 111320.7020701615,

    0.00369383431289, 823725.6402795718,

    0.46104986909093, 2351.343141331292,

    1.58060784298199, 8.77738589078284,

    0.37238884252424, 7.45 ] ];

    function Point(lng, lat){

    this.lng = lng;

    this.lat = lat;

    }

    function convertor (point, ll2mc) {

    if (!point || !ll2mc) {

    return

    }

    // 经度的转换比较简单,一个简单的线性转换就可以了。

    // 0、1的数量级别是这样的-0.0015702102444, 111320.7020616939

    var x = ll2mc[0] + ll2mc[1] * Math.abs(point.lng);

    // 先计算一个线性关系,其中9的数量级是这样的:67.5,a的估值大约是一个个位数

    var a = Math.abs(point.lat) / ll2mc[9];

    // 维度的转换相对比较复杂,y=b+ca+da^2+ea^3+fa^4+ga^5+ha^6

    // 其中,a是维度的线性转换,而最终值则是一个六次方的多项式,2、3、4、5、6、7、8的数值大约是这样的:

    // 278.2353980772752, 2485758.690035394,

    // 6070.750963243378, 54821.18345352118,

    // 9540.606633304236, -2710.55326746645,

    // 1405.483844121726,

    // 这意味着维度会变成一个很大的数,大到多少很难说

    var y = ll2mc[2] + ll2mc[3] * a + ll2mc[4] * a * a + ll2mc[5] * a

    * a * a + ll2mc[6] * a * a * a * a + ll2mc[7] * a

    * a * a * a * a + ll2mc[8] * a * a * a * a

    * a * a;

    // 整个计算是基于绝对值的,符号位最后补回去就行了

    x *= (point.lng 

    y *= (point.lat 

    // 产生一个新的点坐标。果然不一样了啊

    return new Point(x, y)

    }

    function lngLatToMercator(T) {

    return convertLL2MC(T);

    }

    function getLoop(value, min, max) {

    while (value > max) {

    value -= max - min

    }

    while (value 

    value += max - min

    }

    return value

    }

    function convertLL2MC (point) {

    var point1;

    var ll2mc;

    point.lng = getLoop(point.lng, -180, 180);// 标准化到区间内

    point.lat = getRange(point.lat, -74, 74);// 标准化到区间内

    point1 = new Point(point.lng, point.lat);

    // 查找LLBAND的维度字典,字典由大到小排序,找到则停止

    for (var i = 0; i 

    if (point1.lat >= LLBAND[i]) {

    ll2mc = LL2MC[i];

    break;

    }

    }

    // 如果没有找到,则反过来找。找到即停止。

    if (!ll2mc) {

    for (var i = LLBAND.length - 1; i >= 0; i--) {

    if (point1.lat <= -LLBAND[i]) {

    ll2mc = LL2MC[i];

    break;

    }

    }

    }

    var newPoint = convertor(point, ll2mc);

    var point = new Point(newPoint.lng.toFixed(2), newPoint.lat.toFixed(2));

    return point;

    }

    function findAllTiles(map, callback){

    var mapType = map.getMapType();// 地图类型

    var zoomLevel = map.zoomLevel;// 放大倍数

    var center = map.mercatorCenter;// 中心坐标

    this.mapCenterPoint = center;

    var cV = mapType.getZoomUnits(zoomLevel);// zoomLevel相关的一个指数,=2^(18-zoomLevel)

    var unitSize = mapType.getZoomFactor(zoomLevel);// 一个系数,=cV*256

    var longitudeUnits = Math.ceil(center.lng / unitSize);// center.lng是一个很大的数

    var latitudeUnits = Math.ceil(center.lat / unitSize);

    var tileSize = mapType.getTileSize();

    var cP = [ longitudeUnits, latitudeUnits, (center.lng - longitudeUnits * unitSize) / unitSize * tileSize,

    (center.lat - latitudeUnits * unitSize) / unitSize * tileSize ];

    var width0 = cP[0] - Math.ceil((map.width / 2 - cP[2]) / tileSize);

    var height0 = cP[1] - Math.ceil((map.height / 2 - cP[3]) / tileSize);

    var width = cP[0] + Math.ceil((map.width / 2 + cP[2]) / tileSize);

    var c0 = 0;

    if (mapType === BMAP_PERSPECTIVE_MAP && map.getZoom() == 15) {

    c0 = 1

    }

    var height = cP[1] + Math.ceil((map.height / 2 + cP[3]) / tileSize) + c0;

    var xydata = [];

    for (var i = width0; i 

    for (var j = height0; j 

    xydata.push([ i, j ])

    }

    }

    var zoom = map.getZoom();

    //var win = window.open();

    for (var i = 0, len = xydata.length; i 

    showTile([ xydata[i][0], xydata[i][1], zoom ], callback)

    }

    }

    function showTile(xyz, callback){

    console.log(xyz[2]+"/"+xyz[0]+"/"+xyz[1]);

    if(!!callback){

    callback(xyz, getTilesUrl({x:xyz[0],y:xyz[1]}, xyz[2]));

    }

    }

    var j = [ "http://online0.map.bdimg.com/tile/",

    "http://online1.map.bdimg.com/tile/",

    "http://online2.map.bdimg.com/tile/",

    "http://online3.map.bdimg.com/tile/",

    "http://online4.map.bdimg.com/tile/" ];

    function getTilesUrl(xy, z) {

    var x = xy.x;

    var y = xy.y;

    var udt = "20150518";

    var style = "pl";

    // if (this.map.highResolutionEnabled()) {

    //style = "ph"

    // }

    var cM = j[Math.abs(x + y) % j.length] + "?qt=tile&x="

    + (x + "").replace(/-/gi, "M") + "&y="

    + (y + "").replace(/-/gi, "M") + "&z=" + z + "&styles=" + style

    + "&udt=" + udt;

    // 这个地方废弃了上面的计算结果,直接采用本地图片

    //cM = "maptile/" + z + "/" + x + "/" + y + ".jpg";

    return cM.replace(/-(\d+)/gi, "M$1")

    }

    return function(map, callback){findAllTiles(map, callback);};

    }

    然后引入这个js文件,再写个按钮,不断的移动窗口,添加新的下载连接吧。

    function findtiles(){

    var findAllTiles = downloadBaiduTiles();

    findAllTiles(map, addUrls);

    }

    function addUrls(xyz, url){

    var div = document.getElementById("list");

    var anchor = document.createElement("a");

    anchor.href = url;

    anchor.innerHTML = xyz[2]+"/"+xyz[0]+"/"+xyz[1];

    div.appendChild(anchor);

    var br = document.createElement("br");

    div.appendChild(br);

    }

    效果图:

    360aace175b850427e3d31a21bd60c45.png

    59ca0d67f0e79176c1ca40b333c761d1.png

    这个方式有个优点,可以随时缩放地图,然后点击按钮,这样就可以不断的获取新的瓦片地址了。不过代码没有优化,移动地图的时候可能产生重复的瓦片,然后下载程序还没有写。最后根据xyz来安排文件放置位置就可以了。

    展开全文
  • 瓦片地图首先解释一下什么是瓦片地图,我们使用的地图(例如百度,高德)都有一个底图,在每一级的缩放比例下,都有一张很大的底图,这张底图按固定的大小切割成若干份,在地图显示时根据显示范围和缩放比例,请求对应...

    瓦片地图

    首先解释一下什么是瓦片地图,我们使用的地图(例如百度,高德)都有一个底图,在每一级的缩放比例下,都有一张很大的底图,这张底图按固定的大小切割成若干份,在地图显示时根据显示范围和缩放比例,请求对应几张小的底图,这些底图就是瓦片地图。

    项目需求

    项目使用的是高德地图,基本的操作可以参考官方文档,然后需要叠加自己的瓦片地图。在官方文档中找了好久,终于在绘制面_绘制瓦片图层这一节中找到了相应的方法。主要步骤是先添加一个MATileOverlay到地图中,然后实现delegate中的mapView:viewForOverlay:函数,返回一个renderer对象。项目中用到的所有地图都要加载这个瓦片服务,所以直接从MAMapView继承出一个自定义MapView。

    代码实现

    自定义一个PPGMapView,继承自MAMapView。

    #import NS_ASSUME_NONNULL_BEGIN

    @interface PPGMapView : MAMapView

    @end

    NS_ASSUME_NONNULL_END

    在初始化时添加自定义瓦片图层。

    - (void)commonInit {

    // delegate指向自己

    self.delegate = self;

    // 初始化缩放级别

    self.zoomLevel = 18.f;

    self.showsUserLocation = YES;

    self.userTrackingMode = MAUserTrackingModeFollow;

    // 添加自定义瓦片图层

    PPGTileOverlay *overlay = [[PPGTileOverlay alloc] init];

    overlay.maximumZ = 20;

    overlay.minimumZ = 14;

    overlay.boundingMapRect = MAMapRectWorld;

    [self addOverlay:overlay];

    }

    实现renderer方法

    - (MAOverlayRenderer *)mapView:(MAMapView *)mapView rendererForOverlay:(id )overlay {

    // 外部delegate首先进行响应,如果没有实现,则使用自定义地图的实现

    if ([self.extDelegate respondsToSelector:_cmd]) {

    MAOverlayRenderer *renderer = [self.extDelegate mapView:mapView rendererForOverlay:overlay];

    if (renderer) {

    return renderer;

    }

    }

    if ([overlay isKindOfClass:[MATileOverlay class]]) {

    // 默认的瓦片底图renderer

    MATileOverlayRenderer *renderer = [[MATileOverlayRenderer alloc] initWithTileOverlay:overlay];

    return renderer;

    }

    return nil;

    }

    下面是自定义瓦片地图的代码

    /**

    自定义瓦片图层,继承自MATileOverlay

    */

    @interface PPGTileOverlay : MATileOverlay

    @end

    @implementation PPGTileOverlay

    - (NSURL *)URLForTilePath:(MATileOverlayPath)path {

    #warning 自行替换ip和端口号

    NSString *urlStr = [NSString stringWithFormat:@"http://ip:port/mapImg/tiles/%ld/%ld_%ld.png", (long)path.z, (long)path.x, (long)path.y];

    return [NSURL URLWithString:urlStr];

    }

    // 使用template和上面的方法会丢掉端口号,所以自己去请求,然后回调结果

    - (void)loadTileAtPath:(MATileOverlayPath)path result:(void (^)(NSData *, NSError *))result {

    NSURL *url = [self URLForTilePath:path];

    // 使用SDWebImage管理本地瓦片

    SDImageCache *cache = [SDImageCache sharedImageCache];

    UIImage *image = [cache imageFromCacheForKey:[url absoluteString]];

    if (image) {

    result(UIImagePNGRepresentation(image), nil);

    } else {

    // 在3D地图中如果瓦片请求失败,会一直重复去请求,这里用set存储已请求的瓦片,不做重复请求

    static NSMutableSet *urlSet;

    if (urlSet == nil) {

    urlSet = [NSMutableSet new];

    }

    if ([urlSet containsObject:url]) {

    return;

    }

    [[SDWebImageDownloader sharedDownloader] downloadImageWithURL:url options:SDWebImageDownloaderHighPriority progress:nil completed:^(UIImage * _Nullable image, NSData * _Nullable data, NSError * _Nullable error, BOOL finished) {

    if (finished && data) {

    [cache storeImageDataToDisk:data forKey:[url absoluteString]];

    }

    result(data, error);

    [urlSet addObject:url];

    }];

    }

    }

    @end

    到这里瓦片地图就添加上去了,这里还有一个delegate的问题,因为我们初始化的时候设置delegate为自己了,瓦片地图才能正常显示,如果这是在使用的时候delegate设置为另外一个对象,而他没实现上面的renderer 方法,那么我们的瓦片地图又不能显示了,所以这里使用了外部delegate方法。

    在自定义MapView中添加一个Extension,添加私有属性extDelegate

    @interface PPGMapView () /**

    外部的代理

    */

    @property (nonatomic, weak) idextDelegate;

    @end

    重写setDelegate方法和respondsToSelector方法

    // 保存本地delegate,记录外部delegate

    - (void)setDelegate:(id)delegate {

    if (delegate == self) {

    [super setDelegate:delegate];

    } else {

    self.extDelegate = delegate;

    }

    }

    - (BOOL)respondsToSelector:(SEL)aSelector {

    BOOL responds = [super respondsToSelector:aSelector];

    if (responds) {

    return responds;

    } else {

    return [self.extDelegate respondsToSelector:aSelector];

    }

    }

    runtime转发方法到外部delegate

    // runtime消息转发

    - (id)forwardingTargetForSelector:(SEL)aSelector {

    if ([self.extDelegate respondsToSelector:aSelector]) {

    return self.extDelegate;

    }

    return nil;

    }

    代码仓库地址:

    https://github.com/gaopeng-hz/TileOverlay

    展开全文
  • 地图瓦片是包含了一系列比例尺、一定地图范围内的地图切片文件。地图瓦片按照金字塔结构组织,每张瓦片都可通过级别、行列号唯一标记。在平移、缩放地图时,浏览器根据金字塔规则,计算出所需的瓦片,从瓦片服务器...

    什么是地图瓦片?

    地图瓦片是包含了一系列比例尺、一定地图范围内的地图切片文件。地图瓦片按照金字塔结构组织,每张瓦片都可通过级别、行列号唯一标记。在平移、缩放地图时,浏览器根据金字塔规则,计算出所需的瓦片,从瓦片服务器获取并拼接。地图瓦片,是一种改善地图浏览用户体验的优化策略。

    随着测绘技术的发展,地图数据的体量越来越大,一般情况下,电子地图生成地图瓦片(以下简称切图)少则需要几天,多则一个月乃至更长时间。如何才能高效地生成地图瓦片,是众多技术人员共同关心的问题。

    瓦片地图和缩放级别

    一幅精确到街道级别的世界地图图片宽度为数以百万计的像素,由于这些数据太大了,从而导致无法一次下载并且在内存里也无法一次都hold住。实际上,Web地图由许多小的正方形的图片组成,这些小图片称作瓦片。瓦片的大小一般为256*256像素,这些瓦片一个挨一个并列放置以组成一张很大的看似无缝的地图。

    如果我们想看到更多的地图细节,如想了解国家轮廓级别的地图与街道级别地图的不同,可以使用不同的缩放级别达到目的。缩放级别越高,显示地图的物理尺寸和细节表现也会相应增加。

    为了组织如此多的地图瓦片,Web地图使用了一个简单的坐标系统。每一个瓦片都有一个z坐标来表示其缩放级别,还有一个x坐标和一个y坐标用来表示该瓦片在当前缩放级别下的网格内的位置,如:z/x/y。

    第一张瓦片在Web地图系统中的坐标为0/0/0,此时缩放级别为0,只有一张瓦片并覆盖了整个世界的范围。

    https://img-blog.csdn.net/20150304111708852?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvYWhlbmNl/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center

    当缩放级别为1时,把缩放级别为0时的那张瓦片分割成四个相等的方块,其中坐标为1/0/0和1/1/0的两块覆盖北半球,坐标为1/0/1和1/1/1的两块覆盖南半球。

    https://img-blog.csdn.net/20150304111711454?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvYWhlbmNl/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center

    每一个缩放级别包含的瓦片数量为4的n次方,其中n为缩放级别。如:

    缩放级别0包含1张瓦片;

    缩放级别1包含4张瓦片;

    缩放级别2包含16张瓦片;

    依此类推。

    由于瓦片数量是随缩放级别按指数增长的,因此每提高一个缩放级别会增加大量的地图细节,同时为了应付越来越多的瓦片,对带宽和存储空间的需求也会相应增加。

    例如,一张缩放级别为15的地图,精确到可以看到城市建筑,大约需要11亿张瓦片才能覆盖整个世界,而缩放级别为17时,仅仅是增加了两个缩放级别,同样覆盖全世界却需要170亿张瓦片。

    为什么要使用瓦片?

    简单来说,因为瓦片地图可以很好的工作,所以Web地图使用瓦片。

    1.瓦片地图缓存非常高效。如果你曾查看中央公园的地图而下载过曼哈顿的瓦片,当你需要显示泽西城的地图时,你的浏览器可以使用之前缓存的相同的瓦片,而不是重新再下载一次。

    2.瓦片地图可以渐进加载。中央公园的瓦片会在曼哈顿地图边缘加载之前加载,你可以移动或缩放地图到某一个特定点,即使当前地图的边缘部分还没有加载完成。

    3.瓦片地图简单易用。描述地图瓦片的坐标系统很简单,使得很容易在服务器、网络、桌面或移动设备上实现技术集成。

    地图客户端与瓦片

    让我们来展示一下中央公园的地图。因为地图瓦片是在网络上的图片,你需要把如下HTML代码嵌入到你的网页中。

    <img src='https://a.tiles.mapbox.com/v4/examples.map-i86l3621/0/0/0.png?access_token=pk.eyJ1IjoidHJpc3RlbiIsImEiOiJuZ2E5MG5BIn0.39lpfFC5Nxyqck1qbTNquQ' />

    你将会在浏览器中看到坐标为0/0/0的瓦片。

    https://img-blog.csdn.net/20150304111812353?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvYWhlbmNl/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center

    你需要进行许多缩放才能定位到中央公园。通过一些HTML、CSS和JavaScript代码,你可以按如下步骤显示中央公园的地图:

    1. 首先确定能够覆盖曼哈顿且能够详细显示中央公园的瓦片的z/x/y坐标。
    2. 在网页中添加一系列<img>标签并使用CSS以便在网格中将它们定位到合适的位置。
    3. 为地图添加缩放按钮及拖拽平移等事件的响应处理,然后再次开始这些处理过程。

    幸运的是,你已不需要再做上面这些,这是地图客户端做的事情。地图客户端通常是一个JavaScript库,这个库可以帮你找到需要显示的瓦片,帮助你从地图服务器下载并将它们显示到地图的合适位置。MapBox JavaScript API就是一种地图客户端,当然你还可以使用其他的地图客户端。

    地图客户端需要知道你要显示的中心位置以及缩放级别,你可以输入一个位置的坐标然后MapBox.js就能找到你需要的瓦片。

    中央公园的经纬度为40.783和-73.966,且查看该公园的最佳缩放级别为13。我们可以使用setView([40.783, -73.966], 13)方法告诉MapBox.js将中央公园的位置在地图上居中并缩放到13的级别。显示效果如下图:

    https://img-blog.csdn.net/20150304111842740?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvYWhlbmNl/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center

    谷歌瓦片像素点与经纬度的对应关系

    当分析谷歌瓦片的时候会发现,在高纬度区域单位像素表示的经度跨度大,低纬度的跨度小,这是因为谷歌地图采用了非线性拉伸方法。具体原因还未深究,或许是因为低纬度需要表现更好的细节吧,先上一些代码:

    经度到像素X值

    double lngToPixel(double lng, int zoom) {
    
    return (lng + 180) * (256 << zoom) / 360;
    
    }

    像素X到经度

    double pixelToLng(double pixelX, int zoom) {
    
    return pixelX * 360 / (256 << zoom) - 180;
    
    }

    纬度到像素Y

    double latToPixel(double lat, int zoom) {
    
    double siny = sin(lat * PI / 180);
    
    double y = log((1 + siny) / (1 - siny));
    
    return (128 << zoom) * (1 - y / (2 * PI));
    
    }

    像素Y到纬度

    #define E 2.7128  // 当然还可以更精确
    
    double pixelToLat(double pixelY, int zoom) {
    
    double y = 2 * PI * (1 - pixelY / (128 << zoom));
    
    double z = power(E, y);
    
    double siny = (z - 1) / (z + 1);
    
    return asin(siny) * 180 / PI;
    
    }

    从以上代码可以看出:(像素横向坐标从左至右,纵向从上至下)

    1)在同一层(zoom),单位像素表现的经度跨度是相同的;

    2)在同一层(zoom),单位像素表现的纬度跨度是不相同的;

    3)维度范围为-85~+85,;

    这样由瓦片的(x,y,z)和像素上的位置,就可以计算出任一点的经纬度了,反过来可以通过经纬度计算瓦片索引和像素位置了。

    同样也可用于计算图片的距离分辨率。当然,从以上代码和分析也可以看出,即使是同一张瓦片,图中不同区域的距离分辨率也是不同的。

     

    OpenLayers是干什么的?

    要想在浏览器中显示交互式的地图很难,因为浏览器默认的只是显示静态的图片,如PNG、JPEG等格式,要交互式很难,因为每一个点击和缩放,地图都要做出正确的反应。

    OpenLayers是一个JavaScript 类库包,主要是用于开发Web GIS客户端。这就是说,要先在网页中引用OpenLayers的JavaScript文件以及相应的css样式表和资源,根据其提供的功能接口,直接调用。所以关键是了解其提供的接口,这是使用一个类库的关键!如果想要优化相应的功能或者定制化,就要深入地了解其实现细节了,这需要有熟练的JavaScript功底。

    OpenLayers支持Google Maps、Yahoo Map、微软Virtual Earth等资源,可以通过WMS服务调用其它服务器上的空间数据,通过WFS服务调用空间服务。在操作方面,OpenLayers 除了可以在浏览器中实现地图浏览的基本效果,如放大、缩小、平移等操作,进行选取面、选取线、要素选择、图层叠加等操作。

    展开全文
  • 求助:百度地图瓦片

    2019-10-01 16:20:25
    现在还有大神研究百度地图瓦片么,为什么我通过访问百度地图的网站,然后用调试模式已经看不到对瓦片的request请求了,百度不给提供了么? 哪位大神给解答一下? ...
  • 地图瓦片是包含了一系列比例尺、一定地图范围内的地图切片文件。地图瓦片按照金字塔结构组织,每张瓦片都可通过级别、行列号唯一标记。在平移、缩放地图时,浏览器根据金字塔规则,计算出所需的瓦片,从瓦片服务器...
  • 上一篇文章写到了什么是瓦片,这一篇记录一下如果制作地图瓦片 1. 地图瓦片制作 打开太乐地图下载器,左上角选择地图切换 > 高德地图 > 高德街道地图 然后点击右侧选择行政区划下载,选择上海 选好之后就能...
  • SuperMap系列——GIS数据之地图瓦片

    千次阅读 2019-10-28 16:42:20
    作者:xinxin 一、 前言     在古代,地图主要用军事和水利勘测,随着科技的发展,现如今地图已应用于各行各业,融入到百姓的生活当中。目前,地图包含的内容越来越...地图瓦片是包含了一系列比例尺、一...
  • 瓦片地图面面观

    2019-07-19 21:22:52
    前言 当前互联网地图迅猛发展,...瓦片地图到底是什么? 本博客将陆续放出《瓦片地图面面观》系列文章试图揭开瓦片地图的神秘面纱。 什么是瓦片地图 所谓的瓦片地图实际上就是指整个地图各个缩放级别均是由一...
  • 瓦片地图到底是什么?本博客将陆续放出《瓦片地图面面观》系列文章试图揭开瓦片地图的神秘面纱。什么是瓦片地图所谓的瓦片地图实际上就是指整个地图各个缩放级别均是由一张张瓦片(通常为256*2...
  • 瓦片地图到底是什么?本博客将陆续放出《瓦片地图面面观》系列文章试图揭开瓦片地图的神秘面纱。什么是瓦片地图所谓的瓦片地图实际上就是指整个地图各个缩放级别均是由一张张瓦片(通常为256*2...
  • 瓦片大小128   url: 'http://mt{0-3}.google.cn/maps/vt/pb=!1m4!1m3!1i{z}!2i{x}!3i{y}!2m3!1e0!2sm!3i376063156!3m8!2szh-CN!3scn!5e1105!12m4!1e68!2m2!1sset!2sRoadmap!4e0!5m1!1e0',   瓦片大小256 ...
  • leaflet加载离线瓦片地图

    千次阅读 热门讨论 2019-02-18 14:08:54
    其实瓦片地图并不是什么特殊的文件,就是最普通的png图片。之所以为地图,就是带有了地理坐标。 打开network,查看其请求的的url就能明白其请求的原理了。 主要在于最后三位,含义依次是14级的13528行,6250列。...
  • 第二章节里介绍了什么是瓦片行列号以及计算它的原因,第三章节里介绍了如何通过地理范围计算出这个范围内瓦片的行列号,第四和第五章节里介绍了在得到瓦片行列号后如何获得离线和在线地图的URL,这个章节里,我们将...
  • 上一篇也说到瓦片,我们为什么使用瓦片?这一篇主要关于如何拼接地图?  下面的一张图,可以一眼明了,地图是如何切割以及拼接的。 瓦片信息  瓦片信息包括切图原点,瓦片...
  • 但是问题,只要你细心研究过,你就会发现,cesium 加载瓦片地图,居然用 ajax 请求的方式来加载贴图的。 这种加载方式的优劣我们姑且不论,cesium 选择这种方式必然会有其意义所在。 但是问题,为什么翻遍 ...
  • 第二章节里介绍了什么是瓦片行列号以及计算它的原因,第三章节里介绍了如何通过地理范围计算出这个范围内瓦片的行列号,第四和第五章节里介绍了在得到瓦片行列号后如何获得离线和在线地图的URL,这个章节里,我们
  • 第二章节里介绍了什么是瓦片行列号以及计算它的原因,第三章节里介绍了如何通过地理范围计算出这个范围内瓦片的行列号,第四和第五章节里介绍了在得到瓦片行列号后如何获得离线和在线地图的URL,...
  • 请问这是什么问题呢?瓦片地图地址用的是http://mt{random}.google.cn/vt/lyrs=m@167000000&hl=zh-CN&gl=cn&x=j&y=b&z=k&s=Galil,random是谷歌服务器为1,2,3,4,通过j b k三个变量来获取瓦片。是基于supermap ...
  • 一、首先说一下为什么要用arcgis瓦片,一方面甲方爸爸会提供一批测绘瓦片地图,效果非常好;另一方面可以通过水经注等地图下载器下载各类地图,下载后的地图可以导出为各种格式,本文以mbtiles和arcgis瓦片对比...
  • 地理计算语言,为大众赋能地理智慧。——DAS Team爬取分析DAS系统下载地址:...目前的DAS系统支持ArcGIS 10.2-10.8、Word 2010以上的所有版本。什么是瓦片地图在使用地图时,有时我们需要看宏观的地图信息...
  • 从底层谈WebGIS 原理设计与实现(六):WebGIS中地图瓦片在Canvas上的拼接显示原理 作者:naaoveGI…文章来源:naaoveGIS点击数:1145更新时间:2014-9-14 摘要:在之前的五个章节中,我们在第一章节里介绍了...
  • # // 计算当前层级下瓦片总数的一半,用于定位整个地图的中心点 # var halfTileNum = Math.pow(2, z-1); # // 原点移到中心点后,计算xy方向上新的坐标位置 # var baiduX = x - halfTileNum; # var baiduY = y +...
  • Android平台上,瓦片地图的引入失败

    千次阅读 2016-07-01 22:55:53
    版本:cocos2d-x 3.10 语言:C++ 平台:Android   这一个困扰我很久的问题,一开始...在代码中添加相应的输出代码,定位到了瓦片地图的加载上,但没有什么提示信息,唯一几个提示信息Assert null,如下图:
  • 首先看openlayers官网中wmts模块,...这个需要地图需要参数,controlId封装所需要的,而这个layerName对应得就是openlayer的layer字段,url就是ope...
  • 离线地图_openstreetmap_postgresql_瓦片 离线地图_openstreetmap_postgresql_postgis_mapnik_osm2pgsql_osm数据 写于20150414 关于软件地址 事先说明这其实就是我全部放到百度网盘空间里了。 所以万一一不小心我...

空空如也

空空如也

1 2 3 4 5 ... 7
收藏数 125
精华内容 50
关键字:

地图瓦片是什么