MaxVoidsPerElement

This commit is contained in:
Thomas Krijnen
2026-07-09 22:14:31 +02:00
parent 552576fcc3
commit 241b276de0
5 changed files with 109 additions and 5 deletions
+9 -1
View File
@@ -177,7 +177,15 @@ IfcGeom::BRepElement* ifcopenshell::geometry::Converter::create_brep_for_represe
// Note that openings for IfcOpeningElements are not processed
auto openings = mapping_->find_openings(product);
if (!settings_.get<ifcopenshell::geometry::settings::DisableOpeningSubtractions>().get() && !openings.empty()) {
const bool no_openings = openings.empty();
const bool disable_opening_subtractions = settings_.get<ifcopenshell::geometry::settings::DisableOpeningSubtractions>().get();
const bool above_limit = settings_.get<ifcopenshell::geometry::settings::MaxVoidsPerElement>().has() && settings_.get<ifcopenshell::geometry::settings::MaxVoidsPerElement>().get() != 0 && openings.size() > settings_.get<ifcopenshell::geometry::settings::MaxVoidsPerElement>().get();
if (above_limit) {
logger_.warning("GEO", 403, "Element has more openings than the maximum allowed. Openings will not be processed for this element:", product);
}
if (!no_openings && !disable_opening_subtractions && !above_limit) {
representation_id_builder << "-openings";
for (auto& op : openings) {
representation_id_builder << "-" << op.id();
+12 -1
View File
@@ -3,9 +3,20 @@
add_executable(test_ifcopenshell_geometry
test_ifcopenshell_geometry.cpp
)
target_link_libraries(test_ifcopenshell_geometry PRIVATE Catch2::Catch2WithMain)
if(NOT TARGET parse_schema_ifc2x3)
message(FATAL_ERROR "test_ifcopenshell_geometry requires SCHEMA_VERSIONS to include 2x3.")
endif()
target_include_directories(test_ifcopenshell_geometry PRIVATE "${CMAKE_SOURCE_DIR}/../src")
target_link_libraries(test_ifcopenshell_geometry PRIVATE Catch2::Catch2WithMain IfcGeom IfcParse parse_schema_ifc2x3)
add_dependencies(test_ifcopenshell_geometry geometry_mapping_ifc2x3 geometry_kernel_passthrough)
catch_discover_tests(test_ifcopenshell_geometry
DL_PATHS
$<TARGET_FILE_DIR:Catch2::Catch2>
$<TARGET_FILE_DIR:Catch2::Catch2WithMain>
$<TARGET_FILE_DIR:IfcGeom>
$<TARGET_FILE_DIR:IfcParse>
$<TARGET_FILE_DIR:parse_schema_ifc2x3>
$<TARGET_FILE_DIR:plugin>
# Catch2 discovery uses DL_PATHS in order; CTest PATH prepends reverse it.
$<TARGET_FILE_DIR:IfcGeom>
)
@@ -1,7 +1,81 @@
// This file was generated with the assistance of an AI coding tool.
#include <algorithm>
#include <string>
#include <catch2/catch_test_macros.hpp>
TEST_CASE("IfcGeom C++ test scaffold is registered", "[ifcgeom]") {
REQUIRE(true);
#include "ifcgeom/Converter.h"
#include "ifcgeom/kernel_registry.h"
#define IfcSchema Ifc2x3
#include "ifcparse/hierarchy_helper.h"
#include "ifcparse/macros.h"
#include "ifcparse/schemas/Ifc2x3.h"
namespace {
constexpr int MAX_VOIDS = 30;
IfcSchema::IfcWallStandardCase create_wall_with_voids(hierarchy_helper<IfcSchema>& file, int void_count) {
file.header().file_name().setname("wall-with-voids.ifc");
auto wall = file.create<IfcSchema::IfcWallStandardCase>();
wall.setGlobalId(ifcopenshell::global_id());
wall.setName("Wall with " + std::to_string(void_count) + " voids");
file.addBuildingProduct(wall);
const auto owner_history = file.getSingle<IfcSchema::IfcOwnerHistory>();
const auto storey_placement = file.getSingle<IfcSchema::IfcBuildingStorey>().ObjectPlacement();
const double opening_spacing = 350.0;
const double wall_width = std::max(12000.0, void_count * opening_spacing + 1000.0);
const double wall_depth = 360.0;
const double wall_height = 3000.0;
wall.setOwnerHistory(owner_history);
wall.setObjectPlacement(file.addLocalPlacement(storey_placement));
wall.setRepresentation(file.addAxisBox(wall_width, wall_depth, wall_height));
const double first_opening_x = -((void_count - 1) * opening_spacing) / 2.0;
for (int i = 0; i < void_count; ++i) {
auto opening = file.create<IfcSchema::IfcOpeningElement>();
opening.setGlobalId(ifcopenshell::global_id());
opening.setOwnerHistory(owner_history);
opening.setName("Opening " + std::to_string(i + 1));
opening.setObjectPlacement(file.addLocalPlacement(
wall.ObjectPlacement(),
first_opening_x + i * opening_spacing,
0.0,
900.0));
opening.setRepresentation(file.addBox(200.0, wall_depth + 40.0, 1200.0));
auto void_element = file.create<IfcSchema::IfcRelVoidsElement>();
void_element.setGlobalId(ifcopenshell::global_id());
void_element.setOwnerHistory(owner_history);
void_element.setRelatingBuildingElement(wall);
void_element.setRelatedOpeningElement(opening);
}
return wall;
}
std::size_t count_geo403_for_wall(hierarchy_helper<IfcSchema>& file, const IfcSchema::IfcWallStandardCase& wall) {
ifcopenshell::geometry::Settings settings;
settings.set("max-voids-per-element", MAX_VOIDS);
logger log;
log.output_format(logger::FMT_INMEMORY);
ifcopenshell::geometry::Converter converter(
ifcopenshell::geometry::kernels::construct(&file, "opencascade", settings), &file, settings, log);
delete converter.create_brep_for_representation_and_product(wall.Representation().Representations().back(), wall);
return log.count("GEO403");
}
} // namespace
TEST_CASE("IfcGeom C++ fixture creates walls below and above the void limit", "[ifcgeom][voids]") {
hierarchy_helper<IfcSchema> below_limit_file;
const auto below_limit_wall = create_wall_with_voids(below_limit_file, MAX_VOIDS - 1);
REQUIRE(count_geo403_for_wall(below_limit_file, below_limit_wall) == 0);
hierarchy_helper<IfcSchema> above_limit_file;
const auto above_limit_wall = create_wall_with_voids(above_limit_file, MAX_VOIDS + 1);
REQUIRE(count_geo403_for_wall(above_limit_file, above_limit_wall) == 1);
}
+9
View File
@@ -290,6 +290,15 @@ std::string logger::get_log() {
return log_stream_.str();
}
std::size_t logger::count(const std::string& code) {
std::lock_guard<std::mutex> lock(mutex_);
std::size_t count = 0;
for (const auto& message : log_messages_) {
count += code == message.code;
}
return count;
}
void logger::clear() {
std::lock_guard<std::mutex> lock(mutex_);
log_stream_.str(std::string());
+2
View File
@@ -24,6 +24,7 @@
#include "express.h"
#include <boost/scope_exit.hpp>
#include <cstddef>
#include <cstdint>
#include <exception>
#include <map>
@@ -136,6 +137,7 @@ class IFC_PARSE_API logger {
void progress_bar(int progress);
std::string get_log();
std::size_t count(const std::string& code);
void clear();
void append(logger& other);
void print_performance_stats();