'An TileWMS -> TileLayer -> Map -> View based on a WMS `GetTile` request with openlayers only duplicates the same tile on the map
Until 2020, I was displaying an IGN map with Openlayers with this code:
import { Component, OnInit, Input } from '@angular/core';
import Map from 'ol/Map';
import View from 'ol/View';
import TileWMS from 'ol/source/TileWMS';
import * as olProj from 'ol/proj';
import TileLayer from 'ol/layer/Tile';
@Component({
selector: 'carte',
templateUrl: './carte.component.html',
styleUrls: ['./carte.component.css']
})
export class CarteComponent implements OnInit {
/** Carte Openlayers. */
map: Map;
/* Longitude. */
@Input() longitude: number;
/* Latitude. */
@Input() latitude: number;
/** Niveau de zoom initial. */
@Input() zoom: number;
constructor() {
}
ngOnInit(): void {
var ign_source = new TileWMS({
url: 'http://wxs.ign.fr/cdw20cou9clqe59fvn39rmcu/geoportail/r/wms',
params: {'LAYERS': 'GEOGRAPHICALGRIDSYSTEMS.PLANIGN', 'TILED': false}
});
var ign = new TileLayer({
source: ign_source
});
this.map = new Map({
target: "carte_principale",
view: new View({
center: olProj.fromLonLat([this.longitude, this.latitude]),
zoom: this.zoom
})
});
this.map.addLayer(ign);
}
}
Then IGN geoportail made big changes for months, and when it went back, I had to adapt my code to use it again.
It documentation looks to use GetTile requests to display the map, instead of GetMap it was suggesting to use before.
And according to it, I changed my code that way:
ngOnInit(): void {
const planIGN = new TileWMS( {
url: 'https://wxs.ign.fr/decouverte/geoportail/wmts',
params: {
REQUEST: 'GetTile',
VERSION: '1.0.0',
LAYER: 'GEOGRAPHICALGRIDSYSTEMS.PLANIGNV2',
STYLE: 'normal',
FORMAT: 'image/png',
SERVICE: 'WMTS',
TILEMATRIX: 14,
TILEMATRIXSET: 'PM',
TILECOL: 8180,
TILEROW: 5905
}});
const ign = new TileLayer({
source: planIGN
});
this.map = new Map({
target: 'carte_principale',
view: new View({
center: olProj.fromLonLat([this.longitude, this.latitude]),
zoom: this.zoom
})
});
this.map.addLayer(ign);
}
It works... but the display isn't the one expected:
- the same tile is duplicated along the map.
- the latitude/longitude isn't resolved
- the zoom doesn't work
The two last points, because I don't know how to parametrize the request correctly.
When I attempt that displaying with QGis (where the map is shown fine) using its network tool, it see that kind of requests exchanged, so I'm not so far:
https://wxs.ign.fr/decouverte/geoportail/wmts?SERVICE=WMTS&REQUEST=GetTile&VERSION=1.0.0&LAYER=GEOGRAPHICALGRIDSYSTEMS.PLANIGNV2&STYLE=normal&FORMAT=image/png&TILEMATRIXSET=PM&TILEMATRIX=13&TILEROW=2946&TILECOL=4093
Openlayers is powerful, but often tricky for me:
what should I change to have a better behavior?
Epilog: after @Solomon and others replied to my question, here the code I've eventually produced and that worked:
import { Component, OnInit, Input } from '@angular/core';
import Map from 'ol/Map';
import View from 'ol/View';
import Tile from 'ol/layer/Tile';
import TileLayer from 'ol/layer/Tile';
import WMTS from 'ol/source/WMTS';
import WMTSTileGrid from 'ol/tilegrid/WMTS';
import {fromLonLat, get as getProjection} from 'ol/proj';
import {getWidth, getTopLeft} from 'ol/extent';
@Component({
selector: 'carte',
templateUrl: './carte.component.html',
styleUrls: ['./carte.component.css']
})
export class CarteComponent implements OnInit {
/** Carte Openlayers. */
map: Map;
/* Longitude. */
@Input() longitude: number;
/* Latitude. */
@Input() latitude: number;
/** Niveau de zoom initial. */
@Input() zoom: number;
/** Couche Plan IGN V2 */
planIGNV2: TileLayer<WMTS> = this.couche('https://wxs.ign.fr/decouverte/geoportail/wmts', 'GEOGRAPHICALGRIDSYSTEMS.PLANIGNV2',
'EPSG:3857', 'image/png');
/* Couche : Orthophotos
orthoPhotos: TileLayer<WMTS> = this.couche('https://wxs.ign.fr/decouverte/geoportail/wmts', 'ORTHOIMAGERY.ORTHOPHOTOS',
'EPSG:3857', 'image/jpeg')
*/
ngOnInit() {
const map = new Map({
layers: [ this.planIGNV2 ],
target: 'carte_principale', // id de l'élément HTML
view: new View({
center: fromLonLat([this.longitude, this.latitude]),
zoom: this.zoom
})
});
}
/**
* Crée une couche tuilée WMTS
* @param url URL
* @param layer Nom de la couche
* @param projection Projection à utiliser pour calculer la grille de tuiles (exemple : EPSG:3857)
* @param format Format d'image à utiliser.
*/
couche(url: string, layer: string, projection: string, format: string): TileLayer<WMTS> {
return new Tile({
source : new WMTS({
url,
layer,
matrixSet: 'PM',
format,
style: 'normal',
tileGrid: this.grilleTuiles(projection)
})
});
}
/**
* Renvoie une grille de tuiles
* @param projection Projection (exemple : EPSG:3857)
*/
grilleTuiles(projection: string): WMTSTileGrid {
const proj = getProjection(projection);
const maxResolution = getWidth(proj.getExtent()) / 256;
const projectionExtent = proj.getExtent();
const resolutions = [];
const matrixIds = [];
for (let i = 0; i < 20; i++) {
matrixIds[i] = i.toString();
resolutions[i] = maxResolution / Math.pow(2, i);
}
return new WMTSTileGrid( {
origin: getTopLeft(projectionExtent), // coin supérieur gauche
resolutions,
matrixIds
});
}
}
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|

