diff --git a/src/ifcgeom/IfcBooleanResult.cpp b/src/ifcgeom/IfcBooleanResult.cpp index 760c2a614a..5e8bd7c2fd 100644 --- a/src/ifcgeom/IfcBooleanResult.cpp +++ b/src/ifcgeom/IfcBooleanResult.cpp @@ -209,8 +209,8 @@ bool IfcGeom::Kernel::convert(const IfcSchema::IfcBooleanResult* l, TopoDS_Shape TopoDS_Compound compound; builder.MakeCompound(compound); builder.Add(compound, s1); - for (const auto& s2 : second_operand_shapes) { - builder.Add(compound, s2); + for (auto& p : opening_vector) { + builder.Add(compound, p.second); } shape = compound; return true; diff --git a/src/ifcgeom_schema_agnostic/boolean_utils.cpp b/src/ifcgeom_schema_agnostic/boolean_utils.cpp index 8d93436a5c..442035d11e 100644 --- a/src/ifcgeom_schema_agnostic/boolean_utils.cpp +++ b/src/ifcgeom_schema_agnostic/boolean_utils.cpp @@ -27,6 +27,7 @@ #include #include #include +#include #include #include @@ -406,6 +407,30 @@ bool IfcGeom::util::is_extrusion(const gp_Vec & v, const TopoDS_Shape & s, TopoD return true; } +int IfcGeom::util::eliminate_narrow_operands(double prec, const TopTools_ListOfShape& bs, TopTools_ListOfShape & c) { + int N = 0; + TopTools_ListIteratorOfListOfShape it(bs); + for (; it.More(); it.Next()) { + + Bnd_OBB box; + BRepBndLib::AddOBB(it.Value(), box, false, false, false); + + auto min_dimension = box.XHSize() < box.YHSize() ? box.XHSize() : box.YHSize(); + min_dimension = min_dimension < box.ZHSize() ? min_dimension : box.ZHSize(); + + bool is_narrow = min_dimension < prec; + + Logger::Notice("Min OBB dimension of operand = " + std::to_string(min_dimension)); + + if (!is_narrow) { + c.Append(it.Value()); + } else { + ++N; + } + } + return N; +} + int IfcGeom::util::eliminate_touching_operands(double prec, const TopoDS_Shape & a, const TopTools_ListOfShape & bs, TopTools_ListOfShape & c) { TopTools_IndexedMapOfShape a_faces; TopExp::MapShapes(a, TopAbs_FACE, a_faces); @@ -806,6 +831,7 @@ bool IfcGeom::util::boolean_operation(const boolean_settings& settings, const To const bool do_unify = true; const bool do_subtraction_eliminate_disjoint_bbox = true; const bool do_subtraction_eliminate_touching = true; + const bool do_eliminate_narrow_obb = true; const bool do_attempt_2d_boolean = settings.attempt_2d; const bool debug = settings.debug; @@ -858,6 +884,8 @@ bool IfcGeom::util::boolean_operation(const boolean_settings& settings, const To b = b_input; } + bool is_2d = count(a, TopAbs_FACE) > 0 && count(a, TopAbs_SHELL) == 0; + bool success = false; BRepAlgoAPI_BooleanOperation* builder; TopTools_ListOfShape b_tmp; @@ -875,7 +903,7 @@ bool IfcGeom::util::boolean_operation(const boolean_settings& settings, const To } } - if (do_subtraction_eliminate_touching) { + if (!is_2d && do_subtraction_eliminate_touching) { PERF("boolean subtraction: eliminate touching"); b_tmp.Clear(); @@ -886,6 +914,17 @@ bool IfcGeom::util::boolean_operation(const boolean_settings& settings, const To } } + if (!is_2d && do_eliminate_narrow_obb) { + PERF("boolean subtraction: eliminate narrow"); + + b_tmp.Clear(); + auto N = eliminate_narrow_operands(fuzziness, b, b_tmp); + if (N) { + Logger::Notice("Eliminated " + std::to_string(N) + " narrow operands"); + std::swap(b, b_tmp); + } + } + } else if (op == BOPAlgo_COMMON) { builder = new BRepAlgoAPI_Common(); } else if (op == BOPAlgo_FUSE) { @@ -895,6 +934,7 @@ bool IfcGeom::util::boolean_operation(const boolean_settings& settings, const To } if (b.Extent() == 0) { + Logger::Warning("No other operands remaining, using first operand"); result = a; return true; } diff --git a/src/ifcgeom_schema_agnostic/boolean_utils.h b/src/ifcgeom_schema_agnostic/boolean_utils.h index 1e67dabed1..3eda7f5c54 100644 --- a/src/ifcgeom_schema_agnostic/boolean_utils.h +++ b/src/ifcgeom_schema_agnostic/boolean_utils.h @@ -81,6 +81,8 @@ namespace IfcGeom { int eliminate_touching_operands(double prec, const TopoDS_Shape& a, const TopTools_ListOfShape& bs, TopTools_ListOfShape& c); + int eliminate_narrow_operands(double prec, const TopTools_ListOfShape& bs, TopTools_ListOfShape & c); + TopoDS_Shape unify(const TopoDS_Shape& s, double tolerance); bool boolean_subtraction_2d_using_builder(const TopoDS_Shape& a_input, const TopTools_ListOfShape& b_input, TopoDS_Shape& result, double eps);