openlayers 加载瓦片详解 一

摘要:
在这先说点题外话,本人在研究webgl三维球过程中惊人发现,openlayers的开发人员也在研究webgl并经证实他们也正在研发基于webgl的三维gis开源平台,这可能是首个开源的三维平台,在现在三维大趋势下,看来openlayers前景还是一片大好,闲话少说,静候佳音。在这将分4篇文章来系统的详细的介绍openlayers是怎么来加载本地及服务器瓦片,为了提高开发人员的工作效率采用倒叙,在第一篇先给实用的算法及简单的参数说明,后面介绍原理,彻底的理解其工作原理。

在这先说点题外话,本人在研究webgl三维球过程中惊人发现,openlayers 的开发人员也在研究webgl并经证实他们也正在研发基于

webgl的三维gis开源平台,这可能是首个开源的三维平台,在现在三维大趋势下,看来openlayers 前景还是一片大好,闲话少说,静候佳音。

在这将分4篇文章来系统的详细的介绍openlayers 是怎么来加载本地及服务器瓦片,为了提高开发人员的工作效率 采用倒叙,

在第一篇先给实用的算法及简单的参数说明,后面介绍原理,彻底的理解其工作原理。

第一篇 :加载瓦片的算法类

第二篇 :瓦片制作

第三篇 :瓦片参数确定

第四篇 :openlayers 加载的瓦片投影

第一篇加载瓦片的算法类

1、先给个类图简单的介绍下

openlayers 加载瓦片详解 一第1张

我们在客户端看到的瓦片其实是一个图片列表 也就是上面的grid 类 ,每张图片都是通过http从后来请求过来的图片也就是方法getURL(bound),

每张图片都有自己的url 也就是他的请求地址,而且grid的列表的每个单元格都有边框也就是bound,那要获取每个单元格中正确的图片都是通过bound来计

算而获取到相应的图片,如想要加载自己瓦片就需要重写grid中的getURL(bound)方法,这也就是最下排6个不同类型的瓦片根据自己的瓦片特点及地图服务

的特点编写的类,如果你有自己的瓦片却跟上面的几种都不相同也不相似,那你可以选择重写grid类,如果你的瓦片操作跟下面的6中服务相同或者类似,那

可以根据自己工作考虑重写那面6个类中的其中某一个中的getURL(bound)的方法。在计算的过程中能涉及到多个参数将在下篇来详细介绍,在这给几个重写

getURL(bound)的例子, 第一个例子是网上的不过在工作中验证过,绝对可用,写的还不错给大家个参考。

1、重写grid类中的getURL(bound)方法加载本地图片(天地图)

OpenLayers.Layer.TiandituLayer = OpenLayers.Class(OpenLayers.Layer.Grid,
		{
			TileType : null,
			mirrorUrls : null,
			topLevel : null,
			bottomLevel : null,
			topLevelIndex : 0,
			bottomLevelIndex : 20,
			topTileFromX : -180,
			topTileFromY : 90,
			topTileToX : 180,
			topTileToY : -90,
			isBaseLayer : true,
			initialize : function(name, url, options) {
				options.topLevel = options.topLevel ? options.topLevel
						: this.topLevelIndex;
				options.bottomLevel = options.bottomLevel ? options.bottomLevel
						: this.bottomLevelIndex;
				options.maxResolution = this
						.getResolutionForLevel(options.topLevel);
				options.minResolution = this
						.getResolutionForLevel(options.bottomLevel);
				var newArguments = [ name, url, {}, options ];
				OpenLayers.Layer.Grid.prototype.initialize.apply(this,
						newArguments);
			},
			clone : function(obj) {
				if (obj == null) {
					obj = new OpenLayers.Layer.TDTLayer(this.name, this.url,
							this.options);
				}
				obj = OpenLayers.Layer.Grid.prototype.clone
						.apply(this, [ obj ]);
				return obj;
			},
			getURL : function(bounds) {
				var level = this.getLevelForResolution(this.map.getResolution());
				var coef = 360 / Math.pow(2, level);
				var Row = this.topTileFromX < this.topTileToX ? Math.round((bounds.left - this.topTileFromX) / coef) : Math.round((this.topTileFromX - bounds.right) / coef);
				var Col = this.topTileFromY < this.topTileToY ? Math.round((bounds.bottom - this.topTileFromY) / coef): Math.round((this.topTileFromY - bounds.top) / coef);
				var type = this.TileType;
				if (type == "EMap") {
					if (level >= 2 && level <= 10) {
						type = "A0512_EMap";
					} else if (level == 11 || level == 12) {
						type = "B0627_EMap1112";
					} else if (level >= 13 && level <= 18) {
						type = "siwei0608";
					}
				}else if(type=="RMap"){
				    if (level >= 2 && level <= 7) {
						type = "sbsm0210";
					} else if (level >= 8 && level <= 10) {
						type = "sbsm0210";
					} else if (level >= 11 && level <= 14) {
						type = "e11";
					}else if (level >= 15 && level <= 18) {
						type = "sbsm1518";
					}
				}
				var url = this.url;
				if (this.mirrorUrls != null) {
					url = this.selectUrl(Row, this.mirrorUrls);
				}
				return this.getFullRequestString({
					T : type,
					X : Row,
					Y : Col,
					L : level
				}, url);
			},
			selectUrl : function(a, b) {
				return b[a % b.length]
			},
			getLevelForResolution : function(res) {
				var ratio = this.getMaxResolution() / res;
				if (ratio < 1)
					return 0;
				for ( var level = 0; ratio / 2 >= 1;) {
					level++;
					ratio /= 2;
				}
				return level;
			},
			getResolutionForLevel : function(level) {
				return 360 / 256 / Math.pow(2, level);
			},
			getMaxResolution : function() {
				return this.getResolutionForLevel(this.topLevelIndex)
			},
			getMinResolution : function() {
				return this.getResolutionForLevel(this.bottomLevelIndex)
			},
			addTile : function(bounds, position) {
				var url = this.getURL(bounds);
				return new OpenLayers.Tile.Image(this, position, bounds, url,
						this.tileSize);
			},
			CLASS_NAME : "OpenLayers.Layer.TiandituLayer"
		});

