Salome HOME
0023588: [CEA 2272] : GEOM test failed after transition to OCC 7.3
[modules/geom.git] / src / GEOMImpl / GEOMImpl_IMeasureOperations.cxx
index 8bc4768d5ebada6c1cb66eb26fddccf5c7ba178c..a06332644285efcee503ab9dcc6dbfac9d83bc89 100644 (file)
@@ -1,4 +1,4 @@
-// Copyright (C) 2007-2014  CEA/DEN, EDF R&D, OPEN CASCADE
+// Copyright (C) 2007-2016  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
 // OCCT Includes
 #include <Bnd_Box.hxx>
 #include <BOPAlgo_CheckerSI.hxx>
-#include <BOPCol_ListOfShape.hxx>
+#include <TopTools_ListOfShape.hxx>
 #include <BOPDS_DS.hxx>
-#include <BOPDS_MapOfPassKey.hxx>
+#include <BOPDS_MapOfPair.hxx>
+#include <BOPDS_Pair.hxx>
 #include <BRepBndLib.hxx>
 #include <BRepBuilderAPI_Copy.hxx>
 #include <BRepCheck_ListIteratorOfListOfStatus.hxx>
@@ -48,6 +49,9 @@
 #include <BRepClass3d_SolidClassifier.hxx>
 #include <BRepClass_FaceClassifier.hxx>
 #include <BRepExtrema_DistShapeShape.hxx>
+#include <BRepExtrema_ShapeProximity.hxx>
+#include <BRepExtrema_SelfIntersection.hxx>
+#include <BRepExtrema_MapOfIntegerPackedMapOfInteger.hxx>
 #include <BRepGProp.hxx>
 #include <BRepTools.hxx>
 #include <BRep_Tool.hxx>
@@ -56,6 +60,7 @@
 #include <GeomAPI_ProjectPointOnSurf.hxx>
 #include <GeomLProp_CLProps.hxx>
 #include <GeomLProp_SLProps.hxx>
+#include <Geom_Plane.hxx>
 #include <GProp_GProps.hxx>
 #include <GProp_PrincipalProps.hxx>
 #include <ShapeAnalysis.hxx>
 #include <TopoDS_Edge.hxx>
 #include <TopTools_IndexedMapOfShape.hxx>
 #include <TopTools_DataMapIteratorOfDataMapOfIntegerListOfShape.hxx>
+#include <TColStd_MapIteratorOfPackedMapOfInteger.hxx>
 #include <TopTools_ListIteratorOfListOfShape.hxx>
 #include <TopTools_ListOfShape.hxx>
 #include <Standard_ErrorHandler.hxx> // CAREFUL ! position of this file is critic : see Lucien PIGNOLONI / OCC
 
+#include <set>
+
 //=============================================================================
 /*!
  *  Constructor
  */
 //=============================================================================
-GEOMImpl_IMeasureOperations::GEOMImpl_IMeasureOperations (GEOM_Engine* theEngine, int theDocID)
-: GEOM_IOperations(theEngine, theDocID)
+GEOMImpl_IMeasureOperations::GEOMImpl_IMeasureOperations (GEOM_Engine* theEngine)
+: GEOM_IOperations(theEngine)
 {
   MESSAGE("GEOMImpl_IMeasureOperations::GEOMImpl_IMeasureOperations");
 }
@@ -121,7 +129,7 @@ GEOMImpl_IMeasureOperations::ShapeKind GEOMImpl_IMeasureOperations::KindOfShape
   int geom_type = theShape->GetType();
 
   // check if it's advanced shape
