Contributors: Arda Baysal · Daman Dogra · Tejas Ziegler
mkdir build && cd build
cmake .. -DCMAKE_BUILD_TYPE=Release
make -j4or more modern:
cmake -B build -DCMAKE_BUILD_TYPE=Release
cmake --build build
Requires: CMake ≥ 3.16, CGAL, C++17 compiler.
Before running the C++ pipeline, convert the source IFC to OBJ. This requires IfcConvert from the IfcOpenShell library.
How to run:
If you are using the provided Conda environment (ifco_env), you can call IfcConvert directly. If you are using a standalone executable, ensure the .exe is in your project root and use ./IfcConvert instead.
Run the following command from the repository root: for wellness_center_sama.ifc:
IfcConvert data/input/Wellness_center_Sama.ifc data/intermediate/Wellness_center_Sama.obj `
--include entities IfcWall IfcSlab IfcRoof IfcWindow IfcDoor `
--exclude entities IfcSite IfcOpeningElement IfcFurnishingElement IfcBuildingElementProxy IfcFlowTerminal IfcStair IfcRailing `
--use-element-names `
--reorient-shells
or macOS-friendly:
IfcConvert data/input/Duplex.ifc data/intermediate/Duplex.obj \
--include entities IfcWall IfcSlab IfcRoof IfcWindow IfcDoor \
--exclude entities IfcSite IfcOpeningElement IfcFurnishingElement IfcBuildingElementProxy IfcFlowTerminal IfcStair IfcRailing \
--use-element-names \
--reorient-shells
The resulting OBJ file(s) must be placed in data/intermediate/.
This is the default configuration that reproduces the submitted CityJSON and the best result in the report (voxel size 0.25 m, with min_width = 0.3 m hard-coded into src/marker.cpp). Note: a 0.25 m grid is the slow, fine-resolution case.
./build/bim2geo data/intermediate/Wellness_center_Sama.obj 0.25 data/output/Wellness_center_Sama_0.25.city.json
Arguments:
| Position | Description | Example |
|---|---|---|
| 1 | Path to input OBJ | data/intermediate/mybuilding.obj |
| 2 | Voxel size in metres | 0.5 |
| 3 | Path to output CityJSON | data/output/mybuilding.city.json |
The voxel-size sweep figures in the report are generated by two helper scripts.
Both scripts use paths relative to the repository root, so run every command
from inside GEO1004_HW3/.
- The
bim2geobinary is built incmake-build-debug/(see the build instructions above). The sweep does not compile — it calls the existing binary, so rebuild after any source change. - The intermediate meshes exist in
data/intermediate/*.obj(produced by the IfcConvert step). - Python 3 with
matplotlibis installed (pip install matplotlib). - The folder
data/output/exists (the binary writes results there).
- Build the binary (or press Run in the IDE), so
cmake-build-debug/bim2geois up to date withsrc/marker.cpp. - Run the sweep — this voxelises every OBJ in
data/intermediate/at voxel sizes 1.0 → 0.1 (step 0.05) and writes one CityJSON per (building, size):
bash data/voxel_size_sweep
- Plot the room counts (one panel per building):
python data/room_analysis.py
The two filters are compile-time constants in src/marker.cpp
(min_volume, in m³, and min_width, in m). To regenerate a specific figure,
set the values below, rebuild, clear old results
(rm data/output/*.city.json, so the plot is not contaminated by a previous
configuration), then rerun steps 2–3:
| Figure (label) | min_volume |
min_width |
|---|---|---|
vanilla (no filtering) |
0.0 |
0.0* |
min_volume (6 m³ / 4 m³) |
6.0 / 4.0 |
0.0* |
min_width = 0.3 |
0.0 |
0.3 |
*To make min_width = 0.0 a true "off" switch, the one-line floor
if (k < 1) k = 1; in room_marker() must be removed (otherwise one erosion
pass always runs regardless of min_width).
room_analysis.py parses <building>_<voxelsize>.city.json by splitting on the
last underscore, so building names may contain underscores
(e.g. Wellness_center_Sama_0.40.city.json) but the voxel size must be the final
_<number> before .city.json. Files that don't match are skipped.
geo1004-hw3/
├── CMakeLists.txt
├── README.md
├── data/
│ ├── input/ ← place source IFC file here
│ ├── intermediate/ ← OBJ file(s) from IfcConvert go here
│ └── output/ ← generated CityJSON written here & experiment scripts
├── include/
│ ├── obj_reader.h (Person A)
│ ├── voxel_grid.h (Person A)
│ ├── voxeliser.h (Person B)
│ ├── marker.h (Person B)
│ ├── surface_extractor.h (Person C)
│ └── cityjson_writer.h (Person C)
├── src/
│ ├── main.cpp
│ ├── obj_reader.cpp (Person A)
│ ├── voxel_grid.cpp (Person A)
│ ├── voxeliser.cpp (Person B)
│ ├── marker.cpp (Person B)
│ ├── surface_extractor.cpp (Person C)
│ └── cityjson_writer.cpp (Person C)
└── report/
└── report.pdf