WCS van AHN3: werkt een bounding box als clip?

Hi allen,

Ik heb een vraag over het inladen van de AHN3 service via een WCS in FME. Doordat ik meerdere kleine get requests wil doen heb ik ervoor gekozen om met kleinere bounding boxes te werken en meerdere get requests te sturen. Bij het inlezen van de AHN3 data in FME valt mij iets op wat ik niet zo goed kan plaatsen. Een google search kan mij tot dusver ook niet helpen.

In theorie zou het kunnen dat AHN3 cellen (ik gebruik de 0.5 meter dtm) deels binnen en deels buiten mijn bounding box vallen. Het lijkt mij zeer onwaarschijnlijk dat de rastercellen altijd exact in mijn bounding box vallen. Toch zie ik dat in de bounding box altijd hele AHN cellen van dezelfde grootte zitten. Het lijkt dus zo te zijn dat een bounding box niet als ‘clip’ wordt gebruikt voor de AHN3 dataset, maar dat vanaf de origin (0,0) van de bounding box de AHN3 wordt opgebouwd.

Ik gebruik de volgende url voor het ophalen van de AHN3:

https://geodata.nationaalgeoregister.nl/ahn3/wcs?SERVICE=WCS&VERSION=1.0.0&REQUEST=GetCoverage&FORMAT=GeoTIFF_FLOAT32&COVERAGE=ahn3_05m_dtm&BBOX=@Value(_xmin),@Value(_ymin),@Value(_xmax),@Value(_ymax)&CRS=EPSG:28992&RESPONSE_CRS=EPSG:28992&RESX=0.5&RESY=0.5

De bounding box wordt gevuld afhankelijk van de input data en is daarom niet hard-coded in deze url.

Ik ben benieuwd of iemand mij wat meer kan vertellen over de werking van de AHN en bounding boxes? In mijn veronderstelling werd een bounding box ingezet als clip op de landsdekkende AHN3 dataset, en zouden rastercellen aan de randen van de bounding box dus ook maar gedeeltelijk ingeladen kunnen worden. Dit lijkt dus niet. Wellicht zit er iets in de url die ik gebruik? Ik heb er zelf ook wat aan gesleuteld.

Met vriendelijke groet,

Vince

Hoi Vince,

Ik liep tegen hetzefde probleem. Ik kreeg pas betrouwbare hoogte waardes toen ik hele raster cellen ging inladen.

Ik weet niet precies de achterliggende technische reden maar mijn logica zegt dat het te maken heeft met de resolutie van de pixels. Via de WCS haal je pixels op van een resolutie van 0.5 x 0.5. Dus om de bijbehorende hoogte data op te halen moet je een bounding box hebben die exact te verdelen valt over de 0.5 x 0.5 resolutie.

groeten,
Jelle

Bedankt voor je reactie Jelle! Mijn bounding box heeft een grootte waar alle 0.5 x 0.5 cellen precies invallen, maar het verbaast me dat er nooit ‘grensgevallen’ zijn, waarbij de bounding box start op bijvoorbeeld de helft van een cel.

In het figuur zie je 2 bounding boxes met de cellen die er precies invallen, terwijl als je de bovenste rij cellen van de onderste bounding box naar boven door zou trekken, ze niet op dezelfde plek komen te liggen als de onderste rij cellen van de bovenste bounding box. Dit voedt mijn vermoeden dat een bounding box niet wordt gebruikt als ‘clip’.

De WCS spec zegt het volgende over de BBOX parameter van een GetCoverage request (sectie 9.2.2.7 BBOX):

For any part of the coverage domain that is partly or entirely contained in the Bounding Box defined by BBOX, the server must return coverage data in the requested format.

Dus elk deel van de coverage in de WCS wat geheel of gedeeltelijk overlapt met de BBOX komt terug in de response. Dit is de reden dat bij een arbitraire BBOX een grote kans is op “overshoot” aan alle kanten.

Dit is te ondervangen door de BBOX zo te kiezen dat deze overeenkomt met de RectifiedGrid van het coverage in de WCS. Het RectifiedGrid van het coverage beschrijft o.a. de afmetingen van de gridcellen en de oorsprong van het grid. Deze definitie is op te vragen middels een WCS DescribeCoverage request, bijv.:

