From 437cd1debd6083920b8d1849d2096381b2119f70 Mon Sep 17 00:00:00 2001 From: vsr Date: Fri, 4 Oct 2013 14:29:52 +0000 Subject: [PATCH] 0022258: [CEA 897] Bug in boolean operations on spheres external layer Additional check of arguments of boolean operations is added to avoid passing self-intersted objects to BOP --- src/GEOMImpl/GEOMImpl_BooleanDriver.cxx | 105 ++++++++++++++++++++---- 1 file changed, 87 insertions(+), 18 deletions(-) diff --git a/src/GEOMImpl/GEOMImpl_BooleanDriver.cxx b/src/GEOMImpl/GEOMImpl_BooleanDriver.cxx index e1dccd8d0..a6cf81408 100644 --- a/src/GEOMImpl/GEOMImpl_BooleanDriver.cxx +++ b/src/GEOMImpl/GEOMImpl_BooleanDriver.cxx @@ -39,6 +39,8 @@ #include #include #include +#include +#include #include #include @@ -54,6 +56,13 @@ #include #include +// Comment next macro in order to avoid check of boolean operations arguments for self-intersections +#define BOP_CHECK_SELF_INTERSECTIONS +// Depth of self-intersection check (see BOPAlgo_CheckerSI::SetLevelOfCheck() for more details) +// Default value for BOPAlgo_CheckerSI gives very long computation when checking face-to-face intersections; +// here check level is decreased to more appropriate value to avoid problems with performance). +#define BOP_SELF_INTERSECTIONS_LEVEL 4 + //======================================================================= //function : GetID //purpose : @@ -106,6 +115,22 @@ Standard_Integer GEOMImpl_BooleanDriver::Execute (TFunction_Logbook& log) const if (!ana.IsValid()) StdFail_NotDone::Raise("Boolean operation will not be performed, because argument shape is not valid"); +#ifdef BOP_CHECK_SELF_INTERSECTIONS + BOPAlgo_CheckerSI aCSI; // checker of self-interferences + aCSI.SetLevelOfCheck(BOP_SELF_INTERSECTIONS_LEVEL); + BOPCol_ListOfShape aList1, aList2; + aList1.Append(aShape1); + aList2.Append(aShape2); + aCSI.SetArguments(aList1); + aCSI.Perform(); + if (aCSI.ErrorStatus() || aCSI.DS().Interferences().Extent() > 0) + StdFail_NotDone::Raise("Boolean operation will not be performed, because argument shape is self-intersected"); + aCSI.SetArguments(aList2); + aCSI.Perform(); + if (aCSI.ErrorStatus() || aCSI.DS().Interferences().Extent() > 0) + StdFail_NotDone::Raise("Boolean operation will not be performed, because argument shape is self-intersected"); +#endif + aShape = performOperation (aShape1, aShape2, aType); if (aShape.IsNull()) @@ -127,30 +152,51 @@ Standard_Integer GEOMImpl_BooleanDriver::Execute (TFunction_Logbook& log) const if (nbShapes > 0) { aRefShape = Handle(GEOM_Function)::DownCast(aShapes->Value(1)); aShape = aRefShape->GetValue(); - + if (!aShape.IsNull()) { BRepCheck_Analyzer anAna (aShape, Standard_True); - +#ifdef BOP_CHECK_SELF_INTERSECTIONS + BOPAlgo_CheckerSI aCSI; // checker of self-interferences + aCSI.SetLevelOfCheck(BOP_SELF_INTERSECTIONS_LEVEL); +#endif if (!anAna.IsValid()) { StdFail_NotDone::Raise("Boolean operation will not be performed, because argument shape is not valid"); } +#ifdef BOP_CHECK_SELF_INTERSECTIONS + BOPCol_ListOfShape aList1; + aList1.Append(aShape); + aCSI.SetArguments(aList1); + aCSI.Perform(); + if (aCSI.ErrorStatus() || aCSI.DS().Interferences().Extent() > 0) { + StdFail_NotDone::Raise("Boolean operation will not be performed, because argument shape is self-intersected"); + } +#endif for (i = 2; i <= nbShapes; i++) { - aRefShape = Handle(GEOM_Function)::DownCast(aShapes->Value(i)); - aShape2 = aRefShape->GetValue(); - anAna.Init(aShape2); - - if (!anAna.IsValid()) { - StdFail_NotDone::Raise("Boolean operation will not be performed, because argument shape is not valid"); - } - - aShape = performOperation (aShape, aShape2, aSimpleType); - - if (aShape.IsNull()) { - return 0; - } - } - } + aRefShape = Handle(GEOM_Function)::DownCast(aShapes->Value(i)); + aShape2 = aRefShape->GetValue(); + anAna.Init(aShape2); + + if (!anAna.IsValid()) { + StdFail_NotDone::Raise("Boolean operation will not be performed, because argument shape is not valid"); + } + +#ifdef BOP_CHECK_SELF_INTERSECTIONS + BOPCol_ListOfShape aList2; + aList2.Append(aShape2); + aCSI.SetArguments(aList2); + aCSI.Perform(); + if (aCSI.ErrorStatus() || aCSI.DS().Interferences().Extent() > 0) { + StdFail_NotDone::Raise("Boolean operation will not be performed, because argument shape is self-intersected"); + } +#endif + aShape = performOperation (aShape, aShape2, aSimpleType); + + if (aShape.IsNull()) { + return 0; + } + } + } } } break; @@ -163,11 +209,24 @@ Standard_Integer GEOMImpl_BooleanDriver::Execute (TFunction_Logbook& log) const if (!aShape.IsNull()) { // check arguments for Mantis issue 0021019 BRepCheck_Analyzer anAna (aShape, Standard_True); - +#ifdef BOP_CHECK_SELF_INTERSECTIONS + BOPAlgo_CheckerSI aCSI; // checker of self-interferences + aCSI.SetLevelOfCheck(BOP_SELF_INTERSECTIONS_LEVEL); +#endif if (!anAna.IsValid()) { StdFail_NotDone::Raise("Boolean operation will not be performed, because argument shape is not valid"); } +#ifdef BOP_CHECK_SELF_INTERSECTIONS + BOPCol_ListOfShape aList1; + aList1.Append(aShape); + aCSI.SetArguments(aList1); + aCSI.Perform(); + if (aCSI.ErrorStatus() || aCSI.DS().Interferences().Extent() > 0) { + StdFail_NotDone::Raise("Boolean operation will not be performed, because argument shape is self-intersected"); + } +#endif + Handle(TColStd_HSequenceOfTransient) aTools = aCI.GetShapes(); const Standard_Integer nbShapes = aTools->Length(); Standard_Integer i; @@ -183,6 +242,16 @@ Standard_Integer GEOMImpl_BooleanDriver::Execute (TFunction_Logbook& log) const StdFail_NotDone::Raise("Boolean operation will not be performed, because argument shape is not valid"); } +#ifdef BOP_CHECK_SELF_INTERSECTIONS + BOPCol_ListOfShape aList2; + aList2.Append(aTool); + aCSI.SetArguments(aList2); + aCSI.Perform(); + if (aCSI.ErrorStatus() || aCSI.DS().Interferences().Extent() > 0) { + StdFail_NotDone::Raise("Boolean operation will not be performed, because argument shape is self-intersected"); + } +#endif + aShape = performOperation (aShape, aTool, BOOLEAN_CUT); if (aShape.IsNull()) { -- 2.39.2