测试页面

<!DOCTYPE html>
<html>
  <head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0">
    <meta name="apple-mobile-web-app-capable" content="yes">
    <title>OpenLayers Tiled Map Service Example</title>
    <link rel="stylesheet" href="http://t.zoukankan.com/theme/default/style.css" type="text/css">
    <link rel="stylesheet" href="http://t.zoukankan.com/style.css" type="text/css">
   <script src="http://t.zoukankan.com/lib/OpenLayers.js"></script>
    <script type="text/javascript">
        var map, layer;
        function init(){
		    var extent = new OpenLayers.Bounds(-180.0, -90.0, 180.0, 90.0);
            var tempScales = [295497593.05875003,147748796.52937502,73874398.264687508,36937199.132343754,18468599.566171877];
		    var mapOptions = {
                maxExtent: extent
            };
			var options= {
			    mapType:"EMap",
                topLevel: 3, 
                bottomLevel: 20
            };
            map = new OpenLayers.Map("map",mapOptions);
			layer = new OpenLayers.Layer.TiandituLayer("qincy", "http://tile0.tianditu.com/DataServer",options);
            map.addLayer(layer);
            map.addControls([new OpenLayers.Control.MousePosition()]);
            map.setCenter(new OpenLayers.LonLat(106,39), 3);
        }
    </script>
  </head>
  <body onload="init()">
    <div   style="1000px;height:500px"></div>
  </body>
</html>

2、重写TileCache类加载本地图片。

/**
 * 对自定义规则切割的图片进行拼装的类
 */
SimpleTileCache=OpenLayers.Class(OpenLayers.Layer.TileCache,{
	initialize:function(name,url,options){
		var tempoptions = OpenLayers.Util.extend(
{'format': 'image/png',isBaseLayer:true},options);			        
		OpenLayers.Layer.TileCache.prototype.initialize.apply(this,[name, url, {}, tempoptions]);
		this.extension = this.format.split('/')[1].toLowerCase();
		this.extension = (this.extension == 'jpg') ? 'jpeg' : this.extension;
		this.transitionEffect="resize";
		this.buffer=2;		
	},
	/**
     *   按地图引擎切图规则实现的拼接方式
	 */
	getURL: function(bounds) {		    
		var res   = this.map.getResolution();			        
		var bbox  = this.map.getMaxExtent();
		var size  = this.tileSize;
		//计算列号		        
		var tileX = Math.round((bounds.left - bbox.left) / (res * size.w));
           //计算行号
		var tileY = Math.round((bbox.top-bounds.top) / (res * size.h));	
		//当前的等级			
		var tileZ = this.map.zoom;				        						        
		if(tileX<0) tileX=tileX+Math.round(bbox.getWidth()/bounds.getWidth());       
		if(tileY<0)  tileY=tileY+Math.round(bbox.getHeight()/bounds.getHeight());			        
		return	this.getTilePic(tileX,tileY,tileZ);
	},
	getTilePic: function(tileX,tileY,tileZ){
		var dir = '';
		if(tileZ > 6) {
			var delta       = Math.pow(2,tileZ-5);	    
			var rowDir   = 'R'+ Math.floor(tileY /delta);
			var colDir   = 'C'+Math.floor(tileX /delta);
			dir      = tileZ  + "/" + rowDir + "/" + colDir + "/";
		} else {
			dir= tileZ + '/';
		}				    
		var tileNo  = tileZ + "-" + tileX + "-" + tileY;
		var sUrl = this.url + dir + tileNo + '.png';
		return sUrl;
	},
	clone: function (obj) { 
		if (obj == null) {
		obj = new SimpleTileCache(this.name,this.url,this.options);
		}
		obj = OpenLayers.Layer.TileCache.prototype.clone.apply(this, [obj]);
		return obj;
	},
	CLASS_NAME: "SimpleTileCache"
});

