久久国产成人av_抖音国产毛片_a片网站免费观看_A片无码播放手机在线观看,色五月在线观看,亚洲精品m在线观看,女人自慰的免费网址,悠悠在线观看精品视频,一级日本片免费的,亚洲精品久,国产精品成人久久久久久久

分享

讓OpenLayers添加百度地圖(未完版)

 quasiceo 2012-12-19

     KoalaGIS的在線地圖系統(tǒng),打算采用國(guó)內(nèi)外主要的幾個(gè)地圖服務(wù):google地圖,、百度地圖,、OpenStreet Map,、天地圖。google、百度,、openstreet的服務(wù)器性能好,,速度快,,但google由于政策原因,,不確定因素太多,,Openstreet Map個(gè)人感覺(jué)配圖不怎么好看,添加天地圖完全就是為了顧忌下咱們這個(gè)GIS專業(yè)的臉面,,畢竟總要搞點(diǎn)專業(yè)的東西吧,,雖然他很垃圾,但勝于無(wú),!

     為此,,需要在OpenLayers上擴(kuò)展一個(gè)百度地圖圖層出來(lái),讓其能在Openlayers中顯示出來(lái),。為了疊加百度地圖,,首先必須了解其瓦片的組織規(guī)則,通過(guò)對(duì)百度api的js文件解析和網(wǎng)上相關(guān)資料的收集,,經(jīng)過(guò)程序測(cè)試,,推論正確,現(xiàn)講解下其基本的參數(shù),,以及編寫(xiě)的KoalaGIS.Layer.WMTS.Baidu圖層,。

     百度地圖也是采用的魔卡托投影,個(gè)人感覺(jué)和google的web 墨卡托投影是一樣的,,但據(jù)網(wǎng)友測(cè)試,,兩者計(jì)算結(jié)果有點(diǎn)出入,我猜測(cè)可能是百度或者google地圖有偏移參數(shù)的影響吧,,該文暫不分析此原因,,且該問(wèn)題本人還沒(méi)正式測(cè)試過(guò),有待考證,!

利用百度提供的API進(jìn)行坐標(biāo)轉(zhuǎn)換

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

用Openlayers提供的web墨卡托投影對(duì)該經(jīng)緯度投影得出的結(jié)果為:,??,?,?

百度地圖的分辨率問(wèn)題

對(duì)百度地圖api的js腳本進(jìn)行解析,可以看到該函數(shù):

以看到兩個(gè)獲取分辨率相關(guān)的函數(shù)如下:
getZoomUnits: function(T) {
     return Math.pow(2, (18 - T))    //從這里可以看出,,百度地圖的分辨率幾乎就是固定的2的N次冪來(lái)計(jì)算的
},
詳細(xì)請(qǐng)見(jiàn)該文《百度地圖的瓦片參數(shù)解析http://blog.sina.com.cn/s/blog_4c8b1bdd0100xij4.html
 

百度地圖的坐標(biāo)系統(tǒng):平面坐標(biāo)系的原點(diǎn)與經(jīng)緯度的原點(diǎn)一致,,即赤道與0度經(jīng)線相交的位置

 

百度地圖瓦片編號(hào)方式:

百度地圖API在展示地圖時(shí)是將整個(gè)地圖圖片切割成若干圖塊來(lái)顯示的,當(dāng)?shù)貓D初始化或是地圖級(jí)別,、中心點(diǎn)位置發(fā)生變化時(shí),,地圖API會(huì)根據(jù)當(dāng)前像素坐標(biāo)計(jì)算出視野內(nèi)需要的圖塊坐標(biāo)(也叫圖塊編號(hào)),從而加載對(duì)應(yīng)的圖塊用以顯示地圖,。

百度地圖的圖塊坐標(biāo)原點(diǎn)與平面坐標(biāo)一致,從原點(diǎn)向右上方開(kāi)始編號(hào)為0, 0:

 

如何通過(guò)一個(gè)坐標(biāo)和縮放級(jí)別計(jì)算出百度瓦片所在的行列號(hào)呢,?

百度瓦片的計(jì)算方式很簡(jiǎn)單,,大致如下:

1.計(jì)算出坐標(biāo)的平面坐標(biāo)位置,,瓦片的切割起止點(diǎn)就是0,0

2. 用平面坐標(biāo)除以分辨率就能得到坐標(biāo)到起點(diǎn)的像素大小,然后除以每張瓦片的大小取整就是瓦片的行列號(hào)了

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

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

   分辨率前面已經(jīng)講過(guò),,res = Math.Pow(2, level - 18 );

3.舉例來(lái)說(shuō)吧,,第18級(jí)下,選取經(jīng)緯度為(116.404, 39.915)的坐標(biāo)點(diǎn),,該點(diǎn)大致在北京天安門(mén)那,,經(jīng)過(guò)投影得出其平面位置為(12958175, 4825923.77)采用百度的api計(jì)算出來(lái)的,用openlayers計(jì)算的不是該坐標(biāo),。利用上面的行列號(hào)計(jì)算公式推算出瓦片行列號(hào)為:50617, 18851,。利用百度地圖提供的瓦片服務(wù)器地址,根據(jù)行列號(hào)和縮放級(jí)別,,可以調(diào)用該瓦片地址:

 

 

OpenLayers中添加百度地圖

遇到的問(wèn)題:

1,,坐標(biāo)系不一致。

Openlayers中采用的坐標(biāo)系并非百度地圖的數(shù)學(xué)坐標(biāo)系

2,,行列號(hào)的計(jì)算方式不一樣

百度地圖是從左到右,,從下到上;但Openlayers和google以及通常的wmts服務(wù)都是從左到右,,從上到下的,!

 

解決辦法:坐標(biāo)系還是按照Openlayers的思路,所有的方式都不動(dòng),,只是把他計(jì)算瓦片的方式改變就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}'; var y_str = '${y}';
if (x < 0)
x_str = 'M${x}';
if (y < 0)
y_str = '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'

});

 

 

 

參考資料:

1.百度地圖API詳解之地圖坐標(biāo)系統(tǒng)http://www.cnblogs.com/jz1108/archive/2011/07/02/2095376.html

2.一撇一捺的博客 http://blog.sina.com.cn/simplester

    本站是提供個(gè)人知識(shí)管理的網(wǎng)絡(luò)存儲(chǔ)空間,所有內(nèi)容均由用戶發(fā)布,,不代表本站觀點(diǎn),。請(qǐng)注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購(gòu)買(mǎi)等信息,,謹(jǐn)防詐騙,。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請(qǐng)點(diǎn)擊一鍵舉報(bào),。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評(píng)論

    發(fā)表

    請(qǐng)遵守用戶 評(píng)論公約