https://service.pdok.nl/rws/ahn/wcs/v1_0?SERVICE=WCS&request=DescribeCoverage&version=1.0.0&coverageId=dtm_05m

Het relevante gedeelte wat betreft de uitlijning van de coverage zit in het gml:RectifiedGrid element van de response:

<gml:origin>
    <gml:pos>10000 618750</gml:pos>
</gml:origin>
<gml:offsetVector>0.5 0</gml:offsetVector>
<gml:offsetVector>0 -0.5</gml:offsetVector>

Dit stelt dat het raster begint op coördinaten 10000,618750 (elders in de response wordt vermeld dat de nativeCRS RD is; EPSG:28992), de breedte van een 1 gridcel 0.5m bij een 0.5m is. Afmetingen zijn in meters want de eenheden van RD zijn in meters. De y-richting is negatief in het RectifiedGrid element, want de origin is gedefinieerd als linksboven. Om een GetCoverage request te maken zonder overshoot zul je dus waardes moet kiezen voor de BBOX coördinaten die een veelvoud zijn van een 0.5 t.o.v. de origin.

Een voorbeeld:

niet-uitgelijnd

wcs - uitgelijnd

De reden achter het niet beschikbaar zijn van een exacte clip operatie op de WCS, is dat zo de data niet geresampled hoeft te worden. Als je de gridcel grootte wijzigt of de origin dan zal er namelijk geresampled moet worden. Bij dit resamplen treedt over het algemeen kwaliteitsverlies op, omdat waardes gemiddeld worden. Vandaar dat het aan te bevelen is resample te voorkomen, mits dat mogelijk is. Daarbij moet dan ook de BBOX precies een veelvoud aan gridcellen groot zijn.

Overigens biedt de WCS ook verschillende resample methodes aan, in het geval je toch een request doet waarbij reresampled moet worden (bij een GetCoverage request met afwijkende resolutie/pixel grootte). Zie de supportedInterpolations in het DescribeCoverage request. Het voert wat te diep om hier de verschillen tussen de resampling methodes uit te leggen. Hier is een gis.stackexchange post die de verschillen kort beschrijft.

Bedankt voor de uitgebreide reactie Anton.

Ik kan de werking van een WCS en een BBOX nu wat meer plaatsen. Wat ik nog niet begrijp, is het volgende:

De GetCoverage requests die ik doe zijn dynamisch, wat wil zeggen dat de BBOX in de URL afhankelijk is van de inputdata. De coordinaten van mijn inputdata zijn nagenoeg nooit een perfect uitgelijnde BBOX (dus een veelvoud van 0.5 t.o.v. de origin). Toch zijn de cellen die ik terug krijg in mijn BBOX (zoals ook te zien in de afbeelding van mijn post hierboven) telkens uitgelijnd, terwijl ik die expliciet niet verwacht.

Betekent dit:

dat de cellen aan de randen van mijn BBOX, dus de ‘overshoots’, worden opgeschoven naar de arbitraire origin van mijn BBOX, zodat de cellen met de door mij gespecificeerde afmetingen er precies invallen?

Dit had ik niet volledig en correct uitgelegd, maar wat je stelt is juist volgens mij. De origin van het request wordt inderdaad per request bepaald aan de hand van de BBOX en de gekozen gridcel grootte.

In bovenstaand screenshot is de kleinste BBOX niet uitgelijnd en geen exact veelvoud van de gridcelgrootte. De WCS genereert dan een coverage waarbij de BBOX volledig uitgevuld is (mits er data aanwezig is).

Wil je uitgelijnde gridcellen tussen meerdere requests dan zal je de BBOX coördinaten die je binnenkrijgt dus moeten omzetten naar de dichtstbijzijnde grid coördinaten. Hier is een stukje Python code wat een x,y coördinaat naar een BBOX van 2x2, wellicht dat het helpt.

1 like

Beste Anton, dank voor deze post. Weliswaar alweer bijna 3 jaar oud, maar volgens mij nog steeds interessant en actueel. Helaas zijn de links naar de voorbeelden verouderd. Kun je deze misschien updaten?

1 like

Ik heb zojuist de URL’s geĂŒpdatet in de post, bedankt voor het melden!