<commit_before>// Copyright (C) 2007-2013  CEA/DEN, EDF R&D, OPEN CASCADE
//
// Copyright (C) 2003-2007  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
// CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, <NAME>
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 2.1 of the License.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
//
// See http://www.salome-platform.org/ or email : <EMAIL>
//

#include <GEOMImpl_BooleanDriver.hxx>
#include <GEOMImpl_IBoolean.hxx>
#include <GEOMImpl_Types.hxx>
#include <GEOMImpl_GlueDriver.hxx>
#include <GEOM_Function.hxx>
#include <GEOMUtils.hxx>

#include <TNaming_CopyShape.hxx>

#include <ShapeFix_ShapeTolerance.hxx>
#include <ShapeFix_Shape.hxx>

#include <BRep_Builder.hxx>
#include <BRepAlgo.hxx>
#include <BRepAlgoAPI_Common.hxx>
#include <BRepAlgoAPI_Cut.hxx>
#include <BRepAlgoAPI_Fuse.hxx>
#include <BRepAlgoAPI_Section.hxx>
#include <BRepCheck_Analyzer.hxx>

#include <TopExp_Explorer.hxx>
#include <TopoDS_Compound.hxx>
#include <TopoDS_Iterator.hxx>
#include <TopTools_MapOfShape.hxx>
#include <TopTools_ListOfShape.hxx>
#include <TopTools_ListIteratorOfListOfShape.hxx>

#include <TColStd_IndexedDataMapOfTransientTransient.hxx>

#include <Precision.hxx>

#include <Standard_ConstructionError.hxx>
#include <StdFail_NotDone.hxx>

//=======================================================================
//function : GetID
//purpose  :
//=======================================================================
const Standard_GUID& GEOMImpl_BooleanDriver::GetID()
{
  static Standard_GUID aBooleanDriver("FF1BBB21-5D14-4df2-980B-3A668264EA16");
  return aBooleanDriver;
}

//=======================================================================
//function : GEOMImpl_BooleanDriver
//purpose  :
//=======================================================================
GEOMImpl_BooleanDriver::GEOMImpl_BooleanDriver()
{
}

