Building heights from DHM — Recipe (QGIS)

Tool-bound implementation of the Building heights from elevation models (Task) Schema, for Danish data. Used in Urban Design Visualisation (Example) (step 1).

Before you start: install the workshop scripts

Four small Processing scripts do the repetitive steps in this Recipe and in Surface partitioning (Recipe - QGIS).

Script fileTool name in QGISWhat it does
clip_visible_layers_to_gpkg.pyClip visible layers to GeoPackageClips all visible layers to the project area and saves them, with styles, in one GeoPackage
building_heights_from_dhm.pyBuilding heights from DHM (surface - terrain)Height, eave height and roof type for every building, with chimneys and trees filtered out
partition_1_build_lines.pyPartition 1 - Build partition linesCollects edges into one line layer and marks gaps
partition_2_polygonize.pyPartition 2 - Polygonize partition linesTurns the cleaned lines into surface polygons with a class drop-down
  1. Processing Toolbox (⚙ icon or Ctrl+Alt+T) → click the Python icon → Add Script to Toolbox…
  2. Select each of the four files.
  3. They appear under Scripts → Workshop tools.

1. Set up the project

  1. New QGIS project. Project → Properties → CRS: EPSG:25832.
  2. Save it in 02_qgis/.
  3. Draw a study area polygon (a new GeoPackage layer) about 200–300 m around the square. Everything is clipped to this.

2. Download the data

From Dataforsyningen (free login):

DatasetUsed forFormat
GeoDanmark vector data – buildings (Bygning)FootprintsGeoPackage / Shapefile
Danmarks Højdemodel – Terræn (DTM)Ground level, contours, terrainGeoTIFF, 0.4 m
Danmarks Højdemodel – Overflade (DSM)Roof heightsGeoTIFF, 0.4 m
Orthophoto (WMS/WMTS service)Background while you work — not in final drawingsWeb service

Save downloads in 01_data/. The two height models can also be added directly as WCS web services — the height tool reads them without a download.

3. Clip everything to the study area

  1. Turn on only the layers you need: buildings, Vejkant, Vejmidte, any other GeoDanmark layers you want in the plan, and the study area.
  2. Run Clip visible layers to GeoPackage: Project area = your polygon, Output = 02_qgis/context.gpkg.
  3. The clipped layers appear in a new group, with their styles. Hide the originals and work only with the clipped layers from now on.

4. Run the height tool

Building heights from DHM (surface - terrain):

  • Buildings: the clipped building layer
  • Surface model (DSM): DHM Overflade · Terrain model (DTM): DHM Terræn (WCS layers or files)
  • Defaults: resolution 0.4 m, inward buffer 0.5 m, percentile 95, outlier filter k = 3, eave percentile 10, flat-roof threshold 1.0 m
  • Optional: save the clipped DTM as 03_exchange/terrain.tif (terrain for Blender) and the nDSM to check the result visually
FieldMeaningUsed for
heightTop of the building / ridge above ground (m)LOD1 extrusion
eaveEstimated eave height above ground (m)LOD2 extrusion, before modelling the roof
roof_riseheight − eave (m)How far to raise the ridge in Blender
roof_typeflat or pitchedWhich buildings need a roof
groundTerrain elevation under the building (m, DVR90)Placing buildings on the terrain
h_medianMedian height (m)Alternative LOD1 height for pitched roofs
h_checkok, few pixels, no data, negativeFinding problems

Check the result: sort the attribute table by h_check. “Few pixels” is usually a shed. A very large roof_rise often means a lower wing inside the same footprint — check it against the orthophoto.

5. Export for Blender

Add an integer field lod: 2 for the 4–8 buildings that frame the square and show in your views, 1 for all others. Then export twice with Export → Save Features As…, each time selecting the buildings first (Select by Expression) and ticking Save only selected features:

FileBuildingsFields to keep
03_exchange/context_lod1.shp"lod" = 1id, height, ground
03_exchange/context_lod2.shp"lod" = 2id, height, eave, roof_rise, roof_type, ground

Format ESRI Shapefile, CRS EPSG:25832. Shapefile field names are cut at 10 characters, which these names respect. Shapefile is only the transport format; the master data stays in context.gpkg.

Troubleshooting

ProblemCauseFix
Height tool cannot read the height modelsWCS service slow or refuses large requestsSelect fewer buildings (Selected features only), or lower the tile size in the script
Very tall or very low buildingsTrees or street pixels in the zonal statisticsIncrease the inward buffer; fix outliers by hand
Eave much too low, roof_rise very largeLower wing or annex inside the same footprintSet the eave by hand from orthophoto / site photos, or split the footprint