-  if ( geom_type > ADVANCED_BASE ) {
+  if ( geom_type > USER_TYPE ) {
     SetErrorCode(OK);
     return SK_ADVANCED;
   }
@@ -130,14 +138,48 @@ GEOMImpl_IMeasureOperations::ShapeKind GEOMImpl_IMeasureOperations::KindOfShape
   GEOMAlgo_ShapeInfoFiller aSF;
   aSF.SetShape(aShape);
   aSF.Perform();
+
   Standard_Integer iErr = aSF.ErrorStatus();
+
   if (iErr) {
     SetErrorCode("Error in GEOMAlgo_ShapeInfoFiller");
     return SK_NO_SHAPE;
   }
   const GEOMAlgo_ShapeInfo& anInfo = aSF.Info();
 
-  // Interprete results
+  // specific processing for some "advanced" objects
+  switch ( geom_type ) {
+  case GEOM_MARKER:
+    // local coordinate system
+    // (+) geompy.kind.LCS  xc yc zc xx xy xz yx yy yz zx zy zz
+
+    TopoDS_Face aFace = TopoDS::Face( aShape );
+    Handle(Geom_Plane) aPlane = Handle(Geom_Plane)::DownCast( BRep_Tool::Surface( aFace ) );
+    gp_Pnt aC = aPlane->Pln().Location();
+    gp_Ax3 anAx3 = aPlane->Pln().Position();
+
+    theDoubles->Append(aC.X());
+    theDoubles->Append(aC.Y());
+    theDoubles->Append(aC.Z());
+    
+    gp_Dir aD = anAx3.XDirection();
+    theDoubles->Append(aD.X());
+    theDoubles->Append(aD.Y());
+    theDoubles->Append(aD.Z());
+    aD = anAx3.YDirection();
+    theDoubles->Append(aD.X());
+    theDoubles->Append(aD.Y());
+    theDoubles->Append(aD.Z());
+    aD = anAx3.Direction();
+    theDoubles->Append(aD.X());
+    theDoubles->Append(aD.Y());
+    theDoubles->Append(aD.Z());
+
+    SetErrorCode(OK);
+    return SK_LCS;
+  }
+
+  // Interpret results
   TopAbs_ShapeEnum aType = anInfo.Type();
   switch (aType)
   {
@@ -518,35 +560,22 @@ GEOMImpl_IMeasureOperations::ShapeKind GEOMImpl_IMeasureOperations::KindOfShape
           theDoubles->Append(aD.X());
           theDoubles->Append(aD.Y());
           theDoubles->Append(aD.Z());
+
+          if (anInfo.KindOfBounds() != GEOMAlgo_KB_INFINITE)
+          {
+            // (+) geompy.kind.PLANAR  xo yo zo  dx dy dz  nb_edges nb_vertices
+            aKind = SK_PLANAR;
+            
+            theIntegers->Append(anInfo.NbSubShapes(TopAbs_EDGE));
+            theIntegers->Append(anInfo.NbSubShapes(TopAbs_VERTEX));
+          }
         }
         break;
       default:
-        if (anInfo.KindOfShape() == GEOMAlgo_KS_PLANE) {
-          // (+) geompy.kind.PLANAR  xo yo zo  dx dy dz  nb_edges nb_vertices
-
-          aKind = SK_PLANAR;
-
-          gp_Pnt aC = anInfo.Location();
-          theDoubles->Append(aC.X());
-          theDoubles->Append(aC.Y());
-          theDoubles->Append(aC.Z());
-
-          gp_Ax3 anAx3 = anInfo.Position();
-          gp_Dir aD = anAx3.Direction();
-          theDoubles->Append(aD.X());
-          theDoubles->Append(aD.Y());
-          theDoubles->Append(aD.Z());
-
-          theIntegers->Append(anInfo.NbSubShapes(TopAbs_EDGE));
-          theIntegers->Append(anInfo.NbSubShapes(TopAbs_VERTEX));
-        }
-        else {
-          // ??? geompy.kind.FACE  nb_edges nb_vertices _surface_type_id_
-          // (+) geompy.kind.FACE  nb_edges nb_vertices
-
-          theIntegers->Append(anInfo.NbSubShapes(TopAbs_EDGE));
-          theIntegers->Append(anInfo.NbSubShapes(TopAbs_VERTEX));
-        }
+        // ??? geompy.kind.FACE  nb_edges nb_vertices _surface_type_id_
+        // (+) geompy.kind.FACE  nb_edges nb_vertices
+        theIntegers->Append(anInfo.NbSubShapes(TopAbs_EDGE));
+        theIntegers->Append(anInfo.NbSubShapes(TopAbs_VERTEX));
       }
     }
     break;
@@ -707,6 +736,7 @@ GEOMImpl_IMeasureOperations::ShapeKind GEOMImpl_IMeasureOperations::KindOfShape
       theDoubles->Append(aP.Z());
     }
     break;
+  default:;
   }
 
   SetErrorCode(OK);
@@ -755,9 +785,8 @@ void GEOMImpl_IMeasureOperations::GetPosition
     aDirZ.Coord(Zx, Zy, Zz);
     aDirX.Coord(Xx, Xy, Xz);
   }
-  catch (Standard_Failure) {
-    Handle(Standard_Failure) aFail = Standard_Failure::Caught();
-    SetErrorCode(aFail->GetMessageString());
+  catch (Standard_Failure& aFail) {
+    SetErrorCode(aFail.GetMessageString());
     return;
   }
 
@@ -777,7 +806,7 @@ Handle(GEOM_Object) GEOMImpl_IMeasureOperations::GetCentreOfMass
   if (theShape.IsNull()) return NULL;
 
   //Add a new CentreOfMass object
-  Handle(GEOM_Object) aCDG = GetEngine()->AddObject(GetDocID(), GEOM_CDG);
+  Handle(GEOM_Object) aCDG = GetEngine()->AddObject(GEOM_CDG);
 
   //Add a new CentreOfMass function
   Handle(GEOM_Function) aFunction =
@@ -802,9 +831,8 @@ Handle(GEOM_Object) GEOMImpl_IMeasureOperations::GetCentreOfMass
       return NULL;
     }
   }
