From 03d4782cb79d38d1d5cf99d7793e2f0dd4ec7d31 Mon Sep 17 00:00:00 2001 From: Thomas Krijnen Date: Sun, 19 Dec 2021 21:55:41 +0100 Subject: [PATCH] Ground work for processing opening placement up to parent wall --- src/ifcgeom/IfcGeom.h | 15 ++++--- src/ifcgeom/IfcGeomFunctions.cpp | 22 ++++++++++- src/ifcgeom/IfcGeomHelpers.cpp | 44 +++++++++++++++------ src/ifcgeom/IfcGeomIteratorImplementation.h | 4 +- 4 files changed, 64 insertions(+), 21 deletions(-) diff --git a/src/ifcgeom/IfcGeom.h b/src/ifcgeom/IfcGeom.h index efae3ff959..aabf995317 100644 --- a/src/ifcgeom/IfcGeom.h +++ b/src/ifcgeom/IfcGeom.h @@ -275,7 +275,8 @@ private: double precision_factor; // For stopping PlacementRelTo recursion in convert(const IfcSchema::IfcObjectPlacement* l, gp_Trsf& trsf) - const IfcParse::declaration* placement_rel_to; + const IfcParse::declaration* placement_rel_to_type_; + const IfcUtil::IfcBaseEntity* placement_rel_to_instance_; faceset_helper<>* faceset_helper_; double disable_boolean_result; @@ -305,7 +306,8 @@ public: , no_wire_intersection_check(-1) , no_wire_intersection_tolerance(-1) , precision_factor(10.) - , placement_rel_to(nullptr) + , placement_rel_to_type_(nullptr) + , placement_rel_to_instance_(nullptr) , faceset_helper_(nullptr) , disable_boolean_result(-1.) {} @@ -320,7 +322,8 @@ public: , dimensionality(other.dimensionality) // @nb faceset_helper_ always initialized to 0 , layerset_first(other.layerset_first) - , placement_rel_to(other.placement_rel_to) + , placement_rel_to_type_(other.placement_rel_to_type_) + , placement_rel_to_instance_(other.placement_rel_to_instance_) , faceset_helper_(nullptr) , disable_boolean_result(other.disable_boolean_result) @@ -337,7 +340,8 @@ public: ifc_planeangle_unit = other.ifc_planeangle_unit; modelling_precision = other.modelling_precision; dimensionality = other.dimensionality; - placement_rel_to = other.placement_rel_to; + placement_rel_to_type_ = other.placement_rel_to_type_; + placement_rel_to_instance_ = other.placement_rel_to_instance_; layerset_first = other.layerset_first; disable_boolean_result = other.disable_boolean_result; @@ -534,7 +538,8 @@ public: #endif } - void set_conversion_placement_rel_to(const IfcParse::declaration* type); + void set_conversion_placement_rel_to_type(const IfcParse::declaration* type); + void set_conversion_placement_rel_to_instance(const IfcUtil::IfcBaseEntity* instance); #include "mapping_kernel_header.i" diff --git a/src/ifcgeom/IfcGeomFunctions.cpp b/src/ifcgeom/IfcGeomFunctions.cpp index a81d4983c3..3a4681710a 100644 --- a/src/ifcgeom/IfcGeomFunctions.cpp +++ b/src/ifcgeom/IfcGeomFunctions.cpp @@ -1020,6 +1020,23 @@ bool IfcGeom::Kernel::convert_openings_fast(const IfcSchema::IfcProduct* entity, if (fes->declaration().is(IfcSchema::IfcOpeningElement::Class())) { if (!fes->Representation()) continue; + /* + // Not yet implemented and tested, process opening placement up to parent wall + // placement so that the matrix inverse can be eliminated. + // @todo property check and handle the decomposition into parts (where element + // carying geom and opening are in different branches). + // @todo properly check whether opening correctly references wall placement + // and fallback to matrix inverse when not the case. + auto relative = entity; + { + auto ds = relative->Decomposes(); + if (ds->size() == 1) { + relative = (*ds->begin())->RelatingObject()->as(); + } + } + set_conversion_placement_rel_to_instance(relative); + */ + // Convert the IfcRepresentation of the IfcOpeningElement gp_Trsf opening_trsf; if (fes->ObjectPlacement()) { @@ -1032,6 +1049,8 @@ bool IfcGeom::Kernel::convert_openings_fast(const IfcSchema::IfcProduct* entity, } } + // set_conversion_placement_rel_to_instance(nullptr); + // Move the opening into the coordinate system of the IfcProduct opening_trsf.PreMultiply(entity_trsf.Inverted()); @@ -1102,8 +1121,7 @@ bool IfcGeom::Kernel::convert_openings_fast(const IfcSchema::IfcProduct* entity, TopoDS_Shape intermediate_result; if (boolean_operation(result, opening_list, BOPAlgo_CUT, intermediate_result)) { result = intermediate_result; - } - else { + } else { Logger::Message(Logger::LOG_ERROR, "Opening subtraction failed for " + boost::lexical_cast(std::distance(jt, it)) + " openings", entity); } diff --git a/src/ifcgeom/IfcGeomHelpers.cpp b/src/ifcgeom/IfcGeomHelpers.cpp index 3a48581b10..ee2918a1f6 100644 --- a/src/ifcgeom/IfcGeomHelpers.cpp +++ b/src/ifcgeom/IfcGeomHelpers.cpp @@ -415,8 +415,12 @@ bool IfcGeom::Kernel::convert(const IfcSchema::IfcAxis2Placement2D* l, gp_Trsf2d return true; } -void IfcGeom::Kernel::set_conversion_placement_rel_to(const IfcParse::declaration* type) { - placement_rel_to = type; +void IfcGeom::Kernel::set_conversion_placement_rel_to_type(const IfcParse::declaration* type) { + placement_rel_to_type_ = type; +} + +void IfcGeom::Kernel::set_conversion_placement_rel_to_instance(const IfcUtil::IfcBaseEntity* instance) { + placement_rel_to_instance_ = instance; } bool IfcGeom::Kernel::convert(const IfcSchema::IfcObjectPlacement* l, gp_Trsf& trsf) { @@ -427,26 +431,42 @@ bool IfcGeom::Kernel::convert(const IfcSchema::IfcObjectPlacement* l, gp_Trsf& t } IfcSchema::IfcLocalPlacement* current = (IfcSchema::IfcLocalPlacement*)l; for (;;) { + gp_Trsf trsf2; IfcSchema::IfcAxis2Placement* relplacement = current->RelativePlacement(); if (relplacement->as()) { IfcGeom::Kernel::convert(relplacement->as(),trsf2); trsf.PreMultiply(trsf2); } - if ( current->PlacementRelTo() ) { + + if (current->PlacementRelTo()) { IfcSchema::IfcObjectPlacement* parent = current->PlacementRelTo(); - IfcSchema::IfcProduct::list::ptr parentPlaces = parent->PlacesObject(); - bool parentPlacesType = false; - for ( IfcSchema::IfcProduct::list::it iter = parentPlaces->begin(); - iter != parentPlaces->end(); ++iter) { - if ( (*iter)->declaration().is(*placement_rel_to) ) parentPlacesType = true; + + bool parent_placement_ignored = false; + if (placement_rel_to_type_ || placement_rel_to_instance_) { + IfcSchema::IfcProduct::list::ptr parent_places = parent->PlacesObject(); + for (auto iter = parent_places->begin(); iter != parent_places->end(); ++iter) { + if ((placement_rel_to_type_ && (*iter)->declaration().is(*placement_rel_to_type_)) || + (placement_rel_to_instance_ && (*iter)->as() == placement_rel_to_instance_)) { + parent_placement_ignored = true; + } + } } - if ( parentPlacesType ) break; - else if ( parent->declaration().is(IfcSchema::IfcLocalPlacement::Class()) ) + if (parent_placement_ignored) { + // The parent placement of the current is a placement for a type that is + // being ignored (Site or Building) or it is the host element of an opening. + break; + } else if (parent->declaration().is(IfcSchema::IfcLocalPlacement::Class())) { + // Keep processing parent placements current = current->PlacementRelTo()->as(); - else break; - } else break; + } else { + // This is the root placement (typically Site). + break; + } + } else { + break; + } } trsf.PreMultiply(offset_and_rotation); diff --git a/src/ifcgeom/IfcGeomIteratorImplementation.h b/src/ifcgeom/IfcGeomIteratorImplementation.h index cf11b2274f..1f396a6866 100644 --- a/src/ifcgeom/IfcGeomIteratorImplementation.h +++ b/src/ifcgeom/IfcGeomIteratorImplementation.h @@ -1171,9 +1171,9 @@ namespace IfcGeom { if (settings.get(IteratorSettings::SITE_LOCAL_PLACEMENT)) { Logger::Message(Logger::LOG_WARNING, "building-local-placement takes precedence over site-local-placement"); } - kernel.set_conversion_placement_rel_to(&IfcSchema::IfcBuilding::Class()); + kernel.set_conversion_placement_rel_to_type(&IfcSchema::IfcBuilding::Class()); } else if (settings.get(IteratorSettings::SITE_LOCAL_PLACEMENT)) { - kernel.set_conversion_placement_rel_to(&IfcSchema::IfcSite::Class()); + kernel.set_conversion_placement_rel_to_type(&IfcSchema::IfcSite::Class()); } kernel.set_offset(settings.offset); kernel.set_rotation(settings.rotation);