mirror of
https://github.com/IfcOpenShell/IfcOpenShell.git
synced 2026-09-18 22:33:33 +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
|
// Note that openings for IfcOpeningElements are not processed
|
||||||
auto openings = mapping_->find_openings(product);
|
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";
|
representation_id_builder << "-openings";
|
||||||
for (auto& op : openings) {
|
for (auto& op : openings) {
|
||||||
representation_id_builder << "-" << op.id();
|
representation_id_builder << "-" << op.id();
|
||||||
|
|||||||
@@ -3,9 +3,20 @@
|
|||||||
add_executable(test_ifcopenshell_geometry
|
add_executable(test_ifcopenshell_geometry
|
||||||
test_ifcopenshell_geometry.cpp
|
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
|
catch_discover_tests(test_ifcopenshell_geometry
|
||||||
DL_PATHS
|
DL_PATHS
|
||||||
$<TARGET_FILE_DIR:Catch2::Catch2>
|
$<TARGET_FILE_DIR:Catch2::Catch2>
|
||||||
$<TARGET_FILE_DIR:Catch2::Catch2WithMain>
|
$<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>
|
#include <catch2/catch_test_macros.hpp>
|
||||||
|
|
||||||
TEST_CASE("IfcGeom C++ test scaffold is registered", "[ifcgeom]") {
|
#include "ifcgeom/Converter.h"
|
||||||
REQUIRE(true);
|
#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();
|
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() {
|
void logger::clear() {
|
||||||
std::lock_guard<std::mutex> lock(mutex_);
|
std::lock_guard<std::mutex> lock(mutex_);
|
||||||
log_stream_.str(std::string());
|
log_stream_.str(std::string());
|
||||||
|
|||||||
@@ -24,6 +24,7 @@
|
|||||||
#include "express.h"
|
#include "express.h"
|
||||||
|
|
||||||
#include <boost/scope_exit.hpp>
|
#include <boost/scope_exit.hpp>
|
||||||
|
#include <cstddef>
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
#include <exception>
|
#include <exception>
|
||||||
#include <map>
|
#include <map>
|
||||||
@@ -136,6 +137,7 @@ class IFC_PARSE_API logger {
|
|||||||
|
|
||||||
void progress_bar(int progress);
|
void progress_bar(int progress);
|
||||||
std::string get_log();
|
std::string get_log();
|
||||||
|
std::size_t count(const std::string& code);
|
||||||
void clear();
|
void clear();
|
||||||
void append(logger& other);
|
void append(logger& other);
|
||||||
void print_performance_stats();
|
void print_performance_stats();
|
||||||
|
|||||||
Reference in New Issue
Block a user