refactor: extract src/ifcutil/ from src/ifcviewer/ (Unit, Geolocation, Placement)

Unit / Geolocation / Placement are schema-agnostic IFC helpers ported
from ifcopenshell.util.{unit,geolocation,placement}. Nothing about
them is viewer-specific: pure IfcParse + Eigen, no Qt, no IfcGeom, no
renderer. Living under src/ifcviewer/ implies an unwanted dependency
direction every time a non-viewer caller (test_federation, the bonsai
SettingsView georef readout, a future standalone IFC tool) wants to
use them.

Move them to a new `src/ifcutil/` static lib (IfcUtil). The lib has
PUBLIC `target_include_directories(${CMAKE_CURRENT_SOURCE_DIR})` so
callers that link IfcUtil can keep `#include "Unit.h"` etc. without
relative-path adjustments — the include dir propagates transitively
via IfcViewer's PUBLIC link.

## Changes

* `git mv src/ifcviewer/{Geolocation,Placement,Unit}.{h,cpp}
   → src/ifcutil/` (history follows the rename).
* `src/ifcutil/CMakeLists.txt`: IfcUtil static lib, PUBLIC links
  IfcParse + Eigen3::Eigen, PUBLIC include dir.
* `cmake/CMakeLists.txt`: `add_subdirectory(../src/ifcutil ifcutil)`
  before ifcviewer/ so the link target exists when IfcViewer's
  CMakeLists runs.
* `src/ifcviewer/CMakeLists.txt`: IfcUtil added to IfcViewer's PUBLIC
  link_libraries.
* `src/ifcviewer/tests/CMakeLists.txt`: test_federation drops the
  explicit `${IFCVIEWER_SRC}/{Unit,Geolocation,Placement}.cpp`
  source list and links `IfcUtil` instead (matches how production
  code resolves the symbols).
* `src/bonsaiviewer/modules/models/SettingsView.cpp`: the two
  explicit `#include "../../../ifcviewer/{Geolocation,Unit}.h"`
  paths swap to `../../../ifcutil/…`. All other callers use bare
  `#include "Unit.h"` style and continue to work via the propagated
  include dir.

## Verification

* `ninja -C build-viewer` builds clean: IfcUtil + IfcViewer +
  IfcViewerMinimal + BonsaiViewer + all four pre-existing
  ifcviewer tests + the two from-wgpu tests.
* `test_federation` runs green: 226 assertions in 22 test cases
  pass with IfcUtil linked instead of the explicit-source compile.
* `git log --follow` traces e.g. `Geolocation.cpp` back through the
  rename to its prior location in src/ifcviewer/.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