3、直接修改TileCache类中的getURL方法

修改后 的 TileCache.js

OpenLayers.Layer.TileCache = OpenLayers.Class(OpenLayers.Layer.Grid, {
    isBaseLayer: true,
    format: 'image/png',
    serverResolutions: null,
    initialize: function(name, url, layername, options) {
        this.layername = layername;
        OpenLayers.Layer.Grid.prototype.initialize.apply(this,
                                                         [name, url, {}, options]);
        this.extension = this.format.split('/')[1].toLowerCase();
        this.extension = (this.extension == 'jpg') ? 'jpeg' : this.extension;
    },    
    clone: function (obj) {
        if (obj == null) {
            obj = new OpenLayers.Layer.TileCache(this.name,
                                                 this.url,
                                                 this.layername,
                                                 this.getOptions());
        }
        //get all additions from superclasses
        obj = OpenLayers.Layer.Grid.prototype.clone.apply(this, [obj]);
        // copy/set any non-init, non-simple values here
        return obj;
    },    
	 getURL: function(bounds) {
	    var res = this.map.getResolution();
		var x = Math.round ((bounds.left - this.maxExtent.left) / (res * this.tileSize.w));
		var y = Math.round ((this.maxExtent.top - bounds.top) / (res * this.tileSize.h));
		var z = this.map.getZoom();
		var path =z+9+ "/" + x + "/" + y + "." + this.type;
		var url = this.url;
		if (url instanceof Array) {
			url = this.selectUrl(path, url);
		}
		//我用resin 发布的地图瓦片的位置
		url="http://192.168.0.90:88/roadmap2/"+path;
        return url
    },
    /*getURL: function(bounds) {
        var res = this.getServerResolution();
        var bbox = this.maxExtent;
        var size = this.tileSize;
        var tileX = Math.round((bounds.left - bbox.left) / (res * size.w));
        var tileY = Math.round((bounds.bottom - bbox.bottom) / (res * size.h));
        var tileZ = this.serverResolutions != null ?
            OpenLayers.Util.indexOf(this.serverResolutions, res) :
            this.map.getZoom();
        var components = [
            this.layername,
            OpenLayers.Number.zeroPad(tileZ, 2),
            OpenLayers.Number.zeroPad(parseInt(tileX / 1000000), 3),
            OpenLayers.Number.zeroPad((parseInt(tileX / 1000) % 1000), 3),
            OpenLayers.Number.zeroPad((parseInt(tileX) % 1000), 3),
            OpenLayers.Number.zeroPad(parseInt(tileY / 1000000), 3),
            OpenLayers.Number.zeroPad((parseInt(tileY / 1000) % 1000), 3),
            OpenLayers.Number.zeroPad((parseInt(tileY) % 1000), 3) + '.' + this.extension
        ];
        var path = components.join('/'); 
        var url = this.url;
        if (OpenLayers.Util.isArray(url)) {
            url = this.selectUrl(path, url);
        }
        url = (url.charAt(url.length - 1) == '/') ? url : url + '/'; //url+path
		//alert(url+path);
        return "http://192.168.0.90:88/roadmap/1/0/0.png"
    },*/
    CLASS_NAME: "OpenLayers.Layer.TileCache"
});

测试页面

