Salome HOME
Add new command GetShapesOnBox.
[modules/geom.git] / src / GEOMImpl / GEOMImpl_IShapesOperations.cxx
index 071b5c3df268681ba5e26ec94a52aa948be6913d..199f2c0c569191aa0b8b2afd31a26333d5a36d99 100644 (file)
@@ -1,4 +1,23 @@
-using namespace std;
+// Copyright (C) 2005  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 : webmaster.salome@opencascade.com
+//
+#include <Standard_Stream.hxx>
 
 #include "GEOMImpl_IShapesOperations.hxx"
 
@@ -16,8 +35,13 @@ using namespace std;
 #include "GEOMImpl_Block6Explorer.hxx"
 
 #include "GEOM_Function.hxx"
+#include "GEOM_PythonDump.hxx"
 
-#include "GEOMAlgo_FinderShapeOn.hxx"
+#include "GEOMAlgo_FinderShapeOn1.hxx"
+#include "GEOMAlgo_FinderShapeOnQuad.hxx"
+#include "GEOMAlgo_FinderShapeOn2.hxx"
+#include "GEOMAlgo_ClsfBox.hxx"
+//#include "GEOMAlgo_ClsfSurf.hxx"
 
 #include "utilities.h"
 #include "OpUtil.hxx"
@@ -33,14 +57,19 @@ using namespace std;
 #include <BRepExtrema_ExtCF.hxx>
 
 #include <BRep_Tool.hxx>
+#include <BRepTools.hxx>
 #include <BRepGProp.hxx>
 #include <BRepAdaptor_Curve.hxx>
+#include <BRepAdaptor_Surface.hxx>
+#include <BRepBndLib.hxx>
 #include <BRepBuilderAPI_MakeFace.hxx>
+#include <BRepMesh_IncrementalMesh.hxx>
 
 #include <TopAbs.hxx>
 #include <TopExp.hxx>
 #include <TopoDS.hxx>
 #include <TopoDS_Shape.hxx>
+#include <TopoDS_Solid.hxx>
 #include <TopoDS_Face.hxx>
 #include <TopoDS_Edge.hxx>
 #include <TopoDS_Vertex.hxx>
@@ -48,6 +77,7 @@ using namespace std;
 #include <TopExp_Explorer.hxx>
 #include <TopLoc_Location.hxx>
 #include <TopTools_MapOfShape.hxx>
+#include <TopTools_MapOfOrientedShape.hxx>
 #include <TopTools_Array1OfShape.hxx>
 #include <TopTools_ListIteratorOfListOfShape.hxx>
 #include <TopTools_IndexedMapOfShape.hxx>
@@ -58,18 +88,21 @@ using namespace std;
 #include <Geom_CylindricalSurface.hxx>
 #include <GeomAdaptor_Surface.hxx>
 
+#include <GeomLib_Tool.hxx>
 #include <Geom2d_Curve.hxx>
 
+#include <Bnd_Box.hxx>
 #include <GProp_GProps.hxx>
 #include <gp_Pnt.hxx>
 #include <gp_Lin.hxx>
-#include <TColStd_Array1OfReal.hxx>
-#include <TColStd_HArray1OfInteger.hxx>
 #include <TColStd_ListOfInteger.hxx>
 #include <TColStd_ListIteratorOfListOfInteger.hxx>
+#include <TColStd_Array1OfReal.hxx>
+#include <TColStd_HArray1OfInteger.hxx>
 
-//#include <OSD_Timer.hxx>
+#include <vector>
 
+#include <Standard_Failure.hxx>
 #include <Standard_ErrorHandler.hxx> // CAREFUL ! position of this file is critic : see Lucien PIGNOLONI / OCC
 
 //=============================================================================
