mirror of
https://github.com/IfcOpenShell/IfcOpenShell.git
synced 2026-08-09 09:21:46 +00:00
MaxVoidsPerElement
This commit is contained in:
@@ -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();
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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());
|
||||
|
||||
@@ -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();
|
||||
|
||||
Reference in New Issue
Block a user