Skip to content

Methodiek

Jip Claassens edited this page Jul 14, 2026 · 1 revision

Methodiek Pand Hoogte Nederland (PHN)

PHN koppelt per BAG-pand een hoogte op basis van AHN-hoogterasters (DSM/DTM, 0,5 m resolutie). Output is een landsdekkende tabel met per pand een representatieve hoogte, nokhoogte, tophoogte en kwaliteitsvelden.

Laatst bijgewerkt: juli 2026 (BAG-peildatum 2026-01-01, AHN4/5/6-combinatie).

Inputdata

Bron Bestand Inhoud
BAG pand.mmd (snapshot) Pandgeometrieën, bouwjaar, status; selectie = voorraad op peildatum (CBS-definitie)
AHN AHN4_AHN5_AHN6_combination.gpkg 501 tegels à 10×10 km (RD), met per tegel verwijzingen naar de gebruikte AHN4/5/6-inwinningen
AHN DSM/<tile>_05m.tif, DTM/<tile>_05m.tif Hoogterasters per tegel, 0,5 m; cm boven (NAP + ~100 m offset), uint16
AHN DSM/<tile>_src.tif Provenance: welke AHN-versie (4/5/6) per pixel

Let op het tif-formaat: de waarden zijn centimeters mét een offset van ~+100 m (zodat waarden onder NAP in een unsigned type passen). Gevolg: waarden boven 32.767 cm (≈ 228 m NAP, Zuid-Limburg én de hoogste torens) passen niet in int16. Zie overwegingen.

Verwerkingsketen

Per tegel (parallel over 462 tegels met panden):

  1. Selectie: panden waarvan de centroïde in de tegel valt (point_in_polygon).
  2. Area of Interest: bounding box van die panden + 2 m buffer; DSM en DTM worden hierop uitgesneden (raster_merge).
  3. Rasterisatie: pandpolygonen → grid (poly2grid), zodat elke 0,5 m-cel weet bij welk pand hij hoort.
  4. Maaiveldbepaling per pand: rond elk pand wordt een buffer van gridcellen gelegd (proximity-kernel, ~2,5 m). Van de DTM-waarden in die buffer wordt het 15e percentiel genomen als maaiveldreferentie (buffer_hoogte_offset). Een laag percentiel drukt verstoring door buurpanden, geparkeerde auto's en vegetatie in de buffer.
  5. Dakhoogtebepaling per pand: percentielen van de DSM-waarden binnen de footprint (zie hieronder).
  6. Hoogte = dak − maaiveld (beide inclusief tif-offset; de offset valt in het verschil weg).
  7. Wegschrijven per tegel; daarna worden alle tegels ge-unioneerd tot één landsdekkende tabel.

Outputvelden

Veld Definitie Gebruik
hoogte p70 van DSM in footprint − maaiveld; alleen gevuld als betrouwbaar representatieve pandhoogte
hoogte_ruw idem, óngedrempeld validatie, artefactopsporing
hoogte_nok p80 − maaiveld nokindicatie
hoogte_top p99 − maaiveld tophoogte torens (ruis-robuust ~max)
hoogte_maaiveld_offset maaiveld (15e pct buffer-DTM), inclusief tif-offset diagnose
betrouwbaar zie kwaliteitscriteria filter
bouwjaar, n_pixels, n_pixels_boven_mv BAG-bouwjaar, footprintcellen, dakcellen ≥ 1 m boven maaiveld diagnose
ahn_bron_min / ahn_bron_max oudste/nieuwste AHN-versie binnen footprint (uit _src.tif) temporele duiding

Alle hoogtevelden in cm, int32.

Kwaliteitscriteria (betrouwbaar)

Een pand is betrouwbaar als:

  • 1 m ≤ hoogte ≤ 250 m, én
  • ≥ 4 dakcellen (≈ 1 m²) liggen minstens 1 m boven het buffermaaiveld van het pand.

Onder de 1 m: fysiek onmogelijk als gebouw — in de praktijk nieuwbouw ná de AHN-vlucht (DSM ziet nog maaiveld), sloop, of kassen (laser door glas). Boven de 250 m: geen Nederlands gebouw (hoogste ≈ 215 m) — dit zijn DSM-artefacten (bouwkranen, scanfouten). Bij betrouwbaar = false is hoogte null; hoogte_ruw behoudt de gemeten waarde.

Validatie (BAG 2026): onbetrouwbare panden pieken scherp bij bouwjaar ≥ 2023 — precies de panden die ná de AHN-inwinning zijn gebouwd. Landelijke uitval: ~1,0%.

Overwegingen en leergeld

Percentiel (rth_element) in plaats van mean

De pandhoogte is het 70e percentiel van de DSM-cellen in de footprint, niet het gemiddelde. Het gemiddelde is overwogen en verworpen, want het onderschat structureel:

  • Randcellen van de footprint vangen dakoverstek + maaiveld en trekken het gemiddelde omlaag. Het effect is het grootst bij kleine panden (hoge omtrek/oppervlak-verhouding) en gaf een kunstmatige piek rond 2,5 m.
  • Pieken worden weggemiddeld: een slanke toren met setbacks/plint krijgt een gemiddelde ver onder de top. Concreet: met mean kwam het hoogste gebouw van Nederland uit op 165 m (Maastoren) in plaats van de Zalmhaven (~215 m).

