OpenLayers集成MapGuide切片地图:tileCoord转换及请求参数修正
OpenLayers中MapGuide切片地图的tileCoord转换问题
我正尝试在OpenLayers(OL)地图中添加MapGuide切片地图,但当前代码生成的请求X、Y值不正确。我已尝试通过指定切片网格(TileGrid)的分辨率和范围来解决,但似乎没有效果;也考虑过使用WMTS及WMTS网格,但因所需请求结构不支持而无法采用。请问如何将OpenLayers生成的tileCoord转换为符合请求要求的格式?
当前代码
import Map from 'ol/Map.js'; import TileLayer from 'ol/layer/Tile.js'; import View from 'ol/View.js'; import {getTopLeft} from 'ol/extent.js'; import proj4 from 'proj4'; import { register } from 'ol/proj/proj4'; import OSM from 'ol/source/OSM'; import TileGrid from 'ol/tilegrid/TileGrid.js'; import XYZ from 'ol/source/XYZ.js'; proj4.defs('EPSG:25831', '+proj=utm +zone=31 +ellps=GRS80 +towgs84=0,0,0,0,0,0,0 +units=m +no_defs'); register(proj4); // Define projection extent var projectionExtent = [494035.69730822, 4676149.38116713, 502474.0732031, 4682213.46977595]; var resolutions = [ 50000, 40000, 30000, 25000, 20000, 17500, 15000, 12000, 10000, 9000, 8000, 7000, 6000, 5000, 4500, 4000, 3500, 3000, 2500, 2000, 1500, 1000, 900, 800, 700, 600, 550, 500, 450, 400, 350, 300, 250, 200, 150, 100 ]; // Function to build custom tile URL function buildTileURL() { let url url='https://wgis.test123.org/mapguide/mapagent/mapagent.fcgi?mapdefinition= ... other parameters .... &version=1.2.0&tilecol={x}&tilerow={y}&scaleindex={z}'; // Assuming scaleindex corresponds to the zoom level console.log(url) return url } // XYZ source with custom URL function var mapGuideSource = new XYZ({ tileUrlFunction: function(tileCoord) { if (tileCoord) { console.log(tileCoord) return buildTileURL() .replace('{x}', tileCoord[1].toString()) .replace('{y}', tileCoord[2].toString()) .replace('{z}', tileCoord[0].toString()); } return undefined; }, projection: 'EPSG:25831', }); const tileGrid = new TileGrid({ extent: projectionExtent, resolutions: resolutions, tileSize: [300, 300], origin: getTopLeft(projectionExtent) }); // Create the map layer var mapGuideLayer = new TileLayer({ source: mapGuideSource, tileGrid: tileGrid, extent: projectionExtent, }); export const osmLayer = new TileLayer({ source: new OSM(), }); // Create the map var map = new Map({ target: 'map', layers: [mapGuideLayer,osmLayer], view: new View({ projection: 'EPSG:25831', center: [498254.88525566, 4679681.39547154], zoom: 12 }) });
解决方案
核心问题
你当前的自定义TileGrid只传给了TileLayer,但并没有关联到XYZ Source,导致OpenLayers使用默认的网格规则生成tileCoord,自然和MapGuide的切片规则不匹配。
步骤1:将TileGrid关联到XYZ Source
把自定义的TileGrid直接传入XYZ的构造参数中,让Source使用这个网格生成坐标:
var mapGuideSource = new XYZ({ tileUrlFunction: function(tileCoord) { // ... 原有逻辑 }, projection: 'EPSG:25831', tileGrid: tileGrid, // 新增:关联自定义TileGrid });
步骤2:适配MapGuide的行号(tilerow)规则
OpenLayers默认以左上角为原点,Y轴从上到下递增;但MapGuide的切片行号通常以左下角为原点,Y轴从下到上递增。需要反转Y值:
tileUrlFunction: function(tileCoord) { if (!tileCoord) return undefined; const [z, x, y] = tileCoord; // 获取当前层级的行列范围 const tileRange = tileGrid.getTileRangeForExtentAndZ(projectionExtent, z); // 反转Y值 const reversedY = tileRange.maxY - y; return buildTileURL() .replace('{x}', x.toString()) .replace('{y}', reversedY.toString()) .replace('{z}', z.toString()); }
步骤3:验证scaleindex与分辨率的对应关系
确保resolutions数组的索引和MapGuide的scaleindex完全匹配:
- 如果MapGuide的
scaleindex和你的resolutions顺序一致,直接用z即可; - 如果是倒序,需要转换:
const scaleIndex = resolutions.length - 1 - z;
修改后的完整代码
import Map from 'ol/Map.js'; import TileLayer from 'ol/layer/Tile.js'; import View from 'ol/View.js'; import {getTopLeft} from 'ol/extent.js'; import proj4 from 'proj4'; import { register } from 'ol/proj/proj4'; import OSM from 'ol/source/OSM'; import TileGrid from 'ol/tilegrid/TileGrid.js'; import XYZ from 'ol/source/XYZ.js'; proj4.defs('EPSG:25831', '+proj=utm +zone=31 +ellps=GRS80 +towgs84=0,0,0,0,0,0,0 +units=m +no_defs'); register(proj4); // Define projection extent var projectionExtent = [494035.69730822, 4676149.38116713, 502474.0732031, 4682213.46977595]; var resolutions = [ 50000, 40000, 30000, 25000, 20000, 17500, 15000, 12000, 10000, 9000, 8000, 7000, 6000, 5000, 4500, 4000, 3500, 3000, 2500, 2000, 1500, 1000, 900, 800, 700, 600, 550, 500, 450, 400, 350, 300, 250, 200, 150, 100 ]; // Function to build custom tile URL function buildTileURL() { return 'https://wgis.test123.org/mapguide/mapagent/mapagent.fcgi?mapdefinition= ... other parameters .... &version=1.2.0&tilecol={x}&tilerow={y}&scaleindex={z}'; } const tileGrid = new TileGrid({ extent: projectionExtent, resolutions: resolutions, tileSize: [300, 300], origin: getTopLeft(projectionExtent) }); // XYZ source with custom URL function var mapGuideSource = new XYZ({ tileUrlFunction: function(tileCoord) { if (!tileCoord) return undefined; const [z, x, y] = tileCoord; // 反转Y值适配MapGuide的行号规则 const tileRange = tileGrid.getTileRangeForExtentAndZ(projectionExtent, z); const reversedY = tileRange.maxY - y; // 若scaleindex是倒序,替换为resolutions.length-1-z const scaleIndex = z; return buildTileURL() .replace('{x}', x.toString()) .replace('{y}', reversedY.toString()) .replace('{z}', scaleIndex.toString()); }, projection: 'EPSG:25831', tileGrid: tileGrid, // 关联自定义TileGrid }); // Create the map layer var mapGuideLayer = new TileLayer({ source: mapGuideSource, extent: projectionExtent, }); export const osmLayer = new TileLayer({ source: new OSM(), }); // Create the map var map = new Map({ target: 'map', layers: [mapGuideLayer, osmLayer], view: new View({ projection: 'EPSG:25831', center: [498254.88525566, 4679681.39547154], zoom: 12 }) });
内容的提问来源于stack exchange,提问作者OSimon
相关产品推荐
相关产品推荐

