`
jie66989
  • 浏览: 254753 次
  • 性别: Icon_minigender_1
  • 来自: 西安
社区版块
存档分类
最新评论

让OpenLayers添加百度地图(未完版)

阅读更多
来自:http://www.cnblogs.com/laoyu/archive/2012/06/10/2544379.html


让OpenLayers添加百度地图(未完版)

     KoalaGIS的在线地图系统,打算采用国内外主要的几个地图服务:google地图、百度地图、OpenStreet Map、天地图。google、百度、openstreet的服务器性能好,速度快,但google由于政策原因,不确定因素太多,Openstreet Map个人感觉配图不怎么好看,添加天地图完全就是为了顾忌下咱们这个GIS专业的脸面,毕竟总要搞点专业的东西吧,虽然他很垃圾,但胜于无!

     为此,需要在OpenLayers上扩展一个百度地图图层出来,让其能在Openlayers中显示出来。为了叠加百度地图,首先必须了解其瓦片的组织规则,通过对百度api的js文件解析和网上相关资料的收集,经过程序测试,推论正确,现讲解下其基本的参数,以及编写的KoalaGIS.Layer.WMTS.Baidu图层。

     百度地图也是采用的魔卡托投影,个人感觉和google的web 墨卡托投影是一样的,但据网友测试,两者计算结果有点出入,我猜测可能是百度或者google地图有偏移参数的影响吧,该文暂不分析此原因,且该问题本人还没正式测试过,有待考证!

利用百度提供的API进行坐标转换

var projection =new BMap.MercatorProjection();
var point = projection.lngLatToPoint(new BMap.Point(116.404, 39.915));
得出的结果是12958175,4825923.77

用Openlayers提供的web墨卡托投影对该经纬度投影得出的结果为:????

百度地图的分辨率问题

对百度地图api的js脚本进行解析,可以看到该函数:

可以看到两个获取分辨率相关的函数如下:
getZoomUnits: function(T) {
     return Math.pow(2, (18 - T))    //从这里可以看出,百度地图的分辨率几乎就是固定的2的N次幂来计算的
},
详细请见该文《百度地图的瓦片参数解析》http://blog.sina.com.cn/s/blog_4c8b1bdd0100xij4.html



百度地图的坐标系统:平面坐标系的原点与经纬度的原点一致,即赤道与0度经线相交的位置





百度地图瓦片编号方式:

百度地图API在展示地图时是将整个地图图片切割成若干图块来显示的,当地图初始化或是地图级别、中心点位置发生变化时,地图API会根据当前像素坐标计算出视野内需要的图块坐标(也叫图块编号),从而加载对应的图块用以显示地图。

百度地图的图块坐标原点与平面坐标一致,从原点向右上方开始编号为0, 0:



如何通过一个坐标和缩放级别计算出百度瓦片所在的行列号呢?

百度瓦片的计算方式很简单,大致如下:

1.计算出坐标的平面坐标位置,瓦片的切割起止点就是0,0

2. 用平面坐标除以分辨率就能得到坐标到起点的像素大小,然后除以每张瓦片的大小取整就是瓦片的行列号了

   cx = [( ( x - 0 ) / res ) / tileWidth]

 cy = [( ( y - 0 ) / res ) / tileHeight]

   分辨率前面已经讲过,res = Math.Pow(2, level - 18 );

3.举例来说吧,第18级下,选取经纬度为(116.404, 39.915)的坐标点,该点大致在北京天,安,门那,经过投影得出其平面位置为(12958175, 4825923.77)采用百度的api计算出来的,用openlayers计算的不是该坐标。利用上面的行列号计算公式推算出瓦片行列号为:50617, 18851。利用百度地图提供的瓦片服务器地址,根据行列号和缩放级别,可以调用该瓦片地址:





OpenLayers中添加百度地图

遇到的问题:

1,坐标系不一致。

Openlayers中采用的坐标系并非百度地图的数学坐标系

2,行列号的计算方式不一样

百度地图是从左到右,从下到上;但Openlayers和google以及通常的wmts服务都是从左到右,从上到下的!



解决办法:坐标系还是按照Openlayers的思路,所有的方式都不动,只是把他计算瓦片的方式改变就OK了。



KoalaGIS.Layer.WMTS.Baidu.js文件

代码如下:

(function () {
window.KoalaGIS = {
VERSION: '1.0.0',
Author: 'KolaGIS Studio'
};

KoalaGIS.Layer = {};

KoalaGIS.Layer.WMTS = {};

})();


KoalaGIS.Layer.WMTS.Baidu = OpenLayers.Class(OpenLayers.Layer.XYZ, {

url: null,

tileOrigin: new OpenLayers.LonLat(-20037508.34, 20037508.34),

tileSize: new OpenLayers.Size(256, 256),

type: 'png',



useScales: false,

overrideDPI: false,

initialize: function (options) {
this.resolutions = [];
for (var i = 0; i < 19; i++) {
this.resolutions[i] = Math.pow(2, 18 - i);
}

OpenLayers.Layer.XYZ.prototype.initialize.apply(this, arguments);

if (this.resolutions) {
this.serverResolutions = this.resolutions;
this.maxExtent = this.getMaxExtentForResolution(this.resolutions[0]);
}

// this block steps through translating the values from the server layer JSON
// capabilities object into values that we can use. This is also a helpful
// reference when configuring this layer directly.
if (this.layerInfo) {
// alias the object
var info = this.layerInfo;

// build our extents
var startingTileExtent = new OpenLayers.Bounds(
info.fullExtent.xmin,
info.fullExtent.ymin,
info.fullExtent.xmax,
info.fullExtent.ymax
);

// set our projection based on the given spatial reference.
// esri uses slightly different IDs, so this may not be comprehensive
this.projection = 'EPSG:' + info.spatialReference.wkid;
this.sphericalMercator = (info.spatialReference.wkid == 102100);

// convert esri units into openlayers units (basic feet or meters only)
this.units = (info.units == "esriFeet") ? 'ft' : 'm';

// optional extended section based on whether or not the server returned
// specific tile information
if (!!info.tileInfo) {
// either set the tiles based on rows/columns, or specific width/height
this.tileSize = new OpenLayers.Size(
info.tileInfo.width || info.tileInfo.cols,
info.tileInfo.height || info.tileInfo.rows
);

// this must be set when manually configuring this layer
this.tileOrigin = new OpenLayers.LonLat(
info.tileInfo.origin.x,
info.tileInfo.origin.y
);

var upperLeft = new OpenLayers.Geometry.Point(
startingTileExtent.left,
startingTileExtent.top
);

var bottomRight = new OpenLayers.Geometry.Point(
startingTileExtent.right,
startingTileExtent.bottom
);

if (this.useScales) {
this.scales = [];
} else {
this.resolutions = [];
}

this.lods = [];
for (var key in info.tileInfo.lods) {
if (info.tileInfo.lods.hasOwnProperty(key)) {
var lod = info.tileInfo.lods[key];
if (this.useScales) {
this.scales.push(lod.scale);
} else {
this.resolutions.push(lod.resolution);
}

var start = this.getContainingTileCoords(upperLeft, lod.resolution);
lod.startTileCol = start.x;
lod.startTileRow = start.y;

var end = this.getContainingTileCoords(bottomRight, lod.resolution);
lod.endTileCol = end.x;
lod.endTileRow = end.y;
this.lods.push(lod);
}
}

this.maxExtent = this.calculateMaxExtentWithLOD(this.lods[0]);
this.serverResolutions = this.resolutions;
if (this.overrideDPI && info.tileInfo.dpi) {
// see comment above for 'overrideDPI'
OpenLayers.DOTS_PER_INCH = info.tileInfo.dpi;
}
}
}
},


getContainingTileCoords: function (point, res) {
// return new OpenLayers.Pixel(
// Math.max(Math.floor((point.x - this.tileOrigin.lon) / (this.tileSize.w * res)), 0),
// Math.max(Math.floor((this.tileOrigin.lat - point.y) / (this.tileSize.h * res)), 0)
// );

return new OpenLayers.Pixel(
Math.floor((point.x - this.tileOrigin.lon) / (this.tileSize.w * res)),
Math.floor((point.y - this.tileOrigin.lat) / (this.tileSize.h * res))
);
},

calculateMaxExtentWithLOD: function (lod) {
// the max extent we're provided with just overlaps some tiles
// our real extent is the bounds of all the tiles we touch

var numTileCols = (lod.endTileCol - lod.startTileCol) + 1;
var numTileRows = (lod.endTileRow - lod.startTileRow) + 1;

var minX = this.tileOrigin.lon + (lod.startTileCol * this.tileSize.w * lod.resolution);
var maxX = minX + (numTileCols * this.tileSize.w * lod.resolution);

var maxY = this.tileOrigin.lat - (lod.startTileRow * this.tileSize.h * lod.resolution);
var minY = maxY - (numTileRows * this.tileSize.h * lod.resolution);
return new OpenLayers.Bounds(minX, minY, maxX, maxY);
},

calculateMaxExtentWithExtent: function (extent, res) {
var upperLeft = new OpenLayers.Geometry.Point(extent.left, extent.top);
var bottomRight = new OpenLayers.Geometry.Point(extent.right, extent.bottom);
var start = this.getContainingTileCoords(upperLeft, res);
var end = this.getContainingTileCoords(bottomRight, res);
var lod = {
resolution: res,
startTileCol: start.x,
startTileRow: start.y,
endTileCol: end.x,
endTileRow: end.y
};
return this.calculateMaxExtentWithLOD(lod);
},


getUpperLeftTileCoord: function (res) {
var upperLeft = new OpenLayers.Geometry.Point(
this.maxExtent.left,
this.maxExtent.top);
return this.getContainingTileCoords(upperLeft, res);
},

getLowerRightTileCoord: function (res) {
var bottomRight = new OpenLayers.Geometry.Point(
this.maxExtent.right,
this.maxExtent.bottom);
return this.getContainingTileCoords(bottomRight, res);
},

getMaxExtentForResolution: function (res) {
var start = this.getUpperLeftTileCoord(res);
var end = this.getLowerRightTileCoord(res);

var numTileCols = (end.x - start.x) + 1;

//var numTileRows = (end.y - start.y) + 1;

var numTileRows = (start.y - end.y) + 1;

var minX = this.tileOrigin.lon + (start.x * this.tileSize.w * res);
var maxX = minX + (numTileCols * this.tileSize.w * res);

//var maxY = this.tileOrigin.lat - (start.y * this.tileSize.h * res);
var maxY = this.tileOrigin.lat + (start.y * this.tileSize.h * res);
var minY = maxY - (numTileRows * this.tileSize.h * res);
return new OpenLayers.Bounds(minX, minY, maxX, maxY);
},

clone: function (obj) {
if (obj == null) {
obj = new OpenLayers.Layer.ArcGISCache(this.name, this.url, this.options);
}
return OpenLayers.Layer.XYZ.prototype.clone.apply(this, [obj]);
},

getMaxExtent: function () {
var resolution = this.map.getResolution();
return this.maxExtent = this.getMaxExtentForResolution(resolution);
},

getTileOrigin: function () {
//debugger;
var extent = this.getMaxExtent();
return new OpenLayers.LonLat(extent.left, extent.bottom);
},


getURL: function (bounds) {
//debugger;

var z = this.map.getZoom();


var res = this.getResolution();

// z = 18 - z;

// var res = Math.pow(2, z - 18);

// tile center
var originTileX = (this.tileOrigin.lon + (res * this.tileSize.w / 2));
// var originTileY = (this.tileOrigin.lat - (res * this.tileSize.h / 2));

var originTileY = (this.tileOrigin.lat + (res * this.tileSize.h / 2));

originTileX = 0;
originTileY = 0;

var center = bounds.getCenterLonLat();
//center.lat = 4825923.77;
//center.lon = 12958175;
var point = { x: center.lon, y: center.lat };


// var x = (Math.round(Math.abs((center.lon - originTileX) / (res * this.tileSize.w))));
// //var y = (Math.round(Math.abs((originTileY - center.lat) / (res * this.tileSize.h))));
// var y = (Math.round(Math.abs((center.lat - originTileY) / (res * this.tileSize.h))));

var x = (Math.round((center.lon - originTileX) / (res * this.tileSize.w)));
//var y = (Math.round(Math.abs((originTileY - center.lat) / (res * this.tileSize.h))));
var y = (Math.round((center.lat - originTileY) / (res * this.tileSize.h)));

// x = Math.round(center.lon * 1 / this.tileSize.w);
// y = Math.round(center.lat * 1 / this.tileSize.h);

//var x = Math.floor(Math.abs((center.lon) * res / this.tileSize.w));
//var y = (Math.round(Math.abs((originTileY - center.lat) / (res * this.tileSize.h))));
//var y = Math.floor(Math.abs((center.lat ) * res / this.tileSize.h));

//x = Math.round(Math.abs(x) / 256 );
// y = Math.round(Math.abs(y) / 256 );



// this prevents us from getting pink tiles (non-existant tiles)
if (this.lods) {
var lod = this.lods[this.map.getZoom()];
if ((x < lod.startTileCol || x > lod.endTileCol)
|| (y < lod.startTileRow || y > lod.endTileRow)) {
return null;
}
}
else {
var start = this.getUpperLeftTileCoord(res);
var end = this.getLowerRightTileCoord(res);
// if ((x < start.x || x >= end.x)
// || (y < start.y || y >= end.y)) {
// return null;
// }

if ((x < start.x || x >= end.x)
|| (y >= start.y || y < end.y)) {
//return null;
}
}

// Construct the url string
var url = this.url;
var s = '' + x + y + z;

if (OpenLayers.Util.isArray(url)) {
url = this.selectUrl(s, url);
}

// Accessing tiles through ArcGIS Server uses a different path
// structure than direct access via the folder structure.
if (this.useArcGISServer) {
// AGS MapServers have pretty url access to tiles
url = url + '/tile/z/{y}/{x}'; } else { // The tile images are stored using hex values on disk. //x = 'C' + this.zeroPad(x, 8, 16); // y = 'R' + this.zeroPad(y, 8, 16); // z = 'L' + this.zeroPad(z, 2, 16); // url = url + '/{z}/y/{x}.' + this.type;

var x_str = 'x′;varystr=′{y}';
if (x < 0)
x_str = 'Mx′;if(y<0)ystr=′M{y}';
url = url + '/u=x=' + x_str + ';y=' + y_str + ';z=${z};v=011;type=web&fm=44';
}

// Write the values into our formatted url
url = OpenLayers.String.format(url, { 'x': Math.abs(x), 'y': Math.abs(y), 'z': z });

return url;
},

zeroPad: function (num, len, radix) {
var str = num.toString(radix || 10);
while (str.length < len) {
str = "0" + str;
}
return str;
},

CLASS_NAME: 'KoalaGIS.Layer.WMTS.Baidu'

});
分享到:
评论

相关推荐

    openlayers 调用百度地图

    我们可以利用百度地图API创建地图对象,然后将其作为图像源(`ol.source.Image`)添加到OpenLayers的图层中: ```javascript var baiduSource = new ol.source.Image({ url: function(extent) { return '...

    openlayers5加载百度地图.zip

    这个压缩包“openlayers5加载百度地图.zip”显然包含了使用OpenLayers 5版本与百度地图API集成的示例代码。OpenLayers 5是这个库的一个重要升级,提供了更多的功能、性能优化以及对现代Web标准的支持。 首先,让...

    解决openlayers加载百度地图,坐标偏移,热力图渲染闪烁问题

    项目需求是想在百度地图上面用openlayers渲染热力图,然后就去看了相关openlayers的文档,选择了6.15.1版本,然后仿照地震热力图例子写了代码,但是由于自带是OSM地图,不符合项目要求,所以研究了如何加载百度地图...

    openlayers3添加各种地图资源

    下面将详细阐述如何使用OpenLayers 3 添加这些地图资源。 一、OpenLayers 3 简介 OpenLayers 3 是一个完全重写版本,相比早期的OpenLayers 2,它具有更好的性能、更简洁的API和更强的灵活性。其核心特性包括矢量...

    openlayers 4.2 加载百度 高德

    首先,让我们了解一下百度地图API。百度地图是中国领先的在线地图服务提供商,提供了一系列API供开发者使用。在OpenLayers 4.2中集成百度地图,你需要获取百度地图的API密钥,然后创建一个新的TileLayer实例,设置其...

    openlayers加载瓦片地图并手动标记坐标点

    通过以上步骤,你可以在OpenLayers加载的瓦片地图上手动添加和显示坐标点。如果需要处理多个标记点,只需重复创建特征对象和矢量图层的步骤即可。同时,OpenLayers提供了丰富的API,可以实现更复杂的交互功能,如...

    openlayers 添加文字标注

    openlayers 实现在地图上添加文字标注。为图片注记添加文本标签

    baiduMap_openlayer(openlayer加载百度地图例子)

    本示例重点展示了如何利用OpenLayers库加载百度地图,让开发者能够在一个Web应用中展示百度地图的地理信息。OpenLayers是一个强大的JavaScript库,专门用于创建交互式的地图应用程序,而百度地图则提供了丰富的地图...

    使用openlayers加载离线地图实例

    在IT行业中,前端开发是构建Web应用程序的关键部分,而OpenLayers是一个流行的JavaScript库,用于创建交互式的、基于Web的地图应用。本实例将详细介绍如何利用OpenLayers加载离线地图,并通过mui将其打包成移动应用...

    openlayers 添加标注 markers

    openlayers 添加标注 markers 怎么给Google地图添加标注

    openlayers 加载天地图示例

    在这个文件中,我们将创建OpenLayers地图实例,并添加天地图图层。天地图的图层通常包括WMTS(Web Map Tile Service)服务,我们可以使用`ol.layer.Tile`类来创建这些图层。下面是一个可能的示例代码片段: ```...

    baiduMap_openlayer(openlayer加载百度地图和高德地图例子)

    本示例“baiduMap_openlayer”是关于如何利用OpenLayers加载和展示百度地图与高德地图的教程。这个教程对开发者来说具有很高的参考价值,特别是那些想要在自己的Web应用中集成地图功能的人员。 首先,让我们深入...

    openlayers发布离线地图DEMO

    5. **添加图层**:创建一个OpenLayers.Layer,将瓦片源与地图关联起来: ```javascript var layer = new ol.layer.Tile({ source: tileSource }); ``` 6. **添加图层到地图**:最后,将图层添加到地图实例中:...

    基于openlayers扩展添加天地图背景组件

    本话题聚焦于如何在OpenLayers中扩展功能,添加天地图作为背景地图组件。天地图是由中国国家测绘局提供的官方地理信息服务平台,提供了丰富的地理数据资源。 首先,了解OpenLayers的基本概念是必要的。OpenLayers是...

    离线地图的比较,百度地图离线,天地图,openlayers地图

    离线地图的比较,百度地图离线,天地图,openlayers地图

    openlayers3+ 地图右键

    1. **创建地图实例**:首先,你需要创建一个OpenLayers地图实例,指定地图容器、投影、源(如WMS服务)和图层。 ```javascript var map = new ol.Map({ target: 'map', view: new ol.View({ center: [0, 0], ...

    openlayers5加载天地图影像.zip

    2. **创建地图实例**:在JavaScript文件(如app.js)中,初始化OpenLayers地图实例,设置地图容器、视图和投影。 ```javascript var map = new ol.Map({ target: 'map', view: new ol.View({ center: [116.404, ...

    Openlayers2多地图联动

    OpenLayers2是一个开源JavaScript库,专门用于在Web浏览器中创建交互式地图应用。这个库支持多种地图服务,包括WMS、WFS等,使得开发者能够方便地集成来自不同地图服务提供商的数据。"OpenLayers2多地图联动"这个...

    openlayers添加覆盖层

    首先,我们需要创建一个基本的OpenLayers地图实例,这通常涉及设置视口、投影和地图的容器元素。例如: ```javascript import Map from 'ol/Map'; import View from 'ol/View'; import TileLayer from 'ol/layer/...

    openlayers加载本地离线地图瓦片(重新发2018-10-23)

    6. **加载本地瓦片**:在`emss.html`中,我们需要编写JavaScript代码来实例化OpenLayers地图,并指定瓦片源为本地文件。这通常涉及到创建一个`TileLayer`对象,设置其源为`TileImage`,并提供本地瓦片的URL模板,...

Global site tag (gtag.js) - Google Analytics