Assignment 2

3D city model processing

Deadline is 01 June 2026 at 12:30 pm

Late submission? 10% will be removed for each day that you are late.

You’re allowed for this assignment to work in a group of 3 (and thus submit only one solution for all of you). If you prefer to work alone or in pairs, it’s also fine.

The assignment is worth 20% of your final mark.

cover



Overview

In its current form, the 3DBAG dataset contains for each of the ~11M buildings in the Netherlands:

  1. the 3D geometry at three LoDs: 1.2+1.3+2.2
  2. several attributes, e.g. the construction year, the height of the ground, the type of roof, current status of the building, etc.

For this assignment, you are asked to modify/manipulate the 3DBAG and add some attributes that are useful in practice. Given one tile of the 3DBAG, your programme should do the following:

  1. keep only the LoD2.2 (and remove other LoDs in the file)
  2. put the LoD2.2 geometry into its parent "Building" (and delete the "BuildingPart")
  3. triangulate the geometry (and update all parts related, e.g. semantic surfaces)
  4. calculate the volume of the LoD2.2 geometry and add it as attribute
  5. calculate the total area of the roofs and add it as attribute

The updated model must be delivered in the CityJSON format (v2.0).

Your code should be able to read any 3DBAG file as input

The 3DBAG, developed by the 3D geoinformation group at TU Delft and by 3DGI (and also the topic of Lesson 7.1), is a dataset containing 3D models of all the buildings in the Netherlands. The 3DBAG is open data and it contains 3D models at multiple levels of detail (LoDs), which are generated by combining two open datasets: the building data from the BAG and the height data from the AHN. The 3DBAG is updated regularly, keeping it up-to-date with the latest openly available building stock and elevation information. More details about the 3DBAG are available on its website.

The buildings are tiled, and you can download a tile (which typically contains a few hundred buildings). To start, you can practice on the tile where BK-City is located:

9-284-556.city.json

Methodology/workflow to use

You have to use C++ and the CGAL library to do this assignment.

Your code needs to be a single binary/executable that reads one 3DBAG tile in CityJSON, and it will output a new one with the modifications applied.

You can use any packages of CGAL except the following functions, which you have to code (these are essential for the assignment and it’s one learning objective to learn how to implement those yourself):

(Perhaps we forgot one that is similar to those, but the idea is to learn to code those, so ask us in doubt)

1. Keep only LoD2.2 and merge it to its parents

In the 3DBAG, a "Building" has a "lod": "0" geometry with several attributes, and the 3 LoDs (1.2, 1.3, and 2.2) are in its child "BuildingPart".

For your programme, you need to delete all LoDs except LoD2.2, which you move to its parent. The "BuildingPart" should be deleted.

2. Triangulation of the surfaces

We refer to a triangulation of the surfaces of the buildings, not a volumetric triangulation.

Since you may not use CGAL’s triangulate_face() / triangulate_faces() / triangulate_polygons() functions, you must implement the triangulation yourself. We recommend the following approach (since it works for polygons with holes):

  1. For each polygon (surface) of the building’s LoD2.2 geometry, compute its best-fitting plane using principal component analysis.
  2. Project the polygon’s vertices to 2D using that plane (CGAL’s Plane_3::to_2d()).
  3. Create a constrained 2D triangulation containing all of the polygon’s edges as constraints.
  4. Label each triangle of the 2D triangulation as interior or exterior using the odd-even rule: starting from the infinite face (which is exterior), traverse neighbours; crossing an odd number of constraints means interior, an even number means exterior.
  5. Extract the interior triangles back to 3D using the plane’s to_3d().

Observe that the orientation must be preserved, and validity (with val3dity) must be maintained: if a LoD2.2 geometry is valid in the input file, it should also be valid in the output file.

3. Volume

You have to calculate the volume of each "Building" (their LoD2.2 geometry) and this value needs to stored as a new attribute called "geo1004_volume").

If \(E\) is the exterior boundary/envelope of a building, then we define its volume by \(Vol(E)\).

You have to implement the method yourself, you are thus not allowed to use an off-the-shelf solution that you find somewhere or the CGAL::volume() functions.

Moreover, we prescribe the method that needs to be used, which is a generalisation of the method that you learned in GEO1002. You need to decompose the solid of the building into tetrahedra, and sum the (signed) volume of each.

Observe that the 3DBAG (which you use) already has an attribute b3_volume_lod22; I guess your aim is to verify that those values are correct.

4. Total area of the RoofSurfaces

Also, for each "Building", you need to add one attribute (called "geo1004_total_roof_area") that gives the total area, in square metres, of the surfaces with semantics "RoofSurface".

Requirements for the program

It should take one argument (the input CityJSON file), and output in the same folder as the file a new file called where _out is added before .city.json (so myfile.city.json becomes myfile_out.city.json).

The demo code for hw02 shows how this can be done; feel free to use that code and modify it. You can also start from scratch, it’s up to you.

Requirements for the CityJSON output

  1. use CityJSON version 2.0
  2. the file you produce must be valid according to the CityJSON schema v2.0 (use cjval to verify this).
  3. The only difference allowed is that the order of the properties doesn’t need to be the same since your library might not allow you to have control over this.
  4. Be careful about the types and names of the attributes, they are shown below.

Some tips

Report

The short report should only discuss, for each of the parts (triangulation, area, and volume), the algorithm you used, the engineering decisions you took (why did you do it this way or not another way?), and the difficulties/issues you faced and how you solved them. And add a short section who-did-what (we will check the commits also).

We expect a report of about 4 pages max (including figures).

Marking

Criterion Points
report (quality/readability/etc) 2
file valid + rules respected 1
triangulation 3
volume 2
area of RoofSurfaces 2

What to submit and how to submit it

Everything will be done with GitHub. You have to create a private GitHub repository where all the code, output data, and the report go.

Before the deadline, you need to invite @hugoledoux, @kenohori, and @GinaStavropoulou as collaborators to the repository (how to do this).

After that, email me (h.ledoux@tudelft.nl) with (one email per team):

  1. the URL of the repository,
  2. the name and student number of each member.

Do not add or modify anything after the deadline! You will get penalised for late submission.

The structure of your repository should be as follows (if you have more files before submission, just delete them from the final version please):

├── report
│   └── report.pdf 
│   └── (report.tex if used, if you want)
│   └── (report.docx if used, if you want)
├── data
│   └── nextbk_2b.city.json 
│   └── 9-284-556_out.city.json 
├── cpp
│   └── src/
│       └── main.cpp
│       └── (others *.cpp or *.h if needed)
│   └── include/
│       └── json.hpp
│   └── CMakeLists.txt (it should work with the code you submitted)
├── README.md

The /data folder contains the output you obtain with your code for the 3DBAG tile 9-284-556

In the README.md, add the name and student number of each of the members.

[last updated: 2026-05-13 10:57]