//=======================================================================
//function : Execute
//purpose  :
//=======================================================================
Standard_Integer GEOMImpl_BooleanDriver::Execute (TFunction_Logbook& log) const
{
  if (Label().IsNull()) return 0;
  Handle(GEOM_Function) aFunction = GEOM_Function::GetFunction(Label());

  GEOMImpl_IBoolean aCI (aFunction);
  Standard_Integer aType = aFunction->GetType();

  TopoDS_Shape aShape;

  switch (aType) {
  case BOOLEAN_COMMON:
  case BOOLEAN_CUT:
  case BOOLEAN_FUSE:
  case BOOLEAN_SECTION:
    {
      Handle(GEOM_Function) aRefShape1 = aCI.GetShape1();
      Handle(GEOM_Function) aRefShape2 = aCI.GetShape2();
      TopoDS_Shape aShape1 = aRefShape1->GetValue();
      TopoDS_Shape aShape2 = aRefShape2->GetValue();

      if (!aShape1.IsNull() && !aShape2.IsNull()) {
        // check arguments for Mantis issue 0021019
        BRepCheck_Analyzer ana (aShape1, Standard_True);
        if (!ana.IsValid())
          StdFail_NotDone::Raise("Boolean operation will not be performed, because argument shape is not valid");
        ana.Init(aShape2);
        if (!ana.IsValid())
          StdFail_NotDone::Raise("Boolean operation will not be performed, because argument shape is not valid");

        aShape = performOperation (aShape1, aShape2, aType);

        if (aShape.IsNull())
          return 0;
      }
    }
    break;
  case BOOLEAN_COMMON_LIST:
  case BOOLEAN_FUSE_LIST:
    {
      Handle(TColStd_HSequenceOfTransient) aShapes = aCI.GetShapes();
      const Standard_Integer nbShapes = aShapes->Length();
      Standard_Integer i;
      Handle(GEOM_Function) aRefShape;
      TopoDS_Shape aShape2;
      Standard_Integer aSimpleType =
        (aType == BOOLEAN_FUSE_LIST ? BOOLEAN_FUSE : BOOLEAN_COMMON);

      if (nbShapes > 0) {
        aRefShape = Handle(GEOM_Function)::DownCast(aShapes->Value(1));
        aShape = aRefShape->GetValue();

        if (!aShape.IsNull()) {
          BRepCheck_Analyzer anAna (aShape, Standard_True);

          if (!anAna.IsValid()) {
            StdFail_NotDone::Raise("Boolean operation will not be performed, because argument shape is not valid");
          }

          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;
            }
          }
        }
      }
    }
    break;
  case BOOLEAN_CUT_LIST:
    {
      Handle(GEOM_Function) aRefObject = aCI.GetShape1();

      aShape = aRefObject->GetValue();

      if (!aShape.IsNull()) {
        // check arguments for Mantis issue 0021019
        BRepCheck_Analyzer anAna (aShape, Standard_True);

        if (!anAna.IsValid()) {
          StdFail_NotDone::Raise("Boolean operation will not be performed, because argument shape is not valid");
        }

        Handle(TColStd_HSequenceOfTransient) aTools = aCI.GetShapes();
        const Standard_Integer nbShapes = aTools->Length();
        Standard_Integer i;
        Handle(GEOM_Function) aRefTool;
        TopoDS_Shape aTool;

        for (i = 1; i <= nbShapes; i++) {
          aRefTool = Handle(GEOM_Function)::DownCast(aTools->Value(i));
          aTool = aRefTool->GetValue();
          anAna.Init(aTool);

          if (!anAna.IsValid()) {
            StdFail_NotDone::Raise("Boolean operation will not be performed, because argument shape is not valid");
          }

          aShape = performOperation (aShape, aTool, BOOLEAN_CUT);

          if (aShape.IsNull()) {
            return 0;
          }
        }
      }
    }
    break;
  default:
    break;
  }

  aFunction->SetValue(aShape);

  log.SetTouched(Label());

  return 1;
}