-  catch (Standard_Failure) {
-    Handle(Standard_Failure) aFail = Standard_Failure::Caught();
-    SetErrorCode(aFail->GetMessageString());
+  catch (Standard_Failure& aFail) {
+    SetErrorCode(aFail.GetMessageString());
     return NULL;
   }
 
@@ -832,7 +860,7 @@ Handle(GEOM_Object) GEOMImpl_IMeasureOperations::GetVertexByIndex
   if (aRefShape.IsNull()) return NULL;
 
   //Add a new Vertex object
-  Handle(GEOM_Object) aVertex = GetEngine()->AddObject(GetDocID(), GEOM_POINT);
+  Handle(GEOM_Object) aVertex = GetEngine()->AddObject(GEOM_POINT);
 
   //Add a function
   Handle(GEOM_Function) aFunction =
@@ -854,9 +882,8 @@ Handle(GEOM_Object) GEOMImpl_IMeasureOperations::GetVertexByIndex
       return NULL;
     }
   }
-  catch (Standard_Failure) {
-    Handle(Standard_Failure) aFail = Standard_Failure::Caught();
-    SetErrorCode(aFail->GetMessageString());
+  catch (Standard_Failure& aFail) {
+    SetErrorCode(aFail.GetMessageString());
     return NULL;
   }
 
@@ -881,7 +908,7 @@ Handle(GEOM_Object) GEOMImpl_IMeasureOperations::GetNormal
   if (theFace.IsNull()) return NULL;
 
   //Add a new Normale object
-  Handle(GEOM_Object) aNorm = GetEngine()->AddObject(GetDocID(), GEOM_VECTOR);
+  Handle(GEOM_Object) aNorm = GetEngine()->AddObject(GEOM_VECTOR);
 
   //Add a new Normale function
   Handle(GEOM_Function) aFunction =
@@ -911,9 +938,8 @@ Handle(GEOM_Object) GEOMImpl_IMeasureOperations::GetNormal
       return NULL;
     }
   }
-  catch (Standard_Failure) {
-    Handle(Standard_Failure) aFail = Standard_Failure::Caught();
-    SetErrorCode(aFail->GetMessageString());
+  catch (Standard_Failure& aFail) {
+    SetErrorCode(aFail.GetMessageString());
     return NULL;
   }
 
@@ -935,6 +961,7 @@ Handle(GEOM_Object) GEOMImpl_IMeasureOperations::GetNormal
  */
 //=============================================================================
 void GEOMImpl_IMeasureOperations::GetBasicProperties (Handle(GEOM_Object) theShape,
+                                                      const Standard_Real theTolerance,
                                                       Standard_Real& theLength,
                                                       Standard_Real& theSurfArea,
                                                       Standard_Real& theVolume)
@@ -954,26 +981,26 @@ void GEOMImpl_IMeasureOperations::GetBasicProperties (Handle(GEOM_Object) theSha
 
   //Compute the parameters
   GProp_GProps LProps, SProps;
+  Standard_Real anEps = theTolerance >= 0 ? theTolerance : 1.e-6;
   try {
     OCC_CATCH_SIGNALS;
-    BRepGProp::LinearProperties(aShape, LProps);
+    BRepGProp::LinearProperties(aShape, LProps, Standard_True);
     theLength = LProps.Mass();
 
-    BRepGProp::SurfaceProperties(aShape, SProps);
+    BRepGProp::SurfaceProperties(aShape, SProps, anEps, Standard_True);
     theSurfArea = SProps.Mass();
 
     theVolume = 0.0;
     if (aShape.ShapeType() < TopAbs_SHELL) {
       for (TopExp_Explorer Exp (aShape, TopAbs_SOLID); Exp.More(); Exp.Next()) {
         GProp_GProps VProps;
-        BRepGProp::VolumeProperties(Exp.Current(), VProps);
+        BRepGProp::VolumeProperties(Exp.Current(), VProps, anEps, Standard_True);
         theVolume += VProps.Mass();
       }
     }
   }
-  catch (Standard_Failure) {
-    Handle(Standard_Failure) aFail = Standard_Failure::Caught();
-    SetErrorCode(aFail->GetMessageString());
+  catch (Standard_Failure& aFail) {
+    SetErrorCode(aFail.GetMessageString());
     return;
   }
 
@@ -1013,12 +1040,12 @@ void GEOMImpl_IMeasureOperations::GetInertia
     if (aShape.ShapeType() == TopAbs_VERTEX ||
         aShape.ShapeType() == TopAbs_EDGE ||
         aShape.ShapeType() == TopAbs_WIRE) {
-      BRepGProp::LinearProperties(aShape, System);
+      BRepGProp::LinearProperties(aShape, System, Standard_True);
     } else if (aShape.ShapeType() == TopAbs_FACE ||
                aShape.ShapeType() == TopAbs_SHELL) {
-      BRepGProp::SurfaceProperties(aShape, System);
+      BRepGProp::SurfaceProperties(aShape, System, Standard_True);
     } else {
-      BRepGProp::VolumeProperties(aShape, System);
+      BRepGProp::VolumeProperties(aShape, System, Standard_True);
     }
     gp_Mat I = System.MatrixOfInertia();
 
@@ -1037,9 +1064,8 @@ void GEOMImpl_IMeasureOperations::GetInertia
     GProp_PrincipalProps Pr = System.PrincipalProperties();
     Pr.Moments(Ix,Iy,Iz);
   }
-  catch (Standard_Failure) {
-    Handle(Standard_Failure) aFail = Standard_Failure::Caught();
-    SetErrorCode(aFail->GetMessageString());
+  catch (Standard_Failure& aFail) {
+    SetErrorCode(aFail.GetMessageString());
     return;
   }
 
@@ -1098,9 +1124,8 @@ void GEOMImpl_IMeasureOperations::GetBoundingBox
 
     B.Get(Xmin, Ymin, Zmin, Xmax, Ymax, Zmax);
   }
-  catch (Standard_Failure) {
-    Handle(Standard_Failure) aFail = Standard_Failure::Caught();
-    SetErrorCode(aFail->GetMessageString());
+  catch (Standard_Failure& aFail) {
+    SetErrorCode(aFail.GetMessageString());
     return;
   }
 
@@ -1121,7 +1146,7 @@ Handle(GEOM_Object) GEOMImpl_IMeasureOperations::GetBoundingBox
   if (theShape.IsNull()) return NULL;
 
   //Add a new BoundingBox object
-  Handle(GEOM_Object) aBnd = GetEngine()->AddObject(GetDocID(), GEOM_BOX);
+  Handle(GEOM_Object) aBnd = GetEngine()->AddObject(GEOM_BOX);
 
   //Add a new BoundingBox function
   const int aType = (precise ? BND_BOX_MEASURE_PRECISE : BND_BOX_MEASURE);
@@ -1147,9 +1172,8 @@ Handle(GEOM_Object) GEOMImpl_IMeasureOperations::GetBoundingBox
       return NULL;
     }
   }
-  catch (Standard_Failure) {
-    Handle(Standard_Failure) aFail = Standard_Failure::Caught();
-    SetErrorCode(aFail->GetMessageString());
+  catch (Standard_Failure& aFail) {
+    SetErrorCode(aFail.GetMessageString());
     return NULL;
   }
 
@@ -1224,9 +1248,8 @@ void GEOMImpl_IMeasureOperations::GetTolerance
         VertMin = T;
     }
   }
