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 file | Tool name in QGIS | What it does |
|---|---|---|
clip_visible_layers_to_gpkg.py | Clip visible layers to GeoPackage | Clips all visible layers to the project area and saves them, with styles, in one GeoPackage |
building_heights_from_dhm.py | Building heights from DHM (surface - terrain) | Height, eave height and roof type for every building, with chimneys and trees filtered out |
partition_1_build_lines.py | Partition 1 - Build partition lines | Collects edges into one line layer and marks gaps |
partition_2_polygonize.py | Partition 2 - Polygonize partition lines | Turns the cleaned lines into surface polygons with a class drop-down |
- Processing Toolbox (⚙ icon or Ctrl+Alt+T) → click the Python icon → Add Script to Toolbox…
- Select each of the four files.
- They appear under Scripts → Workshop tools.
1. Set up the project
- New QGIS project. Project → Properties → CRS:
EPSG:25832. - Save it in
02_qgis/. - 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):
| Dataset | Used for | Format |
|---|---|---|
| GeoDanmark vector data – buildings (Bygning) | Footprints | GeoPackage / Shapefile |
| Danmarks Højdemodel – Terræn (DTM) | Ground level, contours, terrain | GeoTIFF, 0.4 m |
| Danmarks Højdemodel – Overflade (DSM) | Roof heights | GeoTIFF, 0.4 m |
| Orthophoto (WMS/WMTS service) | Background while you work — not in final drawings | Web 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
- Turn on only the layers you need: buildings, Vejkant, Vejmidte, any other GeoDanmark layers you want in the plan, and the study area.
- Run Clip visible layers to GeoPackage: Project area = your polygon, Output =
02_qgis/context.gpkg. - 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
| Field | Meaning | Used for |
|---|---|---|
height | Top of the building / ridge above ground (m) | LOD1 extrusion |
eave | Estimated eave height above ground (m) | LOD2 extrusion, before modelling the roof |
roof_rise | height − eave (m) | How far to raise the ridge in Blender |
roof_type | flat or pitched | Which buildings need a roof |
ground | Terrain elevation under the building (m, DVR90) | Placing buildings on the terrain |
h_median | Median height (m) | Alternative LOD1 height for pitched roofs |
h_check | ok, few pixels, no data, negative | Finding 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:
| File | Buildings | Fields to keep |
|---|---|---|
03_exchange/context_lod1.shp | "lod" = 1 | id, height, ground |
03_exchange/context_lod2.shp | "lod" = 2 | id, 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
| Problem | Cause | Fix |
|---|---|---|
| Height tool cannot read the height models | WCS service slow or refuses large requests | Select fewer buildings (Selected features only), or lower the tile size in the script |
| Very tall or very low buildings | Trees or street pixels in the zonal statistics | Increase the inward buffer; fix outliers by hand |
Eave much too low, roof_rise very large | Lower wing or annex inside the same footprint | Set the eave by hand from orthophoto / site photos, or split the footprint |