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 Rijksdriehoek

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])
});

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 :

Ook is het 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 :


// 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 ArcGIS Online services in Rijksdriehoek

Ook Esri Nederland biedt een aantal basiskaarten aan via ArcGIS Online. 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 RD 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',
    maxZoom: 14,
    minZoom: 0,
});
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);