Dion Moult
2026-06-04 13:25:28 +10:00
parent 32d9fd6c1c
commit b3fbcd6a66
11 changed files with 74 additions and 12 deletions
+5
View File
@@ -700,6 +700,11 @@ if(BUILD_BONSAIVIEWER_TESTS)
endif()
if(BUILD_BONSAIVIEWER)
# IfcUtil first — schema-agnostic helpers (Unit, Geolocation,
# Placement) that IfcViewer's Federation links against. Adding here
# before ifcviewer/ so the link target exists when IfcViewer's
# CMakeLists runs.
add_subdirectory(../src/ifcutil ifcutil)
# IfcViewer is the unified scene + render lib since the wgpu/ifcviewer
# merge — wgpu-native is fetched inside its CMakeLists.txt.
add_subdirectory(../src/ifcviewer ifcviewer)
@@ -23,9 +23,9 @@
#include "../../SessionState.h"
#include "../../../ifcviewer/Federation.h"
#include "../../../ifcviewer/Geolocation.h"
#include "../../../ifcutil/Geolocation.h"
#include "../../../ifcviewer/SceneLoader.h"
#include "../../../ifcviewer/Unit.h"
#include "../../../ifcutil/Unit.h"
#include <cmath>
+60
View File
@@ -0,0 +1,60 @@
################################################################################
# #
# This file is part of IfcOpenShell. #
# #
# IfcOpenShell is free software: you can redistribute it and/or modify #
# it under the terms of the Lesser GNU General Public License as published by #
# the Free Software Foundation, either version 3.0 of the License, or #
# (at your option) any later version. #
# #
# IfcOpenShell is distributed in the hope that it will be useful, #
# but WITHOUT ANY WARRANTY; without even the implied warranty of #
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the #
# Lesser GNU General Public License for more details. #
# #
# You should have received a copy of the Lesser GNU General Public License #
# along with this program. If not, see <http://www.gnu.org/licenses/>. #
# #
################################################################################
message("Running CMakeLists.txt in /src/ifcutil")
# Schema-agnostic IFC helpers ported from ifcopenshell.util.*. Pure
# IfcParse + Eigen, no Qt, no IfcGeom, no viewer/renderer deps — so unit
# tests and standalone IFC tools can pull them in without dragging
# OpenCASCADE or Qt6 into the link.
#
# Currently:
# * Unit — unit conversions (ifcopenshell.util.unit)
# * Geolocation — IfcMapConversion / WCS / helmert helpers
# (ifcopenshell.util.geolocation)
# * Placement — IfcLocalPlacement / IfcAxis2Placement reduction
# (ifcopenshell.util.placement)
find_package(Eigen3 REQUIRED)
file(GLOB IFCUTIL_CPP_FILES ${CMAKE_CURRENT_SOURCE_DIR}/*.cpp)
file(GLOB IFCUTIL_H_FILES ${CMAKE_CURRENT_SOURCE_DIR}/*.h)
add_library(IfcUtil STATIC ${IFCUTIL_CPP_FILES} ${IFCUTIL_H_FILES})
set_target_properties(IfcUtil PROPERTIES
VERSION "${PROJECT_VERSION}"
SOVERSION "${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}"
)
# PUBLIC: callers (IfcViewer, test_federation, future tools) get
# `#include "Unit.h"` etc. via this directory automatically, no
# `#include "../ifcutil/Unit.h"` ugliness at call sites.
target_include_directories(IfcUtil PUBLIC ${CMAKE_CURRENT_SOURCE_DIR})
target_link_libraries(IfcUtil PUBLIC
IfcParse
Eigen3::Eigen
)
install(TARGETS IfcUtil EXPORT ${IFCOPENSHELL_EXPORT_TARGETS})
install(FILES ${IFCUTIL_H_FILES}
DESTINATION ${INCLUDEDIR}/ifcutil
)
+1
View File
@@ -140,6 +140,7 @@ target_include_directories(IfcViewer PUBLIC ${CMAKE_CURRENT_SOURCE_DIR})
add_dependencies(IfcViewer ${kernel_libraries} ${mapping_libraries})
target_link_libraries(IfcViewer PUBLIC
IfcUtil
IfcGeom
IfcParse
${OpenCASCADE_LIBRARIES}
+6 -10
View File
@@ -66,15 +66,6 @@ find_package(Eigen3 REQUIRED)
add_executable(test_federation
test_federation.cpp
${IFCVIEWER_SRC}/Federation.cpp
# Federation pulls in Unit::convert for federationUnitToMeters and
# Geolocation helpers (helmertMetersFromParameters, getWcs, getMapUnit)
# for computeModelGeoref; compile both directly so the test doesn't
# have to link the whole IfcViewer library (which would drag in
# Qt6::OpenGL, OpenCASCADE, etc.). Placement.cpp provides
# getAxis2Placement, called from Geolocation::getWcs.
${IFCVIEWER_SRC}/Unit.cpp
${IFCVIEWER_SRC}/Geolocation.cpp
${IFCVIEWER_SRC}/Placement.cpp
)
set_target_properties(test_federation PROPERTIES AUTOMOC ON)
target_include_directories(test_federation PRIVATE ${IFCVIEWER_SRC})
@@ -84,6 +75,11 @@ target_link_libraries(test_federation PRIVATE
Qt${QT_VERSION}::Gui # Federation::HomeView uses QVector3D from QtGui
Qt${QT_VERSION}::Test # QSignalSpy
Eigen3::Eigen # Federation.h: composed matrices use Eigen
IfcParse # Unit.cpp uses express::Base / file APIs
# IfcUtil provides Unit::convert + Geolocation helpers
# (helmertMetersFromParameters, getWcs, getMapUnit) + Placement
# (getAxis2Placement, called from Geolocation::getWcs). Linking the
# static lib avoids re-compiling those .cpp files here and pulls
# the IfcUtil include dir + IfcParse transitively.
IfcUtil
)
catch_discover_tests(test_federation)