-  catch (Standard_Failure) {
-    Handle(Standard_Failure) aFail = Standard_Failure::Caught();
-    SetErrorCode(aFail->GetMessageString());
+  catch (Standard_Failure& aFail) {
+    SetErrorCode(aFail.GetMessageString());
     return;
   }
 
@@ -1267,9 +1290,8 @@ bool GEOMImpl_IMeasureOperations::CheckShape (Handle(GEOM_Object)     theShape,
       FillErrors(ana, aShape, theErrors);
     }
   }
-  catch (Standard_Failure) {
-    Handle(Standard_Failure) aFail = Standard_Failure::Caught();
-    SetErrorCode(aFail->GetMessageString());
+  catch (Standard_Failure& aFail) {
+    SetErrorCode(aFail.GetMessageString());
     return false;
   }
 
@@ -1501,10 +1523,10 @@ TCollection_AsciiString GEOMImpl_IMeasureOperations::PrintShapeErrors
 //=============================================================================
 bool GEOMImpl_IMeasureOperations::CheckSelfIntersections
                          (Handle(GEOM_Object)                 theShape,
+                          const SICheckLevel                  theCheckLevel,
                           Handle(TColStd_HSequenceOfInteger)& theIntersections)
 {
   SetErrorCode(KO);
-  bool isGood = false;
 
   if (theIntersections.IsNull())
     theIntersections = new TColStd_HSequenceOfInteger;
@@ -1512,13 +1534,13 @@ bool GEOMImpl_IMeasureOperations::CheckSelfIntersections
     theIntersections->Clear();
 
   if (theShape.IsNull())
-    return isGood;
+    return false;
 
   Handle(GEOM_Function) aRefShape = theShape->GetLastFunction();
-  if (aRefShape.IsNull()) return isGood;
+  if (aRefShape.IsNull()) return false;
 
   TopoDS_Shape aShape = aRefShape->GetValue();
-  if (aShape.IsNull()) return isGood;
+  if (aShape.IsNull()) return false;
 
   // 0. Prepare data
   TopoDS_Shape aScopy;
@@ -1529,31 +1551,31 @@ bool GEOMImpl_IMeasureOperations::CheckSelfIntersections
   TopTools_IndexedMapOfShape anIndices;
   TopExp::MapShapes(aScopy, anIndices);
 
-  BOPCol_ListOfShape aLCS;
+  TopTools_ListOfShape aLCS;
   aLCS.Append(aScopy);
   //
   BOPAlgo_CheckerSI aCSI; // checker of self-interferences
   aCSI.SetArguments(aLCS);
+  aCSI.SetLevelOfCheck(theCheckLevel);
 
   // 1. Launch the checker
   aCSI.Perform();
-  Standard_Integer iErr = aCSI.ErrorStatus();
+  Standard_Boolean iErr = aCSI.HasErrors();
 
-  isGood = true;
   //
   Standard_Integer aNbS, n1, n2;
-  BOPDS_MapIteratorMapOfPassKey aItMPK;
+  BOPDS_MapIteratorOfMapOfPair aItMPK;
   //
   // 2. Take the shapes from DS
   const BOPDS_DS& aDS = aCSI.DS();
   aNbS=aDS.NbShapes();
   //
   // 3. Get the pairs of interfered shapes
-  const BOPDS_MapOfPassKey& aMPK=aDS.Interferences();
+  const BOPDS_MapOfPair& aMPK=aDS.Interferences();
   aItMPK.Initialize(aMPK);
   for (; aItMPK.More(); aItMPK.Next()) {
-    const BOPDS_PassKey& aPK=aItMPK.Value();
-    aPK.Ids(n1, n2);
+    const BOPDS_Pair& aPK=aItMPK.Value();
+    aPK.Indices(n1, n2);
     //
     if (n1 > aNbS || n2 > aNbS){
       return false; // Error
@@ -1563,13 +1585,197 @@ bool GEOMImpl_IMeasureOperations::CheckSelfIntersections
 
     theIntersections->Append(anIndices.FindIndex(aS1));
     theIntersections->Append(anIndices.FindIndex(aS2));
-    isGood = false;
   }
 
   if (!iErr) {
     SetErrorCode(OK);
   }
 
+  return theIntersections->IsEmpty();
+}
+
+//=============================================================================
+/*!
+ *  CheckSelfIntersectionsFast
+ */
+//=============================================================================
+bool GEOMImpl_IMeasureOperations::CheckSelfIntersectionsFast
+                         (Handle(GEOM_Object) theShape,
+                          float theDeflection, double theTolerance,
+                          Handle(TColStd_HSequenceOfInteger)& theIntersections)
+{
+  SetErrorCode(KO);
+
+  if (theIntersections.IsNull())
+    theIntersections = new TColStd_HSequenceOfInteger;
+  else
+    theIntersections->Clear();
+
+  if (theShape.IsNull())
+    return false;
+
+  Handle(GEOM_Function) aRefShape = theShape->GetLastFunction();
+  if (aRefShape.IsNull()) return false;
+
+  TopoDS_Shape aShape = aRefShape->GetValue();
+  if (aShape.IsNull()) return false;
+
+  // Prepare data
+  TopoDS_Shape aScopy;
+
+  GEOMAlgo_AlgoTools::CopyShape(aShape, aScopy);
+  GEOMUtils::MeshShape(aScopy, theDeflection);
+
+  // Map sub-shapes and their indices
+  TopTools_IndexedMapOfShape anIndices;
+  TopExp::MapShapes(aScopy, anIndices);
+
+  // Checker of fast interferences
+  BRepExtrema_SelfIntersection aTool(aScopy, (theTolerance <= 0.) ? 0.0 : theTolerance);
+
+  // Launch the checker
+  aTool.Perform();
+  
+  const BRepExtrema_MapOfIntegerPackedMapOfInteger& intersections = aTool.OverlapElements();
+  
+  std::set<Standard_Integer> processed;
+  
+  for (BRepExtrema_MapOfIntegerPackedMapOfInteger::Iterator it(intersections); it.More(); it.Next()) {
+    Standard_Integer idxLeft = it.Key();
+    if (processed.count(idxLeft) > 0) continue; // already added
+    processed.insert(idxLeft);
+    const TColStd_PackedMapOfInteger& overlaps = it.Value();
+    for (TColStd_MapIteratorOfPackedMapOfInteger subit(overlaps); subit.More(); subit.Next()) {
+      Standard_Integer idxRight = subit.Key();
+      if (processed.count(idxRight) > 0) continue; // already added
+      const TopoDS_Shape& aS1 = aTool.GetSubShape(idxLeft);
+      const TopoDS_Shape& aS2 = aTool.GetSubShape(idxRight);
+      theIntersections->Append(anIndices.FindIndex(aS1));
+      theIntersections->Append(anIndices.FindIndex(aS2));
+    }
+  }
+
+  if (aTool.IsDone())
+    SetErrorCode(OK);
+
+  return theIntersections->IsEmpty();
+}
+
+//=============================================================================
+/*!
+ *  CheckBOPArguments
+ */
+//=============================================================================
+bool GEOMImpl_IMeasureOperations::CheckBOPArguments
+                                      (const Handle(GEOM_Object) &theShape)
+{
+  SetErrorCode(KO);
+
+  if (theShape.IsNull()) {
+    return false;
+  }
+
+  Handle(GEOM_Function) aRefShape = theShape->GetLastFunction();
+
+  if (aRefShape.IsNull()) {
+    return false;
+  }
+
+  TopoDS_Shape aShape = aRefShape->GetValue();
+
+  if (aShape.IsNull()) {
+    return false;
+  }
+
+  //Compute the parameters
+  bool isValid = GEOMUtils::CheckBOPArguments(aShape);
+
+  SetErrorCode(OK);
+
+  return isValid;
+}
+
+//=============================================================================
+/*!
+ *  FastIntersect
+ */
+//=============================================================================
+bool GEOMImpl_IMeasureOperations::FastIntersect (Handle(GEOM_Object) theShape1, Handle(GEOM_Object) theShape2,
+                                                 double theTolerance, float theDeflection,
+                                                 Handle(TColStd_HSequenceOfInteger)& theIntersections1,
+                                                 Handle(TColStd_HSequenceOfInteger)& theIntersections2)
+{
+  SetErrorCode(KO);
+  bool isGood = false;
+
+  if (theIntersections1.IsNull())
+    theIntersections1 = new TColStd_HSequenceOfInteger;
+  else
+    theIntersections1->Clear();
+
+  if (theIntersections2.IsNull())
+    theIntersections2 = new TColStd_HSequenceOfInteger;
+  else
+    theIntersections2->Clear();
+
+  if (theShape1.IsNull() || theShape2.IsNull()) {
+    SetErrorCode("Objects have NULL Shape");
+    return isGood;
+  }
+
+  if (theShape1 == theShape2) {
+    SetErrorCode("Objects are equal");
+    return isGood;
+  }
+  Handle(GEOM_Function) aRefShape1 = theShape1->GetLastFunction();
+  Handle(GEOM_Function) aRefShape2 = theShape2->GetLastFunction();
+  if (aRefShape1.IsNull() || aRefShape2.IsNull()) return isGood;
+
+  TopoDS_Shape aShape1 = aRefShape1->GetValue();
+  TopoDS_Shape aShape2 = aRefShape2->GetValue();
+  if (aShape1.IsNull() || aShape2.IsNull()) return isGood;
+
+  // 0. Prepare data
+  TopoDS_Shape aScopy1, aScopy2;
+  GEOMAlgo_AlgoTools::CopyShape(aShape1, aScopy1);
+  GEOMAlgo_AlgoTools::CopyShape(aShape2, aScopy2);
+
+  GEOMUtils::MeshShape(aScopy1, theDeflection);
+  GEOMUtils::MeshShape(aScopy2, theDeflection);
+  //
+  // Map sub-shapes and their indices
+  TopTools_IndexedMapOfShape anIndices1, anIndices2;
+  TopExp::MapShapes(aScopy1, anIndices1);
+  TopExp::MapShapes(aScopy2, anIndices2);
+
+  TopTools_ListOfShape aLCS1, aLCS2;
+  aLCS1.Append(aScopy1); aLCS2.Append(aScopy2);
+  //
+  BRepExtrema_ShapeProximity aBSP; // checker of fast interferences
+  aBSP.LoadShape1(aScopy1); aBSP.LoadShape2(aScopy2);
+  aBSP.SetTolerance((theTolerance <= 0.) ? 0.0 : theTolerance);
+
+  // 1. Launch the checker
+  aBSP.Perform();
+  // 2. Get sets of IDs of overlapped faces
+  for (BRepExtrema_MapOfIntegerPackedMapOfInteger::Iterator anIt1 (aBSP.OverlapSubShapes1()); anIt1.More(); anIt1.Next())
+  {
+    const TopoDS_Shape& aS1 = aBSP.GetSubShape1(anIt1.Key());
+    theIntersections1->Append(anIndices1.FindIndex(aS1));
+  }
+  
+  for (BRepExtrema_MapOfIntegerPackedMapOfInteger::Iterator anIt2 (aBSP.OverlapSubShapes2()); anIt2.More(); anIt2.Next())
+  {
+    const TopoDS_Shape& aS2 = aBSP.GetSubShape2(anIt2.Key());
+    theIntersections2->Append(anIndices2.FindIndex(aS2));
+  }
+
+  isGood = !theIntersections1->IsEmpty() && !theIntersections1->IsEmpty();
+
+  if (aBSP.IsDone())
+    SetErrorCode(OK);
+
   return isGood;
 }
 
@@ -1654,9 +1860,11 @@ TCollection_AsciiString GEOMImpl_IMeasureOperations::WhatIs (Handle(GEOM_Object)
 
   try {
     OCC_CATCH_SIGNALS;
-    int iType, nbTypes [TopAbs_SHAPE];
-    for (iType = 0; iType < TopAbs_SHAPE; ++iType)
+    int iType, nbTypes [TopAbs_SHAPE], nbFlatType [TopAbs_SHAPE];
+    for (iType = 0; iType < TopAbs_SHAPE; ++iType) {
       nbTypes[iType] = 0;
+      nbFlatType[iType] = 0;
+    }
     nbTypes[aShape.ShapeType()]++;
 
     TopTools_MapOfShape aMapOfShape;
@@ -1666,12 +1874,16 @@ TCollection_AsciiString GEOMImpl_IMeasureOperations::WhatIs (Handle(GEOM_Object)
 
     TopTools_ListIteratorOfListOfShape itL (aListOfShape);
     for (; itL.More(); itL.Next()) {
-      TopoDS_Iterator it (itL.Value());
+      TopoDS_Shape sp = itL.Value();
+      TopoDS_Iterator it (sp);
       for (; it.More(); it.Next()) {
         TopoDS_Shape s = it.Value();
         if (aMapOfShape.Add(s)) {
           aListOfShape.Append(s);
           nbTypes[s.ShapeType()]++;
+          if ((sp.ShapeType() == TopAbs_COMPOUND) || (sp.ShapeType() == TopAbs_COMPSOLID)) {
+            nbFlatType[s.ShapeType()]++;
+          }
         }
       }
     }
@@ -1684,11 +1896,26 @@ TCollection_AsciiString GEOMImpl_IMeasureOperations::WhatIs (Handle(GEOM_Object)
     Astr = Astr + " SOLID : " + TCollection_AsciiString(nbTypes[TopAbs_SOLID]) + "\n";
     Astr = Astr + " COMPSOLID : " + TCollection_AsciiString(nbTypes[TopAbs_COMPSOLID]) + "\n";
     Astr = Astr + " COMPOUND : " + TCollection_AsciiString(nbTypes[TopAbs_COMPOUND]) + "\n";
-    Astr = Astr + " SHAPE : " + TCollection_AsciiString(aMapOfShape.Extent());
+    Astr = Astr + " SHAPE : " + TCollection_AsciiString(aMapOfShape.Extent()) + "\n";
+
+    if ((aShape.ShapeType() == TopAbs_COMPOUND) || (aShape.ShapeType() == TopAbs_COMPSOLID)){
+      Astr = Astr + " --------------------- \n Flat content : \n";
+      if (nbFlatType[TopAbs_VERTEX] > 0)
+        Astr = Astr + " VERTEX : " + TCollection_AsciiString(nbFlatType[TopAbs_VERTEX]) + "\n";
+      if (nbFlatType[TopAbs_EDGE] > 0)
+        Astr = Astr + " EDGE : " + TCollection_AsciiString(nbFlatType[TopAbs_EDGE]) + "\n";
+      if (nbFlatType[TopAbs_WIRE] > 0)
+        Astr = Astr + " WIRE : " + TCollection_AsciiString(nbFlatType[TopAbs_WIRE]) + "\n";
+      if (nbFlatType[TopAbs_FACE] > 0)
+        Astr = Astr + " FACE : " + TCollection_AsciiString(nbFlatType[TopAbs_FACE]) + "\n";
+      if (nbFlatType[TopAbs_SHELL] > 0)
+        Astr = Astr + " SHELL : " + TCollection_AsciiString(nbFlatType[TopAbs_SHELL]) + "\n";
+      if (nbFlatType[TopAbs_SOLID] > 0)
+        Astr = Astr + " SOLID : " + TCollection_AsciiString(nbFlatType[TopAbs_SOLID]) + "\n";
+    }
   }
-  catch (Standard_Failure) {
-    Handle(Standard_Failure) aFail = Standard_Failure::Caught();
-    SetErrorCode(aFail->GetMessageString());
+  catch (Standard_Failure& aFail) {
+    SetErrorCode(aFail.GetMessageString());
     return Astr;
   }
 
@@ -1764,7 +1991,7 @@ GEOMImpl_IMeasureOperations::AreCoordsInside(Handle(GEOM_Object)        theShape
                    project.NbPoints() > 0 &&
                    project.LowerDistance() <= tolerance )
               {
-                Quantity_Parameter u, v;
+                Standard_Real u, v;
                 project.LowerDistanceParameters(u, v);
                 gp_Pnt2d uv( u, v );
                 BRepClass_FaceClassifier FC ( face, uv, tolerance );
@@ -1859,9 +2086,8 @@ GEOMImpl_IMeasureOperations::GetMinDistance (Handle(GEOM_Object) theShape1,
       return MinDist;
     }
   }
-  catch (Standard_Failure) {
-    Handle(Standard_Failure) aFail = Standard_Failure::Caught();
-    SetErrorCode(aFail->GetMessageString());
+  catch (Standard_Failure& aFail) {
+    SetErrorCode(aFail.GetMessageString());
     return MinDist;
   }
 
@@ -1900,21 +2126,9 @@ Standard_Integer GEOMImpl_IMeasureOperations::ClosestPoints (Handle(GEOM_Object)
 
     // skl 30.06.2008
     // additional workaround for bugs 19899, 19908 and 19910 from Mantis
-    gp_Pnt P1, P2;
-    double dist = GEOMUtils::GetMinDistanceSingular(aShape1, aShape2, P1, P2);
-    if (dist > -1.0) {
-      nbSolutions = 1;
-
-      theDoubles->Append(P1.X());
-      theDoubles->Append(P1.Y());
-      theDoubles->Append(P1.Z());
-      theDoubles->Append(P2.X());
-      theDoubles->Append(P2.Y());
-      theDoubles->Append(P2.Z());
-
-      SetErrorCode(OK);
-      return nbSolutions;
-    }
+    gp_Pnt P1s, P2s;
+    double dist = GEOMUtils::GetMinDistanceSingular(aShape1, aShape2, P1s, P2s);
+    bool singularBetter = dist >= 0;
 
     BRepExtrema_DistShapeShape dst (aShape1, aShape2);
     if (dst.IsDone()) {
@@ -1925,19 +2139,35 @@ Standard_Integer GEOMImpl_IMeasureOperations::ClosestPoints (Handle(GEOM_Object)
       for (int i = 1; i <= nbSolutions; i++) {
         P1 = dst.PointOnShape1(i);
         P2 = dst.PointOnShape2(i);
-
+       
         theDoubles->Append(P1.X());
         theDoubles->Append(P1.Y());
         theDoubles->Append(P1.Z());
         theDoubles->Append(P2.X());
         theDoubles->Append(P2.Y());
         theDoubles->Append(P2.Z());
+       
+       Standard_Real Dist = P1.Distance(P2);
+       singularBetter = singularBetter && dist < Dist;
       }
     }
+
+    if (singularBetter) {
+      if (theDoubles.IsNull()) theDoubles = new TColStd_HSequenceOfReal;
+      else theDoubles->Clear();
+
+      nbSolutions = 1;
+    
+      theDoubles->Append(P1s.X());
+      theDoubles->Append(P1s.Y());
+      theDoubles->Append(P1s.Z());
+      theDoubles->Append(P2s.X());
+      theDoubles->Append(P2s.Y());
+      theDoubles->Append(P2s.Z());
+    }
   }
-  catch (Standard_Failure) {
-    Handle(Standard_Failure) aFail = Standard_Failure::Caught();
-    SetErrorCode(aFail->GetMessageString());
+  catch (Standard_Failure& aFail) {
+    SetErrorCode(aFail.GetMessageString());
     return nbSolutions;
   }
 
@@ -1978,10 +2208,9 @@ void GEOMImpl_IMeasureOperations::PointCoordinates (Handle(GEOM_Object) theShape
 
     SetErrorCode(OK);
   }
-  catch (Standard_Failure)
+  catch (Standard_Failure& aFail)
   {
-    Handle(Standard_Failure) aFail = Standard_Failure::Caught();
-    SetErrorCode( aFail->GetMessageString() );
+    SetErrorCode( aFail.GetMessageString() );
   }
 }
 
@@ -2051,10 +2280,9 @@ Standard_Real GEOMImpl_IMeasureOperations::GetAngle (Handle(GEOM_Object) theLine
 
     SetErrorCode(OK);
   }
-  catch (Standard_Failure)
+  catch (Standard_Failure& aFail)
   {
-    Handle(Standard_Failure) aFail = Standard_Failure::Caught();
-    SetErrorCode(aFail->GetMessageString());
+    SetErrorCode(aFail.GetMessageString());
   }
 
   return anAngle;
@@ -2116,10 +2344,9 @@ Standard_Real GEOMImpl_IMeasureOperations::GetAngleBtwVectors (Handle(GEOM_Objec
 
     SetErrorCode(OK);
   }
-  catch (Standard_Failure)
+  catch (Standard_Failure& aFail)
   {
-    Handle(Standard_Failure) aFail = Standard_Failure::Caught();
-    SetErrorCode(aFail->GetMessageString());
+    SetErrorCode(aFail.GetMessageString());
   }
 
   return anAngle;
@@ -2162,9 +2389,8 @@ Standard_Real GEOMImpl_IMeasureOperations::CurveCurvatureByParam
     aRes = fabs(Prop.Curvature());
     SetErrorCode(OK);
   }
-  catch (Standard_Failure) {
-    Handle(Standard_Failure) aFail = Standard_Failure::Caught();
-    SetErrorCode(aFail->GetMessageString());
+  catch (Standard_Failure& aFail) {
+    SetErrorCode(aFail.GetMessageString());
     return aRes;
   }
 
@@ -2217,9 +2443,8 @@ Standard_Real GEOMImpl_IMeasureOperations::CurveCurvatureByPoint
       SetErrorCode(OK);
     }
   }
-  catch (Standard_Failure) {
-    Handle(Standard_Failure) aFail = Standard_Failure::Caught();
-    SetErrorCode(aFail->GetMessageString());
+  catch (Standard_Failure& aFail) {
+    SetErrorCode(aFail.GetMessageString());
     return aRes;
   }
 
@@ -2269,9 +2494,8 @@ Standard_Real GEOMImpl_IMeasureOperations::getSurfaceCurvatures
       SetErrorCode(OK);
     }
   }
-  catch (Standard_Failure) {
-    Handle(Standard_Failure) aFail = Standard_Failure::Caught();
-    SetErrorCode(aFail->GetMessageString());
+  catch (Standard_Failure& aFail) {
+    SetErrorCode(aFail.GetMessageString());
     return aRes;
   }