使用openlayers调用本地瓦片数据方案
- 格式:docx
- 大小:90.22 KB
- 文档页数:3
使用openlayers调用本地瓦片数据方案
身边经常有一些朋友在与GIS项目的时候抱怨没有地图数据,而实际上他们在做具体的应用的时候常常仅仅是需要一个地图来使得应用程序变得更漂亮。以前自己也遇到过一些这些问题,在08年公司做兼职的时候,就行开发一个离线的GIS数据包,这些的话,对于一些小型的应用程序就不用花大笔的钱去购买地图数据。
对于以上的问题,大家常常采用的是两种解决方案:一种解决方案就是直接使用一些第三方数据服务,例如Google maps 或者是MapABC的API来实现自己的功能,这种方法开发比较简单,很容易上手,但是一个重要问题就是给一些不能上网的客户来说,这样的开发方式就不适合了;另外一种方式就是让客户购买地图数据去支持应用程序,这样的方式用户需要花一些钱去购买地图数据(我以前在做项目的过程中,由于地图数据量不是很大,所以也可以用一些基础图层,然后再加上一些影像数据进行数字化)。其实上述的两种方式是目前大多数应用程序解决地图数据的主要方法,下面本片文章介绍第三种方式来实现(特在此申明,文章中提出的方法仅仅是提供交流和学习使用,如果使用商业用途用户自行负责)。
如果想从本地访问瓦片数据的话,首先需要解决的问题是从一些公共地图服务中获取瓦片数据。在这里将使用工具/?page_id=66下载地图的瓦片数据。瓦片数据下载到本地之后,可以看到瓦片的数据命名
“m_14_13519_6253.png”,其中m后面的14代表的目前的缩放级别,“13519”代表的是瓦片数据的横坐标,“6253”代表的是瓦片数据的纵坐标。对于Google maps用的是墨卡托投影方式,将地图投影成了一个40075016.685578488 m的正方形坐标的形式,然后根据缩放级别将这个正方形分割成不不同粒度的小正方形,这种分割的形式采用的是四叉树索引的方式进行。具体的分割如下图所示。
首先在level 0级别的时候,就是将这个正方形划分为一个256 像素的图片,如果化成米的形式的话,就是40075016.685578488的正方形,从这里可以计算出比例为:40075016.685578488/256 = 156543.033928041 (米/像素)。对于level 1级别时,然后再将这个正方形划分为一个4个256像素的正方形,此时计算出的比例为:40075016.685578488/512 = 78271.51696402 (米/像素)。
对于OpenLayers来说,首先会向wms服务发送一个请求,这个请求会有一个bbox 参数,参数的形式是这个box的左上角坐标和右下角坐标的值,对于后来服务来说,就是将这个box的图片发送到前台去显示。对于要使用本地的瓦片数据,根据上面对于瓦片数据的命名方式我们可以知道需要求三个参数:缩放级别zoom、横坐标 x和纵坐标的值 y。而对于请求来说,只有bbox的值,所以需要根据根据bbox的值来求出x,y和缩放级别的值zoom。首先从前台来说,展现的总图片应该是一个360°×360°的正方形的图片,这是对于缩放级别为一级的来说的;对于一个bbox中的经纬度,可以计算出缩放级别:
Java代码:
double mapUnit = 360/(x1-x0);//156543.033929687
double z = Math.log(mapUnit)/Math.log(2);
long zoom = Math.round(z);
计算出缩放级别之后,然后根据公式x = ((20037508.343 * 2 * ( x0 + 180 ) / 360 ) / pixelResolution)/256可以计算出x的坐标,同理根据公式y = ((20037508.343 * 2 * ( y0 + 90 ) / 360 ) / pixelResolution)/256可以计算出y的坐标,根据计算结果,可以直接访问到这个缩放级别的的256×256的图片,然后用 openlayer将图片展现到前天的界面中来。关于JavaScript代码如下:
JavaScript Code :
function init(){
map = new OpenLayers.Map(“map”,{numZoomLevels :
5,minScale:216281.173********,restrictedExtent: extent
});
map.maxExtent = new OpenLayers.Bounds(-180, -90, 180, 270);
var ol_wms = new yer.WMS(
“basic map”,
“test”,
{layers: “basic”,format: “image/png”},{transitionEffect:
‘resize’}
);
map.addLayers([ol_wms]);
selectControl = new OpenLayers.Control.SelectFeature(layer);
map.addControl(selectControl);
selectControl.activate();
map.addControl(new yerSwitcher());
map.zoomToMaxExtent();
}
如上述代码所属,在前台添加一个wsm的图层,他会想后台发送一个请求,这个请求参数是一个bbox,然后根据请求过来的参数进行分析,计算出需要返回给前台的图片的名称。
上述过程能够完成一个地图底图的应用,方式仅供学习使用,如果需要将显示相关信息的话,可以将点信息存数到数据库中或者是文本文件中,然后在使用openlayer的vector图层添加上去
var layer = new yer.Vector(“POIs”, {
strategies: [new OpenLayers.Strategy.BBOX({resFactor: 1.1})], protocol: new OpenLayers.Protocol.HTTP({
url: “TextLayer”,
format: new OpenLayers.Format.Text()
})
});
如果是wgs1984的坐标体系的话,需要将坐标进行简单的转换,对于经度来说,和之前的一样,而对于纬度来说,首先换算成莫非托投影形式,然后将换成[-180,90,180,270]的坐标形式,转换算法如下:
x = Math.Log(Math.Tan((90 + latitude) * Math.PI / 360)) / (Math.PI / 180) * 20037508.343 / 180
x= x+ 20037508.343) * 360 / (20037508.343 * 2) – 90
最后这些都会添加到地图上,形式一个与业务相关的地图信息系统。总的上来说这样的实现方式可以满足一些只需要底图数据的系统,但是对于一些需要原始数据的应用系统来说,无法满足,因为无法获取底图的数据信息。