Percentielkeuzes: p70 voor hoogte (representatief dakniveau, ontsnapt aan de randcellen), p80 voor nok, p99 voor top (pakt de piek maar niet de losse ruispixel/antenne). Een echte max is bewust vermeden: één corrupte pixel (vogel, kraan, scanfout) zou de waarde bepalen. De keuze p60 vs p70 is nog niet formeel gevalideerd tegen een referentie (bv. 3D BAG) — openstaand punt.

Value types: int32 in plaats van int16

Twee aparte bugs dwongen de hele keten van cm_int16 naar cm_int32:

  1. Inleeswrap: door de ~+100 m-offset in de tifs overschrijden opgeslagen waarden boven ≈ 228 m NAP het int16-bereik. De conversie wrapte naar negatief, waardoor heel zuidoost-Limburg (Vaals, tot 322 m NAP) op null uitkwam en ook de hoogste Rotterdamse torens corrumpeerden.
  2. Outputcast: GeoDMS' int16() van een waarde > 32.767 geeft null (geen wrap). Daardoor kregen artefact-panden een gevulde hoogte maar een null hoogte_nok/hoogte_top — stille datacorruptie.

Vuistregel: alles wat de absolute tif-waarde (incl. offset) bevat past niet gegarandeerd in int16; verschillen (pandhoogtes) wel, maar één type door de hele keten voorkomt beide fouten.

AHN6-DTM: geen DSM−DTM-criteria gebruiken

In AHN6-tegels (o.a. Zwolle, Arnhem, Groningen) bevat de DTM onder panden het dak in plaats van geïnterpoleerd maaiveld — anders dan bij AHN4/5. Meetbaar: de fractie footprintcellen met DSM−DTM > 1 m is daar mediaal 0,02, tegen 1,00 in AHN4/5-gebied.

Gevolg: elk kwaliteitscriterium op DSM−DTM per cel keurt daar massaal af. Een eerdere versie van het dakpixel-criterium deed dit en veroorzaakte ~50% onterechte uitval in die regio's — wat downstream oogde als regionale dekkingsgaten in PHN. De hoogtes zelf waren steeds correct (die gebruiken de DTM alleen naast het pand, waar hij wél maaiveld is).

Het criterium telt daarom dakcellen ten opzichte van het per-pand buffermaaiveld, nooit DSM−DTM per cel. Na deze fix: uitval Zwolle 51,7% → 1,0%, landelijk 7,8% → 1,0%.

Maaiveld via buffer-percentiel

Maaiveld = 15e percentiel van de DTM in een smalle ring rond het pand. Laag genoeg om obstakels in de ring te negeren, hoog genoeg om niet op één corrupte lage pixel te leunen. Bekende beperking: bij een pand aan diep water of een bouwput kan de referentie te laag uitvallen (zeldzaam; herkenbaar aan extreme hoogte_maaiveld_offset).

Bekende beperkingen

  • Temporele mismatch: panden gebouwd ná de lokale AHN-inwinning hebben geen dak in de DSM → betrouwbaar = false. Dit is de grootste restgroep (~1%), geconcentreerd in nieuwbouwwijken (bv. Zeewolde: 96% van de uitval heeft bouwjaar ≥ 2023). Koppel zo nodig terug op een oudere PHN-versie.
  • Lokale inwinningsgaten: enkele kleine gebieden missen DSM-data in de gecombineerde tifs (bv. deel van Noordoostpolder/Urk, ~1.200 panden). Herkenbaar aan hoogte_ruw = null.
  • Kassen: glas reflecteert de laser slecht; kasgebieden vallen deels uit.
  • Spitsen/masten: p99 vangt de laserpuls-top, niet per se de architectonische hoogte (Zalmhaven meet 204 m op p99 bij 215 m nominaal).
  • De tif-offset (~+100 m) is empirisch afgeleid, niet formeel gedocumenteerd; voor de hoogtes valt hij weg in het dak−maaiveld-verschil.

Reproduceren

  1. GeoDMS, config cfg/main.dms; paden naar AHN/BAG in ConfigSettings/Overridable.
  2. Peildatum in Parameters (BAG_FileDate, BAG_Date).
  3. Draai Results/Koppel_AHN_aan_Pand_perTile/generates/Generate (per-tegel berekening, %LocalDataProjDir%/Temp/PHN_<datum>_<tegel>.mmd), daarna Results/Unioned_Result (landsdekkend bestand).
  4. Na een schemawijziging: eerst de Temp-bestanden én het unionbestand verwijderen; de union herrekent niets en leest anders verouderde tegels.

Kwaliteitsdrempels (min_pandhoogte, max_pandhoogte, min_pixels_boven_mv) staan als parameters in cfg/main.dms.