@@ -127,6 +160,9 @@ Handle(GEOM_Object) GEOMImpl_IShapesOperations::MakeEdge
 
   //Compute the Edge value
   try {
+#if (OCC_VERSION_MAJOR << 16 | OCC_VERSION_MINOR << 8 | OCC_VERSION_MAINTENANCE) > 0x060100
+    OCC_CATCH_SIGNALS;
+#endif
     if (!GetSolver()->ComputeFunction(aFunction)) {
       SetErrorCode("Vector driver failed");
       return NULL;
@@ -139,15 +175,8 @@ Handle(GEOM_Object) GEOMImpl_IShapesOperations::MakeEdge
   }
 
   //Make a Python command
-  TCollection_AsciiString anEntry, aDescr;
-  TDF_Tool::Entry(anEdge->GetEntry(), anEntry);
-  aDescr += (anEntry+" = IShapesOperations.MakeEdge(");
-  TDF_Tool::Entry(thePnt1->GetEntry(), anEntry);
-  aDescr += (anEntry+", ");
-  TDF_Tool::Entry(thePnt2->GetEntry(), anEntry);
-  aDescr += (anEntry+")");
-
-  aFunction->SetDescription(aDescr);
+  GEOM::TPythonDump(aFunction) << anEdge << " = geompy.MakeEdge("
+                               << thePnt1 << ", " << thePnt2 << ")";
 
   SetErrorCode(OK);
   return anEdge;
@@ -198,6 +227,9 @@ Handle(GEOM_Object) GEOMImpl_IShapesOperations::MakeFace (Handle(GEOM_Object) th
 
   //Compute the Face value
   try {
+#if (OCC_VERSION_MAJOR << 16 | OCC_VERSION_MINOR << 8 | OCC_VERSION_MAINTENANCE) > 0x060100
+    OCC_CATCH_SIGNALS;
+#endif
     if (!GetSolver()->ComputeFunction(aFunction)) {
       SetErrorCode("Shape driver failed to compute a face");
       return NULL;
@@ -210,19 +242,8 @@ Handle(GEOM_Object) GEOMImpl_IShapesOperations::MakeFace (Handle(GEOM_Object) th
   }
 
   //Make a Python command
-  TCollection_AsciiString anEntry, aDescr;
-  TDF_Tool::Entry(aFace->GetEntry(), anEntry);
-  aDescr += anEntry;
-  aDescr += " = IShapesOperations.MakeFace(";
-  TDF_Tool::Entry(theWire->GetEntry(), anEntry);
-  aDescr += anEntry;
-  if (isPlanarWanted)
-    aDescr += ", 1)";
-
-  else
-    aDescr += ", 0)";
-
-  aFunction->SetDescription(aDescr);
+  GEOM::TPythonDump(aFunction) << aFace << " = geompy.MakeFace("
+    << theWire << ", " << (int)isPlanarWanted << ")";
 
   SetErrorCode(OK);
   return aFace;
@@ -270,6 +291,9 @@ Handle(GEOM_Object) GEOMImpl_IShapesOperations::MakeFaceWires
 
   //Compute the shape
   try {
+#if (OCC_VERSION_MAJOR << 16 | OCC_VERSION_MINOR << 8 | OCC_VERSION_MAINTENANCE) > 0x060100
+    OCC_CATCH_SIGNALS;
+#endif
     if (!GetSolver()->ComputeFunction(aFunction)) {
       SetErrorCode("Shape driver failed");
       return NULL;
@@ -282,28 +306,18 @@ Handle(GEOM_Object) GEOMImpl_IShapesOperations::MakeFaceWires
   }
 
   //Make a Python command
-  TCollection_AsciiString anEntry, aDescr;
-  TDF_Tool::Entry(aShape->GetEntry(), anEntry);
-  aDescr += (anEntry + " = IShapesOperations.MakeFaceWires([");
+  GEOM::TPythonDump pd (aFunction);
+  pd << aShape << " = geompy.MakeFaceWires([";
+
   // Shapes
   it = theShapes.begin();
   if (it != theShapes.end()) {
-    TDF_Tool::Entry((*it)->GetEntry(), anEntry);
-    it++;
-    aDescr += (anEntry+", ");
-    for (; it != theShapes.end(); it++) {
-      aDescr += ", ";
-      TDF_Tool::Entry((*it)->GetEntry(), anEntry);
-      aDescr += anEntry;
+    pd << (*it++);
+    while (it != theShapes.end()) {
+      pd << ", " << (*it++);
     }
   }
-  if (isPlanarWanted)
-    aDescr += "], 1)";
-
-  else
-    aDescr += "], 0)";
-
-  aFunction->SetDescription(aDescr);
+  pd << "], " << (int)isPlanarWanted << ")";
 
   SetErrorCode(OK);
   return aShape;
@@ -328,7 +342,7 @@ Handle(GEOM_Object) GEOMImpl_IShapesOperations::MakeShell
 Handle(GEOM_Object) GEOMImpl_IShapesOperations::MakeSolidShells
                              (list<Handle(GEOM_Object)> theShapes)
 {
-  return MakeShape(theShapes, GEOM_SOLID, SOLID_SHELLS, "MakeSolidShells");
+  return MakeShape(theShapes, GEOM_SOLID, SOLID_SHELLS, "MakeSolid");
 }
 
 //=============================================================================
@@ -363,6 +377,9 @@ Handle(GEOM_Object) GEOMImpl_IShapesOperations::MakeSolidShell (Handle(GEOM_Obje
 
   //Compute the Solid value
   try {
+#if (OCC_VERSION_MAJOR << 16 | OCC_VERSION_MINOR << 8 | OCC_VERSION_MAINTENANCE) > 0x060100
+    OCC_CATCH_SIGNALS;
+#endif
     if (!GetSolver()->ComputeFunction(aFunction)) {
       SetErrorCode("Solid driver failed");
       return NULL;
@@ -375,14 +392,8 @@ Handle(GEOM_Object) GEOMImpl_IShapesOperations::MakeSolidShell (Handle(GEOM_Obje
   }
 
   //Make a Python command
-  TCollection_AsciiString anEntry, aDescr("");
-  TDF_Tool::Entry(aSolid->GetEntry(), anEntry);
-  aDescr += anEntry;
-  aDescr += " = IShapesOperations.MakeSolidShell(";
-  TDF_Tool::Entry(theShell->GetEntry(), anEntry);
-  aDescr += (anEntry+")");
-
-  aFunction->SetDescription(aDescr);
+  GEOM::TPythonDump(aFunction) << aSolid
+    << " = geompy.MakeSolid(" << theShell << ")";
 
   SetErrorCode(OK);
   return aSolid;
@@ -405,10 +416,10 @@ Handle(GEOM_Object) GEOMImpl_IShapesOperations::MakeCompound
  */
 //=============================================================================
 Handle(GEOM_Object) GEOMImpl_IShapesOperations::MakeShape
-                             (list<Handle(GEOM_Object)>     theShapes,
-                              const Standard_Integer        theObjectType,
-                              const Standard_Integer        theFunctionType,
-                              const TCollection_AsciiString theMethodName)
+                             (list<Handle(GEOM_Object)>      theShapes,
+                              const Standard_Integer         theObjectType,
+                              const Standard_Integer         theFunctionType,
+                              const TCollection_AsciiString& theMethodName)
 {
   SetErrorCode(KO);
 
@@ -441,6 +452,9 @@ Handle(GEOM_Object) GEOMImpl_IShapesOperations::MakeShape
 
   //Compute the shape
   try {
+#if (OCC_VERSION_MAJOR << 16 | OCC_VERSION_MINOR << 8 | OCC_VERSION_MAINTENANCE) > 0x060100
+    OCC_CATCH_SIGNALS;
+#endif
     if (!GetSolver()->ComputeFunction(aFunction)) {
       SetErrorCode("Shape driver failed");
       return NULL;
@@ -453,25 +467,18 @@ Handle(GEOM_Object) GEOMImpl_IShapesOperations::MakeShape
   }
 
   //Make a Python command
-  TCollection_AsciiString anEntry, aDescr("");
-  TDF_Tool::Entry(aShape->GetEntry(), anEntry);
-  aDescr += (anEntry + " = IShapesOperations.");
-  aDescr += (theMethodName + "([");
+  GEOM::TPythonDump pd (aFunction);
+  pd << aShape << " = geompy." << theMethodName.ToCString() << "([";
+
   // Shapes
   it = theShapes.begin();
   if (it != theShapes.end()) {
-    TDF_Tool::Entry((*it)->GetEntry(), anEntry);
-    it++;
-    aDescr += (anEntry+", ");
-    for (; it != theShapes.end(); it++) {
-      aDescr += ", ";
-      TDF_Tool::Entry((*it)->GetEntry(), anEntry);
-      aDescr += anEntry;
+    pd << (*it++);
+    while (it != theShapes.end()) {
+      pd << ", " << (*it++);
     }
   }
-  aDescr += "])";
-
-  aFunction->SetDescription(aDescr);
+  pd << "])";
 
   SetErrorCode(OK);
   return aShape;
@@ -512,6 +519,9 @@ Handle(GEOM_Object) GEOMImpl_IShapesOperations::MakeGlueFaces
   //Compute the sub-shape value
   Standard_Boolean isWarning = Standard_False;
   try {
+#if (OCC_VERSION_MAJOR << 16 | OCC_VERSION_MINOR << 8 | OCC_VERSION_MAINTENANCE) > 0x060100
+    OCC_CATCH_SIGNALS;
+#endif
     if (!GetSolver()->ComputeFunction(aFunction)) {
       SetErrorCode("Shape driver failed to glue faces");
       return NULL;
@@ -529,15 +539,8 @@ Handle(GEOM_Object) GEOMImpl_IShapesOperations::MakeGlueFaces
   }
 
   //Make a Python command
-  TCollection_AsciiString anEntry, aDescr;
-  TDF_Tool::Entry(aGlued->GetEntry(), anEntry);
-  aDescr += anEntry;
-  aDescr += " = IShapesOperations.MakeGlueFaces(";
-  TDF_Tool::Entry(theShape->GetEntry(), anEntry);
-  aDescr += anEntry + ", ";
-  aDescr += TCollection_AsciiString(theTolerance) + ")";
-
-  aFunction->SetDescription(aDescr);
+  GEOM::TPythonDump(aFunction) << aGlued << " = geompy.MakeGlueFaces("
+    << theShape << ", " << theTolerance << ")";
 
   // to provide warning
   if (!isWarning) SetErrorCode(OK);
@@ -554,9 +557,6 @@ Handle(TColStd_HSequenceOfTransient) GEOMImpl_IShapesOperations::MakeExplode
                                            const Standard_Integer theShapeType,
                                            const Standard_Boolean isSorted)
 {
-//  OSD_Timer timer1, timer2, timer3, timer4;
-//  timer1.Start();
-
   SetErrorCode(KO);
 
   if (theShape.IsNull()) return NULL;
@@ -594,21 +594,15 @@ Handle(TColStd_HSequenceOfTransient) GEOMImpl_IShapesOperations::MakeExplode
     return aSeq;
   }
 
-//  timer1.Stop();
-//  timer2.Start();
-
   if (isSorted)
     SortShapes(listShape);
 
-//  timer2.Stop();
-//  timer3.Start();
-
   TopTools_IndexedMapOfShape anIndices;
   TopExp::MapShapes(aShape, anIndices);
   Handle(TColStd_HArray1OfInteger) anArray;
 
   TopTools_ListIteratorOfListOfShape itSub (listShape);
-  TCollection_AsciiString anAsciiList = "[", anEntry;
+  TCollection_AsciiString anAsciiList, anEntry;
   for (int index = 1; itSub.More(); itSub.Next(), ++index) {
     TopoDS_Shape aValue = itSub.Value();
     anArray = new TColStd_HArray1OfInteger(1,1);
@@ -616,49 +610,24 @@ Handle(TColStd_HSequenceOfTransient) GEOMImpl_IShapesOperations::MakeExplode
     anObj = GetEngine()->AddSubShape(theShape, anArray);
     aSeq->Append(anObj);
 
+    // for python command
     TDF_Tool::Entry(anObj->GetEntry(), anEntry);
     anAsciiList += anEntry;
     anAsciiList += ",";
   }
 
-//  timer3.Stop();
-//  timer4.Start();
-
+  //Make a Python command
   anAsciiList.Trunc(anAsciiList.Length() - 1);
-  anAsciiList += "]";
-
-  anAsciiList = TCollection_AsciiString("\n") + anAsciiList;
 
-  //The explode doesn't change object so no new function is requiered.
   aFunction = theShape->GetLastFunction();
 
-  //Make a Python command
-  TCollection_AsciiString aDescr(anAsciiList);
-  TDF_Tool::Entry(theShape->GetEntry(), anEntry);
-  aDescr += " = IShapesOperations.MakeExplode(";
-  aDescr += (anEntry + ",");
-  if (isSorted)
-    aDescr += (TCollection_AsciiString(theShapeType) + ", 1)");
-  else
-    aDescr += (TCollection_AsciiString(theShapeType) + ", 0)");
-
-  TCollection_AsciiString anOldDescr = aFunction->GetDescription();
-  anOldDescr = anOldDescr + aDescr;
-  aFunction->SetDescription(anOldDescr);
+  GEOM::TPythonDump pd (aFunction, /*append=*/true);
+  pd << "[" << anAsciiList.ToCString();
+  pd << "] = geompy.SubShapeAll" << (isSorted ? "Sorted(" : "(");
+  pd << theShape << ", " << TopAbs_ShapeEnum(theShapeType) << ")";
 
   SetErrorCode(OK);
 
-//  timer4.Stop();
-
-//  cout << "Explosure takes:" << endl;
-//  timer1.Show();
-//  cout << "Sorting takes:" << endl;
-//  timer2.Show();
-//  cout << "Sub-shapes addition takes:" << endl;
-//  timer3.Show();
-//  cout << "Update Description takes:" << endl;
-//  timer4.Show();
-
   return aSeq;
 }
 
@@ -720,23 +689,13 @@ Handle(TColStd_HSequenceOfInteger) GEOMImpl_IShapesOperations::SubShapeAllIDs
     aSeq->Append(anIndices.FindIndex(aValue));
   }
 
-  //The explode doesn't change object so no new function is required.
   Handle(GEOM_Function) aFunction = theShape->GetLastFunction();
 
   //Make a Python command
-  TCollection_AsciiString aDescr
-    ("\nlistSubShapeAllIDs = IShapesOperations.SubShapeAllIDs(");
-  TCollection_AsciiString anEntry;
-  TDF_Tool::Entry(theShape->GetEntry(), anEntry);
-  aDescr += (anEntry + ",");
-  if (isSorted)
-    aDescr += (TCollection_AsciiString(theShapeType) + ", 1)");
-  else
-    aDescr += (TCollection_AsciiString(theShapeType) + ", 0)");
-
-  TCollection_AsciiString anOldDescr = aFunction->GetDescription();
-  anOldDescr = anOldDescr + aDescr;
-  aFunction->SetDescription(anOldDescr);
+  GEOM::TPythonDump pd (aFunction, /*append=*/true);
+  pd << "listSubShapeIDs = geompy.SubShapeAll";
+  pd << (isSorted ? "SortedIDs(" : "IDs(");
+  pd << theShape << ", " << TopAbs_ShapeEnum(theShapeType) << ")";
 
   SetErrorCode(OK);
   return aSeq;
@@ -757,32 +716,179 @@ Handle(GEOM_Object) GEOMImpl_IShapesOperations::GetSubShape
 
   Handle(TColStd_HArray1OfInteger) anArray = new TColStd_HArray1OfInteger(1,1);
   anArray->SetValue(1, theID);
-  Handle(GEOM_Object) anObj = GetEngine()->AddSubShape(theMainShape, anArray);
+  Handle(GEOM_Object) anObj = GetEngine()->AddSubShape(theMainShape, anArray,true);
   if (anObj.IsNull()) {
     SetErrorCode("Can not get a sub-shape with the given ID");
     return NULL;
   }
 
-  //The GetSubShape() doesn't change object so no new function is requiered.
-  Handle(GEOM_Function) aFunction = theMainShape->GetLastFunction();
+  Handle(GEOM_Function) aFunction = anObj->GetLastFunction();
 
   //Make a Python command
-  TCollection_AsciiString aDescr ("\n");
-  TCollection_AsciiString anEntry;
-  TDF_Tool::Entry(anObj->GetEntry(), anEntry);
-  aDescr += anEntry + " = IShapesOperations.GetSubShape(";
-  TDF_Tool::Entry(theMainShape->GetEntry(), anEntry);
-  aDescr += anEntry + ", ";
-  aDescr += TCollection_AsciiString(theID) + ")";
-
-  TCollection_AsciiString anOldDescr = aFunction->GetDescription();
-  anOldDescr = anOldDescr + aDescr;
-  aFunction->SetDescription(anOldDescr);
+  GEOM::TPythonDump(aFunction) << anObj << " = geompy.GetSubShape("
+                               << theMainShape << ", [" << theID << "])";
 
   SetErrorCode(OK);
   return anObj;
 }
 
+//=============================================================================
+/*!
+ *  GetSubShapeIndex
+ */
+//=============================================================================
+Standard_Integer GEOMImpl_IShapesOperations::GetSubShapeIndex (Handle(GEOM_Object) theMainShape,
+                                                               Handle(GEOM_Object) theSubShape)
+{
+  SetErrorCode(KO);
+
+  TopoDS_Shape aMainShape = theMainShape->GetValue();
+  TopoDS_Shape aSubShape = theSubShape->GetValue();
+
+  if (aMainShape.IsNull() || aSubShape.IsNull()) return -1;
+
+  TopTools_IndexedMapOfShape anIndices;
+  TopExp::MapShapes(aMainShape, anIndices);
+  if (anIndices.Contains(aSubShape)) {
+    SetErrorCode(OK);
+    return anIndices.FindIndex(aSubShape);
+  }
+
+  return -1;
+}
+
+//=============================================================================
+/*!
+ *  GetTopologyIndex
+ */
+//=============================================================================
+Standard_Integer GEOMImpl_IShapesOperations::GetTopologyIndex (Handle(GEOM_Object) theMainShape,
+                                                               Handle(GEOM_Object) theSubShape)
+{
+  SetErrorCode(OK);
+
+  TopoDS_Shape aMainShape = theMainShape->GetValue();
+  TopoDS_Shape aSubShape = theSubShape->GetValue();
+
+  if (aMainShape.IsNull() || aSubShape.IsNull()) {
+    SetErrorCode("Null argument shape given");
+    return -1;
+  }
+
+  int index = 1;
+  if (aSubShape.ShapeType() == TopAbs_COMPOUND) {
+    TopoDS_Iterator it;
+    TopTools_ListOfShape CL;
+    CL.Append(aMainShape);
+    TopTools_ListIteratorOfListOfShape itC;
+    for (itC.Initialize(CL); itC.More(); itC.Next()) {
+      for (it.Initialize(itC.Value()); it.More(); it.Next()) {
+       if (it.Value().ShapeType() == TopAbs_COMPOUND) {
+         if (it.Value().IsSame(aSubShape))
+           return index;
+         else
+           index++;
+         CL.Append(it.Value());
+       }
+      }
+    }
+  } else {
+    TopExp_Explorer anExp (aMainShape, aSubShape.ShapeType());
+    TopTools_MapOfShape M;
+    for (; anExp.More(); anExp.Next()) {
+      if (M.Add(anExp.Current())) {
+       if (anExp.Current().IsSame(aSubShape))
+         return index;
+       index++;
+      }
+    }
+  }
+
+  SetErrorCode("The sub-shape does not belong to the main shape");
+  return -1;
+}
+
+//=============================================================================
+/*!
+ *  GetShapeTypeString
+ */
+//=============================================================================
+TCollection_AsciiString GEOMImpl_IShapesOperations::GetShapeTypeString (Handle(GEOM_Object) theShape)
+{
+  SetErrorCode(KO);
+
+  TCollection_AsciiString aTypeName ("Null Shape");
+
+  TopoDS_Shape aShape = theShape->GetValue();
+  if (aShape.IsNull())
+    return aTypeName;
+
+  switch (aShape.ShapeType() )
+  {
+  case TopAbs_COMPOUND:
+    aTypeName = "Compound";
+    break;
+  case  TopAbs_COMPSOLID:
+    aTypeName = "Compound Solid";
+    break;
+  case TopAbs_SOLID:
+    aTypeName = "Solid";
+    break;
+  case TopAbs_SHELL:
+    aTypeName = "Shell";
+    break;
+  case TopAbs_FACE:
+    {
+      BRepAdaptor_Surface surf (TopoDS::Face(aShape));
+      if (surf.GetType() == GeomAbs_Plane)
+       aTypeName = "Plane";
+      else if (surf.GetType() == GeomAbs_Cylinder)
+       aTypeName = "Cylindrical Face";
+      else if (surf.GetType() == GeomAbs_Sphere)
+       aTypeName = "Spherical Face";
+      else if (surf.GetType() == GeomAbs_Torus)
+       aTypeName = "Toroidal Face";
+      else if (surf.GetType() == GeomAbs_Cone)
+       aTypeName = "Conical Face";
+      else
+       aTypeName = "GEOM::FACE";
+    }
+    break;
+  case TopAbs_WIRE:
+    aTypeName = "Wire";
+    break;
+  case TopAbs_EDGE:
+    {
+      BRepAdaptor_Curve curv (TopoDS::Edge(aShape));
+      if (curv.GetType() == GeomAbs_Line) {
+       if ((Abs(curv.FirstParameter()) >= 1E6) ||
+            (Abs(curv.LastParameter()) >= 1E6))
+          aTypeName = "Line";
+       else
+         aTypeName = "Edge" ;
+      } else if (curv.GetType() == GeomAbs_Circle) {
+       if (curv.IsClosed())
+          aTypeName = "Circle";
+       else
+          aTypeName = "Arc";
+      } else {
+        aTypeName = "Edge";
+      }
+    }
+    break;
+  case TopAbs_VERTEX:
+    aTypeName = "Vertex";
+    break;
+  case TopAbs_SHAPE:
+    aTypeName = "Shape";
+    break;
+  default:
+    aTypeName = "Shape of unknown type";
+  }
+
+  return aTypeName;
+}
+
 
 //=============================================================================
 /*!
@@ -867,6 +973,9 @@ Handle(GEOM_Object) GEOMImpl_IShapesOperations::ReverseShape(Handle(GEOM_Object)
 
   //Compute the sub-shape value
   try {
+#if (OCC_VERSION_MAJOR << 16 | OCC_VERSION_MINOR << 8 | OCC_VERSION_MAINTENANCE) > 0x060100
+    OCC_CATCH_SIGNALS;
+#endif
     if (!GetSolver()->ComputeFunction(aFunction)) {
       SetErrorCode("Shape driver failed to reverse shape");
       return NULL;
@@ -879,14 +988,8 @@ Handle(GEOM_Object) GEOMImpl_IShapesOperations::ReverseShape(Handle(GEOM_Object)
   }
 
   //Make a Python command
-  TCollection_AsciiString anEntry, aDescr;
-  TDF_Tool::Entry(aReversed->GetEntry(), anEntry);
-  aDescr += anEntry;
-  aDescr += " = IShapesOperations.ReverseShape(";
-  TDF_Tool::Entry(theShape->GetEntry(), anEntry);
-  aDescr += anEntry + ")";
-
-  aFunction->SetDescription(aDescr);
+  GEOM::TPythonDump(aFunction) << aReversed
+    << " = geompy.ChangeOrientation(" << theShape << ")";
 
   SetErrorCode(OK);
   return aReversed;
@@ -934,24 +1037,18 @@ Handle(TColStd_HSequenceOfInteger) GEOMImpl_IShapesOperations::GetFreeFacesIDs
   Handle(GEOM_Function) aFunction = theShape->GetLastFunction();
 
   //Make a Python command
-  TCollection_AsciiString aDescr ("\nlistFreeFacesIDs = IShapesOperations.GetFreeFacesIDs(");
-  TCollection_AsciiString anEntry;
-  TDF_Tool::Entry(theShape->GetEntry(), anEntry);
-  aDescr += (anEntry + ")");
-
-  TCollection_AsciiString anOldDescr = aFunction->GetDescription();
-  anOldDescr = anOldDescr + aDescr;
-  aFunction->SetDescription(anOldDescr);
+  GEOM::TPythonDump(aFunction, /*append=*/true)
+    << "listFreeFacesIDs = geompy.GetFreeFacesIDs(" << theShape << ")";
 
   SetErrorCode(OK);
   return aSeq;
 }
 
-//=============================================================================
-/*!
- *  GetSharedShapes
- */
-//=============================================================================
+//=======================================================================
+//function : GetSharedShapes
+//purpose  : 
+//=======================================================================
+
 Handle(TColStd_HSequenceOfTransient) GEOMImpl_IShapesOperations::GetSharedShapes
                                                 (Handle(GEOM_Object)    theShape1,
                                                  Handle(GEOM_Object)    theShape2,
@@ -975,6 +1072,7 @@ Handle(TColStd_HSequenceOfTransient) GEOMImpl_IShapesOperations::GetSharedShapes
 
   Handle(GEOM_Object) anObj;
   Handle(TColStd_HSequenceOfTransient) aSeq = new TColStd_HSequenceOfTransient;
+  TCollection_AsciiString anAsciiList, anEntry;
 
   TopTools_MapOfShape mapShape2;
   TopExp_Explorer exp (aShape2, TopAbs_ShapeEnum(theShapeType));
@@ -985,6 +1083,11 @@ Handle(TColStd_HSequenceOfTransient) GEOMImpl_IShapesOperations::GetSharedShapes
       anArray->SetValue(1, anIndices.FindIndex(aSS));
       anObj = GetEngine()->AddSubShape(theShape1, anArray);
       aSeq->Append(anObj);
+
+      // for python command
+      TDF_Tool::Entry(anObj->GetEntry(), anEntry);
+      anAsciiList += anEntry;
+      anAsciiList += ",";
     }
   }
 
@@ -993,22 +1096,14 @@ Handle(TColStd_HSequenceOfTransient) GEOMImpl_IShapesOperations::GetSharedShapes
     return aSeq;
   }
 
-  //The explode doesn't change object so no new function is required.
-  Handle(GEOM_Function) aFunction = theShape1->GetLastFunction();
-
   //Make a Python command
-  TCollection_AsciiString aDescr
-    ("\nlistSharedShapes = IShapesOperations.GetSharedShapes(");
-  TCollection_AsciiString anEntry;
-  TDF_Tool::Entry(theShape1->GetEntry(), anEntry);
-  aDescr += (anEntry + ",");
-  TDF_Tool::Entry(theShape2->GetEntry(), anEntry);
-  aDescr += (anEntry + ",");
-  aDescr += TCollection_AsciiString(theShapeType) + ")";
-
-  TCollection_AsciiString anOldDescr = aFunction->GetDescription();
-  anOldDescr = anOldDescr + aDescr;
-  aFunction->SetDescription(anOldDescr);
+  anAsciiList.Trunc(anAsciiList.Length() - 1);
+
+  Handle(GEOM_Function) aFunction = anObj->GetLastFunction();
+
+  GEOM::TPythonDump(aFunction) << "[" << anAsciiList.ToCString()
+    << "] = geompy.GetSharedShapes(" << theShape1 << ", "
+      << theShape2 << ", " << TopAbs_ShapeEnum(theShapeType) << ")";
 
   SetErrorCode(OK);
   return aSeq;
@@ -1016,33 +1111,67 @@ Handle(TColStd_HSequenceOfTransient) GEOMImpl_IShapesOperations::GetSharedShapes
 
 //=============================================================================
 /*!
- *  GetShapesOnPlane
+ *  
  */
 //=============================================================================
-Handle(TColStd_HSequenceOfTransient) GEOMImpl_IShapesOperations::GetShapesOnPlane
-                                        (const Handle(GEOM_Object)& theShape,
-                                         const Standard_Integer     theShapeType,
-                                         const Handle(GEOM_Object)& theAx1,
-                                         const GEOMAlgo_State       theState)
+static GEOM::TPythonDump& operator<< (GEOM::TPythonDump&   theDump,
+                                      const GEOMAlgo_State theState)
 {
-  SetErrorCode(KO);
-
-  if (theShape.IsNull() || theAx1.IsNull()) return NULL;
-
-  TopoDS_Shape aShape = theShape->GetValue();
-  TopoDS_Shape anAx1  = theAx1->GetValue();
+  switch (theState) {
+  case GEOMAlgo_ST_IN:
+    theDump << "geompy.GEOM.ST_IN";
+    break;
+  case GEOMAlgo_ST_OUT:
+    theDump << "geompy.GEOM.ST_OUT";
+    break;
+  case GEOMAlgo_ST_ON:
+    theDump << "geompy.GEOM.ST_ON";
+    break;
+  case GEOMAlgo_ST_ONIN:
+    theDump << "geompy.GEOM.ST_ONIN";
+    break;
+  case GEOMAlgo_ST_ONOUT:
+    theDump << "geompy.GEOM.ST_ONOUT";
+    break;
+  default:
+    theDump << "geompy.GEOM.ST_UNKNOWN";
+    break;
+  }
+  return theDump;
+}
 
-  if (aShape.IsNull() || anAx1.IsNull()) return NULL;
+//=======================================================================
+//function : checkTypeShapesOn
+/*!
+ * \brief Checks if theShapeType parameter of GetShapesOnXXX() is OK
+ * \param theShapeType - the shape type to check
+ * \retval bool  - result of the check
+ */
+//=======================================================================
 
-  TopAbs_ShapeEnum aShapeType = TopAbs_ShapeEnum(theShapeType);
-  if (aShapeType != TopAbs_VERTEX &&
-      aShapeType != TopAbs_EDGE &&
-      aShapeType != TopAbs_FACE) {
-    SetErrorCode("Only vertices, edges or faces can be found by this method");
-    return NULL;
+bool GEOMImpl_IShapesOperations::checkTypeShapesOn(const Standard_Integer theShapeType)
+{
+  if (theShapeType != TopAbs_VERTEX &&
+      theShapeType != TopAbs_EDGE &&
+      theShapeType != TopAbs_FACE &&
+      theShapeType != TopAbs_SOLID) {
+    SetErrorCode("Only solids, vertices, edges or faces can be found by this method");
+    return false;
   }
+  return true;
+}
 
-  // Create plane
+//=======================================================================
+//function : makePlane
+  /*!
+   * \brief Creates Geom_Plane
+    * \param theAx1 - shape object defining plane parameters
+    * \retval Handle(Geom_Surface) - resulting surface
+   */
+//=======================================================================
+
+Handle(Geom_Surface) GEOMImpl_IShapesOperations::makePlane(const TopoDS_Shape& anAx1)
+{
   if (anAx1.ShapeType() != TopAbs_EDGE) return NULL;
   TopoDS_Edge anEdge = TopoDS::Edge(anAx1);
   TopoDS_Vertex V1, V2;
@@ -1057,33 +1186,95 @@ Handle(TColStd_HSequenceOfTransient) GEOMImpl_IShapesOperations::GetShapesOnPlan
     SetErrorCode("Vector with null magnitude given");
     return NULL;
   }
+  return new Geom_Plane(aLoc, aVec);
+}
+
+//=======================================================================
+//function : makeCylinder
+  /*!
+   * \brief Creates Geom_CylindricalSurface
+    * \param theAx1 - edge defining cylinder axis
+    * \param theRadius - cylinder radius
+    * \retval Handle(Geom_Surface) - resulting surface
+   */
+//=======================================================================
+
+Handle(Geom_Surface) GEOMImpl_IShapesOperations::makeCylinder(const TopoDS_Shape& anAxis,
+                                                              const Standard_Real theRadius)
+{
+  //Axis of the cylinder
+  if (anAxis.ShapeType() != TopAbs_EDGE) {
+    SetErrorCode("Not an edge given for the axis");
+    return NULL;
+  }
+  TopoDS_Edge anEdge = TopoDS::Edge(anAxis);
+  TopoDS_Vertex V1, V2;
+  TopExp::Vertices(anEdge, V1, V2, Standard_True);
+  if (V1.IsNull() || V2.IsNull()) {
+    SetErrorCode("Bad edge given for the axis");
+    return NULL;
+  }
+  gp_Pnt aLoc = BRep_Tool::Pnt(V1);
+  gp_Vec aVec (aLoc, BRep_Tool::Pnt(V2));
+  if (aVec.Magnitude() < Precision::Confusion()) {
+    SetErrorCode("Vector with null magnitude given");
+    return NULL;
+  }
+
+  gp_Ax3 anAx3 (aLoc, aVec);
+  return new Geom_CylindricalSurface(anAx3, theRadius);
+}
 
-  Handle(Geom_Plane) aPlane = new Geom_Plane(aLoc, aVec);
+
+//=======================================================================
+//function : getShapesOnBoxIDs
+  /*!
+   * \brief Find IDs of subshapes complying with given status about surface
+    * \param theBox - the box to check state of subshapes against
+    * \param theShape - the shape to explore
+    * \param theShapeType - type of subshape of theShape
+    * \param theState - required state
+    * \retval Handle(TColStd_HSequenceOfInteger) - IDs of found subshapes
+   */
+//=======================================================================
+
+Handle(TColStd_HSequenceOfInteger)
+  GEOMImpl_IShapesOperations::getShapesOnBoxIDs(const Handle(GEOM_Object)& theBox,
+                                               const Handle(GEOM_Object)& theShape,
+                                               const Standard_Integer theShapeType,
+                                               GEOMAlgo_State theState)
+{
+  Handle(TColStd_HSequenceOfInteger) aSeqOfIDs;
+
+  TopoDS_Shape aBox = theBox->GetValue();
+  TopoDS_Shape aShape = theShape->GetValue();
 
   // Call algo
-  GEOMAlgo_FinderShapeOn aFinder;
+  GEOMAlgo_FinderShapeOn2 aFinder;
   Standard_Real aTol = 0.0001; // default value
 
+  Handle(GEOMAlgo_ClsfBox) aClsfBox = new GEOMAlgo_ClsfBox;
+  aClsfBox->SetBox(aBox);
+
   aFinder.SetShape(aShape);
   aFinder.SetTolerance(aTol);
-  aFinder.SetSurface(aPlane);
-  aFinder.SetShapeType(aShapeType);
+  aFinder.SetClsf(aClsfBox);
+  aFinder.SetShapeType( (TopAbs_ShapeEnum)theShapeType );
   aFinder.SetState(theState);
-
   aFinder.Perform();
 
   // Interprete results
   Standard_Integer iErr = aFinder.ErrorStatus();
-  // the detailed description of error codes is in GEOMAlgo_FinderShapeOn.cxx
+  // the detailed description of error codes is in GEOMAlgo_FinderShapeOn1.cxx
   if (iErr) {
     MESSAGE(" iErr : " << iErr);
     TCollection_AsciiString aMsg (" iErr : ");
     aMsg += TCollection_AsciiString(iErr);
     SetErrorCode(aMsg);
-    return NULL;
+    return aSeqOfIDs;
   }
   Standard_Integer iWrn = aFinder.WarningStatus();
-  // the detailed description of warning codes is in GEOMAlgo_FinderShapeOn.cxx
+  // the detailed description of warning codes is in GEOMAlgo_FinderShapeOn1.cxx
   if (iWrn) {
     MESSAGE(" *** iWrn : " << iWrn);
   }
@@ -1091,123 +1282,171 @@ Handle(TColStd_HSequenceOfTransient) GEOMImpl_IShapesOperations::GetShapesOnPlan
   const TopTools_ListOfShape& listSS = aFinder.Shapes(); // the result
 
   if (listSS.Extent() < 1) {
-    SetErrorCode("Not a single sub-shape of the requested type found on the given plane");
-    return NULL;
+    SetErrorCode("Not a single sub-shape of the requested type found on the given surface");
+    return aSeqOfIDs;
   }
 
-  // Fill sequence of objects
+  // Fill sequence of object IDs
+  aSeqOfIDs = new TColStd_HSequenceOfInteger;
+
   TopTools_IndexedMapOfShape anIndices;
   TopExp::MapShapes(aShape, anIndices);
 
-  Handle(GEOM_Object) anObj;
-  Handle(TColStd_HArray1OfInteger) anArray;
-  Handle(TColStd_HSequenceOfTransient) aSeq = new TColStd_HSequenceOfTransient;
-
   TopTools_ListIteratorOfListOfShape itSub (listSS);
   for (int index = 1; itSub.More(); itSub.Next(), ++index) {
     int id = anIndices.FindIndex(itSub.Value());
-    anArray = new TColStd_HArray1OfInteger(1,1);
-    anArray->SetValue(1, id);
-    anObj = GetEngine()->AddSubShape(theShape, anArray);
-    aSeq->Append(anObj);
+    aSeqOfIDs->Append(id);
   }
-  
-  // The GetShapesOnPlane() doesn't change object so no new function is required.
-  Handle(GEOM_Function) aFunction = theShape->GetLastFunction();
+
+  return aSeqOfIDs;
+}
+
+
+//=======================================================================
+//function : GetShapesOnBoxIDs
+/*!
+   * \brief Find subshapes complying with given status about surface
+    * \param theBox - the box to check state of subshapes against
+    * \param theShape - the shape to explore
+    * \param theShapeType - type of subshape of theShape
+    * \param theState - required state
+    * \retval Handle(TColStd_HSequenceOfInteger) - IDs of found subshapes
+ */
+//=======================================================================
+
+Handle(TColStd_HSequenceOfInteger)
+    GEOMImpl_IShapesOperations::GetShapesOnBoxIDs(const Handle(GEOM_Object)& theBox,
+                                                 const Handle(GEOM_Object)& theShape,
+                                                 const Standard_Integer theShapeType,
+                                                 GEOMAlgo_State theState)
+{
+  // Find subshapes ids
+  Handle(TColStd_HSequenceOfInteger) aSeqOfIDs =
+    getShapesOnBoxIDs (theBox, theShape, theShapeType, theState);
+  if ( aSeqOfIDs.IsNull()  || aSeqOfIDs->Length() == 0 )
+    return NULL;
+
+  // The GetShapesOnBox() doesn't change object so no new function is required.
+  Handle(GEOM_Function) aFunction = GEOM::GetCreatedLast(theShape,theBox)->GetLastFunction();
 
   // Make a Python command
-  TCollection_AsciiString anEntry, aDescr
-    ("\nlistShapesOnPlane = IShapesOperations.GetShapesOnPlane(");
-  TDF_Tool::Entry(theShape->GetEntry(), anEntry);
-  aDescr += anEntry + TCollection_AsciiString(theShapeType) + ",";
-  TDF_Tool::Entry(theAx1->GetEntry(), anEntry);
-  aDescr += anEntry + ",";
-  aDescr += TCollection_AsciiString(theState) + ")";
-
-  TCollection_AsciiString anOldDescr = aFunction->GetDescription();
-  anOldDescr += aDescr;
-  aFunction->SetDescription(anOldDescr);
+  GEOM::TPythonDump(aFunction)
+    << "listShapesOnBoxIDs = geompy.GetShapesOnQuadrangleIDs("
+    << theBox << ", "
+    << theShape << ", "
+    << TopAbs_ShapeEnum(theShapeType) << ", "
+    << theState << ")";
 
   SetErrorCode(OK);
-  return aSeq;
+  return aSeqOfIDs;
 }
 
-//=============================================================================
+//=======================================================================
+//function : GetShapesOnBox
 /*!
- *  GetShapesOnCylinder
+   * \brief Find subshapes complying with given status about surface
+    * \param theBox - the box to check state of subshapes against
+    * \param theShape - the shape to explore
+    * \param theShapeType - type of subshape of theShape
+    * \param theState - required state
+    * \retval Handle(TColStd_HSequenceOfTransient) - found subshapes
  */
-//=============================================================================
-Handle(TColStd_HSequenceOfTransient) GEOMImpl_IShapesOperations::GetShapesOnCylinder
-                                          (const Handle(GEOM_Object)& theShape,
-                                           const Standard_Integer     theShapeType,
-                                           const Handle(GEOM_Object)& theAxis,
-                                           const Standard_Real        theRadius,
-                                           const GEOMAlgo_State       theState)
+//=======================================================================
+
+Handle(TColStd_HSequenceOfTransient)
+    GEOMImpl_IShapesOperations::GetShapesOnBox(const Handle(GEOM_Object)& theBox,
+                                              const Handle(GEOM_Object)&  theShape,
+                                              const Standard_Integer theShapeType,
+                                              GEOMAlgo_State theState)
 {
-  SetErrorCode(KO);
+  // Find subshapes ids
+  Handle(TColStd_HSequenceOfInteger) aSeqOfIDs =
+    getShapesOnBoxIDs (theBox, theShape, theShapeType, theState);
+  if ( aSeqOfIDs.IsNull()  || aSeqOfIDs->Length() == 0 )
+    return NULL;
 
-  if (theShape.IsNull() || theAxis.IsNull()) return NULL;
+  // Find objects by indices
+  TCollection_AsciiString anAsciiList;
+  Handle(TColStd_HSequenceOfTransient) aSeq;
+  aSeq = getObjectsShapesOn( theShape, aSeqOfIDs, anAsciiList );
+  if ( aSeq.IsNull() || aSeq->IsEmpty() )
+    return NULL;
 
-  TopoDS_Shape aShape = theShape->GetValue();
-  TopoDS_Shape anAxis = theAxis->GetValue();
+  // Make a Python command
 
-  if (aShape.IsNull() || anAxis.IsNull()) return NULL;
+  Handle(GEOM_Object) anObj = Handle(GEOM_Object)::DownCast( aSeq->Value( 1 ));
+  Handle(GEOM_Function) aFunction = anObj->GetLastFunction();
 
-  TopAbs_ShapeEnum aShapeType = TopAbs_ShapeEnum(theShapeType);
-  if (aShapeType != TopAbs_VERTEX &&
-      aShapeType != TopAbs_EDGE &&
-      aShapeType != TopAbs_FACE) {
-    SetErrorCode("Only vertices, edges or faces can be found by this method");
-    return NULL;
-  }
+  GEOM::TPythonDump(aFunction)
+    << "[" << anAsciiList.ToCString() << "] = geompy.GetShapesOnBox("
+    << theBox << ", "
+    << theShape << ", "
+    << TopAbs_ShapeEnum(theShapeType) << ", "
+    << theState << ")";
 
-  //Axis of the cylinder
-  if (anAxis.ShapeType() != TopAbs_EDGE) {
-    SetErrorCode("Not an edge given for the axis");
-    return NULL;
-  }
-  TopoDS_Edge anEdge = TopoDS::Edge(anAxis);
-  TopoDS_Vertex V1, V2;
-  TopExp::Vertices(anEdge, V1, V2, Standard_True);
-  if (V1.IsNull() || V2.IsNull()) {
-    SetErrorCode("Bad edge given for the axis");
-    return NULL;
-  }
-  gp_Pnt aLoc = BRep_Tool::Pnt(V1);
-  gp_Vec aVec (aLoc, BRep_Tool::Pnt(V2));
-  if (aVec.Magnitude() < Precision::Confusion()) {
-    SetErrorCode("Vector with null magnitude given");
-    return NULL;
-  }
+  SetErrorCode(OK);
+  return aSeq;
+}
 
-  gp_Ax3 anAx3 (aLoc, aVec);
-  Handle(Geom_CylindricalSurface) aCylinder =
-    new Geom_CylindricalSurface(anAx3, theRadius);
+
+//=======================================================================
+//function : getShapesOnSurfaceIDs
+  /*!
+   * \brief Find IDs of subshapes complying with given status about surface
+    * \param theSurface - the surface to check state of subshapes against
+    * \param theShape - the shape to explore
+    * \param theShapeType - type of subshape of theShape
+    * \param theState - required state
+    * \retval Handle(TColStd_HSequenceOfInteger) - IDs of found subshapes
+   */
+//=======================================================================
+
+Handle(TColStd_HSequenceOfInteger)
+  GEOMImpl_IShapesOperations::getShapesOnSurfaceIDs(const Handle(Geom_Surface)& theSurface,
+                                                    const TopoDS_Shape&         theShape,
+                                                    TopAbs_ShapeEnum            theShapeType,
+                                                    GEOMAlgo_State              theState)
+{
+  Handle(TColStd_HSequenceOfInteger) aSeqOfIDs;
+
+  // Check presence of triangulation, build if need
+  if (!CheckTriangulation(theShape))
+    return aSeqOfIDs;
 
   // Call algo
-  GEOMAlgo_FinderShapeOn aFinder;
+  GEOMAlgo_FinderShapeOn1 aFinder;
   Standard_Real aTol = 0.0001; // default value
 
-  aFinder.SetShape(aShape);
+  aFinder.SetShape(theShape);
   aFinder.SetTolerance(aTol);
-  aFinder.SetSurface(aCylinder);
-  aFinder.SetShapeType(aShapeType);
+  aFinder.SetSurface(theSurface);
+  aFinder.SetShapeType(theShapeType);
   aFinder.SetState(theState);
 
+  // Sets the minimal number of inner points for the faces that do not have own
+  // inner points at all (for e.g. rectangular planar faces have just 2 triangles).
+  // Default value=3
+  aFinder.SetNbPntsMin(3);
+  // Sets the maximal number of inner points for edges or faces.
+  // It is usefull for the cases when this number is very big (e.g =2000) to improve
+  // the performance. If this value =0, all inner points will be taken into account.
+  // Default value=0
+  aFinder.SetNbPntsMax(100);
+
   aFinder.Perform();
 
   // Interprete results
   Standard_Integer iErr = aFinder.ErrorStatus();
-  // the detailed description of error codes is in GEOMAlgo_FinderShapeOn.cxx
+  // the detailed description of error codes is in GEOMAlgo_FinderShapeOn1.cxx
   if (iErr) {
     MESSAGE(" iErr : " << iErr);
     TCollection_AsciiString aMsg (" iErr : ");
     aMsg += TCollection_AsciiString(iErr);
     SetErrorCode(aMsg);
-    return NULL;
+    return aSeqOfIDs;
   }
   Standard_Integer iWrn = aFinder.WarningStatus();
-  // the detailed description of warning codes is in GEOMAlgo_FinderShapeOn.cxx
+  // the detailed description of warning codes is in GEOMAlgo_FinderShapeOn1.cxx
   if (iWrn) {
     MESSAGE(" *** iWrn : " << iWrn);
   }
@@ -1215,43 +1454,258 @@ Handle(TColStd_HSequenceOfTransient) GEOMImpl_IShapesOperations::GetShapesOnCyli
   const TopTools_ListOfShape& listSS = aFinder.Shapes(); // the result
 
   if (listSS.Extent() < 1) {
-    SetErrorCode("Not a single sub-shape of the requested type found on the given cylinder");
-    return NULL;
+    SetErrorCode("Not a single sub-shape of the requested type found on the given surface");
+    return aSeqOfIDs;
   }
 
-  // Fill sequence of objects
-  TopTools_IndexedMapOfShape anIndices;
-  TopExp::MapShapes(aShape, anIndices);
+  // Fill sequence of object IDs
+  aSeqOfIDs = new TColStd_HSequenceOfInteger;
 
-  Handle(GEOM_Object) anObj;
-  Handle(TColStd_HArray1OfInteger) anArray;
-  Handle(TColStd_HSequenceOfTransient) aSeq = new TColStd_HSequenceOfTransient;
+  TopTools_IndexedMapOfShape anIndices;
+  TopExp::MapShapes(theShape, anIndices);
 
   TopTools_ListIteratorOfListOfShape itSub (listSS);
   for (int index = 1; itSub.More(); itSub.Next(), ++index) {
     int id = anIndices.FindIndex(itSub.Value());
-    anArray = new TColStd_HArray1OfInteger(1,1);
-    anArray->SetValue(1, id);
-    anObj = GetEngine()->AddSubShape(theShape, anArray);
-    aSeq->Append(anObj);
+    aSeqOfIDs->Append(id);
   }
-  
-  // The GetShapesOnCylinder() doesn't change object so no new function is required.
-  Handle(GEOM_Function) aFunction = theShape->GetLastFunction();
 
-  // Make a Python command
-  TCollection_AsciiString anEntry, aDescr
-    ("\nlistShapesOnCylinder = IShapesOperations.GetShapesOnCylinder(");
-  TDF_Tool::Entry(theShape->GetEntry(), anEntry);
-  aDescr += anEntry + TCollection_AsciiString(theShapeType) + ",";
-  TDF_Tool::Entry(theAxis->GetEntry(), anEntry);
-  aDescr += anEntry + ",";
-  aDescr += TCollection_AsciiString(theRadius) + ",";
-  aDescr += TCollection_AsciiString(theState) + ")";
-
-  TCollection_AsciiString anOldDescr = aFunction->GetDescription();
-  anOldDescr += aDescr;
-  aFunction->SetDescription(anOldDescr);
+  return aSeqOfIDs;
+}
+
+//=======================================================================
+//function : getObjectsShapesOn
+/*!
+ * \brief Find shape objects and their entries by their ids
+ * \param theShapeIDs - incoming shape ids
+ * \param theShapeEntries - outgoing entries like "entry1, entry2, ..."
+ * \retval Handle(TColStd_HSequenceOfTransient) - found shape objects
+ */
+//=======================================================================
+
+Handle(TColStd_HSequenceOfTransient) GEOMImpl_IShapesOperations::
+ getObjectsShapesOn(const Handle(GEOM_Object)&                theShape,
+                    const Handle(TColStd_HSequenceOfInteger)& theShapeIDs,
+                    TCollection_AsciiString &                 theShapeEntries)
+{
+  Handle(TColStd_HSequenceOfTransient) aSeq;
+
+  if ( !theShapeIDs.IsNull() && theShapeIDs->Length() > 0 )
+  {
+    aSeq = new TColStd_HSequenceOfTransient;
+    Handle(TColStd_HArray1OfInteger) anArray = new TColStd_HArray1OfInteger(1,1);
+    TCollection_AsciiString anEntry;
+    for ( int i = 1; i <= theShapeIDs->Length(); ++i )
+    {
+      anArray->SetValue(1, theShapeIDs->Value( i ));
+      Handle(GEOM_Object) anObj = GetEngine()->AddSubShape(theShape, anArray);
+      aSeq->Append( anObj );
+
+      TDF_Tool::Entry(anObj->GetEntry(), anEntry);
+      if ( i != 1 ) theShapeEntries += ",";
+      theShapeEntries += anEntry;
+    }
+  }
+  return aSeq;
+}
+
+//=======================================================================
+//function : getShapesOnSurface
+/*!
+   * \brief Find subshapes complying with given status about surface
+    * \param theSurface - the surface to check state of subshapes against
+    * \param theShape - the shape to explore
+    * \param theShapeType - type of subshape of theShape
+    * \param theState - required state
+    * \param theShapeEntries - outgoing entries like "entry1, entry2, ..."
+    * \retval Handle(TColStd_HSequenceOfInteger) - IDs of found subshapes
+ */
+//=======================================================================
+
+Handle(TColStd_HSequenceOfTransient)
+    GEOMImpl_IShapesOperations::getShapesOnSurface(const Handle(Geom_Surface)& theSurface,
+                                                   const Handle(GEOM_Object)&  theShape,
+                                                   TopAbs_ShapeEnum            theShapeType,
+                                                   GEOMAlgo_State              theState,
+                                                   TCollection_AsciiString &   theShapeEntries)
+{
+  // Find subshapes ids
+  Handle(TColStd_HSequenceOfInteger) aSeqOfIDs =
+    getShapesOnSurfaceIDs (theSurface, theShape->GetValue(), theShapeType, theState);
+  if ( aSeqOfIDs.IsNull()  || aSeqOfIDs->Length() == 0 )
+    return NULL;
+
+  return getObjectsShapesOn( theShape, aSeqOfIDs, theShapeEntries );
+}
+
+//=============================================================================
+/*!
+ *  GetShapesOnPlane
+ */
+//=============================================================================
+Handle(TColStd_HSequenceOfTransient) GEOMImpl_IShapesOperations::GetShapesOnPlane
+                                        (const Handle(GEOM_Object)& theShape,
+                                         const Standard_Integer     theShapeType,
+                                         const Handle(GEOM_Object)& theAx1,
+                                         const GEOMAlgo_State       theState)
+{
+  SetErrorCode(KO);
+
+  if (theShape.IsNull() || theAx1.IsNull()) return NULL;
+
+  TopoDS_Shape aShape = theShape->GetValue();
+  TopoDS_Shape anAx1  = theAx1->GetValue();
+
+  if (aShape.IsNull() || anAx1.IsNull()) return NULL;
+
+  TopAbs_ShapeEnum aShapeType = TopAbs_ShapeEnum(theShapeType);
+  if ( !checkTypeShapesOn( theShapeType ))
+    return NULL;
+
+  // Create plane
+  Handle(Geom_Surface) aPlane = makePlane( anAx1 );
+  if ( aPlane.IsNull() )
+    return NULL;
+
+  // Find objects
+  TCollection_AsciiString anAsciiList;
+  Handle(TColStd_HSequenceOfTransient) aSeq;
+  aSeq = getShapesOnSurface( aPlane, theShape, aShapeType, theState, anAsciiList );
+  if ( aSeq.IsNull() || aSeq->Length() == 0 )
+    return NULL;
+
+  // Make a Python command
+
+  Handle(GEOM_Object) anObj = Handle(GEOM_Object)::DownCast( aSeq->Value( 1 ));
+  Handle(GEOM_Function) aFunction = anObj->GetLastFunction();
+
+  GEOM::TPythonDump(aFunction) << "[" << anAsciiList.ToCString()
+    << "] = geompy.GetShapesOnPlane(" << theShape << ", "
+      << aShapeType << ", " << theAx1 << ", " << theState << ")";
+
+  SetErrorCode(OK);
+  return aSeq;
+}
+
+//=============================================================================
+/*!
+ *  GetShapesOnPlaneWithLocation
+ */
+//=============================================================================
+Handle(TColStd_HSequenceOfTransient) GEOMImpl_IShapesOperations::GetShapesOnPlaneWithLocation
+                                        (const Handle(GEOM_Object)& theShape,
+                                         const Standard_Integer     theShapeType,
+                                         const Handle(GEOM_Object)& theAx1,
+                                        const Handle(GEOM_Object)& thePnt,
+                                         const GEOMAlgo_State       theState)
+{
+  SetErrorCode(KO);
+
+  if (theShape.IsNull() || theAx1.IsNull() || thePnt.IsNull()) return NULL;
+
+  TopoDS_Shape aShape = theShape->GetValue();
+  TopoDS_Shape anAx1  = theAx1->GetValue();
+  TopoDS_Shape anPnt = thePnt->GetValue();
+
+  if (aShape.IsNull() || anAx1.IsNull() || anPnt.IsNull()) return NULL;
+
+  TopAbs_ShapeEnum aShapeType = TopAbs_ShapeEnum(theShapeType);
+  if ( !checkTypeShapesOn( theShapeType ))
+    return NULL;
+
+  // Create plane
+  if ( anAx1.ShapeType() != TopAbs_EDGE || anPnt.ShapeType() != TopAbs_VERTEX ) return NULL;
+  TopoDS_Vertex V1, V2, V3;
+  TopoDS_Edge anEdge = TopoDS::Edge(anAx1);
+  TopExp::Vertices(anEdge, V1, V2, Standard_True);
+
+  if (V1.IsNull() || V2.IsNull()) {
+    SetErrorCode("Bad edge given for the plane normal vector");
+    return NULL;
+  }
+  V3 = TopoDS::Vertex(anPnt);
+
+  if(V3.IsNull()) {
+    SetErrorCode("Bad vertex given for the plane location");
+      return NULL;
+  }
+  gp_Pnt aLoc = BRep_Tool::Pnt(V3);
+  gp_Vec aVec(BRep_Tool::Pnt(V1),BRep_Tool::Pnt(V2));
+
+  if (aVec.Magnitude() < Precision::Confusion()) {
+     SetErrorCode("Vector with null magnitude given");
+    return NULL;
+  }
+  Handle(Geom_Surface) aPlane = new Geom_Plane(aLoc, aVec);
+
+  if ( aPlane.IsNull() )
+    return NULL;
+  
+  // Find objects
+  TCollection_AsciiString anAsciiList;
+  Handle(TColStd_HSequenceOfTransient) aSeq;
+  aSeq = getShapesOnSurface( aPlane, theShape, aShapeType, theState, anAsciiList );
+  if ( aSeq.IsNull() || aSeq->Length() == 0 )
+    return NULL;
+
+  // Make a Python command
+
+  Handle(GEOM_Object) anObj = Handle(GEOM_Object)::DownCast( aSeq->Value( 1 ));
+  Handle(GEOM_Function) aFunction = anObj->GetLastFunction();
+
+  GEOM::TPythonDump(aFunction) << "[" << anAsciiList.ToCString()
+    << "] = geompy.GetShapesOnPlaneWithLocation(" << theShape << ", "
+    << aShapeType << ", " << theAx1 << ", "<< thePnt <<", " << theState << ")";
+
+  SetErrorCode(OK);
+  return aSeq;
+}
+
+//=============================================================================
+/*!
+ *  GetShapesOnCylinder
+ */
+//=============================================================================
+Handle(TColStd_HSequenceOfTransient) GEOMImpl_IShapesOperations::GetShapesOnCylinder
+                                          (const Handle(GEOM_Object)& theShape,
+                                           const Standard_Integer     theShapeType,
+                                           const Handle(GEOM_Object)& theAxis,
+                                           const Standard_Real        theRadius,
+                                           const GEOMAlgo_State       theState)
+{
+  SetErrorCode(KO);
+
+  if (theShape.IsNull() || theAxis.IsNull()) return NULL;
+
+  TopoDS_Shape aShape = theShape->GetValue();
+  TopoDS_Shape anAxis = theAxis->GetValue();
+
+  if (aShape.IsNull() || anAxis.IsNull()) return NULL;
+
+  TopAbs_ShapeEnum aShapeType = TopAbs_ShapeEnum(theShapeType);
+  if ( !checkTypeShapesOn( aShapeType ))
+    return NULL;
+
+  // Create a cylinder surface
+  Handle(Geom_Surface) aCylinder = makeCylinder( anAxis, theRadius );
+  if ( aCylinder.IsNull() )
+    return NULL;
+
+  // Find objects
+  TCollection_AsciiString anAsciiList;
+  Handle(TColStd_HSequenceOfTransient) aSeq;
+  aSeq = getShapesOnSurface( aCylinder, theShape, aShapeType, theState, anAsciiList );
+  if ( aSeq.IsNull() || aSeq->Length() == 0 )
+    return NULL;
+  
+  // Make a Python command
+
+  Handle(GEOM_Object) anObj = Handle(GEOM_Object)::DownCast( aSeq->Value( 1 ));
+  Handle(GEOM_Function) aFunction = anObj->GetLastFunction();
+
+  GEOM::TPythonDump(aFunction) << "[" << anAsciiList.ToCString()
+    << "] = geompy.GetShapesOnCylinder(" << theShape << ", " << aShapeType
+      << ", " << theAxis << ", " << theRadius << ", " << theState << ")";
 
   SetErrorCode(OK);
   return aSeq;
@@ -1279,12 +1733,220 @@ Handle(TColStd_HSequenceOfTransient) GEOMImpl_IShapesOperations::GetShapesOnSphe
   if (aShape.IsNull() || aCenter.IsNull()) return NULL;
 
   TopAbs_ShapeEnum aShapeType = TopAbs_ShapeEnum(theShapeType);
-  if (aShapeType != TopAbs_VERTEX &&
-      aShapeType != TopAbs_EDGE &&
-      aShapeType != TopAbs_FACE) {
-    SetErrorCode("Only vertices, edges or faces can be found by this method");
+  if ( !checkTypeShapesOn( aShapeType ))
+    return NULL;
+
+  // Center of the sphere
+  if (aCenter.ShapeType() != TopAbs_VERTEX) return NULL;
+  gp_Pnt aLoc = BRep_Tool::Pnt(TopoDS::Vertex(aCenter));
+
+  gp_Ax3 anAx3 (aLoc, gp::DZ());
+  Handle(Geom_SphericalSurface) aSphere =
+    new Geom_SphericalSurface(anAx3, theRadius);
+
+  // Find objects
+  TCollection_AsciiString anAsciiList;
+  Handle(TColStd_HSequenceOfTransient) aSeq;
+  aSeq = getShapesOnSurface( aSphere, theShape, aShapeType, theState, anAsciiList );
+  if ( aSeq.IsNull() || aSeq->Length() == 0 )
+    return NULL;
+    
+  // Make a Python command
+
+  Handle(GEOM_Object) anObj = Handle(GEOM_Object)::DownCast( aSeq->Value( 1 ));
+  Handle(GEOM_Function) aFunction = anObj->GetLastFunction();
+
+  GEOM::TPythonDump(aFunction) << "[" << anAsciiList.ToCString()
+    << "] = geompy.GetShapesOnSphere(" << theShape << ", " << aShapeType
+      << ", " << theCenter << ", " << theRadius << ", " << theState << ")";
+
+  SetErrorCode(OK);
+  return aSeq;
+}
+
+//=============================================================================
+/*!
+ *  GetShapesOnPlaneIDs
+ */
+//=============================================================================
+Handle(TColStd_HSequenceOfInteger) GEOMImpl_IShapesOperations::GetShapesOnPlaneIDs
+                                        (const Handle(GEOM_Object)& theShape,
+                                         const Standard_Integer     theShapeType,
+                                         const Handle(GEOM_Object)& theAx1,
+                                         const GEOMAlgo_State       theState)
+{
+  SetErrorCode(KO);
+
+  if (theShape.IsNull() || theAx1.IsNull()) return NULL;
+
+  TopoDS_Shape aShape = theShape->GetValue();
+  TopoDS_Shape anAx1  = theAx1->GetValue();
+
+  if (aShape.IsNull() || anAx1.IsNull()) return NULL;
+
+  TopAbs_ShapeEnum aShapeType = TopAbs_ShapeEnum(theShapeType);
+  if ( !checkTypeShapesOn( aShapeType ))
     return NULL;
+
+  // Create plane
+  Handle(Geom_Surface) aPlane = makePlane( anAx1 );
+  if ( aPlane.IsNull() )
+    return NULL;
+
+  // Find object IDs
+  Handle(TColStd_HSequenceOfInteger) aSeq;
+  aSeq = getShapesOnSurfaceIDs( aPlane, aShape, aShapeType, theState );
+
+  // The GetShapesOnPlaneIDs() doesn't change object so no new function is required.
+  Handle(GEOM_Function) aFunction = GEOM::GetCreatedLast(theShape,theAx1)->GetLastFunction();
+
+  // Make a Python command
+  GEOM::TPythonDump(aFunction, /*append=*/true)
+    << "listShapesOnPlane = geompy.GetShapesOnPlaneIDs"
+    << "(" << theShape << "," << aShapeType << "," << theAx1 << "," << theState << ")";
+
+  SetErrorCode(OK);
+  return aSeq;
+}
+
+//=============================================================================
+/*!
+ *  GetShapesOnPlaneWithLocationIDs
+ */
+//=============================================================================
+Handle(TColStd_HSequenceOfInteger) GEOMImpl_IShapesOperations::GetShapesOnPlaneWithLocationIDs
+                                        (const Handle(GEOM_Object)& theShape,
+                                         const Standard_Integer     theShapeType,
+                                         const Handle(GEOM_Object)& theAx1,
+                                        const Handle(GEOM_Object)& thePnt,
+                                         const GEOMAlgo_State       theState)
+{
+  SetErrorCode(KO);
+
+  if (theShape.IsNull() || theAx1.IsNull() || thePnt.IsNull()) return NULL;
+
+  TopoDS_Shape aShape = theShape->GetValue();
+  TopoDS_Shape anAx1  = theAx1->GetValue();
+  TopoDS_Shape anPnt  = thePnt->GetValue();
+
+  if (aShape.IsNull() || anAx1.IsNull() || anPnt.IsNull()) return NULL;
+
+  TopAbs_ShapeEnum aShapeType = TopAbs_ShapeEnum(theShapeType);
+  if ( !checkTypeShapesOn( aShapeType ))
+    return NULL;
+
+  // Create plane
+  if (anAx1.ShapeType() != TopAbs_EDGE || anPnt.ShapeType() != TopAbs_VERTEX) return NULL;
+  TopoDS_Edge anEdge = TopoDS::Edge(anAx1);
+  TopoDS_Vertex V1, V2, V3;
+  TopExp::Vertices(anEdge, V1, V2, Standard_True);
+  if (V1.IsNull() || V2.IsNull()) {
+    SetErrorCode("Bad edge given for the plane normal vector");
+    return NULL;
+  }
+  V3 = TopoDS::Vertex(anPnt);
+  if(V3.IsNull()) {
+    SetErrorCode("Bad vertex given for the plane location");
+      return NULL;
   }
+  gp_Pnt aLoc = BRep_Tool::Pnt(V3);
+  gp_Vec aVec(BRep_Tool::Pnt(V1),BRep_Tool::Pnt(V2));
+  if (aVec.Magnitude() < Precision::Confusion()) {
+    SetErrorCode("Vector with null magnitude given");
+    return NULL;
+  }
+  
+  Handle(Geom_Surface) aPlane = new Geom_Plane(aLoc, aVec);  
+  if ( aPlane.IsNull() )
+    return NULL;
+
+  // Find object IDs
+  Handle(TColStd_HSequenceOfInteger) aSeq;
+  aSeq = getShapesOnSurfaceIDs( aPlane, aShape, aShapeType, theState );
+
+  // The GetShapesOnPlaneIDs() doesn't change object so no new function is required.
+  Handle(GEOM_Function) aFunction = GEOM::GetCreatedLast(theShape,theAx1)->GetLastFunction();
+
+  // Make a Python command
+  GEOM::TPythonDump(aFunction, /*append=*/true)
+    << "listShapesOnPlane = geompy.GetShapesOnPlaneWithLocationIDs"
+    << "(" << theShape << ", " << aShapeType << ", " << theAx1 << ", "<< thePnt << ", "  << theState << ")";
+
+  SetErrorCode(OK);
+  return aSeq;
+}
+
+//=============================================================================
+/*!
+ *  GetShapesOnCylinderIDs
+ */
+//=============================================================================
+Handle(TColStd_HSequenceOfInteger) GEOMImpl_IShapesOperations::GetShapesOnCylinderIDs
+                                          (const Handle(GEOM_Object)& theShape,
+                                           const Standard_Integer     theShapeType,
+                                           const Handle(GEOM_Object)& theAxis,
+                                           const Standard_Real        theRadius,
+                                           const GEOMAlgo_State       theState)
+{
+  SetErrorCode(KO);
+
+  if (theShape.IsNull() || theAxis.IsNull()) return NULL;
+
+  TopoDS_Shape aShape = theShape->GetValue();
+  TopoDS_Shape anAxis = theAxis->GetValue();
+
+  if (aShape.IsNull() || anAxis.IsNull()) return NULL;
+
+  TopAbs_ShapeEnum aShapeType = TopAbs_ShapeEnum(theShapeType);
+  if ( !checkTypeShapesOn( aShapeType ))
+    return NULL;
+
+  // Create a cylinder surface
+  Handle(Geom_Surface) aCylinder = makeCylinder( anAxis, theRadius );
+  if ( aCylinder.IsNull() )
+    return NULL;
+  
+  // Find object IDs
+  Handle(TColStd_HSequenceOfInteger) aSeq;
+  aSeq = getShapesOnSurfaceIDs( aCylinder, aShape, aShapeType, theState );
+
+  // The GetShapesOnCylinder() doesn't change object so no new function is required.
+  Handle(GEOM_Function) aFunction = GEOM::GetCreatedLast(theShape,theAxis)->GetLastFunction();
+
+  // Make a Python command
+  GEOM::TPythonDump(aFunction, /*append=*/true)
+    << "listShapesOnCylinder = geompy.GetShapesOnCylinderIDs"
+    << "(" << theShape << ", " << aShapeType << ", " << theAxis << ", "
+    << theRadius << ", " << theState << ")";
+
+  SetErrorCode(OK);
+  return aSeq;
+}
+
+//=============================================================================
+/*!
+ *  GetShapesOnSphereIDs
+ */
+//=============================================================================
+Handle(TColStd_HSequenceOfInteger) GEOMImpl_IShapesOperations::GetShapesOnSphereIDs
+                                          (const Handle(GEOM_Object)& theShape,
+                                           const Standard_Integer     theShapeType,
+                                           const Handle(GEOM_Object)& theCenter,
+                                           const Standard_Real        theRadius,
+                                           const GEOMAlgo_State       theState)
+{
+  SetErrorCode(KO);
+
+  if (theShape.IsNull() || theCenter.IsNull()) return NULL;
+
+  TopoDS_Shape aShape  = theShape->GetValue();
+  TopoDS_Shape aCenter = theCenter->GetValue();
+
+  if (aShape.IsNull() || aCenter.IsNull()) return NULL;
+
+  TopAbs_ShapeEnum aShapeType = TopAbs_ShapeEnum(theShapeType);
+  if ( !checkTypeShapesOn( aShapeType ))
+    return NULL;
 
   // Center of the sphere
   if (aCenter.ShapeType() != TopAbs_VERTEX) return NULL;
@@ -1294,30 +1956,122 @@ Handle(TColStd_HSequenceOfTransient) GEOMImpl_IShapesOperations::GetShapesOnSphe
   Handle(Geom_SphericalSurface) aSphere =
     new Geom_SphericalSurface(anAx3, theRadius);
 
+  // Find object IDs
+  Handle(TColStd_HSequenceOfInteger) aSeq;
+  aSeq = getShapesOnSurfaceIDs( aSphere, aShape, aShapeType, theState );
+  
+  // The GetShapesOnSphere() doesn't change object so no new function is required.
+  Handle(GEOM_Function) aFunction = GEOM::GetCreatedLast(theShape,theCenter)->GetLastFunction();
+
+  // Make a Python command
+  GEOM::TPythonDump(aFunction, /*append=*/true)
+    << "listShapesOnCylinder = geompy.GetShapesOnCylinderIDs"
+    << "(" << theShape << ", " << aShapeType << ", " << theCenter << ", "
+    << theRadius << ", " << theState << ")";
+
+  SetErrorCode(OK);
+  return aSeq;
+}
+
+//=======================================================================
+//function : getShapesOnQuadrangleIDs
+  /*!
+   * \brief Find IDs of subshapes complying with given status about quadrangle
+    * \param theShape - the shape to explore
+    * \param theShapeType - type of subshape of theShape
+    * \param theTopLeftPoint - top left quadrangle corner
+    * \param theTopRigthPoint - top right quadrangle corner
+    * \param theBottomLeftPoint - bottom left quadrangle corner
+    * \param theBottomRigthPoint - bottom right quadrangle corner
+    * \param theState - required state
+    * \retval Handle(TColStd_HSequenceOfInteger) - IDs of found subshapes
+   */
+//=======================================================================
+
+Handle(TColStd_HSequenceOfInteger)
+  GEOMImpl_IShapesOperations::getShapesOnQuadrangleIDs (const Handle(GEOM_Object)& theShape,
+                                                        const Standard_Integer     theShapeType,
+                                                        const Handle(GEOM_Object)& theTopLeftPoint,
+                                                        const Handle(GEOM_Object)& theTopRigthPoint,
+                                                        const Handle(GEOM_Object)& theBottomLeftPoint,
+                                                        const Handle(GEOM_Object)& theBottomRigthPoint,
+                                                        const GEOMAlgo_State       theState)
+{
+  SetErrorCode(KO);
+
+  if ( theShape.IsNull() ||
+       theTopLeftPoint.IsNull() ||
+       theTopRigthPoint.IsNull() ||
+       theBottomLeftPoint.IsNull() ||
+       theBottomRigthPoint.IsNull() )
+    return NULL;
+
+  TopoDS_Shape aShape = theShape->GetValue();
+  TopoDS_Shape aTL = theTopLeftPoint->GetValue();
+  TopoDS_Shape aTR = theTopRigthPoint->GetValue();
+  TopoDS_Shape aBL = theBottomLeftPoint->GetValue();
+  TopoDS_Shape aBR = theBottomRigthPoint->GetValue();
+
+  if (aShape.IsNull() ||
+      aTL.IsNull() || 
+      aTR.IsNull() || 
+      aBL.IsNull() || 
+      aBR.IsNull() ||
+      aTL.ShapeType() != TopAbs_VERTEX || 
+      aTR.ShapeType() != TopAbs_VERTEX || 
+      aBL.ShapeType() != TopAbs_VERTEX || 
+      aBR.ShapeType() != TopAbs_VERTEX )
+    return NULL;
+
+  TopAbs_ShapeEnum aShapeType = TopAbs_ShapeEnum(theShapeType);
+  if ( !checkTypeShapesOn( aShapeType ))
+    return NULL;
+
+  Handle(TColStd_HSequenceOfInteger) aSeqOfIDs;
+
+  // Check presence of triangulation, build if need
+  if (!CheckTriangulation(aShape))
+    return aSeqOfIDs;
+
   // Call algo
-  GEOMAlgo_FinderShapeOn aFinder;
+  gp_Pnt aPntTL = BRep_Tool::Pnt(TopoDS::Vertex(aTL));
+  gp_Pnt aPntTR = BRep_Tool::Pnt(TopoDS::Vertex(aTR));
+  gp_Pnt aPntBL = BRep_Tool::Pnt(TopoDS::Vertex(aBL));
+  gp_Pnt aPntBR = BRep_Tool::Pnt(TopoDS::Vertex(aBR));
+
+  GEOMAlgo_FinderShapeOnQuad aFinder( aPntTL, aPntTR, aPntBL, aPntBR );
   Standard_Real aTol = 0.0001; // default value
 
   aFinder.SetShape(aShape);
   aFinder.SetTolerance(aTol);
-  aFinder.SetSurface(aSphere);
+  //aFinder.SetSurface(theSurface);
   aFinder.SetShapeType(aShapeType);
   aFinder.SetState(theState);
 
+  // Sets the minimal number of inner points for the faces that do not have own
+  // inner points at all (for e.g. rectangular planar faces have just 2 triangles).
+  // Default value=3
+  aFinder.SetNbPntsMin(3);
+  // Sets the maximal number of inner points for edges or faces.
+  // It is usefull for the cases when this number is very big (e.g =2000) to improve
+  // the performance. If this value =0, all inner points will be taken into account.
+  // Default value=0
+  aFinder.SetNbPntsMax(100);
+
   aFinder.Perform();
 
   // Interprete results
   Standard_Integer iErr = aFinder.ErrorStatus();
-  // the detailed description of error codes is in GEOMAlgo_FinderShapeOn.cxx
+  // the detailed description of error codes is in GEOMAlgo_FinderShapeOn1.cxx
   if (iErr) {
     MESSAGE(" iErr : " << iErr);
     TCollection_AsciiString aMsg (" iErr : ");
     aMsg += TCollection_AsciiString(iErr);
     SetErrorCode(aMsg);
-    return NULL;
+    return aSeqOfIDs;
   }
   Standard_Integer iWrn = aFinder.WarningStatus();
-  // the detailed description of warning codes is in GEOMAlgo_FinderShapeOn.cxx
+  // the detailed description of warning codes is in GEOMAlgo_FinderShapeOn1.cxx
   if (iWrn) {
     MESSAGE(" *** iWrn : " << iWrn);
   }
@@ -1325,53 +2079,232 @@ Handle(TColStd_HSequenceOfTransient) GEOMImpl_IShapesOperations::GetShapesOnSphe
   const TopTools_ListOfShape& listSS = aFinder.Shapes(); // the result
 
   if (listSS.Extent() < 1) {
-    SetErrorCode("Not a single sub-shape of the requested type found on the given sphere");
-    return NULL;
+    SetErrorCode("Not a single sub-shape of the requested type found on the given surface");
+    return aSeqOfIDs;
   }
 
-  // Fill sequence of objects
+  // Fill sequence of object IDs
+  aSeqOfIDs = new TColStd_HSequenceOfInteger;
+
   TopTools_IndexedMapOfShape anIndices;
   TopExp::MapShapes(aShape, anIndices);
 
-  Handle(GEOM_Object) anObj;
-  Handle(TColStd_HArray1OfInteger) anArray;
-  Handle(TColStd_HSequenceOfTransient) aSeq = new TColStd_HSequenceOfTransient;
-
   TopTools_ListIteratorOfListOfShape itSub (listSS);
   for (int index = 1; itSub.More(); itSub.Next(), ++index) {
     int id = anIndices.FindIndex(itSub.Value());
-    anArray = new TColStd_HArray1OfInteger(1,1);
-    anArray->SetValue(1, id);
-    anObj = GetEngine()->AddSubShape(theShape, anArray);
-    aSeq->Append(anObj);
+    aSeqOfIDs->Append(id);
   }
-  
-  // The GetShapesOnSphere() doesn't change object so no new function is required.
-  Handle(GEOM_Function) aFunction = theShape->GetLastFunction();
+  return aSeqOfIDs;
+}
+
+//=======================================================================
+//function : GetShapesOnQuadrangle
+  /*!
+   * \brief Find subshapes complying with given status about quadrangle
+    * \param theShape - the shape to explore
+    * \param theShapeType - type of subshape of theShape
+    * \param theTopLeftPoint - top left quadrangle corner
+    * \param theTopRigthPoint - top right quadrangle corner
+    * \param theBottomLeftPoint - bottom left quadrangle corner
+    * \param theBottomRigthPoint - bottom right quadrangle corner
+    * \param theState - required state
+    * \retval Handle(TColStd_HSequenceOfInteger) - IDs of found subshapes
+   */
+//=======================================================================
+
+Handle(TColStd_HSequenceOfTransient)
+    GEOMImpl_IShapesOperations::GetShapesOnQuadrangle (const Handle(GEOM_Object)& theShape,
+                                                       const Standard_Integer     theShapeType,
+                                                       const Handle(GEOM_Object)& theTopLeftPoint,
+                                                       const Handle(GEOM_Object)& theTopRigthPoint,
+                                                       const Handle(GEOM_Object)& theBottomLeftPoint,
+                                                       const Handle(GEOM_Object)& theBottomRigthPoint,
+                                                       const GEOMAlgo_State       theState)
+{
+  // Find indices
+  Handle(TColStd_HSequenceOfInteger) aSeqOfIDs =
+    getShapesOnQuadrangleIDs( theShape,
+                              theShapeType,
+                              theTopLeftPoint,
+                              theTopRigthPoint,
+                              theBottomLeftPoint,
+                              theBottomRigthPoint,
+                              theState);
+  if ( aSeqOfIDs.IsNull() || aSeqOfIDs->IsEmpty() )
+    return NULL;
+
+  // Find objects by indices
+  TCollection_AsciiString anAsciiList;
+  Handle(TColStd_HSequenceOfTransient) aSeq;
+  aSeq = getObjectsShapesOn( theShape, aSeqOfIDs, anAsciiList );
+  if ( aSeq.IsNull() || aSeq->IsEmpty() )
+    return NULL;
 
   // Make a Python command
-  TCollection_AsciiString anEntry, aDescr
-    ("\nlistShapesOnSphere = IShapesOperations.GetShapesOnSphere(");
-  TDF_Tool::Entry(theShape->GetEntry(), anEntry);
-  aDescr += anEntry + TCollection_AsciiString(theShapeType) + ",";
-  TDF_Tool::Entry(theCenter->GetEntry(), anEntry);
-  aDescr += anEntry + ",";
-  aDescr += TCollection_AsciiString(theRadius) + ",";
-  aDescr += TCollection_AsciiString(theState) + ")";
-
-  TCollection_AsciiString anOldDescr = aFunction->GetDescription();
-  anOldDescr += aDescr;
-  aFunction->SetDescription(anOldDescr);
+
+  Handle(GEOM_Object) anObj = Handle(GEOM_Object)::DownCast( aSeq->Value( 1 ));
+  Handle(GEOM_Function) aFunction = anObj->GetLastFunction();
+
+  GEOM::TPythonDump(aFunction)
+    << "[" << anAsciiList.ToCString() << "] = geompy.GetShapesOnQuadrangle("
+    << theShape << ", "
+    << TopAbs_ShapeEnum(theShapeType) << ", "
+    << theTopLeftPoint << ", "
+    << theTopRigthPoint << ", "
+    << theBottomLeftPoint << ", "
+    << theBottomRigthPoint << ", "
+    << theState << ")";
 
   SetErrorCode(OK);
   return aSeq;
 }
 
+//=======================================================================
+//function : GetShapesOnQuadrangleIDs
+  /*!
+   * \brief Find IDs of subshapes complying with given status about quadrangle
+    * \param theShape - the shape to explore
+    * \param theShapeType - type of subshape of theShape
+    * \param theTopLeftPoint - top left quadrangle corner
+    * \param theTopRigthPoint - top right quadrangle corner
+    * \param theBottomLeftPoint - bottom left quadrangle corner
+    * \param theBottomRigthPoint - bottom right quadrangle corner
+    * \param theState - required state
+    * \retval Handle(TColStd_HSequenceOfInteger) - IDs of found subshapes
+   */
+//=======================================================================
+
+Handle(TColStd_HSequenceOfInteger)
+  GEOMImpl_IShapesOperations::GetShapesOnQuadrangleIDs (const Handle(GEOM_Object)& theShape,
+                                                        const Standard_Integer     theShapeType,
+                                                        const Handle(GEOM_Object)& theTopLeftPoint,
+                                                        const Handle(GEOM_Object)& theTopRigthPoint,
+                                                        const Handle(GEOM_Object)& theBottomLeftPoint,
+                                                        const Handle(GEOM_Object)& theBottomRigthPoint,
+                                                        const GEOMAlgo_State       theState)
+{
+  // Find indices
+  Handle(TColStd_HSequenceOfInteger) aSeqOfIDs =
+    getShapesOnQuadrangleIDs( theShape,
+                              theShapeType,
+                              theTopLeftPoint,
+                              theTopRigthPoint,
+                              theBottomLeftPoint,
+                              theBottomRigthPoint,
+                              theState);
+  if ( aSeqOfIDs.IsNull() || aSeqOfIDs->IsEmpty() )
+    return NULL;
+
+  // Make a Python command
+
+  // The GetShapesOnCylinder() doesn't change object so no new function is required.
+  Handle(GEOM_Object) lastObj = GEOM::GetCreatedLast(theShape,theTopLeftPoint);
+  lastObj = GEOM::GetCreatedLast(lastObj,theTopRigthPoint);
+  lastObj = GEOM::GetCreatedLast(lastObj,theBottomRigthPoint);
+  lastObj = GEOM::GetCreatedLast(lastObj,theBottomLeftPoint);
+  Handle(GEOM_Function) aFunction = lastObj->GetLastFunction();
+
+  GEOM::TPythonDump(aFunction, /*append=*/true)
+    << "listShapesOnQuadrangle = geompy.GetShapesOnQuadrangleIDs("
+    << theShape << ", "
+    << TopAbs_ShapeEnum(theShapeType) << ", "
+    << theTopLeftPoint << ", "
+    << theTopRigthPoint << ", "
+    << theBottomLeftPoint << ", "
+    << theBottomRigthPoint << ", "
+    << theState << ")";
+
+  SetErrorCode(OK);
+  return aSeqOfIDs;
+}
+
+
 //=============================================================================
 /*!
  *  GetInPlace
  */
 //=============================================================================
+static void SimplifyWhat (TopoDS_Shape& theWhat,
+                          TopTools_IndexedMapOfShape& theArgumentIndices,
+                          TColStd_ListOfInteger& theSimpleSubWhat)
+{
+  TopTools_MapOfShape mapShape;
+  TopoDS_Iterator It (theWhat, Standard_True, Standard_True);
+  for (; It.More(); It.Next()) {
+    if (mapShape.Add(It.Value())) {
+      TopoDS_Shape curSh = It.Value();
+      if (curSh.ShapeType() == TopAbs_COMPOUND ||
+          curSh.ShapeType() == TopAbs_COMPSOLID) {
+        SimplifyWhat(curSh, theArgumentIndices, theSimpleSubWhat);
+      } else {
+        theSimpleSubWhat.Append(theArgumentIndices.FindIndex(curSh));
+      }
+    }
+  }
+}
+
+static bool GetInPlaceOfCompound (Handle(GEOM_Function)& theWhereFunction,
+                                  TopoDS_Shape& theWhat,
+                                  TColStd_ListOfInteger& theModifiedArray)
+{
+  bool isFoundAny = false;
+  TopTools_MapOfShape mapShape;
+  TopoDS_Iterator It (theWhat, Standard_True, Standard_True);
+  for (; It.More(); It.Next()) {
+    if (mapShape.Add(It.Value())) {
+      TopoDS_Shape curWhat = It.Value();
+      if (curWhat.ShapeType() == TopAbs_COMPOUND ||
+          curWhat.ShapeType() == TopAbs_COMPSOLID) {
+        // Recursive call for compound or compsolid
+        if (GetInPlaceOfCompound(theWhereFunction, curWhat, theModifiedArray))
+          isFoundAny = true;
+      } else {
+        // Try to find for "simple" shape
+        bool isFound = false;
+
+        TDF_LabelSequence aLabelSeq;
+        theWhereFunction->GetDependency(aLabelSeq);
+        Standard_Integer nbArg = aLabelSeq.Length();
+
+        for (Standard_Integer iarg = 1; iarg <= nbArg && !isFound; iarg++) {
+
+          TDF_Label anArgumentRefLabel = aLabelSeq.Value(iarg);
+
+          Handle(GEOM_Object) anArgumentObject = GEOM_Object::GetReferencedObject(anArgumentRefLabel);
+          TopoDS_Shape anArgumentShape = anArgumentObject->GetValue();
+
+          TopTools_IndexedMapOfShape anArgumentIndices;
+          TopExp::MapShapes(anArgumentShape, anArgumentIndices);
+
+          if (anArgumentIndices.Contains(curWhat)) {
+            isFound = Standard_True;
+            Standard_Integer aWhatIndex = anArgumentIndices.FindIndex(curWhat);
+
+            // Find corresponding label in history
+            TDF_Label anArgumentHistoryLabel =
+              theWhereFunction->GetArgumentHistoryEntry(anArgumentRefLabel, Standard_False);
+            if (!anArgumentHistoryLabel.IsNull()) {
+              TDF_Label aWhatHistoryLabel = anArgumentHistoryLabel.FindChild(aWhatIndex, Standard_False);
+              if (!aWhatHistoryLabel.IsNull()) {
+                Handle(TDataStd_IntegerArray) anIntegerArray;
+                if (aWhatHistoryLabel.FindAttribute(TDataStd_IntegerArray::GetID(), anIntegerArray)) {
+                  Standard_Integer imod, aModifLen = anIntegerArray->Array()->Length();
+                  for (imod = 1; imod <= aModifLen; imod++) {
+                    theModifiedArray.Append(anIntegerArray->Array()->Value(imod));
+                  }
+                }
+              }
+            }
+          }
+        }
+        if (isFound)
+          isFoundAny = true;
+      }
+    }
+  }
+  return isFoundAny;
+}
+
 Handle(GEOM_Object) GEOMImpl_IShapesOperations::GetInPlace
                                           (Handle(GEOM_Object) theShapeWhere,
                                            Handle(GEOM_Object) theShapeWhat)
@@ -1404,7 +2337,7 @@ Handle(GEOM_Object) GEOMImpl_IShapesOperations::GetInPlace
 
     TDF_Label aHistoryLabel = aWhereFunction->GetHistoryEntry(Standard_False);
     if (aHistoryLabel.IsNull()) {
-      SetErrorCode("History for an operation, produced the shape, does not exist.");
+      SetErrorCode("Modifications history does not exist for the shape under consideration.");
       return NULL;
     }
 
@@ -1433,38 +2366,98 @@ Handle(GEOM_Object) GEOMImpl_IShapesOperations::GetInPlace
         TDF_Label anArgumentHistoryLabel =
           aWhereFunction->GetArgumentHistoryEntry(anArgumentRefLabel, Standard_False);
         if (anArgumentHistoryLabel.IsNull()) {
-          SetErrorCode("History for this entity does not exist.");
+          // Lost History of operation argument. Possibly, all its entities was removed.
+          SetErrorCode(OK);
           return NULL;
         }
 
         TDF_Label aWhatHistoryLabel = anArgumentHistoryLabel.FindChild(aWhatIndex, Standard_False);
         if (aWhatHistoryLabel.IsNull()) {
-          SetErrorCode("History for this entity does not exist.");
-          return NULL;
-        }
-
-        Handle(TDataStd_IntegerArray) anIntegerArray;
-        if (!aWhatHistoryLabel.FindAttribute(TDataStd_IntegerArray::GetID(), anIntegerArray)) {
-          SetErrorCode("Empty history. Possibly, this entity is absent in result.");
-          return NULL;
-        }
-
-        aModifiedArray = anIntegerArray->Array();
-        if (aModifiedArray->Length() == 0) {
-          SetErrorCode("This entity is absent in result.");
-          return NULL;
+          // Check, if the sought shape is Compound or Compsolid.
+          // In that case we will try to find history for its sub-shapes
+          if (aWhat.ShapeType() == TopAbs_COMPOUND ||
+              aWhat.ShapeType() == TopAbs_COMPSOLID) {
+            TColStd_ListOfInteger aSimpleSubWhat, aModifiedList;
+            SimplifyWhat(aWhat, anArgumentIndices, aSimpleSubWhat);
+            TColStd_ListIteratorOfListOfInteger anIterSub (aSimpleSubWhat);
+            for (; anIterSub.More(); anIterSub.Next()) {
+              Standard_Integer aSubWhatIndex = anIterSub.Value();
+              TDF_Label aSubWhatHistoryLabel =
+                anArgumentHistoryLabel.FindChild(aSubWhatIndex, Standard_False);
+              if (!aSubWhatHistoryLabel.IsNull()) {
+                Handle(TDataStd_IntegerArray) anIntegerArray;
+                if (aSubWhatHistoryLabel.FindAttribute(TDataStd_IntegerArray::GetID(), anIntegerArray)) {
+                  for (Standard_Integer isub = 1; isub <= anIntegerArray->Length(); isub++) {
+                    aModifiedList.Append(anIntegerArray->Value(isub));
+                  }
+                }
+              }
+            }
+            if (aModifiedList.Extent() > 0) {
+              Handle(TColStd_HArray1OfInteger) aModifiedArraySub =
+                new TColStd_HArray1OfInteger (1, aModifiedList.Extent());
+              TColStd_ListIteratorOfListOfInteger anIterModif (aModifiedList);
+              for (Standard_Integer imod = 1; anIterModif.More(); anIterModif.Next(), imod++) {
+                aModifiedArraySub->SetValue(imod, anIterModif.Value());
+              }
+              aModifiedArray = aModifiedArraySub;
+            } else {
+              // Removed entity
+              SetErrorCode(OK);
+              return NULL;
+            }
+          } else {
+            // Removed entity
+            SetErrorCode(OK);
+            return NULL;
+          }
+        } else {
+          Handle(TDataStd_IntegerArray) anIntegerArray;
+          if (!aWhatHistoryLabel.FindAttribute(TDataStd_IntegerArray::GetID(), anIntegerArray)) {
+            SetErrorCode("Error: Empty modifications history for the sought shape.");
+            return NULL;
+          }
+
+          aModifiedArray = anIntegerArray->Array();
+          if (aModifiedArray->Length() == 0) {
+            SetErrorCode("Error: Empty modifications history for the sought shape.");
+            return NULL;
+          }
         }
       }
     }
 
     if (!isFound) {
-      SetErrorCode("Not found in arguments.");
-      return NULL;
+      // try compound element by element
+      if (aWhat.ShapeType() == TopAbs_COMPOUND ||
+          aWhat.ShapeType() == TopAbs_COMPSOLID) {
+        TColStd_ListOfInteger aModifiedList;
+        isFound = GetInPlaceOfCompound(aWhereFunction, aWhat, aModifiedList);
+        if (isFound) {
+          if (aModifiedList.Extent() < 1) {
+            SetErrorCode("Error: Empty modifications history for all sub-shapes of the sought shape.");
+            return NULL;
+          }
+          aModifiedArray = new TColStd_HArray1OfInteger (1, aModifiedList.Extent());
+          TColStd_ListIteratorOfListOfInteger anIterModif (aModifiedList);
+          for (Standard_Integer imod = 1; anIterModif.More(); anIterModif.Next(), imod++) {
+            aModifiedArray->SetValue(imod, anIterModif.Value());
+          }
+        }
+      }
+      if (!isFound) {
+        SetErrorCode("The sought shape does not belong to any operation argument.");
+        return NULL;
+      }
     }
   }
 
   //Add a new object
   Handle(GEOM_Object) aResult = GetEngine()->AddSubShape(theShapeWhere, aModifiedArray);
+  if (aResult.IsNull()) {
+    SetErrorCode("Error in algorithm: result found, but cannot be returned.");
+    return NULL;
+  }
 
   if (aModifiedArray->Length() > 1) {
     //Set a GROUP type
@@ -1477,17 +2470,10 @@ Handle(GEOM_Object) GEOMImpl_IShapesOperations::GetInPlace
   }
 
   //Make a Python command
-  TCollection_AsciiString anEntry, aDescr;
-  TDF_Tool::Entry(aResult->GetEntry(), anEntry);
-  aDescr += anEntry;
-  aDescr += " = IShapesOperations.GetInPlace(";
-  TDF_Tool::Entry(theShapeWhere->GetEntry(), anEntry);
-  aDescr += anEntry + ",";
-  TDF_Tool::Entry(theShapeWhat->GetEntry(), anEntry);
-  aDescr += anEntry + ")";
-
   Handle(GEOM_Function) aFunction = aResult->GetFunction(1);
-  aFunction->SetDescription(aDescr);
+
+  GEOM::TPythonDump(aFunction) << aResult << " = geompy.GetInPlace("
+    << theShapeWhere << ", " << theShapeWhat << ")";
 
   SetErrorCode(OK);
   return aResult;
@@ -1530,6 +2516,7 @@ void GEOMImpl_IShapesOperations::SortShapes(TopTools_ListOfShape& SL)
     MidXYZ.SetValue(Index,
                    GPoint.X()*999 + GPoint.Y()*99 + GPoint.Z()*0.9);
   }
+
   // Sorting
   Standard_Integer aTemp;
   Standard_Boolean exchange, Sort = Standard_True;
@@ -1557,3 +2544,358 @@ void GEOMImpl_IShapesOperations::SortShapes(TopTools_ListOfShape& SL)
   for (Index=1; Index <= MaxShapes; Index++)
     SL.Append( aShapes( OrderInd(Index) ));
 }
+
+//=======================================================================
+//function : CheckTriangulation
+//purpose  :
+//=======================================================================
+bool GEOMImpl_IShapesOperations::CheckTriangulation (const TopoDS_Shape& aShape)
+{
+  TopExp_Explorer exp (aShape, TopAbs_FACE);
+  if (!exp.More()) {
+    SetErrorCode("Shape without faces given");
+    return false;
+  }
+
+  TopLoc_Location aTopLoc;
+  Handle(Poly_Triangulation) aTRF;
+  aTRF = BRep_Tool::Triangulation(TopoDS::Face(exp.Current()), aTopLoc);
+  if (aTRF.IsNull()) {
+    // calculate deflection
+    Standard_Real aDeviationCoefficient = 0.001;
+
+    Bnd_Box B;
+    BRepBndLib::Add(aShape, B);
+    Standard_Real aXmin, aYmin, aZmin, aXmax, aYmax, aZmax;
+    B.Get(aXmin, aYmin, aZmin, aXmax, aYmax, aZmax);
+
+    Standard_Real dx = aXmax - aXmin, dy = aYmax - aYmin, dz = aZmax - aZmin;
+    Standard_Real aDeflection = Max(Max(dx, dy), dz) * aDeviationCoefficient * 4;
+    Standard_Real aHLRAngle = 0.349066;
+
+    BRepMesh_IncrementalMesh Inc (aShape, aDeflection, Standard_False, aHLRAngle);
+  }
+
+  return true;
+}
+
+#define MAX_TOLERANCE 1.e-7
+
+
+//=======================================================================
+//function : isSameEdge
+//purpose  : Returns True if two edges coincide
+//=======================================================================
+static bool isSameEdge(const TopoDS_Edge& theEdge1, const TopoDS_Edge& theEdge2)
+{
+  TopoDS_Vertex V11, V12, V21, V22;
+  TopExp::Vertices(theEdge1, V11, V12);
+  TopExp::Vertices(theEdge2, V21, V22);
+  gp_Pnt P11 = BRep_Tool::Pnt(V11);
+  gp_Pnt P12 = BRep_Tool::Pnt(V12);
+  gp_Pnt P21 = BRep_Tool::Pnt(V21);
+  gp_Pnt P22 = BRep_Tool::Pnt(V22);
+  bool coincide = false;
+
+  //Check that ends of edges coincide
+  if(P11.Distance(P21) <= MAX_TOLERANCE) {
+    if(P12.Distance(P22) <= MAX_TOLERANCE) coincide =  true;
+  }
+  else if(P11.Distance(P22) <= MAX_TOLERANCE) {
+    if(P12.Distance(P21) <= MAX_TOLERANCE) coincide = true; 
+  }
+
+  if(!coincide) return false;
+
+  double U11, U12, U21, U22;
+  Handle(Geom_Curve) C1 = BRep_Tool::Curve(theEdge1, U11, U12);
+  Handle(Geom_Curve) C2 = BRep_Tool::Curve(theEdge2, U21, U22);
+  if(C1->DynamicType() == C2->DynamicType()) return true;
+
+  //Check that both edges has the same geometry
+  double range = U12-U11;
+  double U = U11+ range/3.0;   
+  gp_Pnt P1 = C1->Value(U);     //Compute a point on one third of the edge's length
+  U = U11+range*2.0/3.0;
+  gp_Pnt P2 = C1->Value(U);     //Compute a point on two thirds of the edge's length
+  if(!GeomLib_Tool::Parameter(C2, P1, MAX_TOLERANCE, U) ||  U < U21 || U > U22)    
+    return false;
+  
+  if(P1.Distance(C2->Value(U)) > MAX_TOLERANCE) return false;
+
+  if(!GeomLib_Tool::Parameter(C2, P2, MAX_TOLERANCE, U) || U < U21 || U > U22)    
+    return false;
+
+  if(P2.Distance(C2->Value(U)) > MAX_TOLERANCE) return false;
+
+  return true;
+}
+
+#include <TopoDS_TShape.hxx>
+//=======================================================================
+//function : isSameFace
+//purpose  : Returns True if two faces coincide
+//=======================================================================
+static bool isSameFace(const TopoDS_Face& theFace1, const TopoDS_Face& theFace2)
+{  
+  TopExp_Explorer E(theFace1, TopAbs_EDGE);
+  TopTools_ListOfShape LS1, LS2;
+  for(; E.More(); E.Next()) LS1.Append(E.Current());
+
+  E.Init(theFace2, TopAbs_EDGE);
+  for(; E.More(); E.Next()) LS2.Append(E.Current());
+
+  //Compare the number of edges in the faces
+  if(LS1.Extent() != LS2.Extent()) return false;
+
+  double aMin = RealFirst(), aMax = RealLast();
+  double xminB1=aMax, yminB1=aMax, zminB1=aMax, xminB2=aMax, yminB2=aMax, zminB2=aMax;
+  double xmaxB1=aMin, ymaxB1=aMin, zmaxB1=aMin, xmaxB2=aMin, ymaxB2=aMin, zmaxB2=aMin;   
+
+  for(E.Init(theFace1, TopAbs_VERTEX); E.More(); E.Next()) {
+    gp_Pnt P = BRep_Tool::Pnt(TopoDS::Vertex(E.Current()));
+    if(P.X() < xminB1) xminB1 = P.X();
+    if(P.Y() < yminB1) yminB1 = P.Y();
+    if(P.Z() < zminB1) zminB1 = P.Z();
+    if(P.X() > xmaxB1) xmaxB1 = P.X();
+    if(P.Y() > ymaxB1) ymaxB1 = P.Y();
+    if(P.Z() > zmaxB1) zmaxB1 = P.Z();
+  }
+
+  for(E.Init(theFace2, TopAbs_VERTEX); E.More(); E.Next()) {
+    gp_Pnt P = BRep_Tool::Pnt(TopoDS::Vertex(E.Current()));
+    if(P.X() < xminB2) xminB2 = P.X();
+    if(P.Y() < yminB2) yminB2 = P.Y();
+    if(P.Z() < zminB2) zminB2 = P.Z();
+    if(P.X() > xmaxB2) xmaxB2 = P.X();
+    if(P.Y() > ymaxB2) ymaxB2 = P.Y();
+    if(P.Z() > zmaxB2) zmaxB2 = P.Z();
+  }
+
+  //Compare the bounding boxes of both faces
+  if(gp_Pnt(xminB1, yminB1, zminB1).Distance(gp_Pnt(xminB2, yminB2, zminB2)) > MAX_TOLERANCE)
+    return false;
+
+  if(gp_Pnt(xmaxB1, ymaxB1, zmaxB1).Distance(gp_Pnt(xmaxB2, ymaxB2, zmaxB2)) > MAX_TOLERANCE)
+    return false;
+
+  //Check that each edge of the Face1 has a counterpart in the Face2
+  TopTools_MapOfOrientedShape aMap;
+  TopTools_ListIteratorOfListOfShape LSI1(LS1);
+  for(; LSI1.More(); LSI1.Next()) {
+    TopoDS_Edge E = TopoDS::Edge(LSI1.Value());
+    bool isFound = false;
+    TopTools_ListIteratorOfListOfShape LSI2(LS2);
+    for(; LSI2.More(); LSI2.Next()) {
+      TopoDS_Shape aValue = LSI2.Value();
+      if(aMap.Contains(aValue)) continue; //To avoid checking already found edge several times
+      if(isSameEdge(E, TopoDS::Edge(aValue))) {
+        aMap.Add(aValue);
+        isFound = true;
+        break;
+      }
+    }
+    if(!isFound) return false;
+  }
+
+  Handle(Geom_Surface) S1 = BRep_Tool::Surface(theFace1);
+  Handle(Geom_Surface) S2 = BRep_Tool::Surface(theFace2);
+  if(S1->DynamicType() == S2->DynamicType()) {
+    return true;
+  }
+  else {   //Check if there a coincidence of two surfaces at least in two points
+    double U11, U12, V11, V12, U21, U22, V21, V22;
+    BRepTools::UVBounds(theFace1, U11, U12, V11, V12);
+    BRepTools::UVBounds(theFace2, U21, U22, V21, V22);  
+
+    double rangeU = U12-U11;
+    double rangeV = V12-V11;
+    double U = U11 + rangeU/3.0;   
+    double V = V11 + rangeV/3.0;
+    gp_Pnt P1 = S1->Value(U, V);     
+    U = U11+rangeU*2.0/3.0;
+    V = V11+rangeV*2.0/3.0;
+    gp_Pnt P2 = S1->Value(U, V);
+
+    if(!GeomLib_Tool::Parameters(S2, P1, MAX_TOLERANCE, U, V) || U < U21 || U > U22 || V < V21 || V > V22)    
+      return false;
+
+    if(P1.Distance(S2->Value(U,V)) > MAX_TOLERANCE) return false;
+
+    if(!GeomLib_Tool::Parameters(S2, P2, MAX_TOLERANCE, U, V) || U < U21 || U > U22 || V < V21 || V > V22)    
+      return false;
+
+    if(P2.Distance(S2->Value(U, V)) > MAX_TOLERANCE) return false;
+  }
+  return true;
+}
+
+//=======================================================================
+//function : isSameSolid
+//purpose  : Returns True if two solids coincide
+//=======================================================================
+bool isSameSolid(const TopoDS_Solid& theSolid1, const TopoDS_Solid& theSolid2)
+{
+  TopExp_Explorer E(theSolid1, TopAbs_FACE);
+  TopTools_ListOfShape LS1, LS2;
+  for(; E.More(); E.Next()) LS1.Append(E.Current());
+  E.Init(theSolid2, TopAbs_FACE);
+  for(; E.More(); E.Next()) LS2.Append(E.Current());
+
+  if(LS1.Extent() != LS2.Extent()) return false;
+
+  double aMin = RealFirst(), aMax = RealLast();
+  double xminB1=aMax, yminB1=aMax, zminB1=aMax, xminB2=aMax, yminB2=aMax, zminB2=aMax;
+  double xmaxB1=aMin, ymaxB1=aMin, zmaxB1=aMin, xmaxB2=aMin, ymaxB2=aMin, zmaxB2=aMin;   
+
+  for(E.Init(theSolid1, TopAbs_VERTEX); E.More(); E.Next()) {
+    gp_Pnt P = BRep_Tool::Pnt(TopoDS::Vertex(E.Current()));
+    if(P.X() < xminB1) xminB1 = P.X();
+    if(P.Y() < yminB1) yminB1 = P.Y();
+    if(P.Z() < zminB1) zminB1 = P.Z();
+    if(P.X() > xmaxB1) xmaxB1 = P.X();
+    if(P.Y() > ymaxB1) ymaxB1 = P.Y();
+    if(P.Z() > zmaxB1) zmaxB1 = P.Z();
+  }
+
+  for(E.Init(theSolid2, TopAbs_VERTEX); E.More(); E.Next()) {
+    gp_Pnt P = BRep_Tool::Pnt(TopoDS::Vertex(E.Current()));
+    if(P.X() < xminB2) xminB2 = P.X();
+    if(P.Y() < yminB2) yminB2 = P.Y();
+    if(P.Z() < zminB2) zminB2 = P.Z();
+    if(P.X() > xmaxB2) xmaxB2 = P.X();
+    if(P.Y() > ymaxB2) ymaxB2 = P.Y();
+    if(P.Z() > zmaxB2) zmaxB2 = P.Z();
+  }
+
+  //Compare the bounding boxes of both solids
+  if(gp_Pnt(xminB1, yminB1, zminB1).Distance(gp_Pnt(xminB2, yminB2, zminB2)) > MAX_TOLERANCE)
+    return false;
+
+  if(gp_Pnt(xmaxB1, ymaxB1, zmaxB1).Distance(gp_Pnt(xmaxB2, ymaxB2, zmaxB2)) > MAX_TOLERANCE)
+    return false;
+
+  //Check that each face of the Solid1 has a counterpart in the Solid2
+  TopTools_MapOfOrientedShape aMap;
+  TopTools_ListIteratorOfListOfShape LSI1(LS1);
+  for(; LSI1.More(); LSI1.Next()) {
+    TopoDS_Face F = TopoDS::Face(LSI1.Value());
+    bool isFound = false;
+    TopTools_ListIteratorOfListOfShape LSI2(LS2);
+    for(; LSI2.More(); LSI2.Next()) {
+      if(aMap.Contains(LSI2.Value())) continue; //To avoid checking already found faces several times
+      if(isSameFace(F, TopoDS::Face(LSI2.Value()))) {
+        aMap.Add(LSI2.Value());
+        isFound = true;
+        break;
+      }
+    }
+    if(!isFound) return false;
+  }
+
+  return true;
+}
+
+//=======================================================================
+//function : GetSame
+//purpose  :
+//=======================================================================
+Handle(GEOM_Object) GEOMImpl_IShapesOperations::GetSame(const Handle(GEOM_Object)& theShapeWhere, 
+                                                       const Handle(GEOM_Object)& theShapeWhat)
+{
+  SetErrorCode(KO);
+  if (theShapeWhere.IsNull() || theShapeWhat.IsNull()) return NULL;
+
+  TopoDS_Shape aWhere = theShapeWhere->GetValue();
+  TopoDS_Shape aWhat  = theShapeWhat->GetValue();
+
+  if (aWhere.IsNull() || aWhat.IsNull()) return NULL;
+
+  int anIndex = -1;
+  bool isFound = false;
+  TopoDS_Shape aSubShape;
+  TopTools_MapOfShape aMap;
+
+  switch(aWhat.ShapeType()) {
+    case TopAbs_VERTEX: {
+      gp_Pnt P = BRep_Tool::Pnt(TopoDS::Vertex(aWhat));
+      TopExp_Explorer E(aWhere, TopAbs_VERTEX);
+      for(; E.More(); E.Next()) {
+        if(!aMap.Add(E.Current())) continue;
+        gp_Pnt P2 = BRep_Tool::Pnt(TopoDS::Vertex(E.Current()));
+        if(P.Distance(P2) <= MAX_TOLERANCE) {
+          isFound = true;
+          aSubShape = E.Current();
+          break;
+        }
+      }
+      break;
+                        }
+    case TopAbs_FACE: {
+      TopoDS_Face aFace = TopoDS::Face(aWhat);
+      TopExp_Explorer E(aWhere, TopAbs_FACE);
+      for(; E.More(); E.Next()) {
+        if(!aMap.Add(E.Current())) continue;
+        if(isSameFace(aFace, TopoDS::Face(E.Current()))) {
+          aSubShape = E.Current();
+          isFound = true;
+          break;
+        }
+      }
+      break;
+                      }
+    case TopAbs_EDGE: {
+      TopoDS_Edge anEdge = TopoDS::Edge(aWhat);
+      TopExp_Explorer E(aWhere, TopAbs_EDGE);
+      for(; E.More(); E.Next()) {
+        if(!aMap.Add(E.Current())) continue;
+        if(isSameEdge(anEdge, TopoDS::Edge(E.Current()))) {
+          aSubShape = E.Current();
+          isFound = true;
+          break;
+        }
+      }
+      break;
+                      }
+    case TopAbs_SOLID: {
+      TopoDS_Solid aSolid = TopoDS::Solid(aWhat);
+      TopExp_Explorer E(aWhere, TopAbs_SOLID);
+      for(; E.More(); E.Next()) {
+        if(!aMap.Add(E.Current())) continue;
+        if(isSameSolid(aSolid, TopoDS::Solid(E.Current()))) {
+          aSubShape = E.Current();
+          isFound = true;
+          break;
+        }
+      }
+      break;
+                       }
+    default:
+      return NULL;
+  }
+
+  if(isFound) {
+    TopTools_IndexedMapOfShape anIndices;
+    TopExp::MapShapes(aWhere, anIndices);
+    if (anIndices.Contains(aSubShape))
+      anIndex = anIndices.FindIndex(aSubShape);
+  }
+  
+  if(anIndex < 0) return NULL;
+
+  Handle(TColStd_HArray1OfInteger) anArray = new TColStd_HArray1OfInteger(1,1);
+
+  anArray->SetValue(1, anIndex);
+  Handle(GEOM_Object) aResult = GetEngine()->AddSubShape(theShapeWhere, anArray);
+  Handle(GEOM_Function) aFunction = aResult->GetLastFunction();
+
+  GEOM::TPythonDump(aFunction) << aResult << " = geompy.GetSame("
+    << theShapeWhere << ", " << theShapeWhat << ")";
+
+  SetErrorCode(OK);
+
+  return aResult;
+}