目录
前端代码实现
根据xml配置文件计算出行列号
1、xml配置文件信息样例
2、代码实现
运用到的知识
该文档是根据本人做的项目进行的总结,可能存在知识不准确,仅做参考;
前端代码实现
根据提供一个瓦片服务地址,解析服务的元数据,获取到范围,根据范围,计算出行列号
根据xml配置文件计算出行列号
1、xml配置文件信息样例
2、代码实现
1、解析xml数据为json格式的数据,借助插件x2js
2、本例中,只做了3857和4326坐标系的支持;请求用axios进行请求
3、因为文档中的比例尺分母使用的是米,所以4236中,如果没有提供level时,将度数转为米进行匹配层级信息的
4、4326坐标系的地球半径取值为:6371004;3857坐标系的地球半径取值为:6378137;
import X2JS from 'x2js';
// 1、请求配置文件路径,获取元数据,通过插件x2js解析xml数据为json格式
let url = 'http://xxxxx';
axios.get(url).then((res) => {
if (res.status != 200) {
alert('请检查您的配置文件路径');
return false;
}
var x2js = new X2JS();
var json = x2js.xml2js(res.data);
getColRowLevel({data:json,dpi:90.714});
});
// 2、 根据获取的元数据,获取行列号和层级
const getColRowLevel = (json) => {
let { data, dpi, level } = json;
let Contents = data.Capabilities.Contents;
let TileMatrixSet = Contents.TileMatrixSet;
// 元数据中的crs坐标系
let SupportedCRS = TileMatrixSet.SupportedCRS.__text || TileMatrixSet.SupportedCRS;
// 默认crs是3857
//默认dpi为90.714,dpi一般为90.714或者96;如果不确定dpi请咨询提供服务的后台
dpi = dpi ? Number(dpi) : 90.714;
level = level ? Number(level) : null;
if (SupportedCRS.toLowerCase().includes('epsg::4326')) {
// 4326
return colRowLevel4326(Contents, dpi, level);
} else {
// 3857
return colRowLevel3857(Contents, dpi, level);
}
};
const colRowLevel4326 = (Contents, dpi, level) => {
let Layer = Contents.Layer;
// 服务范围,如果给指定范围,则去掉下面四行,直接let extentObj = {minX,minY,maxX,maxY}
let WGS84BoundingBox = Layer.WGS84BoundingBox;
let LowerCorner = WGS84BoundingBox.LowerCorner.__text;
let UpperCorner = WGS84BoundingBox.UpperCorner.__text;
let extentObj = getExtent4326(LowerCorner, UpperCorner);
let { minX, maxX, minY, maxY } = extentObj;
let canvasWidth = 1000;
let tileSize = 256;
let realTileWidthDegree = (maxX - minX) / (canvasWidth / tileSize);
let realTileWidthMeter = (realTileWidthDegree / 180) * (Math.PI * 6371004);
let resolutions = realTileWidthMeter / tileSize;
let scaleDenominator = resolutions / (0.0254 / dpi);
// // Identifier ScaleDenominator TileHeight TopLeftCorner
let TileMatrixSet = Contents.TileMatrixSet;
let TileMatrixArr = TileMatrixSet.TileMatrix;
// 当前比例尺最接近的对象
let curScaleObj = getScaleInfo(TileMatrixArr,scaleDenominator,level);
if (curScaleObj) {
// Identifier ScaleDenominator TileWidth TopLeftCorner
let { ScaleDenominator, TopLeftCorner, Identifier, TileWidth } = curScaleObj;
Identifier = Identifier.__text;
ScaleDenominator = eToNumber(ScaleDenominator);
let originObj = TopLeftCorner.split(' ');
let originX = originObj[1];
let originY = originObj[0];
var resolution = (((0.0254 / dpi) * ScaleDenominator) / (Math.PI * 6371004)) * 180;
let minCol = Math.floor(Math.abs(originX - minX) / (resolution * tileSize));
let minRow = Math.floor(Math.abs(originY - maxY) / (resolution * tileSize));
let maxCol = Math.ceil(Math.abs(originX - maxX) / (resolution * tileSize));
let maxRow = Math.ceil(Math.abs(originY - minY) / (resolution * tileSize));
return {
minCol,
minRow,
maxCol,
maxRow,
level: Identifier
};
}
return false;
};
const colRowLevel3857 = (Contents, dpi, level) => {
let Layer = Contents.Layer;
// 服务范围,如果给指定范围,则去掉下面四行,直接let extentObj = {minX,minY,maxX,maxY}
let WGS84BoundingBox = Layer.WGS84BoundingBox;
let LowerCorner = WGS84BoundingBox.LowerCorner.__text;
let UpperCorner = WGS84BoundingBox.UpperCorner.__text;
let extentObj = getExtent3857(LowerCorner, UpperCorner);
let { minX, maxX, minY, maxY } = extentObj;
let canvasWidth = 1000;
let tileSize = 256;
let realTileWidth = (maxX - minX) / (canvasWidth / tileSize);
let resolutions = realTileWidth / tileSize;
let scaleDenominator = resolutions / (0.0254 / dpi);
// Identifier ScaleDenominator TileHeight TopLeftCorner
let TileMatrixSet = Contents.TileMatrixSet;
let TileMatrixArr = TileMatrixSet.TileMatrix;
// 当前比例尺最接近的对象
let curScaleObj = getScaleInfo(TileMatrixArr,scaleDenominator,level);
if (curScaleObj) {
// Identifier ScaleDenominator TileWidth TopLeftCorner
let { ScaleDenominator, TopLeftCorner, Identifier, TileWidth } = curScaleObj;
Identifier = Identifier.__text;
ScaleDenominator = eToNumber(ScaleDenominator);
let originObj = getOrigin(TopLeftCorner);
let originX = originObj.x;
let originY = originObj.y;
let resolution = (0.0254 / dpi) * ScaleDenominator;
let minCol = Math.floor(Math.abs(originX - minX) / (resolution * tileSize));
let minRow = Math.floor(Math.abs(originY - maxY) / (resolution * tileSize));
let maxCol = Math.ceil(Math.abs(originX - maxX) / (resolution * tileSize));
let maxRow = Math.ceil(Math.abs(originY - minY) / (resolution * tileSize));
return {
minCol,
minRow,
maxCol,
maxRow,
level: Identifier
};
}
return false;
};
// 得到当前比例尺信息
const getScaleInfo = (TileMatrixArr,scaleDenominator,level)=>{
let curScaleObj = null;
let neastScaleD = undefined;
if (level) {
curScaleObj = TileMatrixArr.find((item) => item.Identifier.__text == level);
}
if (!curScaleObj) {
TileMatrixArr.forEach((item) => {
let ScaleDenominator = eToNumber(item.ScaleDenominator);
let dist = Math.abs(scaleDenominator - ScaleDenominator);
if (neastScaleD == undefined) {
neastScaleD = dist;
curScaleObj = item;
} else if (dist < neastScaleD) {
neastScaleD = dist;
curScaleObj = item;
}
});
}
return curScaleObj;
}
// 得到origin
const getOrigin = (TopLeftCorner) => {
let arr = TopLeftCorner.split(' ');
return { x: eToNumber(arr[0]), y: eToNumber(arr[1]) };
};
// 将自然计数转化为数字
const eToNumber = (eNum) => {
eNum = (eNum + '').toLowerCase();
if (eNum.includes('e')) {
let arr = eNum.split('e');
return Number(arr[0]) * Math.pow(10, arr[1]);
}
return Number(eNum);
};
// 得到范围的坐标点
const getExtent3857 = (LowerCorner, UpperCorner) => {
let lowerArr = LowerCorner.split(' ');
let upperArr = UpperCorner.split(' ');
let min = WGS84ToMercator({ lng: lowerArr[0], lat: lowerArr[1] });
let max = WGS84ToMercator({ lng: upperArr[0], lat: upperArr[1] });
return {
minX: min.lng,
minY: min.lat,
maxX: max.lng,
maxY: max.lat
};
};
const getExtent4326 = (LowerCorner, UpperCorner) => {
let lowerArr = LowerCorner.split(' ');
let upperArr = UpperCorner.split(' ');
return {
minX: lowerArr[0],
minY: lowerArr[1],
maxX: upperArr[0],
maxY: upperArr[1]
};
};
运用到的知识
1、像素和米的换算
1英寸 = 2.54厘米 = 0.0254米
1英寸 = 96像素
所以:1像素 = (0.0254/dpi)米
dpi一般取值96或者90.714,dpi的值不确定的话,需要咨询提供瓦片服务的人
2、分辨率的计算
分辨率 = (0.0254/dpi)*比例尺分母;