//=======================================================================
//function : performOperation
//purpose  :
//=======================================================================
TopoDS_Shape GEOMImpl_BooleanDriver::performOperation
                               (const TopoDS_Shape theShape1,
                                const TopoDS_Shape theShape2,
                                const Standard_Integer theType)const
{<commit_msg>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<commit_after>// Copyright (C) 2007-2013  CEA/DEN, EDF R&D, OPEN CASCADE
//
// Copyright (C) 2003-2007  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
// CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 2.1 of the License.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
//
// See http://www.salome-platform.org/ or email : <EMAIL>
//

#include <GEOMImpl_BooleanDriver.hxx>
#include <GEOMImpl_IBoolean.hxx>
#include <GEOMImpl_Types.hxx>
#include <GEOMImpl_GlueDriver.hxx>
#include <GEOM_Function.hxx>
#include <GEOMUtils.hxx>

#include <TNaming_CopyShape.hxx>

#include <ShapeFix_ShapeTolerance.hxx>
#include <ShapeFix_Shape.hxx>

#include <BRep_Builder.hxx>
#include <BRepAlgo.hxx>
#include <BRepAlgoAPI_Common.hxx>
#include <BRepAlgoAPI_Cut.hxx>
#include <BRepAlgoAPI_Fuse.hxx>
#include <BRepAlgoAPI_Section.hxx>
#include <BRepCheck_Analyzer.hxx>
#include <BOPAlgo_CheckerSI.hxx>
#include <BOPDS_DS.hxx>

#include <TopExp_Explorer.hxx>
#include <TopoDS_Compound.hxx>
#include <TopoDS_Iterator.hxx>
#include <TopTools_MapOfShape.hxx>
#include <TopTools_ListOfShape.hxx>
#include <TopTools_ListIteratorOfListOfShape.hxx>

#include <TColStd_IndexedDataMapOfTransientTransient.hxx>

#include <Precision.hxx>

#include <Standard_ConstructionError.hxx>
#include <StdFail_NotDone.hxx>

// 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  :
//=======================================================================
const Standard_GUID& GEOMImpl_BooleanDriver::GetID()
{
  static Standard_GUID aBooleanDriver("FF1BBB21-5D14-4df2-980B-3A668264EA16");
  return aBooleanDriver;
}

//=======================================================================
//function : GEOMImpl_BooleanDriver
//purpose  :
//=======================================================================
GEOMImpl_BooleanDriver::GEOMImpl_BooleanDriver()
{
}

//=======================================================================
//function : Execute
//purpose  :
//=======================================================================
Standard_Integer GEOMImpl_BooleanDriver::Execute (TFunction_Logbook& log) const
{
  if (Label().IsNull()) return 0;
  Handle(GEOM_Function) aFunction = GEOM_Function::GetFunction(Label());

  GEOMImpl_IBoolean aCI (aFunction);
  Standard_Integer aType = aFunction->GetType();

  TopoDS_Shape aShape;

  switch (aType) {
  case BOOLEAN_COMMON:
  case BOOLEAN_CUT:
  case BOOLEAN_FUSE:
  case BOOLEAN_SECTION:
    {
      Handle(GEOM_Function) aRefShape1 = aCI.GetShape1();
      Handle(GEOM_Function) aRefShape2 = aCI.GetShape2();
      TopoDS_Shape aShape1 = aRefShape1->GetValue();
      TopoDS_Shape aShape2 = aRefShape2->GetValue();

      if (!aShape1.IsNull() && !aShape2.IsNull()) {
        // check arguments for Mantis issue 0021019
        BRepCheck_Analyzer ana (aShape1, Standard_True);
        if (!ana.IsValid())
          StdFail_NotDone::Raise("Boolean operation will not be performed, because argument shape is not valid");
        ana.Init(aShape2);
        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())
          return 0;
      }
    }
    break;
  case BOOLEAN_COMMON_LIST:
  case BOOLEAN_FUSE_LIST:
    {
      Handle(TColStd_HSequenceOfTransient) aShapes = aCI.GetShapes();
      const Standard_Integer nbShapes = aShapes->Length();
      Standard_Integer i;
      Handle(GEOM_Function) aRefShape;
      TopoDS_Shape aShape2;
      Standard_Integer aSimpleType =
        (aType == BOOLEAN_FUSE_LIST ? BOOLEAN_FUSE : BOOLEAN_COMMON);

      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");
	    }
	    
#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;
  case BOOLEAN_CUT_LIST:
    {
      Handle(GEOM_Function) aRefObject = aCI.GetShape1();

      aShape = aRefObject->GetValue();

      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;
        Handle(GEOM_Function) aRefTool;
        TopoDS_Shape aTool;

        for (i = 1; i <= nbShapes; i++) {
          aRefTool = Handle(GEOM_Function)::DownCast(aTools->Value(i));
          aTool = aRefTool->GetValue();
          anAna.Init(aTool);

          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(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()) {
            return 0;
          }
        }
      }
    }
    break;
  default:
    break;
  }

  aFunction->SetValue(aShape);

  log.SetTouched(Label());

  return 1;
}

//=======================================================================
//function : performOperation
//purpose  :
//=======================================================================
TopoDS_Shape GEOMImpl_BooleanDriver::performOperation
                               (const TopoDS_Shape theShape1,
                                const TopoDS_Shape theShape2,
                                const Standard_Integer theType)const
{
{'fraction_non_alphanumeric': 0.16785988994734038, 'fraction_numerical': 0.013726998402461393, 'mean_word_length': 3.6626206896551725, 'pattern_counts': {'":': 0, '<': 64, '<?xml version=': 0, '>': 94, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6801616', 'n_tokens_mistral': 5575, 'n_tokens_neox': 5235, 'n_words': 1219}