leaflet & Rijksdriehoek

Het plaatsen van een kaartje op je web pagina met Leaflet gaat verrassend eenvoudig. Deze z.g. slippy maps maken gebruik van tiled map services (WMTS, TMS). Leaflet maakt standaard gebruik van het 'WGS84' (EPSG:4326) stelsel en de 'Web Mercator' kaart projectie (EPSG:3857). Dat is prima zolang we een tiled map service bevragen die dat ook gebruikt.

Maar wat nou als je een tiled map service wil gebruiken die door b.v. de Nederlandse overheid wordt aangeboden ? Die services zijn via het PDOK loket beschikaar voor bijna alle basisregistratie zoals BRT, BGT, BAG en BRK. Maar die zijn veelal in de Nederlande Rijksdriekhoek kaartprojectie (EPSG:28992) !

Hoe gebruik je zo'n tiled map service in RD, zoals de BRT-Achtergrond kaart, met Leaflet ? En wat als je een mix wil maken ? Nou ... zo ...

Leaflet met PDOK services in Rijksdriehoekstelsel

Als we in Leaflet een kaart in een andere kaart projectie willen gebruiken dan kan dat via de 'crs' optie (coordinate reference system). Hiermee kun je een eigen, niet standaard stelsel opgeven. Handig daarbij zijn Proj4Leaflet en het daarbij horende Proj4 met functies voor kaart projecties en coordinaat transformaties.









Het Rijksdriehoekstelsel heeft de spatial reference code 'EPSG:28992', en de definitie daarvan vinden we hier. Voor Proj4 vinden we de volgende gegevens :

+proj=sterea +lat_0=52.15616055555555 +lon_0=5.38763888888889 +k=0.9999079 +x_0=155000 +y_0=463000 +ellps=bessel +units=m +no_defs
Verder hebben we het gebruikte tiling schema nodig. Voor PDOK is dat het nationale Nederlandse schema dat door Geonovum is vastgelegd in een Praktijkrichtlijn Tiling. Daar vinden we op pagina 6 de volgende gegevens :

De extent van het gebied van de set tiles komt hiermee voor zoomniveau 0 op (uitgedrukt in RD stelsel,
uitgaand van links-boven zoals bij WMTS gebruikelijk):
linksboven: X=-285.401,920 Y=903.401,920;
rechtsonder: X=595.401,920 Y=22.598,080;
In de bijlage B tenslotte vinden we de zoomniveaus (0 t/m 16) en de daarbijbehorende resoluties in meters.
Met al deze gegevens kunnen we de volgende CRS definitie voor gebruik in Leaflet opstellen :

var RD = new L.Proj.CRS(
    'EPSG:28992',
    '+proj=sterea +lat_0=52.15616055555555 +lon_0=5.38763888888889 +k=0.9999079 +x_0=155000 +y_0=463000 +ellps=bessel +units=m +towgs84=565.2369,50.0087,465.658,-0.406857330322398,0.350732676542563,-1.8703473836068,4.0812 +no_defs', {
    origin: [-285401.92, 22598.08],
    resolutions: [3440.640, 1720.320, 860.160, 430.080, 215.040, 107.520, 53.760, 26.880, 13.440, 6.720, 3.360, 1.680, 0.840, 0.420, 0.210, 0.105],
    bounds: L.bounds([-285401.92, 22598.08], [595401.920, 903401.920])
});

Samen met de gegevens van de BRT-Achtergrond kaart service van PDOK kunnen we nu een web kaartje maken :


brtLayer= new L.tileLayer('http://geodata.nationaalgeoregister.nl/tms/1.0.0/brtachtergrondkaart/{z}/{x}/{y}.png', {
    minZoom: 0,
    maxZoom: 14,
    tms: true,
});
var map = new L.Map('kaartje', {
    crs: RD,
    layers: [brtLayer]
});
var center = L.point(227596,513591);
map.setView(RD.projection.unproject(center), 7);

De map functies zoals 'setView', 'zoomTo' en 'panTo' verwachten echter nog steeds WGS84 coordinaten en geen RD !!!. Gelukkin zijn daarvoor de Proj4 functies 'project' en 'unproject' beschikbaar.

We hebben nu alle bouwstenen bij elkaar om een web kaartje te maken :

Nu we dit hebben is het ook mogelijk om een GeoJSON laag aan de kaart toe te voegen, waarbij de coordinaten ook in het RD stelsel zijn :


var jsonRD = {
 "type": "FeatureCollection",
 "crs": {
    "type": "name",
    "properties": { "name": "urn:ogc:def:crs:EPSG::28992" }
 },
 "features": [
   { "type": "Feature",
     "geometry": {"type": "Point", "coordinates": [229684.400, 513480.640]},
     "properties": {"prop0": "value0"}
   }
 ]
};

L.Proj.geoJson( jsonRD ).addTo(map);

Hetzelfde ook voor een z.g. overlay laag met de boundaries in RD:


