Voor een blog post wil ik een simpel kaartje met Groninger gemeenten maken. Als oefening probeer ik dat met de D3 JavaScript library te doen. Daarbij loop ik tegen een vreemd probleem aan.

Gemeentegrenzen van PDOK

De gemeentegrenzen haal ik uit de bestuurlijke grenzen service van PDOK. Ik gebruik de Web Feature Service (WFS). Het service request pas ik aan, zodat de service alleen Groninger gemeenten retourneert in een formaat dat eenvoudig verwerkt kan worden door D3. Dat formaat is GeoJSON met geometrie in het WGS84 coördinatenstelsel.

Service endpoint:

https://geodata.nationaalgeoregister.nl/bestuurlijkegrenzen/wfs

Query parameters:

service=WFS
version=2.0.0
request=GetFeature
typeName=bestuurlijkegrenzen:gemeenten
cql_filter=gemeentenaam IN ('Het Hogeland', 'Loppersum', 'Appingedam', 'Westerkwartier', 'Groningen', 'Delfzijl', 'Midden-Groningen', 'Oldambt', 'Veendam', 'Pekela', 'Westerwolde', 'Stadskanaal')
outputFormat=JSON
srsName=EPSG:4326

Het request - waarbij HTML encoding is toegepast - is dan:

https://geodata.nationaalgeoregister.nl/bestuurlijkegrenzen/wfs?service=WFS&request=GetFeature&typeName=bestuurlijkegrenzen:gemeenten&cql_filter=gemeentenaam%20IN%20(%27Het%20Hogeland%27,%20%27Loppersum%27,%20%27Appingedam%27,%20%27Westerkwartier%27,%20%27Groningen%27,%20%27Delfzijl%27,%20%27Midden-Groningen%27,%20%27Oldambt%27,%20%27Veendam%27,%20%27Pekela%27,%20%27Westerwolde%27,%20%27Stadskanaal%27)&outputFormat=JSON&srsName=EPSG:4326

Bekijk hier de response.

De code voor het visualiseren van de response in een kaart met D3 is eenvoudig. Het resultaat is echter niet wat ik had verwacht, namelijk een zwart vierkant.

Gemeentegrenzen van ESRI

ESRI stelt in de Levende Atlas van Nederland dezelfde gemeentegrenzen als PDOK beschikbaar. Ze zijn op te vragen via de ArcGIS REST API.

Service endpoint:

https://services.arcgis.com/nSZVuSZjHpEZZbRo/arcgis/rest/services/Bestuurlijke_Grenzen_Gemeenten_2019/FeatureServer/0/query 

Query parameters:

where=Gemeentenaam IN ('Het Hogeland', 'Loppersum', 'Appingedam', 'Westerkwartier', 'Groningen', 'Delfzijl', 'Midden-Groningen', 'Oldambt', 'Veendam', 'Pekela', 'Westerwolde', 'Stadskanaal')
outFields=*
outSR=4326
f=geojson

Request:

https://services.arcgis.com/nSZVuSZjHpEZZbRo/arcgis/rest/services/Bestuurlijke_Grenzen_Gemeenten_2019/FeatureServer/0/query?where=Gemeentenaam%20IN%20(%27Het%20Hogeland%27,%20%27Loppersum%27,%20%27Appingedam%27,%20%27Westerkwartier%27,%20%27Groningen%27,%20%27Delfzijl%27,%20%27Midden-Groningen%27,%20%27Oldambt%27,%20%27Veendam%27,%20%27Pekela%27,%20%27Westerwolde%27,%20%27Stadskanaal%27)&outFields=*&outSR=4326&f=geojson

Bekijk hier de response, die net iets anders is dan bij PDOK.

Wanneer ik dezelfde code als eerder gebruik, maar nu met de GeoJSON response van ESRI, krijgen ik wél een mooi kaartje.

Draairichting: left- of right-hand rule

Waarom werkt het niet met het GeoJSON bestand van PDOK en wél met dat van ESRI?

Het antwoord is dat PDOK de right-hand rule volgt voor de draairichting van polygonen. Bij de right-hand rule loopt de buitenste ring van een polygoon tegen de klok in, en de binnenste (de gaten) met de klok mee. Bij de left-hand rule is dat precies andersom. ESRI - en ook D3 - houden zich aan de left-hand rule.

D3 interpreteert de gemeentegrenzen uit de PDOK response dus als gaten. Het visualiseert de inverse polygoon. Die omvat de rest van de wereld en vult het hele (vierkante) canvas. Bekijk ter illustratie van het belang van de draairichting in D3 ook deze voorbeelden van Mike Bostock.

Het probleem met de PDOK polygonen is eenvoudig op te lossen, door de draairichting om te keren. Dit kan bijvoorbeeld met Turf JavaScript library:

var fixed = mapdata.features.map(function(f) {
    return turf.rewind(f, {reverse:true});
});

Met de aangepaste code lukt het vervolgens wél om de GeoJSON van PDOK te visualiseren in D3:

GeoJSON standaardspecificatie

GeoJSON is niet ontstaan vanuit een organisatie als de Internet Engineering Task Force (IETF) of het Open Geospatial Consortium (OGC). Het is een initiatief van een aantal slimme mensen, op zoek naar een eenvoudig formaat voor het uitwisselen van geo-informatie. Dit leidde tot de GeoJSON 2008 specificatie, waarin geen afspraken werden opgenomen over de draairichting van polygonen.

Pas in 2016 heeft de IETF de standaardspecificatie voor het GeoJSON formaat vastgelegd in RFC 7946. Daarin worden wél eisen gesteld aan de draairichting:

A linear ring MUST follow the right-hand rule with respect to the area it bounds, i.e., exterior rings are counterclockwise, and holes are clockwise.

Het komt er op neer dat PDOK zich houdt aan de RFC 7946 specificatie. ESRI en D3 doen dat niet.