<!DOCTYPE html>
<html>
  <head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0">
    <meta name="apple-mobile-web-app-capable" content="yes">
    <title>OpenLayers TileCache Example</title>
     <link rel="stylesheet" href="http://t.zoukankan.com/theme/default/style.css" type="text/css">
        <link rel="stylesheet" href="http://t.zoukankan.com/style.css" type="text/css">
        <script src="http://t.zoukankan.com/lib/OpenLayers.js"></script>
        <script src="http://t.zoukankan.com/lib/Firebug/firebug.js"></script>
    <script type="text/javascript">
	//alert("adsf");
	   var proj='EPSG:900913'; //900913
        var map, layer;
		var proj2 = new OpenLayers.Projection("EPSG:4326");
		var agsTileOrigin = new OpenLayers.LonLat(-180,85);
		agsTileOrigin.transform(proj2, new OpenLayers.Projection("EPSG:900913"));
		//alert(agsTileOrigin.);
		var mapExtent = new OpenLayers.Bounds(-20037508.34,-20037508.34,20037508.34,20037508.34);
        function init(){
		//添加编辑图层 图层名称为editLayer
			var EditLayer=new OpenLayers.Layer.Vector("EidtLayer");
	    //添加地图
            map = new OpenLayers.Map( 'map', {
			    numZoomLevels:3,                             //缩放级别
                resolutions:[305.7481,152.8741,76.437],      //分别率  单位是米
				controls:[                        
                        new OpenLayers.Control.EditingToolbar(EditLayer), //添加编辑控件 
						new OpenLayers.Control.Navigation(),
                        new OpenLayers.Control.PanZoomBar(),
                        new OpenLayers.Control.LayerSwitcher({'ascending':false}),
                        new OpenLayers.Control.Permalink(),
                        new OpenLayers.Control.ScaleLine(),
                        new OpenLayers.Control.Permalink('permalink'),
                        new OpenLayers.Control.MousePosition(),
                        new OpenLayers.Control.OverviewMap(),
                        new OpenLayers.Control.KeyboardDefaults()
						]
            });
            layer = new OpenLayers.Layer.TileCache("TileCache Layer",
                "http://c0.tilecache.osgeo.org/wms-c/cache/",
                "basic",
                {
				 serverResolutions:[305.7481,152.8741,76.437],
										projection:proj,
										type:'png'
                }
            );
            map.addLayers([layer, EditLayer]);
			var  lob_ll=new OpenLayers.LonLat(121.34457, 31.329235);
            map.setCenter(lob_ll.transform(proj2, new OpenLayers.Projection("EPSG:900913")), 0);
        }
    </script>
	<style type="text/css">
	html,body{100%;height:100%;margin:0;}
	</style>
  </head>
  <body onload="init()">
    <div       style="100%; height:100%; backround-color:Red;"></div>
  </body>
</html>

免责声明:文章转载自《openlayers 加载瓦片详解 一》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇使用JLink间接烧写S3C2410、S3C2440开发板Nor、Nand Flash的方法 分类: HI3531 arm-linux-Ubuntu 2013-12-07 15:10 697人阅读 评论(0) 收藏qt中文编码(好多方法)下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

(转)Openlayers 2.X加载天地图

http://blog.csdn.net/gisshixisheng/article/details/44621923 概述: 在前面的章节,讲到了Arcgis for js加载天地图,在本节讲述如何在Openlayers 2.X的版本中加载天地图,并添加自己的wms服务。 效果: 地图 影像 地形 去掉本地wms 实现: 1、天地图服务 在天地图...

重写 geturl Openlayers中使用TileCache加载预切割图片作为基础地图图层

Openlayers中使用TileCache加载预切割图片作为基础地图图层 博客分类:OpenLayers prototype算法 Openlayers使用TileCache对象加载预切割的图片。每张图片一张瓦片;其中的getURL(bound)返回的就是我们需要实现的图片地址;所以实现图片地址计算算法在该函数实现;参数bound就是一张图...

(四)WebGIS中通过行列号来换算出多种瓦片的URL 之离线地图

文章版权由作者李晓晖和博客园共有,若转载请于明显处标明出处:http://www.cnblogs.com/naaoveGIS/ 1.前言 在前面我花了两个篇幅来讲解行列号的获取,也解释了为什么要获取行列号。在这一章,我将把常见的几种请求瓦片时的URL样式罗列出来,并且给出大致的解释。 我在这里将地图分为离线地图和在线地图。所谓离线地图,即保存在本地而没有发...

浅谈利用SQLite存储离散瓦片的思路和实现方法

文章版权由作者李晓晖和博客园共有,若转载请于明显处标明出处:http://www.cnblogs.com/naaoveGIS/ 1.背景 在多个项目中涉及到互联网地图的内网显示,通过自制工具完成了互联网地图的瓦片下载。但是此种方法存在如下几个问题: a.瓦片均是离散型图片,远程部署非常耗时。 b.瓦片下载中,涉及到将互联网瓦片下载至内存,然后建立对应文件夹...

Openlayers中使用Overlay实现点击要素弹窗并且弹窗随之移动

场景 Vue+Openlayer使用overlay实现弹窗弹出显示与关闭: https://blog.csdn.net/BADAO_LIUMANG_QIZHI/article/details/121268946 实现弹窗的效果可以参考上面。 要实现的效果是点击某个元素弹窗显示,并且弹窗随着元素的移动而移动。 实现元素移动的效果可以参考如下: Openlay...

Openlayers 实现轨迹播放/暂停/重新播放/从点击处播放/提速/减速

说明: 我的需求是需要实现轨迹播放/暂停/重新播放/从点击处播放,因此封装了一个类 解决方案: 1、初始化:主要是处理一下图层以及数据,通过插值构造一个全局数组 /** * @description 初始化轨迹 */ (function init() { //地图容器 that....