// bounds in RD  [southWest , northEast]
var imageBounds = L.bounds( [230000.0, 513750.0], [231000.0, 515000.0] );
var imageUrl = './demo.png';

L.Proj.imageOverlay(imageUrl, imageBounds).addTo(map);

Voor een kompleet voorbeeld zie hier.

Leaflet met 'Esri Nederland Content' services in Rijksdriehoek

Naast PDOK biedt ook Esri Nederland een aantal basiskaarten aan via 'Esri Nederland Content'. Een aantal daarvan zijn ook in Rijksdriehoek. Om deze services in Leaflet te gebruiken kunnen we Esri-Leaflet gebruiken.











Een van de basiskaarten is de Topo (in RD). Als we hier naar de definitie van de service kijken, dan zien we een iets andere definitie voor de zoomniveaus (Levels of Detail) en het beginpunt (Origin) van het tiling schema. Er moet dus een andere CRS definitie gemaakt worden :

var RD = new L.Proj.CRS(
    'EPSG:28992',
    '+proj=sterea +lat_0=52.15616055555555 +lon_0=5.38763888888889 +k=0.9999079 +x_0=155000 +y_0=463000 +ellps=bessel +units=m +towgs84=565.2369,50.0087,465.658,-0.406857330322398,0.350732676542563,-1.8703473836068,4.0812 +no_defs', {
    origin: [-285401.92,903401.92],
    resolutions: [3251.206502413005,1625.6032512065026,812.8016256032513,406.40081280162565,203.20040640081282,101.60020320040641, 50.800101600203206,25.400050800101603,12.700025400050801,6.350012700025401,3.1750063500127004,1.5875031750063502,0.7937515875031751,0.39687579375158755,0.19843789687579377,0.09921894843789689,0.04960947421894844]
});

Nu we deze hebben kunnen we de service aanroepen :


var topoLayer = L.esri.tiledMapLayer({
    url: 'https://services.arcgisonline.nl/arcgis/rest/services/Basiskaarten/Topo/MapServer',
    minZoom: 0,
    maxZoom: 14
});
var map = L.map('kaartje', {
    crs: RD,
    layers: [topoLayer]
});
var center = L.point(229684.400, 513480.640);
map.setView(RD.projection.unproject(center), 10);

Voor een kompleet voorbeeld zie hier.

In de mix

Het is niet mogelijk om tiled map services met verschillende stelsels te combineren. Een map heeft immers maar 1 crs definitie ! Je kan wel een mix maken met een GeoJSON laag in het ene stelsel en de basis kaart in het andere, je kunt namelijk kiezen welke je gebruikt L.geoJson of L.Proj.geoJson of beide ! Het is dus niet nodig om de coordinaten vooraf te transformeren.

var map = new L.Map('kaartje', {
    crs: RD,
    layers: [brtLayer]
});

L.Proj.geoJson( jsonRD ).addTo(map);
L.geoJson( jsonWGS84 ).addTo(map);

Leaflet met Historische kaarten

Naast de vele actuele kaarten heeft 'Esri Nederland Content' ook historische kaarten. Deze wordt o.a. gebruikt in de geweldige webapplicatie Topotijdreis van het Kadaster. Ook deze services zijn prima in Leaflet te gebruiken.

Een van de kaarten is de Historische topografische data 1862. Als we hier naar de definitie van de service kijken, dan zien we bij de 'Tile Info' weer een iets andere definitie voor de zoomniveaus (Levels of Detail) en het beginpunt (Origin) van het gebruikte tiling schema. Er moet dus weer een iets andere CRS definitie gemaakt worden :

var RD = new L.Proj.CRS(
    'EPSG:28992',
    '+proj=sterea +lat_0=52.15616055555555 +lon_0=5.38763888888889 +k=0.9999079 +x_0=155000 +y_0=463000 +ellps=bessel +units=m +towgs84=565.2369,50.0087,465.658,-0.406857330322398,0.350732676542563,-1.8703473836068,4.0812 +no_defs', {
    origin: [-3.05155E7,3.1112399999999993E7],
    resolutions: [3251.206502413005,1625.6032512065026,812.8016256032513,406.40081280162565,203.20040640081282,101.60020320040641, 50.800101600203206,25.400050800101603,12.700025400050801,6.350012700025401,3.1750063500127004,1.5875031750063502,0.7937515875031751,0.39687579375158755,0.19843789687579377,0.09921894843789689,0.04960947421894844]
});

Nu we deze hebben kunnen we de service aanroepen :


var layer_1862 = L.esri.tiledMapLayer({
    url: 'http://tiles1.arcgis.com/tiles/nSZVuSZjHpEZZbRo/arcgis/rest/services/Historische_tijdreis_1862/MapServer',
    minZoom: 0,
    maxZoom: 11
});

var map = L.map('kaartje', {
    crs: RD,
    layers: [layer_1862]
});
var center = L.point(229684.400, 513480.640);
map.setView(RD.projection.unproject(center), 10);

Voor een kompleet voorbeeld zie hier.