Salome HOME
09a2477a7446a6b17d0922569c47f38b0c3aa79c
[modules/geom.git] / src / GEOMImpl / GEOMImpl_IShapesOperations.cxx
1 //  Copyright (C) 2007-2008  CEA/DEN, EDF R&D, OPEN CASCADE
2 //
3 //  Copyright (C) 2003-2007  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
4 //  CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
5 //
6 //  This library is free software; you can redistribute it and/or
7 //  modify it under the terms of the GNU Lesser General Public
8 //  License as published by the Free Software Foundation; either
9 //  version 2.1 of the License.
10 //
11 //  This library is distributed in the hope that it will be useful,
12 //  but WITHOUT ANY WARRANTY; without even the implied warranty of
13 //  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14 //  Lesser General Public License for more details.
15 //
16 //  You should have received a copy of the GNU Lesser General Public
17 //  License along with this library; if not, write to the Free Software
18 //  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
19 //
20 //  See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
21 //
22 // File      : GEOMImpl_IShapesOperations.cxx
23 // Created   :
24 // Author    : modified by Lioka RAZAFINDRAZAKA (CEA) 22/06/2007
25 // Project   : SALOME
26 // $Header$
27 //
28 #include <Standard_Stream.hxx>
29
30 #include "GEOMImpl_IShapesOperations.hxx"
31
32 #include "GEOMImpl_Types.hxx"
33
34 #include "GEOMImpl_VectorDriver.hxx"
35 #include "GEOMImpl_ShapeDriver.hxx"
36 #include "GEOMImpl_CopyDriver.hxx"
37 #include "GEOMImpl_GlueDriver.hxx"
38
39 #include "GEOMImpl_IVector.hxx"
40 #include "GEOMImpl_IShapes.hxx"
41 #include "GEOMImpl_IGlue.hxx"
42
43 #include "GEOMImpl_Block6Explorer.hxx"
44
45 #include "GEOM_Function.hxx"
46 #include "GEOM_ISubShape.hxx"
47 #include "GEOM_PythonDump.hxx"
48
49 #include "GEOMAlgo_FinderShapeOn1.hxx"
50 #include "GEOMAlgo_FinderShapeOnQuad.hxx"
51 #include "GEOMAlgo_FinderShapeOn2.hxx"
52 #include "GEOMAlgo_ClsfBox.hxx"
53 #include "GEOMAlgo_ClsfSolid.hxx"
54 #include "GEOMAlgo_Gluer1.hxx"
55 #include "GEOMAlgo_ListIteratorOfListOfCoupleOfShapes.hxx"
56 #include "GEOMAlgo_CoupleOfShapes.hxx"
57 #include "GEOMAlgo_ListOfCoupleOfShapes.hxx"
58
59 #include "utilities.h"
60 #include "OpUtil.hxx"
61 #include "Utils_ExceptHandlers.hxx"
62
63 #include <TFunction_DriverTable.hxx>
64 #include <TFunction_Driver.hxx>
65 #include <TFunction_Logbook.hxx>
66 #include <TDataStd_Integer.hxx>
67 #include <TDataStd_IntegerArray.hxx>
68 #include <TDF_Tool.hxx>
69
70 #include <BRepExtrema_ExtCF.hxx>
71 #include <BRepExtrema_DistShapeShape.hxx>
72
73 #include <BRep_Tool.hxx>
74 #include <BRep_Builder.hxx>
75 #include <BRepTools.hxx>
76 #include <BRepGProp.hxx>
77 #include <BRepAdaptor_Curve.hxx>
78 #include <BRepAdaptor_Surface.hxx>
79 #include <BRepBndLib.hxx>
80 #include <BRepBuilderAPI_MakeFace.hxx>
81 #include <BRepMesh_IncrementalMesh.hxx>
82
83 #include <TopAbs.hxx>
84 #include <TopExp.hxx>
85 #include <TopoDS.hxx>
86 #include <TopoDS_Shape.hxx>
87 #include <TopoDS_Solid.hxx>
88 #include <TopoDS_Face.hxx>
89 #include <TopoDS_Edge.hxx>
90 #include <TopoDS_Vertex.hxx>
91 #include <TopoDS_Compound.hxx>
92 #include <TopoDS_Iterator.hxx>
93 #include <TopExp_Explorer.hxx>
94 #include <TopLoc_Location.hxx>
95 #include <TopTools_MapOfShape.hxx>
96 #include <TopTools_MapOfOrientedShape.hxx>
97 #include <TopTools_Array1OfShape.hxx>
98 #include <TopTools_ListIteratorOfListOfShape.hxx>
99 #include <TopTools_IndexedMapOfShape.hxx>
100
101 #include <Geom_Surface.hxx>
102 #include <Geom_Plane.hxx>
103 #include <Geom_SphericalSurface.hxx>
104 #include <Geom_CylindricalSurface.hxx>
105 #include <GeomAdaptor_Surface.hxx>
106
107 #include <GeomLib_Tool.hxx>
108 #include <Geom2d_Curve.hxx>
109
110 #include <Bnd_Box.hxx>
111 #include <GProp_GProps.hxx>
112 #include <gp_Pnt.hxx>
113 #include <gp_Lin.hxx>
114 #include <TColStd_ListOfInteger.hxx>
115 #include <TColStd_ListIteratorOfListOfInteger.hxx>
116 #include <TColStd_Array1OfReal.hxx>
117 #include <TColStd_HArray1OfInteger.hxx>
118
119 #include <vector>
120
121 #include <Standard_NullObject.hxx>
122 #include <Standard_Failure.hxx>
123 #include <Standard_ErrorHandler.hxx> // CAREFUL ! position of this file is critic : see Lucien PIGNOLONI / OCC
124
125 // Includes added for GetInPlace algorithm improvement
126
127 #include <GEOMImpl_MeasureDriver.hxx>
128 #include <GEOMImpl_IMeasure.hxx>
129 #include <BRepBuilderAPI_MakeVertex.hxx>
130
131 #include <BRepClass_FaceClassifier.hxx>
132 #include <BRepClass3d_SolidClassifier.hxx>
133 #include <Precision.hxx>
134
135 //=============================================================================
136 /*!
137  *   constructor:
138  */
139 //=============================================================================
140 GEOMImpl_IShapesOperations::GEOMImpl_IShapesOperations (GEOM_Engine* theEngine, int theDocID)
141 : GEOM_IOperations(theEngine, theDocID)
142 {
143   MESSAGE("GEOMImpl_IShapesOperations::GEOMImpl_IShapesOperations");
144 }
145
146 //=============================================================================
147 /*!
148  *  destructor
149  */
150 //=============================================================================
151 GEOMImpl_IShapesOperations::~GEOMImpl_IShapesOperations()
152 {
153   MESSAGE("GEOMImpl_IShapesOperations::~GEOMImpl_IShapesOperations");
154 }
155
156 //=============================================================================
157 /*!
158  *  MakeEdge
159  */
160 //=============================================================================
161 Handle(GEOM_Object) GEOMImpl_IShapesOperations::MakeEdge
162                      (Handle(GEOM_Object) thePnt1, Handle(GEOM_Object) thePnt2)
163 {
164   SetErrorCode(KO);
165
166   if (thePnt1.IsNull() || thePnt2.IsNull()) return NULL;
167
168   //Add a new Edge object
169   Handle(GEOM_Object) anEdge = GetEngine()->AddObject(GetDocID(), GEOM_EDGE);
170
171   //Add a new Vector function
172   Handle(GEOM_Function) aFunction =
173     anEdge->AddFunction(GEOMImpl_VectorDriver::GetID(), VECTOR_TWO_PNT);
174
175   //Check if the function is set correctly
176   if (aFunction->GetDriverGUID() != GEOMImpl_VectorDriver::GetID()) return NULL;
177
178   GEOMImpl_IVector aPI (aFunction);
179
180   Handle(GEOM_Function) aRef1 = thePnt1->GetLastFunction();
181   Handle(GEOM_Function) aRef2 = thePnt2->GetLastFunction();
182   if (aRef1.IsNull() || aRef2.IsNull()) return NULL;
183
184   aPI.SetPoint1(aRef1);
185   aPI.SetPoint2(aRef2);
186
187   //Compute the Edge value
188   try {
189 #if (OCC_VERSION_MAJOR << 16 | OCC_VERSION_MINOR << 8 | OCC_VERSION_MAINTENANCE) > 0x060100
190     OCC_CATCH_SIGNALS;
191 #endif
192     if (!GetSolver()->ComputeFunction(aFunction)) {
193       SetErrorCode("Vector driver failed");
194       return NULL;
195     }
196   }
197   catch (Standard_Failure) {
198     Handle(Standard_Failure) aFail = Standard_Failure::Caught();
199     SetErrorCode(aFail->GetMessageString());
200     return NULL;
201   }
202
203   //Make a Python command
204   GEOM::TPythonDump(aFunction) << anEdge << " = geompy.MakeEdge("
205                                << thePnt1 << ", " << thePnt2 << ")";
206
207   SetErrorCode(OK);
208   return anEdge;
209 }
210
211 //=============================================================================
212 /*!
213  *  MakeWire
214  */
215 //=============================================================================
216 Handle(GEOM_Object) GEOMImpl_IShapesOperations::MakeWire
217                              (std::list<Handle(GEOM_Object)> theShapes)
218 {
219   return MakeShape(theShapes, GEOM_WIRE, WIRE_EDGES, "MakeWire");
220 }
221
222 //=============================================================================
223 /*!
224  *  MakeFace
225  */
226 //=============================================================================
227 Handle(GEOM_Object) GEOMImpl_IShapesOperations::MakeFace (Handle(GEOM_Object) theWire,
228                                                           const bool isPlanarWanted)
229 {
230   SetErrorCode(KO);
231
232   if (theWire.IsNull()) return NULL;
233
234   //Add a new Face object
235   Handle(GEOM_Object) aFace = GetEngine()->AddObject(GetDocID(), GEOM_FACE);
236
237   //Add a new Shape function for creation of a face from a wire
238   Handle(GEOM_Function) aFunction =
239     aFace->AddFunction(GEOMImpl_ShapeDriver::GetID(), FACE_WIRE);
240   if (aFunction.IsNull()) return NULL;
241
242   //Check if the function is set correctly
243   if (aFunction->GetDriverGUID() != GEOMImpl_ShapeDriver::GetID()) return NULL;
244
245   GEOMImpl_IShapes aCI (aFunction);
246
247   Handle(GEOM_Function) aRefWire = theWire->GetLastFunction();
248
249   if (aRefWire.IsNull()) return NULL;
250
251   aCI.SetBase(aRefWire);
252   aCI.SetIsPlanar(isPlanarWanted);
253
254   //Compute the Face value
255   try {
256 #if (OCC_VERSION_MAJOR << 16 | OCC_VERSION_MINOR << 8 | OCC_VERSION_MAINTENANCE) > 0x060100
257     OCC_CATCH_SIGNALS;
258 #endif
259     if (!GetSolver()->ComputeFunction(aFunction)) {
260       SetErrorCode("Shape driver failed to compute a face");
261       return NULL;
262     }
263   }
264   catch (Standard_Failure) {
265     Handle(Standard_Failure) aFail = Standard_Failure::Caught();
266     SetErrorCode(aFail->GetMessageString());
267     return NULL;
268   }
269
270   //Make a Python command
271   GEOM::TPythonDump(aFunction) << aFace << " = geompy.MakeFace("
272     << theWire << ", " << (int)isPlanarWanted << ")";
273
274   SetErrorCode(OK);
275   return aFace;
276 }
277
278 //=============================================================================
279 /*!
280  *  MakeFaceWires
281  */
282 //=============================================================================
283 Handle(GEOM_Object) GEOMImpl_IShapesOperations::MakeFaceWires
284                              (std::list<Handle(GEOM_Object)> theShapes,
285                               const bool isPlanarWanted)
286 {
287   SetErrorCode(KO);
288
289   //Add a new object
290   Handle(GEOM_Object) aShape = GetEngine()->AddObject(GetDocID(), GEOM_FACE);
291
292   //Add a new function
293   Handle(GEOM_Function) aFunction =
294     aShape->AddFunction(GEOMImpl_ShapeDriver::GetID(), FACE_WIRES);
295   if (aFunction.IsNull()) return NULL;
296
297   //Check if the function is set correctly
298   if (aFunction->GetDriverGUID() != GEOMImpl_ShapeDriver::GetID()) return NULL;
299
300   GEOMImpl_IShapes aCI (aFunction);
301
302   Handle(TColStd_HSequenceOfTransient) aShapesSeq = new TColStd_HSequenceOfTransient;
303
304   // Shapes
305   std::list<Handle(GEOM_Object)>::iterator it = theShapes.begin();
306   for (; it != theShapes.end(); it++) {
307     Handle(GEOM_Function) aRefSh = (*it)->GetLastFunction();
308     if (aRefSh.IsNull()) {
309       SetErrorCode("NULL argument shape for the face construction");
310       return NULL;
311     }
312     aShapesSeq->Append(aRefSh);
313   }
314   aCI.SetShapes(aShapesSeq);
315
316   aCI.SetIsPlanar(isPlanarWanted);
317
318   //Compute the shape
319   try {
320 #if (OCC_VERSION_MAJOR << 16 | OCC_VERSION_MINOR << 8 | OCC_VERSION_MAINTENANCE) > 0x060100
321     OCC_CATCH_SIGNALS;
322 #endif
323     if (!GetSolver()->ComputeFunction(aFunction)) {
324       SetErrorCode("Shape driver failed");
325       return NULL;
326     }
327   }
328   catch (Standard_Failure) {
329     Handle(Standard_Failure) aFail = Standard_Failure::Caught();
330     SetErrorCode(aFail->GetMessageString());
331     return NULL;
332   }
333
334   //Make a Python command
335   GEOM::TPythonDump pd (aFunction);
336   pd << aShape << " = geompy.MakeFaceWires([";
337
338   // Shapes
339   it = theShapes.begin();
340   if (it != theShapes.end()) {
341     pd << (*it++);
342     while (it != theShapes.end()) {
343       pd << ", " << (*it++);
344     }
345   }
346   pd << "], " << (int)isPlanarWanted << ")";
347
348   SetErrorCode(OK);
349   return aShape;
350 }
351
352 //=============================================================================
353 /*!
354  *  MakeShell
355  */
356 //=============================================================================
357 Handle(GEOM_Object) GEOMImpl_IShapesOperations::MakeShell
358                              (std::list<Handle(GEOM_Object)> theShapes)
359 {
360   return MakeShape(theShapes, GEOM_SHELL, SHELL_FACES, "MakeShell");
361 }
362
363 //=============================================================================
364 /*!
365  *  MakeSolidShells
366  */
367 //=============================================================================
368 Handle(GEOM_Object) GEOMImpl_IShapesOperations::MakeSolidShells
369                              (std::list<Handle(GEOM_Object)> theShapes)
370 {
371   return MakeShape(theShapes, GEOM_SOLID, SOLID_SHELLS, "MakeSolid");
372 }
373
374 //=============================================================================
375 /*!
376  *  MakeSolidShell
377  */
378 //=============================================================================
379 Handle(GEOM_Object) GEOMImpl_IShapesOperations::MakeSolidShell (Handle(GEOM_Object) theShell)
380 {
381   SetErrorCode(KO);
382
383   if (theShell.IsNull()) return NULL;
384
385   //Add a new Solid object
386   Handle(GEOM_Object) aSolid = GetEngine()->AddObject(GetDocID(), GEOM_SOLID);
387
388   //Add a new Solid function for creation of a solid from a shell
389   Handle(GEOM_Function) aFunction =
390     aSolid->AddFunction(GEOMImpl_ShapeDriver::GetID(), SOLID_SHELL);
391   if (aFunction.IsNull()) return NULL;
392
393   //Check if the function is set correctly
394   if (aFunction->GetDriverGUID() != GEOMImpl_ShapeDriver::GetID()) return NULL;
395
396   GEOMImpl_IShapes aCI (aFunction);
397
398   Handle(GEOM_Function) aRefShell = theShell->GetLastFunction();
399
400   if (aRefShell.IsNull()) return NULL;
401
402   aCI.SetBase(aRefShell);
403
404   //Compute the Solid value
405   try {
406 #if (OCC_VERSION_MAJOR << 16 | OCC_VERSION_MINOR << 8 | OCC_VERSION_MAINTENANCE) > 0x060100
407     OCC_CATCH_SIGNALS;
408 #endif
409     if (!GetSolver()->ComputeFunction(aFunction)) {
410       SetErrorCode("Solid driver failed");
411       return NULL;
412     }
413   }
414   catch (Standard_Failure) {
415     Handle(Standard_Failure) aFail = Standard_Failure::Caught();
416     SetErrorCode(aFail->GetMessageString());
417     return NULL;
418   }
419
420   //Make a Python command
421   GEOM::TPythonDump(aFunction) << aSolid
422     << " = geompy.MakeSolid(" << theShell << ")";
423
424   SetErrorCode(OK);
425   return aSolid;
426 }
427
428 //=============================================================================
429 /*!
430  *  MakeCompound
431  */
432 //=============================================================================
433 Handle(GEOM_Object) GEOMImpl_IShapesOperations::MakeCompound
434                              (std::list<Handle(GEOM_Object)> theShapes)
435 {
436   return MakeShape(theShapes, GEOM_COMPOUND, COMPOUND_SHAPES, "MakeCompound");
437 }
438
439 //=============================================================================
440 /*!
441  *  MakeShape
442  */
443 //=============================================================================
444 Handle(GEOM_Object) GEOMImpl_IShapesOperations::MakeShape
445                              (std::list<Handle(GEOM_Object)>      theShapes,
446                               const Standard_Integer         theObjectType,
447                               const Standard_Integer         theFunctionType,
448                               const TCollection_AsciiString& theMethodName)
449 {
450   SetErrorCode(KO);
451
452   //Add a new object
453   Handle(GEOM_Object) aShape = GetEngine()->AddObject(GetDocID(), theObjectType);
454
455   //Add a new function
456   Handle(GEOM_Function) aFunction =
457     aShape->AddFunction(GEOMImpl_ShapeDriver::GetID(), theFunctionType);
458   if (aFunction.IsNull()) return NULL;
459
460   //Check if the function is set correctly
461   if (aFunction->GetDriverGUID() != GEOMImpl_ShapeDriver::GetID()) return NULL;
462
463   GEOMImpl_IShapes aCI (aFunction);
464
465   Handle(TColStd_HSequenceOfTransient) aShapesSeq = new TColStd_HSequenceOfTransient;
466
467   // Shapes
468   std::list<Handle(GEOM_Object)>::iterator it = theShapes.begin();
469   for (; it != theShapes.end(); it++) {
470     Handle(GEOM_Function) aRefSh = (*it)->GetLastFunction();
471     if (aRefSh.IsNull()) {
472       SetErrorCode("NULL argument shape for the shape construction");
473       return NULL;
474     }
475     aShapesSeq->Append(aRefSh);
476   }
477   aCI.SetShapes(aShapesSeq);
478
479   //Compute the shape
480   try {
481 #if (OCC_VERSION_MAJOR << 16 | OCC_VERSION_MINOR << 8 | OCC_VERSION_MAINTENANCE) > 0x060100
482     OCC_CATCH_SIGNALS;
483 #endif
484     if (!GetSolver()->ComputeFunction(aFunction)) {
485       SetErrorCode("Shape driver failed");
486       return NULL;
487     }
488   }
489   catch (Standard_Failure) {
490     Handle(Standard_Failure) aFail = Standard_Failure::Caught();
491     SetErrorCode(aFail->GetMessageString());
492     return NULL;
493   }
494
495   //Make a Python command
496   GEOM::TPythonDump pd (aFunction);
497   pd << aShape << " = geompy." << theMethodName.ToCString() << "([";
498
499   // Shapes
500   it = theShapes.begin();
501   if (it != theShapes.end()) {
502     pd << (*it++);
503     while (it != theShapes.end()) {
504       pd << ", " << (*it++);
505     }
506   }
507   pd << "])";
508
509   SetErrorCode(OK);
510   return aShape;
511 }
512
513 //=============================================================================
514 /*!
515  *  MakeGlueFaces
516  */
517 //=============================================================================
518 Handle(GEOM_Object) GEOMImpl_IShapesOperations::MakeGlueFaces
519                                                 (Handle(GEOM_Object) theShape,
520                                                  const Standard_Real theTolerance,
521                                                  const Standard_Boolean doKeepNonSolids)
522 {
523   SetErrorCode(KO);
524
525   if (theShape.IsNull()) return NULL;
526
527   //Add a new Glued object
528   Handle(GEOM_Object) aGlued = GetEngine()->AddObject(GetDocID(), GEOM_GLUED);
529
530   //Add a new Glue function
531   Handle(GEOM_Function) aFunction;
532   aFunction = aGlued->AddFunction(GEOMImpl_GlueDriver::GetID(), GLUE_FACES);
533   if (aFunction.IsNull()) return NULL;
534
535   //Check if the function is set correctly
536   if (aFunction->GetDriverGUID() != GEOMImpl_GlueDriver::GetID()) return NULL;
537
538   GEOMImpl_IGlue aCI (aFunction);
539
540   Handle(GEOM_Function) aRefShape = theShape->GetLastFunction();
541   if (aRefShape.IsNull()) return NULL;
542
543   aCI.SetBase(aRefShape);
544   aCI.SetTolerance(theTolerance);
545   aCI.SetKeepNonSolids(doKeepNonSolids);
546
547   //Compute the sub-shape value
548   Standard_Boolean isWarning = Standard_False;
549   try {
550 #if (OCC_VERSION_MAJOR << 16 | OCC_VERSION_MINOR << 8 | OCC_VERSION_MAINTENANCE) > 0x060100
551     OCC_CATCH_SIGNALS;
552 #endif
553     if (!GetSolver()->ComputeFunction(aFunction)) {
554       SetErrorCode("Shape driver failed to glue faces");
555       return NULL;
556     }
557   }
558   catch (Standard_Failure) {
559     Handle(Standard_Failure) aFail = Standard_Failure::Caught();
560     SetErrorCode(aFail->GetMessageString());
561     // to provide warning
562     if (!aFunction->GetValue().IsNull()) {
563       isWarning = Standard_True;
564     } else {
565       return NULL;
566     }
567   }
568
569   //Make a Python command
570   GEOM::TPythonDump(aFunction) << aGlued << " = geompy.MakeGlueFaces("
571     << theShape << ", " << theTolerance << ")";
572
573   // to provide warning
574   if (!isWarning) SetErrorCode(OK);
575   return aGlued;
576 }
577
578 //=============================================================================
579 /*!
580  *  GetGlueFaces
581  */
582 //=============================================================================
583 Handle(TColStd_HSequenceOfTransient) GEOMImpl_IShapesOperations::GetGlueFaces
584                                                 (Handle(GEOM_Object) theShape,
585                                                  const Standard_Real theTolerance)
586 {
587   SetErrorCode(KO);
588
589   if (theShape.IsNull()) return NULL;
590   TopoDS_Shape aShape = theShape->GetValue();
591   if (aShape.IsNull()) return NULL;
592
593   Handle(TColStd_HSequenceOfTransient) aSeq = new TColStd_HSequenceOfTransient;
594
595   Standard_Integer iErr;
596   TopoDS_Shape aS;
597   GEOMAlgo_Gluer1 aGluer;
598   GEOMAlgo_ListIteratorOfListOfCoupleOfShapes aItCS;
599   GEOMAlgo_CoupleOfShapes aCS;
600   GEOMAlgo_ListOfCoupleOfShapes aLCS;
601
602   //aGluer = new GEOMAlgo_Gluer1;
603   aGluer.SetShape(aShape);
604   aGluer.SetTolerance(theTolerance);
605   aGluer.Perform();
606   iErr = aGluer.ErrorStatus();
607   if (iErr) return NULL;
608
609   TopTools_ListOfShape listShape;
610   const GEOMAlgo_ListOfCoupleOfShapes& aLCSG = aGluer.GluedFaces();
611   // Access to faces
612   aItCS.Initialize(aLCSG);
613   for (; aItCS.More(); aItCS.Next()) {
614     const GEOMAlgo_CoupleOfShapes& aCSG = aItCS.Value();
615     listShape.Append(aCSG.Shape1());
616   }
617
618   TopTools_ListIteratorOfListOfShape itSub (listShape);
619   TCollection_AsciiString anAsciiList, anEntry;
620   TopTools_IndexedMapOfShape anIndices;
621   TopExp::MapShapes(aShape, anIndices);
622   Handle(TColStd_HArray1OfInteger) anArray;
623   Handle(GEOM_Object) anObj;
624   for (int index = 1; itSub.More(); itSub.Next(), ++index) {
625     TopoDS_Shape aValue = itSub.Value();
626     anArray = new TColStd_HArray1OfInteger(1,1);
627     anArray->SetValue(1, anIndices.FindIndex(aValue));
628     anObj = GetEngine()->AddSubShape(theShape, anArray);
629     if (!anObj.IsNull()) {
630       aSeq->Append(anObj);
631
632       // for python command
633       TDF_Tool::Entry(anObj->GetEntry(), anEntry);
634       anAsciiList += anEntry;
635       anAsciiList += ",";
636     }
637   }
638
639   //Make a Python command
640   if(anAsciiList.Length()>0)
641     anAsciiList.Trunc(anAsciiList.Length() - 1);
642   Handle(GEOM_Function) aFunction = theShape->GetLastFunction();
643   GEOM::TPythonDump pd (aFunction, /*append=*/true);
644   pd << "[" << anAsciiList.ToCString();
645   pd << "] = geompy.GetGlueFaces(" << theShape << ", " << theTolerance << ")";
646
647   SetErrorCode(OK);
648
649   return aSeq;
650 }
651
652 //=============================================================================
653 /*!
654  *  MakeGlueFacesByList
655  */
656 //=============================================================================
657 Handle(GEOM_Object) GEOMImpl_IShapesOperations::MakeGlueFacesByList
658                                                 (Handle(GEOM_Object) theShape,
659                                                  const Standard_Real theTolerance,
660                                                  std::list<Handle(GEOM_Object)> theFaces,
661                                                  const Standard_Boolean doKeepNonSolids)
662 {
663   SetErrorCode(KO);
664
665   if (theShape.IsNull()) return NULL;
666
667   //Add a new Glued object
668   Handle(GEOM_Object) aGlued = GetEngine()->AddObject(GetDocID(), GEOM_GLUED);
669
670   //Add a new Glue function
671   Handle(GEOM_Function) aFunction;
672   aFunction = aGlued->AddFunction(GEOMImpl_GlueDriver::GetID(), GLUE_FACES_BY_LIST);
673   if (aFunction.IsNull()) return NULL;
674
675   //Check if the function is set correctly
676   if (aFunction->GetDriverGUID() != GEOMImpl_GlueDriver::GetID()) return NULL;
677
678   GEOMImpl_IGlue aCI (aFunction);
679
680   Handle(GEOM_Function) aRefShape = theShape->GetLastFunction();
681   if (aRefShape.IsNull()) return NULL;
682
683   aCI.SetBase(aRefShape);
684   aCI.SetTolerance(theTolerance);
685   aCI.SetKeepNonSolids(doKeepNonSolids);
686
687   Handle(TColStd_HSequenceOfTransient) aFaces = new TColStd_HSequenceOfTransient;
688   std::list<Handle(GEOM_Object)>::iterator it = theFaces.begin();
689   for (; it != theFaces.end(); it++) {
690     Handle(GEOM_Function) aRefSh = (*it)->GetLastFunction();
691     if (aRefSh.IsNull()) {
692       SetErrorCode("NULL argument shape for the shape construction");
693       return NULL;
694     }
695     aFaces->Append(aRefSh);
696   }
697   aCI.SetFaces(aFaces);
698
699   //Compute the sub-shape value
700   Standard_Boolean isWarning = Standard_False;
701   try {
702 #if (OCC_VERSION_MAJOR << 16 | OCC_VERSION_MINOR << 8 | OCC_VERSION_MAINTENANCE) > 0x060100
703     OCC_CATCH_SIGNALS;
704 #endif
705     if (!GetSolver()->ComputeFunction(aFunction)) {
706       SetErrorCode("Shape driver failed to glue faces");
707       return NULL;
708     }
709   }
710   catch (Standard_Failure) {
711     Handle(Standard_Failure) aFail = Standard_Failure::Caught();
712     SetErrorCode(aFail->GetMessageString());
713     // to provide warning
714     if (!aFunction->GetValue().IsNull()) {
715       isWarning = Standard_True;
716     } else {
717       return NULL;
718     }
719   }
720
721   //Make a Python command
722
723   GEOM::TPythonDump pd(aFunction);
724   pd << aGlued << " = geompy.MakeGlueFacesByList("
725      << theShape << ", " << theTolerance << ", [";
726   // Faces
727   it = theFaces.begin();
728   if (it != theFaces.end()) {
729     pd << (*it++);
730     while (it != theFaces.end()) {
731       pd << ", " << (*it++);
732     }
733   }
734   pd << "])";
735
736   // to provide warning
737   if (!isWarning) SetErrorCode(OK);
738   return aGlued;
739 }
740
741 //=============================================================================
742 /*!
743  *  MakeExplode
744  */
745 //=============================================================================
746 Handle(TColStd_HSequenceOfTransient) GEOMImpl_IShapesOperations::MakeExplode
747                                           (Handle(GEOM_Object)    theShape,
748                                            const Standard_Integer theShapeType,
749                                            const Standard_Boolean isSorted)
750 {
751   SetErrorCode(KO);
752
753   if (theShape.IsNull()) return NULL;
754   TopoDS_Shape aShape = theShape->GetValue();
755   if (aShape.IsNull()) return NULL;
756
757   Handle(GEOM_Function) aMainShape = theShape->GetLastFunction();
758
759   Handle(TColStd_HSequenceOfTransient) aSeq = new TColStd_HSequenceOfTransient;
760   Handle(GEOM_Object) anObj;
761   TopTools_MapOfShape mapShape;
762   TopTools_ListOfShape listShape;
763
764   if (aShape.ShapeType() == TopAbs_COMPOUND &&
765       (TopAbs_ShapeEnum(theShapeType) == TopAbs_SHAPE ||
766        TopAbs_ShapeEnum(theShapeType) == TopAbs_COMPSOLID ||
767        TopAbs_ShapeEnum(theShapeType) == TopAbs_COMPOUND)) {
768     TopoDS_Iterator It (aShape, Standard_True, Standard_True);
769     for (; It.More(); It.Next()) {
770       if (mapShape.Add(It.Value())) {
771         if (TopAbs_ShapeEnum(theShapeType) == TopAbs_SHAPE ||
772             TopAbs_ShapeEnum(theShapeType) == It.Value().ShapeType()) {
773           listShape.Append(It.Value());
774         }
775       }
776     }
777   } else {
778     TopExp_Explorer exp (aShape, TopAbs_ShapeEnum(theShapeType));
779     for (; exp.More(); exp.Next())
780       if (mapShape.Add(exp.Current()))
781         listShape.Append(exp.Current());
782   }
783
784   if (listShape.IsEmpty()) {
785     //SetErrorCode("The given shape has no sub-shapes of the requested type");
786     SetErrorCode(NOT_FOUND_ANY); // NPAL18017
787     return aSeq;
788   }
789
790   if (isSorted)
791     SortShapes(listShape);
792
793   TopTools_IndexedMapOfShape anIndices;
794   TopExp::MapShapes(aShape, anIndices);
795   Handle(TColStd_HArray1OfInteger) anArray;
796
797   TopTools_ListIteratorOfListOfShape itSub (listShape);
798   TCollection_AsciiString anAsciiList, anEntry;
799   for (int index = 1; itSub.More(); itSub.Next(), ++index)
800   {
801     TopoDS_Shape aValue = itSub.Value();
802     anArray = new TColStd_HArray1OfInteger(1,1);
803     anArray->SetValue(1, anIndices.FindIndex(aValue));
804
805     //anObj = GetEngine()->AddSubShape(theShape, anArray);
806     {
807       anObj = GetEngine()->AddObject(GetDocID(), GEOM_SUBSHAPE);
808       Handle(GEOM_Function) aFunction = anObj->AddFunction(GEOM_Object::GetSubShapeID(), 1);
809       if (aFunction.IsNull()) return aSeq;
810
811       GEOM_ISubShape aSSI (aFunction);
812       aSSI.SetMainShape(aMainShape);
813       aSSI.SetIndices(anArray);
814
815       // Set function value directly, as we know it.
816       // Usage of Solver here would lead to significant loss of time,
817       // because GEOM_SubShapeDriver will build TopTools_IndexedMapOfShape
818       // on the main shape for each being calculated sub-shape separately.
819       aFunction->SetValue(aValue);
820     }
821
822     if (!anObj.IsNull()) {
823       aSeq->Append(anObj);
824
825       // for python command
826       TDF_Tool::Entry(anObj->GetEntry(), anEntry);
827       anAsciiList += anEntry;
828       anAsciiList += ",";
829     }
830   }
831
832   //Make a Python command
833   anAsciiList.Trunc(anAsciiList.Length() - 1);
834
835   GEOM::TPythonDump pd (aMainShape, /*append=*/true);
836   pd << "[" << anAsciiList.ToCString();
837   pd << "] = geompy.SubShapeAll" << (isSorted ? "Sorted(" : "(");
838   pd << theShape << ", " << TopAbs_ShapeEnum(theShapeType) << ")";
839
840   SetErrorCode(OK);
841
842   return aSeq;
843 }
844
845 //=============================================================================
846 /*!
847  *  SubShapeAllIDs
848  */
849 //=============================================================================
850 Handle(TColStd_HSequenceOfInteger) GEOMImpl_IShapesOperations::SubShapeAllIDs
851                                           (Handle(GEOM_Object)    theShape,
852                                            const Standard_Integer theShapeType,
853                                            const Standard_Boolean isSorted)
854 {
855   SetErrorCode(KO);
856
857   if (theShape.IsNull()) return NULL;
858   TopoDS_Shape aShape = theShape->GetValue();
859   if (aShape.IsNull()) return NULL;
860
861   Handle(TColStd_HSequenceOfInteger) aSeq = new TColStd_HSequenceOfInteger;
862   TopTools_MapOfShape mapShape;
863   TopTools_ListOfShape listShape;
864
865   if (aShape.ShapeType() == TopAbs_COMPOUND &&
866       (TopAbs_ShapeEnum(theShapeType) == TopAbs_SHAPE ||
867        TopAbs_ShapeEnum(theShapeType) == TopAbs_COMPSOLID ||
868        TopAbs_ShapeEnum(theShapeType) == TopAbs_COMPOUND)) {
869     TopoDS_Iterator It (aShape, Standard_True, Standard_True);
870     for (; It.More(); It.Next()) {
871       if (mapShape.Add(It.Value())) {
872         if (TopAbs_ShapeEnum(theShapeType) == TopAbs_SHAPE ||
873             TopAbs_ShapeEnum(theShapeType) == It.Value().ShapeType()) {
874           listShape.Append(It.Value());
875         }
876       }
877     }
878   } else {
879     TopExp_Explorer exp (aShape, TopAbs_ShapeEnum(theShapeType));
880     for (; exp.More(); exp.Next())
881       if (mapShape.Add(exp.Current()))
882         listShape.Append(exp.Current());
883   }
884
885   if (listShape.IsEmpty()) {
886     //SetErrorCode("The given shape has no sub-shapes of the requested type");
887     SetErrorCode(NOT_FOUND_ANY); // NPAL18017
888     return aSeq;
889   }
890
891   if (isSorted)
892     SortShapes(listShape);
893
894   TopTools_IndexedMapOfShape anIndices;
895   TopExp::MapShapes(aShape, anIndices);
896   Handle(TColStd_HArray1OfInteger) anArray;
897
898   TopTools_ListIteratorOfListOfShape itSub (listShape);
899   for (int index = 1; itSub.More(); itSub.Next(), ++index) {
900     TopoDS_Shape aValue = itSub.Value();
901     aSeq->Append(anIndices.FindIndex(aValue));
902   }
903
904   Handle(GEOM_Function) aFunction = theShape->GetLastFunction();
905
906   //Make a Python command
907   GEOM::TPythonDump pd (aFunction, /*append=*/true);
908   pd << "listSubShapeIDs = geompy.SubShapeAll";
909   pd << (isSorted ? "SortedIDs(" : "IDs(");
910   pd << theShape << ", " << TopAbs_ShapeEnum(theShapeType) << ")";
911
912   SetErrorCode(OK);
913   return aSeq;
914 }
915
916 //=============================================================================
917 /*!
918  *  GetSubShape
919  */
920 //=============================================================================
921 Handle(GEOM_Object) GEOMImpl_IShapesOperations::GetSubShape
922                                           (Handle(GEOM_Object)    theMainShape,
923                                            const Standard_Integer theID)
924 {
925   SetErrorCode(KO);
926
927   if (theMainShape.IsNull()) return NULL;
928
929   Handle(TColStd_HArray1OfInteger) anArray = new TColStd_HArray1OfInteger(1,1);
930   anArray->SetValue(1, theID);
931   Handle(GEOM_Object) anObj = GetEngine()->AddSubShape(theMainShape, anArray,true);
932   if (anObj.IsNull()) {
933     SetErrorCode("Can not get a sub-shape with the given ID");
934     return NULL;
935   }
936
937   Handle(GEOM_Function) aFunction = anObj->GetLastFunction();
938
939   //Make a Python command
940   GEOM::TPythonDump(aFunction) << anObj << " = geompy.GetSubShape("
941                                << theMainShape << ", [" << theID << "])";
942
943   SetErrorCode(OK);
944   return anObj;
945 }
946
947 //=============================================================================
948 /*!
949  *  GetSubShapeIndex
950  */
951 //=============================================================================
952 Standard_Integer GEOMImpl_IShapesOperations::GetSubShapeIndex (Handle(GEOM_Object) theMainShape,
953                                                                Handle(GEOM_Object) theSubShape)
954 {
955   SetErrorCode(KO);
956
957   TopoDS_Shape aMainShape = theMainShape->GetValue();
958   TopoDS_Shape aSubShape = theSubShape->GetValue();
959
960   if (aMainShape.IsNull() || aSubShape.IsNull()) return -1;
961
962   TopTools_IndexedMapOfShape anIndices;
963   TopExp::MapShapes(aMainShape, anIndices);
964   if (anIndices.Contains(aSubShape)) {
965     SetErrorCode(OK);
966     return anIndices.FindIndex(aSubShape);
967   }
968
969   return -1;
970 }
971
972 //=============================================================================
973 /*!
974  *  GetTopologyIndex
975  */
976 //=============================================================================
977 Standard_Integer GEOMImpl_IShapesOperations::GetTopologyIndex (Handle(GEOM_Object) theMainShape,
978                                                                Handle(GEOM_Object) theSubShape)
979 {
980   SetErrorCode(OK);
981
982   TopoDS_Shape aMainShape = theMainShape->GetValue();
983   TopoDS_Shape aSubShape = theSubShape->GetValue();
984
985   if (aMainShape.IsNull() || aSubShape.IsNull()) {
986     SetErrorCode("Null argument shape given");
987     return -1;
988   }
989
990   int index = 1;
991   if (aSubShape.ShapeType() == TopAbs_COMPOUND) {
992     TopoDS_Iterator it;
993     TopTools_ListOfShape CL;
994     CL.Append(aMainShape);
995     TopTools_ListIteratorOfListOfShape itC;
996     for (itC.Initialize(CL); itC.More(); itC.Next()) {
997       for (it.Initialize(itC.Value()); it.More(); it.Next()) {
998         if (it.Value().ShapeType() == TopAbs_COMPOUND) {
999           if (it.Value().IsSame(aSubShape))
1000             return index;
1001           else
1002             index++;
1003           CL.Append(it.Value());
1004         }
1005       }
1006     }
1007   } else {
1008     TopExp_Explorer anExp (aMainShape, aSubShape.ShapeType());
1009     TopTools_MapOfShape M;
1010     for (; anExp.More(); anExp.Next()) {
1011       if (M.Add(anExp.Current())) {
1012         if (anExp.Current().IsSame(aSubShape))
1013           return index;
1014         index++;
1015       }
1016     }
1017   }
1018
1019   SetErrorCode("The sub-shape does not belong to the main shape");
1020   return -1;
1021 }
1022
1023 //=============================================================================
1024 /*!
1025  *  GetShapeTypeString
1026  */
1027 //=============================================================================
1028 TCollection_AsciiString GEOMImpl_IShapesOperations::GetShapeTypeString (Handle(GEOM_Object) theShape)
1029 {
1030   SetErrorCode(KO);
1031
1032   TCollection_AsciiString aTypeName ("Null Shape");
1033
1034   TopoDS_Shape aShape = theShape->GetValue();
1035   if (aShape.IsNull())
1036     return aTypeName;
1037
1038   switch (aShape.ShapeType() )
1039   {
1040   case TopAbs_COMPOUND:
1041     aTypeName = "Compound";
1042     break;
1043   case  TopAbs_COMPSOLID:
1044     aTypeName = "Compound Solid";
1045     break;
1046   case TopAbs_SOLID:
1047     aTypeName = "Solid";
1048     break;
1049   case TopAbs_SHELL:
1050     aTypeName = "Shell";
1051     break;
1052   case TopAbs_FACE:
1053     {
1054       BRepAdaptor_Surface surf (TopoDS::Face(aShape));
1055       if (surf.GetType() == GeomAbs_Plane)
1056         aTypeName = "Plane";
1057       else if (surf.GetType() == GeomAbs_Cylinder)
1058         aTypeName = "Cylindrical Face";
1059       else if (surf.GetType() == GeomAbs_Sphere)
1060         aTypeName = "Spherical Face";
1061       else if (surf.GetType() == GeomAbs_Torus)
1062         aTypeName = "Toroidal Face";
1063       else if (surf.GetType() == GeomAbs_Cone)
1064         aTypeName = "Conical Face";
1065       else
1066         aTypeName = "GEOM::FACE";
1067     }
1068     break;
1069   case TopAbs_WIRE:
1070     aTypeName = "Wire";
1071     break;
1072   case TopAbs_EDGE:
1073     {
1074       BRepAdaptor_Curve curv (TopoDS::Edge(aShape));
1075       if (curv.GetType() == GeomAbs_Line) {
1076         if ((Abs(curv.FirstParameter()) >= 1E6) ||
1077             (Abs(curv.LastParameter()) >= 1E6))
1078           aTypeName = "Line";
1079         else
1080           aTypeName = "Edge";
1081       } else if (curv.GetType() == GeomAbs_Circle) {
1082         if (curv.IsClosed())
1083           aTypeName = "Circle";
1084         else
1085           aTypeName = "Arc";
1086       } else {
1087         aTypeName = "Edge";
1088       }
1089     }
1090     break;
1091   case TopAbs_VERTEX:
1092     aTypeName = "Vertex";
1093     break;
1094   case TopAbs_SHAPE:
1095     aTypeName = "Shape";
1096     break;
1097   default:
1098     aTypeName = "Shape of unknown type";
1099   }
1100
1101   return aTypeName;
1102 }
1103
1104 //=============================================================================
1105 /*!
1106  *  NumberOfFaces
1107  */
1108 //=============================================================================
1109 Standard_Integer GEOMImpl_IShapesOperations::NumberOfFaces (Handle(GEOM_Object) theShape)
1110 {
1111   SetErrorCode(KO);
1112
1113   Standard_Integer nb = 0;
1114
1115   if (theShape.IsNull()) return -1;
1116   TopoDS_Shape aShape = theShape->GetValue();
1117   if (aShape.IsNull()) return -1;
1118
1119   TopTools_MapOfShape mapShape;
1120
1121   TopExp_Explorer exp (aShape, TopAbs_FACE);
1122   for (; exp.More(); exp.Next())
1123     if (mapShape.Add(exp.Current()))
1124       nb++;
1125
1126   SetErrorCode(OK);
1127   return nb;
1128 }
1129
1130 //=============================================================================
1131 /*!
1132  *  NumberOfEdges
1133  */
1134 //=============================================================================
1135 Standard_Integer GEOMImpl_IShapesOperations::NumberOfEdges (Handle(GEOM_Object) theShape)
1136 {
1137   SetErrorCode(KO);
1138
1139   Standard_Integer nb = 0;
1140
1141   if (theShape.IsNull()) return -1;
1142   TopoDS_Shape aShape = theShape->GetValue();
1143   if (aShape.IsNull()) return -1;
1144
1145   TopTools_MapOfShape mapShape;
1146
1147   TopExp_Explorer exp (aShape, TopAbs_EDGE);
1148   for (; exp.More(); exp.Next())
1149     if (mapShape.Add(exp.Current()))
1150       nb++;
1151
1152   SetErrorCode(OK);
1153   return nb;
1154 }
1155
1156 //=============================================================================
1157 /*!
1158  *  ReverseShape
1159  */
1160 //=============================================================================
1161 Handle(GEOM_Object) GEOMImpl_IShapesOperations::ReverseShape(Handle(GEOM_Object) theShape)
1162 {
1163   SetErrorCode(KO);
1164
1165   if (theShape.IsNull()) return NULL;
1166
1167   //Add a new reversed object
1168   Handle(GEOM_Object) aReversed = GetEngine()->AddObject(GetDocID(), theShape->GetType());
1169
1170   //Add a new Revese function
1171   Handle(GEOM_Function) aFunction;
1172   aFunction = aReversed->AddFunction(GEOMImpl_ShapeDriver::GetID(), REVERSE_ORIENTATION);
1173   if (aFunction.IsNull()) return NULL;
1174
1175   //Check if the function is set correctly
1176   if (aFunction->GetDriverGUID() != GEOMImpl_ShapeDriver::GetID()) return NULL;
1177
1178   GEOMImpl_IShapes aSI (aFunction);
1179
1180   Handle(GEOM_Function) aRefShape = theShape->GetLastFunction();
1181   if (aRefShape.IsNull()) return NULL;
1182
1183   aSI.SetBase(aRefShape);
1184
1185   //Compute the sub-shape value
1186   try {
1187 #if (OCC_VERSION_MAJOR << 16 | OCC_VERSION_MINOR << 8 | OCC_VERSION_MAINTENANCE) > 0x060100
1188     OCC_CATCH_SIGNALS;
1189 #endif
1190     if (!GetSolver()->ComputeFunction(aFunction)) {
1191       SetErrorCode("Shape driver failed to reverse shape");
1192       return NULL;
1193     }
1194   }
1195   catch (Standard_Failure) {
1196     Handle(Standard_Failure) aFail = Standard_Failure::Caught();
1197     SetErrorCode(aFail->GetMessageString());
1198     return NULL;
1199   }
1200
1201   //Make a Python command
1202   GEOM::TPythonDump(aFunction) << aReversed
1203     << " = geompy.ChangeOrientation(" << theShape << ")";
1204
1205   SetErrorCode(OK);
1206   return aReversed;
1207 }
1208
1209 //=============================================================================
1210 /*!
1211  *  GetFreeFacesIDs
1212  */
1213 //=============================================================================
1214 Handle(TColStd_HSequenceOfInteger) GEOMImpl_IShapesOperations::GetFreeFacesIDs
1215                                                  (Handle(GEOM_Object) theShape)
1216 {
1217   SetErrorCode(KO);
1218
1219   if (theShape.IsNull()) return NULL;
1220   TopoDS_Shape aShape = theShape->GetValue();
1221   if (aShape.IsNull()) return NULL;
1222
1223   Handle(TColStd_HSequenceOfInteger) aSeq = new TColStd_HSequenceOfInteger;
1224
1225   TopTools_IndexedDataMapOfShapeListOfShape mapFaceBlocks;
1226   GEOMImpl_Block6Explorer::MapShapesAndAncestors
1227     (aShape, TopAbs_FACE, TopAbs_SOLID, mapFaceBlocks);
1228
1229   Standard_Integer ind = 1, nbFaces = mapFaceBlocks.Extent();
1230
1231   if (nbFaces == 0) {
1232     SetErrorCode("The given shape has no faces");
1233     return aSeq;
1234   }
1235
1236   TopTools_IndexedMapOfShape anIndices;
1237   TopExp::MapShapes(aShape, anIndices);
1238
1239   Standard_Integer id;
1240   for (; ind <= nbFaces; ind++) {
1241     if (mapFaceBlocks.FindFromIndex(ind).Extent() != 2) {
1242       id = anIndices.FindIndex(mapFaceBlocks.FindKey(ind));
1243       aSeq->Append(id);
1244     }
1245   }
1246
1247   //The explode doesn't change object so no new function is required.
1248   Handle(GEOM_Function) aFunction = theShape->GetLastFunction();
1249
1250   //Make a Python command
1251   GEOM::TPythonDump(aFunction, /*append=*/true)
1252     << "listFreeFacesIDs = geompy.GetFreeFacesIDs(" << theShape << ")";
1253
1254   SetErrorCode(OK);
1255   return aSeq;
1256 }
1257
1258 //=======================================================================
1259 //function : GetSharedShapes
1260 //purpose  :
1261 //=======================================================================
1262 Handle(TColStd_HSequenceOfTransient) GEOMImpl_IShapesOperations::GetSharedShapes
1263                                                 (Handle(GEOM_Object)    theShape1,
1264                                                  Handle(GEOM_Object)    theShape2,
1265                                                  const Standard_Integer theShapeType)
1266 {
1267   SetErrorCode(KO);
1268
1269   if (theShape1.IsNull() || theShape2.IsNull()) return NULL;
1270
1271   TopoDS_Shape aShape1 = theShape1->GetValue();
1272   TopoDS_Shape aShape2 = theShape2->GetValue();
1273
1274   if (aShape1.IsNull() || aShape2.IsNull()) return NULL;
1275
1276   TopTools_IndexedMapOfShape anIndices;
1277   TopExp::MapShapes(aShape1, anIndices);
1278   Handle(TColStd_HArray1OfInteger) anArray;
1279
1280   TopTools_IndexedMapOfShape mapShape1;
1281   TopExp::MapShapes(aShape1, TopAbs_ShapeEnum(theShapeType), mapShape1);
1282
1283   Handle(GEOM_Object) anObj;
1284   Handle(TColStd_HSequenceOfTransient) aSeq = new TColStd_HSequenceOfTransient;
1285   TCollection_AsciiString anAsciiList, anEntry;
1286
1287   TopTools_MapOfShape mapShape2;
1288   TopExp_Explorer exp (aShape2, TopAbs_ShapeEnum(theShapeType));
1289   for (; exp.More(); exp.Next()) {
1290     TopoDS_Shape aSS = exp.Current();
1291     if (mapShape2.Add(aSS) && mapShape1.Contains(aSS)) {
1292       anArray = new TColStd_HArray1OfInteger(1,1);
1293       anArray->SetValue(1, anIndices.FindIndex(aSS));
1294       anObj = GetEngine()->AddSubShape(theShape1, anArray);
1295       aSeq->Append(anObj);
1296
1297       // for python command
1298       TDF_Tool::Entry(anObj->GetEntry(), anEntry);
1299       anAsciiList += anEntry;
1300       anAsciiList += ",";
1301     }
1302   }
1303
1304   if (aSeq->IsEmpty()) {
1305     SetErrorCode("The given shapes have no shared sub-shapes of the requested type");
1306     return aSeq;
1307   }
1308
1309   //Make a Python command
1310   anAsciiList.Trunc(anAsciiList.Length() - 1);
1311
1312   Handle(GEOM_Function) aFunction = anObj->GetLastFunction();
1313
1314   GEOM::TPythonDump(aFunction) << "[" << anAsciiList.ToCString()
1315     << "] = geompy.GetSharedShapes(" << theShape1 << ", "
1316       << theShape2 << ", " << TopAbs_ShapeEnum(theShapeType) << ")";
1317
1318   SetErrorCode(OK);
1319   return aSeq;
1320 }
1321
1322 //=============================================================================
1323 /*!
1324  *
1325  */
1326 //=============================================================================
1327 static GEOM::TPythonDump& operator<< (GEOM::TPythonDump&   theDump,
1328                                       const GEOMAlgo_State theState)
1329 {
1330   switch (theState) {
1331   case GEOMAlgo_ST_IN:
1332     theDump << "geompy.GEOM.ST_IN";
1333     break;
1334   case GEOMAlgo_ST_OUT:
1335     theDump << "geompy.GEOM.ST_OUT";
1336     break;
1337   case GEOMAlgo_ST_ON:
1338     theDump << "geompy.GEOM.ST_ON";
1339     break;
1340   case GEOMAlgo_ST_ONIN:
1341     theDump << "geompy.GEOM.ST_ONIN";
1342     break;
1343   case GEOMAlgo_ST_ONOUT:
1344     theDump << "geompy.GEOM.ST_ONOUT";
1345     break;
1346   default:
1347     theDump << "geompy.GEOM.ST_UNKNOWN";
1348     break;
1349   }
1350   return theDump;
1351 }
1352
1353 //=======================================================================
1354 //function : checkTypeShapesOn
1355 /*!
1356  * \brief Checks if theShapeType parameter of GetShapesOnXXX() is OK
1357  * \param theShapeType - the shape type to check
1358  * \retval bool  - result of the check
1359  */
1360 //=======================================================================
1361 bool GEOMImpl_IShapesOperations::checkTypeShapesOn(const Standard_Integer theShapeType)
1362 {
1363   if (theShapeType != TopAbs_VERTEX &&
1364       theShapeType != TopAbs_EDGE &&
1365       theShapeType != TopAbs_FACE &&
1366       theShapeType != TopAbs_SOLID) {
1367     SetErrorCode("Only solids, vertices, edges or faces can be found by this method");
1368     return false;
1369   }
1370   return true;
1371 }
1372
1373 //=======================================================================
1374 //function : makePlane
1375   /*!
1376    * \brief Creates Geom_Plane
1377     * \param theAx1 - shape object defining plane parameters
1378     * \retval Handle(Geom_Surface) - resulting surface
1379    */
1380 //=======================================================================
1381 Handle(Geom_Surface) GEOMImpl_IShapesOperations::makePlane(const TopoDS_Shape& anAx1)
1382 {
1383   if (anAx1.ShapeType() != TopAbs_EDGE) return NULL;
1384   TopoDS_Edge anEdge = TopoDS::Edge(anAx1);
1385   TopoDS_Vertex V1, V2;
1386   TopExp::Vertices(anEdge, V1, V2, Standard_True);
1387   if (V1.IsNull() || V2.IsNull()) {
1388     SetErrorCode("Bad edge given for the plane normal vector");
1389     return NULL;
1390   }
1391   gp_Pnt aLoc = BRep_Tool::Pnt(V1);
1392   gp_Vec aVec (aLoc, BRep_Tool::Pnt(V2));
1393   if (aVec.Magnitude() < Precision::Confusion()) {
1394     SetErrorCode("Vector with null magnitude given");
1395     return NULL;
1396   }
1397   return new Geom_Plane(aLoc, aVec);
1398 }
1399
1400 //=======================================================================
1401 //function : makeCylinder
1402   /*!
1403    * \brief Creates Geom_CylindricalSurface
1404     * \param theAx1 - edge defining cylinder axis
1405     * \param theRadius - cylinder radius
1406     * \retval Handle(Geom_Surface) - resulting surface
1407    */
1408 //=======================================================================
1409 Handle(Geom_Surface) GEOMImpl_IShapesOperations::makeCylinder(const TopoDS_Shape& anAxis,
1410                                                               const Standard_Real theRadius)
1411 {
1412   //Axis of the cylinder
1413   if (anAxis.ShapeType() != TopAbs_EDGE) {
1414     SetErrorCode("Not an edge given for the axis");
1415     return NULL;
1416   }
1417   TopoDS_Edge anEdge = TopoDS::Edge(anAxis);
1418   TopoDS_Vertex V1, V2;
1419   TopExp::Vertices(anEdge, V1, V2, Standard_True);
1420   if (V1.IsNull() || V2.IsNull()) {
1421     SetErrorCode("Bad edge given for the axis");
1422     return NULL;
1423   }
1424   gp_Pnt aLoc = BRep_Tool::Pnt(V1);
1425   gp_Vec aVec (aLoc, BRep_Tool::Pnt(V2));
1426   if (aVec.Magnitude() < Precision::Confusion()) {
1427     SetErrorCode("Vector with null magnitude given");
1428     return NULL;
1429   }
1430
1431   gp_Ax3 anAx3 (aLoc, aVec);
1432   return new Geom_CylindricalSurface(anAx3, theRadius);
1433 }
1434
1435 //=======================================================================
1436 //function : getShapesOnBoxIDs
1437   /*!
1438    * \brief Find IDs of subshapes complying with given status about surface
1439     * \param theBox - the box to check state of subshapes against
1440     * \param theShape - the shape to explore
1441     * \param theShapeType - type of subshape of theShape
1442     * \param theState - required state
1443     * \retval Handle(TColStd_HSequenceOfInteger) - IDs of found subshapes
1444    */
1445 //=======================================================================
1446 Handle(TColStd_HSequenceOfInteger)
1447   GEOMImpl_IShapesOperations::getShapesOnBoxIDs(const Handle(GEOM_Object)& theBox,
1448                                                 const Handle(GEOM_Object)& theShape,
1449                                                 const Standard_Integer theShapeType,
1450                                                 GEOMAlgo_State theState)
1451 {
1452   Handle(TColStd_HSequenceOfInteger) aSeqOfIDs;
1453
1454   TopoDS_Shape aBox = theBox->GetValue();
1455   TopoDS_Shape aShape = theShape->GetValue();
1456
1457   // Check presence of triangulation, build if need
1458   if (!CheckTriangulation(aShape)) {
1459     SetErrorCode("Cannot build triangulation on the shape");
1460     return aSeqOfIDs;
1461   }
1462
1463   // Call algo
1464   GEOMAlgo_FinderShapeOn2 aFinder;
1465   Standard_Real aTol = 0.0001; // default value
1466
1467   Handle(GEOMAlgo_ClsfBox) aClsfBox = new GEOMAlgo_ClsfBox;
1468   aClsfBox->SetBox(aBox);
1469
1470   aFinder.SetShape(aShape);
1471   aFinder.SetTolerance(aTol);
1472   aFinder.SetClsf(aClsfBox);
1473   aFinder.SetShapeType( (TopAbs_ShapeEnum)theShapeType );
1474   aFinder.SetState(theState);
1475   aFinder.Perform();
1476
1477   // Interprete results
1478   Standard_Integer iErr = aFinder.ErrorStatus();
1479   // the detailed description of error codes is in GEOMAlgo_FinderShapeOn1.cxx
1480   if (iErr) {
1481     MESSAGE(" iErr : " << iErr);
1482     TCollection_AsciiString aMsg (" iErr : ");
1483     aMsg += TCollection_AsciiString(iErr);
1484     SetErrorCode(aMsg);
1485     return aSeqOfIDs;
1486   }
1487   Standard_Integer iWrn = aFinder.WarningStatus();
1488   // the detailed description of warning codes is in GEOMAlgo_FinderShapeOn1.cxx
1489   if (iWrn) {
1490     MESSAGE(" *** iWrn : " << iWrn);
1491   }
1492
1493   const TopTools_ListOfShape& listSS = aFinder.Shapes(); // the result
1494
1495   if (listSS.Extent() < 1) {
1496     //SetErrorCode("Not a single sub-shape of the requested type found on the given surface");
1497     SetErrorCode(NOT_FOUND_ANY); // NPAL18017
1498     return aSeqOfIDs;
1499   }
1500
1501   // Fill sequence of object IDs
1502   aSeqOfIDs = new TColStd_HSequenceOfInteger;
1503
1504   TopTools_IndexedMapOfShape anIndices;
1505   TopExp::MapShapes(aShape, anIndices);
1506
1507   TopTools_ListIteratorOfListOfShape itSub (listSS);
1508   for (int index = 1; itSub.More(); itSub.Next(), ++index) {
1509     int id = anIndices.FindIndex(itSub.Value());
1510     aSeqOfIDs->Append(id);
1511   }
1512
1513   return aSeqOfIDs;
1514 }
1515
1516 //=======================================================================
1517 //function : GetShapesOnBoxIDs
1518 /*!
1519    * \brief Find subshapes complying with given status about surface
1520     * \param theBox - the box to check state of subshapes against
1521     * \param theShape - the shape to explore
1522     * \param theShapeType - type of subshape of theShape
1523     * \param theState - required state
1524     * \retval Handle(TColStd_HSequenceOfInteger) - IDs of found subshapes
1525  */
1526 //=======================================================================
1527 Handle(TColStd_HSequenceOfInteger)
1528     GEOMImpl_IShapesOperations::GetShapesOnBoxIDs(const Handle(GEOM_Object)& theBox,
1529                                                   const Handle(GEOM_Object)& theShape,
1530                                                   const Standard_Integer theShapeType,
1531                                                   GEOMAlgo_State theState)
1532 {
1533   // Find subshapes ids
1534   Handle(TColStd_HSequenceOfInteger) aSeqOfIDs =
1535     getShapesOnBoxIDs (theBox, theShape, theShapeType, theState);
1536   if ( aSeqOfIDs.IsNull()  || aSeqOfIDs->Length() == 0 )
1537     return NULL;
1538
1539   // The GetShapesOnBox() doesn't change object so no new function is required.
1540   Handle(GEOM_Function) aFunction = GEOM::GetCreatedLast(theShape,theBox)->GetLastFunction();
1541
1542   // Make a Python command
1543   GEOM::TPythonDump(aFunction)
1544     << "listShapesOnBoxIDs = geompy.GetShapesOnBoxIDs("
1545     << theBox << ", "
1546     << theShape << ", "
1547     << TopAbs_ShapeEnum(theShapeType) << ", "
1548     << theState << ")";
1549
1550   SetErrorCode(OK);
1551   return aSeqOfIDs;
1552 }
1553
1554 //=======================================================================
1555 //function : GetShapesOnBox
1556 /*!
1557    * \brief Find subshapes complying with given status about surface
1558     * \param theBox - the box to check state of subshapes against
1559     * \param theShape - the shape to explore
1560     * \param theShapeType - type of subshape of theShape
1561     * \param theState - required state
1562     * \retval Handle(TColStd_HSequenceOfTransient) - found subshapes
1563  */
1564 //=======================================================================
1565 Handle(TColStd_HSequenceOfTransient)
1566     GEOMImpl_IShapesOperations::GetShapesOnBox(const Handle(GEOM_Object)& theBox,
1567                                                const Handle(GEOM_Object)&  theShape,
1568                                                const Standard_Integer theShapeType,
1569                                                GEOMAlgo_State theState)
1570 {
1571   // Find subshapes ids
1572   Handle(TColStd_HSequenceOfInteger) aSeqOfIDs =
1573     getShapesOnBoxIDs (theBox, theShape, theShapeType, theState);
1574   if ( aSeqOfIDs.IsNull()  || aSeqOfIDs->Length() == 0 )
1575     return NULL;
1576
1577   // Find objects by indices
1578   TCollection_AsciiString anAsciiList;
1579   Handle(TColStd_HSequenceOfTransient) aSeq;
1580   aSeq = getObjectsShapesOn( theShape, aSeqOfIDs, anAsciiList );
1581   if ( aSeq.IsNull() || aSeq->IsEmpty() )
1582     return NULL;
1583
1584   // Make a Python command
1585
1586   Handle(GEOM_Object) anObj = Handle(GEOM_Object)::DownCast( aSeq->Value( 1 ));
1587   Handle(GEOM_Function) aFunction = anObj->GetLastFunction();
1588
1589   GEOM::TPythonDump(aFunction)
1590     << "[" << anAsciiList.ToCString() << "] = geompy.GetShapesOnBox("
1591     << theBox << ", "
1592     << theShape << ", "
1593     << TopAbs_ShapeEnum(theShapeType) << ", "
1594     << theState << ")";
1595
1596   SetErrorCode(OK);
1597   return aSeq;
1598 }
1599
1600 //=======================================================================
1601 //function : getShapesOnShapeIDs
1602 /*!
1603  * \brief Find IDs of subshapes complying with given status about surface
1604  * \param theCheckShape - the shape to check state of subshapes against
1605  * \param theShape - the shape to explore
1606  * \param theShapeType - type of subshape of theShape
1607  * \param theState - required state
1608  * \retval Handle(TColStd_HSequenceOfInteger) - IDs of found subshapes
1609  */
1610 //=======================================================================
1611 Handle(TColStd_HSequenceOfInteger)
1612   GEOMImpl_IShapesOperations::getShapesOnShapeIDs
1613                                  (const Handle(GEOM_Object)& theCheckShape,
1614                                   const Handle(GEOM_Object)& theShape,
1615                                   const Standard_Integer theShapeType,
1616                                   GEOMAlgo_State theState)
1617 {
1618   Handle(TColStd_HSequenceOfInteger) aSeqOfIDs;
1619
1620   TopoDS_Shape aCheckShape = theCheckShape->GetValue();
1621   TopoDS_Shape aShape = theShape->GetValue();
1622   TopTools_ListOfShape res;
1623
1624   // Check presence of triangulation, build if need
1625   if (!CheckTriangulation(aShape)) {
1626     SetErrorCode("Cannot build triangulation on the shape");
1627     return aSeqOfIDs;
1628   }
1629
1630   // Call algo
1631   GEOMAlgo_FinderShapeOn2 aFinder;
1632   Standard_Real aTol = 0.0001; // default value
1633
1634   Handle(GEOMAlgo_ClsfSolid) aClsfSolid = new GEOMAlgo_ClsfSolid;
1635   aClsfSolid->SetShape(aCheckShape);
1636
1637   aFinder.SetShape(aShape);
1638   aFinder.SetTolerance(aTol);
1639   aFinder.SetClsf(aClsfSolid);
1640   aFinder.SetShapeType( (TopAbs_ShapeEnum)theShapeType );
1641   aFinder.SetState(theState);
1642   aFinder.Perform();
1643
1644   // Interprete results
1645   Standard_Integer iErr = aFinder.ErrorStatus();
1646   // the detailed description of error codes is in GEOMAlgo_FinderShapeOn1.cxx
1647   if (iErr) {
1648     MESSAGE(" iErr : " << iErr);
1649     TCollection_AsciiString aMsg (" iErr : ");
1650     aMsg += TCollection_AsciiString(iErr);
1651     SetErrorCode(aMsg);
1652     return aSeqOfIDs;
1653   }
1654   Standard_Integer iWrn = aFinder.WarningStatus();
1655   // the detailed description of warning codes is in GEOMAlgo_FinderShapeOn1.cxx
1656   if (iWrn) {
1657     MESSAGE(" *** iWrn : " << iWrn);
1658   }
1659
1660   const TopTools_ListOfShape& listSS = aFinder.Shapes(); // the result
1661
1662   if (listSS.Extent() < 1) {
1663     //SetErrorCode("Not a single sub-shape of the requested type found on the given surface");
1664     SetErrorCode(NOT_FOUND_ANY); // NPAL18017
1665   }
1666
1667   // Fill sequence of object IDs
1668   aSeqOfIDs = new TColStd_HSequenceOfInteger;
1669
1670   TopTools_IndexedMapOfShape anIndices;
1671   TopExp::MapShapes(aShape, anIndices);
1672
1673   TopTools_ListIteratorOfListOfShape itSub (listSS);
1674   for (int index = 1; itSub.More(); itSub.Next(), ++index) {
1675     int id = anIndices.FindIndex(itSub.Value());
1676     aSeqOfIDs->Append(id);
1677   }
1678
1679   return aSeqOfIDs;
1680 }
1681
1682 //=======================================================================
1683 //function : GetShapesOnShapeIDs
1684 /*!
1685  * \brief Find subshapes complying with given status about surface
1686  * \param theCheckShape - the shape to check state of subshapes against
1687  * \param theShape - the shape to explore
1688  * \param theShapeType - type of subshape of theShape
1689  * \param theState - required state
1690  * \retval Handle(TColStd_HSequenceOfInteger) - IDs of found subshapes
1691  */
1692 //=======================================================================
1693 Handle(TColStd_HSequenceOfInteger)
1694     GEOMImpl_IShapesOperations::GetShapesOnShapeIDs
1695                             (const Handle(GEOM_Object)& theCheckShape,
1696                              const Handle(GEOM_Object)& theShape,
1697                              const Standard_Integer theShapeType,
1698                              GEOMAlgo_State theState)
1699 {
1700   Handle(TColStd_HSequenceOfInteger) aSeqOfIDs =
1701     getShapesOnShapeIDs (theCheckShape, theShape, theShapeType, theState);
1702
1703   if ( aSeqOfIDs.IsNull()  || aSeqOfIDs->Length() == 0 )
1704     return NULL;
1705
1706   // The GetShapesOnShape() doesn't change object so no new function is required.
1707   Handle(GEOM_Function) aFunction =
1708     GEOM::GetCreatedLast(theShape,theCheckShape)->GetLastFunction();
1709
1710   // Make a Python command
1711   GEOM::TPythonDump(aFunction)
1712     << "listShapesOnBoxIDs = geompy.GetShapesOnShapeIDs("
1713     << theCheckShape << ", "
1714     << theShape << ", "
1715     << TopAbs_ShapeEnum(theShapeType) << ", "
1716     << theState << ")";
1717
1718   SetErrorCode(OK);
1719   return aSeqOfIDs;
1720 }
1721
1722 //=======================================================================
1723 //function : GetShapesOnShape
1724 /*!
1725  * \brief Find subshapes complying with given status about surface
1726  * \param theCheckShape - the shape to check state of subshapes against
1727  * \param theShape - the shape to explore
1728  * \param theShapeType - type of subshape of theShape
1729  * \param theState - required state
1730  * \retval Handle(TColStd_HSequenceOfTransient) - found subshapes
1731  */
1732 //=======================================================================
1733 Handle(TColStd_HSequenceOfTransient)
1734   GEOMImpl_IShapesOperations::GetShapesOnShape
1735                              (const Handle(GEOM_Object)& theCheckShape,
1736                               const Handle(GEOM_Object)&  theShape,
1737                               const Standard_Integer theShapeType,
1738                               GEOMAlgo_State theState)
1739 {
1740   Handle(TColStd_HSequenceOfInteger) aSeqOfIDs =
1741     getShapesOnShapeIDs (theCheckShape, theShape, theShapeType, theState);
1742   if ( aSeqOfIDs.IsNull()  || aSeqOfIDs->Length() == 0 )
1743     return NULL;
1744
1745   // Find objects by indices
1746   TCollection_AsciiString anAsciiList;
1747   Handle(TColStd_HSequenceOfTransient) aSeq;
1748   aSeq = getObjectsShapesOn( theShape, aSeqOfIDs, anAsciiList );
1749
1750   if ( aSeq.IsNull() || aSeq->IsEmpty() )
1751     return NULL;
1752
1753   // Make a Python command
1754
1755   Handle(GEOM_Object) anObj = Handle(GEOM_Object)::DownCast( aSeq->Value( 1 ));
1756   Handle(GEOM_Function) aFunction = anObj->GetLastFunction();
1757
1758   GEOM::TPythonDump(aFunction)
1759     << "[" << anAsciiList.ToCString() << "] = geompy.GetShapesOnShape("
1760     << theCheckShape << ", "
1761     << theShape << ", "
1762     << TopAbs_ShapeEnum(theShapeType) << ", "
1763     << theState << ")";
1764
1765   SetErrorCode(OK);
1766   return aSeq;
1767 }
1768
1769 //=======================================================================
1770 //function : GetShapesOnShapeAsCompound
1771 //=======================================================================
1772 Handle(GEOM_Object) GEOMImpl_IShapesOperations::GetShapesOnShapeAsCompound
1773                              (const Handle(GEOM_Object)& theCheckShape,
1774                               const Handle(GEOM_Object)&  theShape,
1775                               const Standard_Integer theShapeType,
1776                               GEOMAlgo_State theState)
1777 {
1778   Handle(TColStd_HSequenceOfInteger) aSeqOfIDs =
1779     getShapesOnShapeIDs (theCheckShape, theShape, theShapeType, theState);
1780
1781   if ( aSeqOfIDs.IsNull()  || aSeqOfIDs->Length() == 0 )
1782     return NULL;
1783
1784   // Find objects by indices
1785   TCollection_AsciiString anAsciiList;
1786   Handle(TColStd_HSequenceOfTransient) aSeq;
1787   aSeq = getObjectsShapesOn( theShape, aSeqOfIDs, anAsciiList );
1788
1789   if ( aSeq.IsNull() || aSeq->IsEmpty() )
1790     return NULL;
1791
1792   TopoDS_Compound aCompound;
1793   BRep_Builder B;
1794   B.MakeCompound(aCompound);
1795   int i = 1;
1796   for(; i<=aSeq->Length(); i++) {
1797     Handle(GEOM_Object) anObj = Handle(GEOM_Object)::DownCast(aSeq->Value(i));
1798     TopoDS_Shape aShape_i = anObj->GetValue();
1799     B.Add(aCompound,aShape_i);
1800   }
1801
1802   //Add a new result object
1803   Handle(GEOM_Object) aRes = GetEngine()->AddObject(GetDocID(), GEOM_SHAPES_ON_SHAPE);
1804   Handle(GEOM_Function) aFunction =
1805     aRes->AddFunction(GEOMImpl_ShapeDriver::GetID(), SHAPES_ON_SHAPE);
1806   aFunction->SetValue(aCompound);
1807
1808   GEOM::TPythonDump(aFunction)
1809     << aRes << " = geompy.GetShapesOnShapeAsCompound("
1810     << theCheckShape << ", "
1811     << theShape << ", "
1812     << TopAbs_ShapeEnum(theShapeType) << ", "
1813     << theState << ")";
1814
1815   SetErrorCode(OK);
1816
1817   return aRes;
1818 }
1819
1820 //=======================================================================
1821 //function : getShapesOnSurfaceIDs
1822   /*!
1823    * \brief Find IDs of subshapes complying with given status about surface
1824     * \param theSurface - the surface to check state of subshapes against
1825     * \param theShape - the shape to explore
1826     * \param theShapeType - type of subshape of theShape
1827     * \param theState - required state
1828     * \retval Handle(TColStd_HSequenceOfInteger) - IDs of found subshapes
1829    */
1830 //=======================================================================
1831 Handle(TColStd_HSequenceOfInteger)
1832   GEOMImpl_IShapesOperations::getShapesOnSurfaceIDs(const Handle(Geom_Surface)& theSurface,
1833                                                     const TopoDS_Shape&         theShape,
1834                                                     TopAbs_ShapeEnum            theShapeType,
1835                                                     GEOMAlgo_State              theState)
1836 {
1837   Handle(TColStd_HSequenceOfInteger) aSeqOfIDs;
1838
1839   // Check presence of triangulation, build if need
1840   if (!CheckTriangulation(theShape)) {
1841     SetErrorCode("Cannot build triangulation on the shape");
1842     return aSeqOfIDs;
1843   }
1844
1845   // Call algo
1846   GEOMAlgo_FinderShapeOn1 aFinder;
1847   Standard_Real aTol = 0.0001; // default value
1848
1849   aFinder.SetShape(theShape);
1850   aFinder.SetTolerance(aTol);
1851   aFinder.SetSurface(theSurface);
1852   aFinder.SetShapeType(theShapeType);
1853   aFinder.SetState(theState);
1854
1855   // Sets the minimal number of inner points for the faces that do not have own
1856   // inner points at all (for e.g. rectangular planar faces have just 2 triangles).
1857   // Default value=3
1858   aFinder.SetNbPntsMin(3);
1859   // Sets the maximal number of inner points for edges or faces.
1860   // It is usefull for the cases when this number is very big (e.g =2000) to improve
1861   // the performance. If this value =0, all inner points will be taken into account.
1862   // Default value=0
1863   aFinder.SetNbPntsMax(100);
1864
1865   aFinder.Perform();
1866
1867   // Interprete results
1868   Standard_Integer iErr = aFinder.ErrorStatus();
1869   // the detailed description of error codes is in GEOMAlgo_FinderShapeOn1.cxx
1870   if (iErr) {
1871     MESSAGE(" iErr : " << iErr);
1872     TCollection_AsciiString aMsg (" iErr : ");
1873     aMsg += TCollection_AsciiString(iErr);
1874     SetErrorCode(aMsg);
1875     return aSeqOfIDs;
1876   }
1877   Standard_Integer iWrn = aFinder.WarningStatus();
1878   // the detailed description of warning codes is in GEOMAlgo_FinderShapeOn1.cxx
1879   if (iWrn) {
1880     MESSAGE(" *** iWrn : " << iWrn);
1881   }
1882
1883   const TopTools_ListOfShape& listSS = aFinder.Shapes(); // the result
1884
1885   if (listSS.Extent() < 1) {
1886     //SetErrorCode("Not a single sub-shape of the requested type found on the given surface");
1887     SetErrorCode(NOT_FOUND_ANY); // NPAL18017
1888     return aSeqOfIDs;
1889   }
1890
1891   // Fill sequence of object IDs
1892   aSeqOfIDs = new TColStd_HSequenceOfInteger;
1893
1894   TopTools_IndexedMapOfShape anIndices;
1895   TopExp::MapShapes(theShape, anIndices);
1896
1897   TopTools_ListIteratorOfListOfShape itSub (listSS);
1898   for (int index = 1; itSub.More(); itSub.Next(), ++index) {
1899     int id = anIndices.FindIndex(itSub.Value());
1900     aSeqOfIDs->Append(id);
1901   }
1902
1903   return aSeqOfIDs;
1904 }
1905
1906 //=======================================================================
1907 //function : getObjectsShapesOn
1908 /*!
1909  * \brief Find shape objects and their entries by their ids
1910  * \param theShapeIDs - incoming shape ids
1911  * \param theShapeEntries - outgoing entries like "entry1, entry2, ..."
1912  * \retval Handle(TColStd_HSequenceOfTransient) - found shape objects
1913  */
1914 //=======================================================================
1915 Handle(TColStd_HSequenceOfTransient) GEOMImpl_IShapesOperations::
1916  getObjectsShapesOn(const Handle(GEOM_Object)&                theShape,
1917                     const Handle(TColStd_HSequenceOfInteger)& theShapeIDs,
1918                     TCollection_AsciiString &                 theShapeEntries)
1919 {
1920   Handle(TColStd_HSequenceOfTransient) aSeq;
1921
1922   if ( !theShapeIDs.IsNull() && theShapeIDs->Length() > 0 )
1923   {
1924     aSeq = new TColStd_HSequenceOfTransient;
1925     Handle(TColStd_HArray1OfInteger) anArray = new TColStd_HArray1OfInteger(1,1);
1926     TCollection_AsciiString anEntry;
1927     for ( int i = 1; i <= theShapeIDs->Length(); ++i )
1928     {
1929       anArray->SetValue(1, theShapeIDs->Value( i ));
1930       Handle(GEOM_Object) anObj = GetEngine()->AddSubShape(theShape, anArray);
1931       aSeq->Append( anObj );
1932
1933       TDF_Tool::Entry(anObj->GetEntry(), anEntry);
1934       if ( i != 1 ) theShapeEntries += ",";
1935       theShapeEntries += anEntry;
1936     }
1937   }
1938   return aSeq;
1939 }
1940
1941 //=======================================================================
1942 //function : getShapesOnSurface
1943 /*!
1944    * \brief Find subshapes complying with given status about surface
1945     * \param theSurface - the surface to check state of subshapes against
1946     * \param theShape - the shape to explore
1947     * \param theShapeType - type of subshape of theShape
1948     * \param theState - required state
1949     * \param theShapeEntries - outgoing entries like "entry1, entry2, ..."
1950     * \retval Handle(TColStd_HSequenceOfInteger) - IDs of found subshapes
1951  */
1952 //=======================================================================
1953 Handle(TColStd_HSequenceOfTransient)
1954     GEOMImpl_IShapesOperations::getShapesOnSurface(const Handle(Geom_Surface)& theSurface,
1955                                                    const Handle(GEOM_Object)&  theShape,
1956                                                    TopAbs_ShapeEnum            theShapeType,
1957                                                    GEOMAlgo_State              theState,
1958                                                    TCollection_AsciiString &   theShapeEntries)
1959 {
1960   // Find subshapes ids
1961   Handle(TColStd_HSequenceOfInteger) aSeqOfIDs =
1962     getShapesOnSurfaceIDs (theSurface, theShape->GetValue(), theShapeType, theState);
1963   if ( aSeqOfIDs.IsNull()  || aSeqOfIDs->Length() == 0 )
1964     return NULL;
1965
1966   return getObjectsShapesOn( theShape, aSeqOfIDs, theShapeEntries );
1967 }
1968
1969 //=============================================================================
1970 /*!
1971  *  GetShapesOnPlane
1972  */
1973 //=============================================================================
1974 Handle(TColStd_HSequenceOfTransient) GEOMImpl_IShapesOperations::GetShapesOnPlane
1975                                         (const Handle(GEOM_Object)& theShape,
1976                                          const Standard_Integer     theShapeType,
1977                                          const Handle(GEOM_Object)& theAx1,
1978                                          const GEOMAlgo_State       theState)
1979 {
1980   SetErrorCode(KO);
1981
1982   if (theShape.IsNull() || theAx1.IsNull()) return NULL;
1983
1984   TopoDS_Shape aShape = theShape->GetValue();
1985   TopoDS_Shape anAx1  = theAx1->GetValue();
1986
1987   if (aShape.IsNull() || anAx1.IsNull()) return NULL;
1988
1989   TopAbs_ShapeEnum aShapeType = TopAbs_ShapeEnum(theShapeType);
1990   if ( !checkTypeShapesOn( theShapeType ))
1991     return NULL;
1992
1993   // Create plane
1994   Handle(Geom_Surface) aPlane = makePlane( anAx1 );
1995   if ( aPlane.IsNull() )
1996     return NULL;
1997
1998   // Find objects
1999   TCollection_AsciiString anAsciiList;
2000   Handle(TColStd_HSequenceOfTransient) aSeq;
2001   aSeq = getShapesOnSurface( aPlane, theShape, aShapeType, theState, anAsciiList );
2002   if ( aSeq.IsNull() || aSeq->Length() == 0 )
2003     return NULL;
2004
2005   // Make a Python command
2006
2007   Handle(GEOM_Object) anObj = Handle(GEOM_Object)::DownCast( aSeq->Value( 1 ));
2008   Handle(GEOM_Function) aFunction = anObj->GetLastFunction();
2009
2010   GEOM::TPythonDump(aFunction) << "[" << anAsciiList.ToCString()
2011     << "] = geompy.GetShapesOnPlane(" << theShape << ", "
2012       << aShapeType << ", " << theAx1 << ", " << theState << ")";
2013
2014   SetErrorCode(OK);
2015   return aSeq;
2016 }
2017
2018 //=============================================================================
2019 /*!
2020  *  GetShapesOnPlaneWithLocation
2021  */
2022 //=============================================================================
2023 Handle(TColStd_HSequenceOfTransient) GEOMImpl_IShapesOperations::GetShapesOnPlaneWithLocation
2024                                         (const Handle(GEOM_Object)& theShape,
2025                                          const Standard_Integer     theShapeType,
2026                                          const Handle(GEOM_Object)& theAx1,
2027                                          const Handle(GEOM_Object)& thePnt,
2028                                          const GEOMAlgo_State       theState)
2029 {
2030   SetErrorCode(KO);
2031
2032   if (theShape.IsNull() || theAx1.IsNull() || thePnt.IsNull()) return NULL;
2033
2034   TopoDS_Shape aShape = theShape->GetValue();
2035   TopoDS_Shape anAx1  = theAx1->GetValue();
2036   TopoDS_Shape anPnt = thePnt->GetValue();
2037
2038   if (aShape.IsNull() || anAx1.IsNull() || anPnt.IsNull()) return NULL;
2039
2040   TopAbs_ShapeEnum aShapeType = TopAbs_ShapeEnum(theShapeType);
2041   if ( !checkTypeShapesOn( theShapeType ))
2042     return NULL;
2043
2044   // Create plane
2045   if ( anAx1.ShapeType() != TopAbs_EDGE || anPnt.ShapeType() != TopAbs_VERTEX ) return NULL;
2046   TopoDS_Vertex V1, V2, V3;
2047   TopoDS_Edge anEdge = TopoDS::Edge(anAx1);
2048   TopExp::Vertices(anEdge, V1, V2, Standard_True);
2049
2050   if (V1.IsNull() || V2.IsNull()) {
2051     SetErrorCode("Bad edge given for the plane normal vector");
2052     return NULL;
2053   }
2054   V3 = TopoDS::Vertex(anPnt);
2055
2056   if(V3.IsNull()) {
2057     SetErrorCode("Bad vertex given for the plane location");
2058       return NULL;
2059   }
2060   gp_Pnt aLoc = BRep_Tool::Pnt(V3);
2061   gp_Vec aVec(BRep_Tool::Pnt(V1),BRep_Tool::Pnt(V2));
2062
2063   if (aVec.Magnitude() < Precision::Confusion()) {
2064      SetErrorCode("Vector with null magnitude given");
2065     return NULL;
2066   }
2067   Handle(Geom_Surface) aPlane = new Geom_Plane(aLoc, aVec);
2068
2069   if ( aPlane.IsNull() )
2070     return NULL;
2071
2072   // Find objects
2073   TCollection_AsciiString anAsciiList;
2074   Handle(TColStd_HSequenceOfTransient) aSeq;
2075   aSeq = getShapesOnSurface( aPlane, theShape, aShapeType, theState, anAsciiList );
2076   if ( aSeq.IsNull() || aSeq->Length() == 0 )
2077     return NULL;
2078
2079   // Make a Python command
2080
2081   Handle(GEOM_Object) anObj = Handle(GEOM_Object)::DownCast( aSeq->Value( 1 ));
2082   Handle(GEOM_Function) aFunction = anObj->GetLastFunction();
2083
2084   GEOM::TPythonDump(aFunction) << "[" << anAsciiList.ToCString()
2085     << "] = geompy.GetShapesOnPlaneWithLocation(" << theShape << ", "
2086     << aShapeType << ", " << theAx1 << ", "<< thePnt <<", " << theState << ")";
2087
2088   SetErrorCode(OK);
2089   return aSeq;
2090 }
2091
2092 //=============================================================================
2093 /*!
2094  *  GetShapesOnCylinder
2095  */
2096 //=============================================================================
2097 Handle(TColStd_HSequenceOfTransient) GEOMImpl_IShapesOperations::GetShapesOnCylinder
2098                                           (const Handle(GEOM_Object)& theShape,
2099                                            const Standard_Integer     theShapeType,
2100                                            const Handle(GEOM_Object)& theAxis,
2101                                            const Standard_Real        theRadius,
2102                                            const GEOMAlgo_State       theState)
2103 {
2104   SetErrorCode(KO);
2105
2106   if (theShape.IsNull() || theAxis.IsNull()) return NULL;
2107
2108   TopoDS_Shape aShape = theShape->GetValue();
2109   TopoDS_Shape anAxis = theAxis->GetValue();
2110
2111   if (aShape.IsNull() || anAxis.IsNull()) return NULL;
2112
2113   TopAbs_ShapeEnum aShapeType = TopAbs_ShapeEnum(theShapeType);
2114   if ( !checkTypeShapesOn( aShapeType ))
2115     return NULL;
2116
2117   // Create a cylinder surface
2118   Handle(Geom_Surface) aCylinder = makeCylinder( anAxis, theRadius );
2119   if ( aCylinder.IsNull() )
2120     return NULL;
2121
2122   // Find objects
2123   TCollection_AsciiString anAsciiList;
2124   Handle(TColStd_HSequenceOfTransient) aSeq;
2125   aSeq = getShapesOnSurface( aCylinder, theShape, aShapeType, theState, anAsciiList );
2126   if ( aSeq.IsNull() || aSeq->Length() == 0 )
2127     return NULL;
2128
2129   // Make a Python command
2130
2131   Handle(GEOM_Object) anObj = Handle(GEOM_Object)::DownCast( aSeq->Value( 1 ));
2132   Handle(GEOM_Function) aFunction = anObj->GetLastFunction();
2133
2134   GEOM::TPythonDump(aFunction) << "[" << anAsciiList.ToCString()
2135     << "] = geompy.GetShapesOnCylinder(" << theShape << ", " << aShapeType
2136       << ", " << theAxis << ", " << theRadius << ", " << theState << ")";
2137
2138   SetErrorCode(OK);
2139   return aSeq;
2140 }
2141
2142 //=============================================================================
2143 /*!
2144  *  GetShapesOnSphere
2145  */
2146 //=============================================================================
2147 Handle(TColStd_HSequenceOfTransient) GEOMImpl_IShapesOperations::GetShapesOnSphere
2148                                           (const Handle(GEOM_Object)& theShape,
2149                                            const Standard_Integer     theShapeType,
2150                                            const Handle(GEOM_Object)& theCenter,
2151                                            const Standard_Real        theRadius,
2152                                            const GEOMAlgo_State       theState)
2153 {
2154   SetErrorCode(KO);
2155
2156   if (theShape.IsNull() || theCenter.IsNull()) return NULL;
2157
2158   TopoDS_Shape aShape  = theShape->GetValue();
2159   TopoDS_Shape aCenter = theCenter->GetValue();
2160
2161   if (aShape.IsNull() || aCenter.IsNull()) return NULL;
2162
2163   TopAbs_ShapeEnum aShapeType = TopAbs_ShapeEnum(theShapeType);
2164   if ( !checkTypeShapesOn( aShapeType ))
2165     return NULL;
2166
2167   // Center of the sphere
2168   if (aCenter.ShapeType() != TopAbs_VERTEX) return NULL;
2169   gp_Pnt aLoc = BRep_Tool::Pnt(TopoDS::Vertex(aCenter));
2170
2171   gp_Ax3 anAx3 (aLoc, gp::DZ());
2172   Handle(Geom_SphericalSurface) aSphere =
2173     new Geom_SphericalSurface(anAx3, theRadius);
2174
2175   // Find objects
2176   TCollection_AsciiString anAsciiList;
2177   Handle(TColStd_HSequenceOfTransient) aSeq;
2178   aSeq = getShapesOnSurface( aSphere, theShape, aShapeType, theState, anAsciiList );
2179   if ( aSeq.IsNull() || aSeq->Length() == 0 )
2180     return NULL;
2181
2182   // Make a Python command
2183
2184   Handle(GEOM_Object) anObj = Handle(GEOM_Object)::DownCast( aSeq->Value( 1 ));
2185   Handle(GEOM_Function) aFunction = anObj->GetLastFunction();
2186
2187   GEOM::TPythonDump(aFunction) << "[" << anAsciiList.ToCString()
2188     << "] = geompy.GetShapesOnSphere(" << theShape << ", " << aShapeType
2189       << ", " << theCenter << ", " << theRadius << ", " << theState << ")";
2190
2191   SetErrorCode(OK);
2192   return aSeq;
2193 }
2194
2195 //=============================================================================
2196 /*!
2197  *  GetShapesOnPlaneIDs
2198  */
2199 //=============================================================================
2200 Handle(TColStd_HSequenceOfInteger) GEOMImpl_IShapesOperations::GetShapesOnPlaneIDs
2201                                         (const Handle(GEOM_Object)& theShape,
2202                                          const Standard_Integer     theShapeType,
2203                                          const Handle(GEOM_Object)& theAx1,
2204                                          const GEOMAlgo_State       theState)
2205 {
2206   SetErrorCode(KO);
2207
2208   if (theShape.IsNull() || theAx1.IsNull()) return NULL;
2209
2210   TopoDS_Shape aShape = theShape->GetValue();
2211   TopoDS_Shape anAx1  = theAx1->GetValue();
2212
2213   if (aShape.IsNull() || anAx1.IsNull()) return NULL;
2214
2215   TopAbs_ShapeEnum aShapeType = TopAbs_ShapeEnum(theShapeType);
2216   if ( !checkTypeShapesOn( aShapeType ))
2217     return NULL;
2218
2219   // Create plane
2220   Handle(Geom_Surface) aPlane = makePlane( anAx1 );
2221   if ( aPlane.IsNull() )
2222     return NULL;
2223
2224   // Find object IDs
2225   Handle(TColStd_HSequenceOfInteger) aSeq;
2226   aSeq = getShapesOnSurfaceIDs( aPlane, aShape, aShapeType, theState );
2227
2228   // The GetShapesOnPlaneIDs() doesn't change object so no new function is required.
2229   Handle(GEOM_Function) aFunction = GEOM::GetCreatedLast(theShape,theAx1)->GetLastFunction();
2230
2231   // Make a Python command
2232   GEOM::TPythonDump(aFunction, /*append=*/true)
2233     << "listShapesOnPlane = geompy.GetShapesOnPlaneIDs"
2234     << "(" << theShape << "," << aShapeType << "," << theAx1 << "," << theState << ")";
2235
2236   SetErrorCode(OK);
2237   return aSeq;
2238 }
2239
2240 //=============================================================================
2241 /*!
2242  *  GetShapesOnPlaneWithLocationIDs
2243  */
2244 //=============================================================================
2245 Handle(TColStd_HSequenceOfInteger) GEOMImpl_IShapesOperations::GetShapesOnPlaneWithLocationIDs
2246                                         (const Handle(GEOM_Object)& theShape,
2247                                          const Standard_Integer     theShapeType,
2248                                          const Handle(GEOM_Object)& theAx1,
2249                                          const Handle(GEOM_Object)& thePnt,
2250                                          const GEOMAlgo_State       theState)
2251 {
2252   SetErrorCode(KO);
2253
2254   if (theShape.IsNull() || theAx1.IsNull() || thePnt.IsNull()) return NULL;
2255
2256   TopoDS_Shape aShape = theShape->GetValue();
2257   TopoDS_Shape anAx1  = theAx1->GetValue();
2258   TopoDS_Shape anPnt  = thePnt->GetValue();
2259
2260   if (aShape.IsNull() || anAx1.IsNull() || anPnt.IsNull()) return NULL;
2261
2262   TopAbs_ShapeEnum aShapeType = TopAbs_ShapeEnum(theShapeType);
2263   if ( !checkTypeShapesOn( aShapeType ))
2264     return NULL;
2265
2266   // Create plane
2267   if (anAx1.ShapeType() != TopAbs_EDGE || anPnt.ShapeType() != TopAbs_VERTEX) return NULL;
2268   TopoDS_Edge anEdge = TopoDS::Edge(anAx1);
2269   TopoDS_Vertex V1, V2, V3;
2270   TopExp::Vertices(anEdge, V1, V2, Standard_True);
2271   if (V1.IsNull() || V2.IsNull()) {
2272     SetErrorCode("Bad edge given for the plane normal vector");
2273     return NULL;
2274   }
2275   V3 = TopoDS::Vertex(anPnt);
2276   if(V3.IsNull()) {
2277     SetErrorCode("Bad vertex given for the plane location");
2278       return NULL;
2279   }
2280   gp_Pnt aLoc = BRep_Tool::Pnt(V3);
2281   gp_Vec aVec(BRep_Tool::Pnt(V1),BRep_Tool::Pnt(V2));
2282   if (aVec.Magnitude() < Precision::Confusion()) {
2283     SetErrorCode("Vector with null magnitude given");
2284     return NULL;
2285   }
2286
2287   Handle(Geom_Surface) aPlane = new Geom_Plane(aLoc, aVec);
2288   if ( aPlane.IsNull() )
2289     return NULL;
2290
2291   // Find object IDs
2292   Handle(TColStd_HSequenceOfInteger) aSeq;
2293   aSeq = getShapesOnSurfaceIDs( aPlane, aShape, aShapeType, theState );
2294
2295   // The GetShapesOnPlaneIDs() doesn't change object so no new function is required.
2296   Handle(GEOM_Function) aFunction = GEOM::GetCreatedLast(theShape,theAx1)->GetLastFunction();
2297
2298   // Make a Python command
2299   GEOM::TPythonDump(aFunction, /*append=*/true)
2300     << "listShapesOnPlane = geompy.GetShapesOnPlaneWithLocationIDs"
2301     << "(" << theShape << ", " << aShapeType << ", " << theAx1 << ", "<< thePnt << ", "  << theState << ")";
2302
2303   SetErrorCode(OK);
2304   return aSeq;
2305 }
2306
2307 //=============================================================================
2308 /*!
2309  *  GetShapesOnCylinderIDs
2310  */
2311 //=============================================================================
2312 Handle(TColStd_HSequenceOfInteger) GEOMImpl_IShapesOperations::GetShapesOnCylinderIDs
2313                                           (const Handle(GEOM_Object)& theShape,
2314                                            const Standard_Integer     theShapeType,
2315                                            const Handle(GEOM_Object)& theAxis,
2316                                            const Standard_Real        theRadius,
2317                                            const GEOMAlgo_State       theState)
2318 {
2319   SetErrorCode(KO);
2320
2321   if (theShape.IsNull() || theAxis.IsNull()) return NULL;
2322
2323   TopoDS_Shape aShape = theShape->GetValue();
2324   TopoDS_Shape anAxis = theAxis->GetValue();
2325
2326   if (aShape.IsNull() || anAxis.IsNull()) return NULL;
2327
2328   TopAbs_ShapeEnum aShapeType = TopAbs_ShapeEnum(theShapeType);
2329   if ( !checkTypeShapesOn( aShapeType ))
2330     return NULL;
2331
2332   // Create a cylinder surface
2333   Handle(Geom_Surface) aCylinder = makeCylinder( anAxis, theRadius );
2334   if ( aCylinder.IsNull() )
2335     return NULL;
2336
2337   // Find object IDs
2338   Handle(TColStd_HSequenceOfInteger) aSeq;
2339   aSeq = getShapesOnSurfaceIDs( aCylinder, aShape, aShapeType, theState );
2340
2341   // The GetShapesOnCylinder() doesn't change object so no new function is required.
2342   Handle(GEOM_Function) aFunction = GEOM::GetCreatedLast(theShape,theAxis)->GetLastFunction();
2343
2344   // Make a Python command
2345   GEOM::TPythonDump(aFunction, /*append=*/true)
2346     << "listShapesOnCylinder = geompy.GetShapesOnCylinderIDs"
2347     << "(" << theShape << ", " << aShapeType << ", " << theAxis << ", "
2348     << theRadius << ", " << theState << ")";
2349
2350   SetErrorCode(OK);
2351   return aSeq;
2352 }
2353
2354 //=============================================================================
2355 /*!
2356  *  GetShapesOnSphereIDs
2357  */
2358 //=============================================================================
2359 Handle(TColStd_HSequenceOfInteger) GEOMImpl_IShapesOperations::GetShapesOnSphereIDs
2360                                           (const Handle(GEOM_Object)& theShape,
2361                                            const Standard_Integer     theShapeType,
2362                                            const Handle(GEOM_Object)& theCenter,
2363                                            const Standard_Real        theRadius,
2364                                            const GEOMAlgo_State       theState)
2365 {
2366   SetErrorCode(KO);
2367
2368   if (theShape.IsNull() || theCenter.IsNull()) return NULL;
2369
2370   TopoDS_Shape aShape  = theShape->GetValue();
2371   TopoDS_Shape aCenter = theCenter->GetValue();
2372
2373   if (aShape.IsNull() || aCenter.IsNull()) return NULL;
2374
2375   TopAbs_ShapeEnum aShapeType = TopAbs_ShapeEnum(theShapeType);
2376   if ( !checkTypeShapesOn( aShapeType ))
2377     return NULL;
2378
2379   // Center of the sphere
2380   if (aCenter.ShapeType() != TopAbs_VERTEX) return NULL;
2381   gp_Pnt aLoc = BRep_Tool::Pnt(TopoDS::Vertex(aCenter));
2382
2383   gp_Ax3 anAx3 (aLoc, gp::DZ());
2384   Handle(Geom_SphericalSurface) aSphere =
2385     new Geom_SphericalSurface(anAx3, theRadius);
2386
2387   // Find object IDs
2388   Handle(TColStd_HSequenceOfInteger) aSeq;
2389   aSeq = getShapesOnSurfaceIDs( aSphere, aShape, aShapeType, theState );
2390
2391   // The GetShapesOnSphere() doesn't change object so no new function is required.
2392   Handle(GEOM_Function) aFunction = GEOM::GetCreatedLast(theShape,theCenter)->GetLastFunction();
2393
2394   // Make a Python command
2395   GEOM::TPythonDump(aFunction, /*append=*/true)
2396     << "listShapesOnCylinder = geompy.GetShapesOnCylinderIDs"
2397     << "(" << theShape << ", " << aShapeType << ", " << theCenter << ", "
2398     << theRadius << ", " << theState << ")";
2399
2400   SetErrorCode(OK);
2401   return aSeq;
2402 }
2403
2404 //=======================================================================
2405 //function : getShapesOnQuadrangleIDs
2406   /*!
2407    * \brief Find IDs of subshapes complying with given status about quadrangle
2408     * \param theShape - the shape to explore
2409     * \param theShapeType - type of subshape of theShape
2410     * \param theTopLeftPoint - top left quadrangle corner
2411     * \param theTopRigthPoint - top right quadrangle corner
2412     * \param theBottomLeftPoint - bottom left quadrangle corner
2413     * \param theBottomRigthPoint - bottom right quadrangle corner
2414     * \param theState - required state
2415     * \retval Handle(TColStd_HSequenceOfInteger) - IDs of found subshapes
2416    */
2417 //=======================================================================
2418 Handle(TColStd_HSequenceOfInteger)
2419   GEOMImpl_IShapesOperations::getShapesOnQuadrangleIDs (const Handle(GEOM_Object)& theShape,
2420                                                         const Standard_Integer     theShapeType,
2421                                                         const Handle(GEOM_Object)& theTopLeftPoint,
2422                                                         const Handle(GEOM_Object)& theTopRigthPoint,
2423                                                         const Handle(GEOM_Object)& theBottomLeftPoint,
2424                                                         const Handle(GEOM_Object)& theBottomRigthPoint,
2425                                                         const GEOMAlgo_State       theState)
2426 {
2427   SetErrorCode(KO);
2428
2429   if ( theShape.IsNull() ||
2430        theTopLeftPoint.IsNull() ||
2431        theTopRigthPoint.IsNull() ||
2432        theBottomLeftPoint.IsNull() ||
2433        theBottomRigthPoint.IsNull() )
2434     return NULL;
2435
2436   TopoDS_Shape aShape = theShape->GetValue();
2437   TopoDS_Shape aTL = theTopLeftPoint->GetValue();
2438   TopoDS_Shape aTR = theTopRigthPoint->GetValue();
2439   TopoDS_Shape aBL = theBottomLeftPoint->GetValue();
2440   TopoDS_Shape aBR = theBottomRigthPoint->GetValue();
2441
2442   if (aShape.IsNull() ||
2443       aTL.IsNull() ||
2444       aTR.IsNull() ||
2445       aBL.IsNull() ||
2446       aBR.IsNull() ||
2447       aTL.ShapeType() != TopAbs_VERTEX ||
2448       aTR.ShapeType() != TopAbs_VERTEX ||
2449       aBL.ShapeType() != TopAbs_VERTEX ||
2450       aBR.ShapeType() != TopAbs_VERTEX )
2451     return NULL;
2452
2453   TopAbs_ShapeEnum aShapeType = TopAbs_ShapeEnum(theShapeType);
2454   if ( !checkTypeShapesOn( aShapeType ))
2455     return NULL;
2456
2457   Handle(TColStd_HSequenceOfInteger) aSeqOfIDs;
2458
2459   // Check presence of triangulation, build if need
2460   if (!CheckTriangulation(aShape)) {
2461     SetErrorCode("Cannot build triangulation on the shape");
2462     return aSeqOfIDs;
2463   }
2464
2465   // Call algo
2466   gp_Pnt aPntTL = BRep_Tool::Pnt(TopoDS::Vertex(aTL));
2467   gp_Pnt aPntTR = BRep_Tool::Pnt(TopoDS::Vertex(aTR));
2468   gp_Pnt aPntBL = BRep_Tool::Pnt(TopoDS::Vertex(aBL));
2469   gp_Pnt aPntBR = BRep_Tool::Pnt(TopoDS::Vertex(aBR));
2470
2471   GEOMAlgo_FinderShapeOnQuad aFinder( aPntTL, aPntTR, aPntBL, aPntBR );
2472   Standard_Real aTol = 0.0001; // default value
2473
2474   aFinder.SetShape(aShape);
2475   aFinder.SetTolerance(aTol);
2476   //aFinder.SetSurface(theSurface);
2477   aFinder.SetShapeType(aShapeType);
2478   aFinder.SetState(theState);
2479
2480   // Sets the minimal number of inner points for the faces that do not have own
2481   // inner points at all (for e.g. rectangular planar faces have just 2 triangles).
2482   // Default value=3
2483   aFinder.SetNbPntsMin(3);
2484   // Sets the maximal number of inner points for edges or faces.
2485   // It is usefull for the cases when this number is very big (e.g =2000) to improve
2486   // the performance. If this value =0, all inner points will be taken into account.
2487   // Default value=0
2488   aFinder.SetNbPntsMax(100);
2489
2490   aFinder.Perform();
2491
2492   // Interprete results
2493   Standard_Integer iErr = aFinder.ErrorStatus();
2494   // the detailed description of error codes is in GEOMAlgo_FinderShapeOn1.cxx
2495   if (iErr) {
2496     MESSAGE(" iErr : " << iErr);
2497     TCollection_AsciiString aMsg (" iErr : ");
2498     aMsg += TCollection_AsciiString(iErr);
2499     SetErrorCode(aMsg);
2500     return aSeqOfIDs;
2501   }
2502   Standard_Integer iWrn = aFinder.WarningStatus();
2503   // the detailed description of warning codes is in GEOMAlgo_FinderShapeOn1.cxx
2504   if (iWrn) {
2505     MESSAGE(" *** iWrn : " << iWrn);
2506   }
2507
2508   const TopTools_ListOfShape& listSS = aFinder.Shapes(); // the result
2509
2510   if (listSS.Extent() < 1) {
2511     //SetErrorCode("Not a single sub-shape of the requested type found on the given surface");
2512     SetErrorCode(NOT_FOUND_ANY); // NPAL18017
2513     return aSeqOfIDs;
2514   }
2515
2516   // Fill sequence of object IDs
2517   aSeqOfIDs = new TColStd_HSequenceOfInteger;
2518
2519   TopTools_IndexedMapOfShape anIndices;
2520   TopExp::MapShapes(aShape, anIndices);
2521
2522   TopTools_ListIteratorOfListOfShape itSub (listSS);
2523   for (int index = 1; itSub.More(); itSub.Next(), ++index) {
2524     int id = anIndices.FindIndex(itSub.Value());
2525     aSeqOfIDs->Append(id);
2526   }
2527   return aSeqOfIDs;
2528 }
2529
2530 //=======================================================================
2531 //function : GetShapesOnQuadrangle
2532   /*!
2533    * \brief Find subshapes complying with given status about quadrangle
2534     * \param theShape - the shape to explore
2535     * \param theShapeType - type of subshape of theShape
2536     * \param theTopLeftPoint - top left quadrangle corner
2537     * \param theTopRigthPoint - top right quadrangle corner
2538     * \param theBottomLeftPoint - bottom left quadrangle corner
2539     * \param theBottomRigthPoint - bottom right quadrangle corner
2540     * \param theState - required state
2541     * \retval Handle(TColStd_HSequenceOfInteger) - IDs of found subshapes
2542    */
2543 //=======================================================================
2544 Handle(TColStd_HSequenceOfTransient)
2545     GEOMImpl_IShapesOperations::GetShapesOnQuadrangle (const Handle(GEOM_Object)& theShape,
2546                                                        const Standard_Integer     theShapeType,
2547                                                        const Handle(GEOM_Object)& theTopLeftPoint,
2548                                                        const Handle(GEOM_Object)& theTopRigthPoint,
2549                                                        const Handle(GEOM_Object)& theBottomLeftPoint,
2550                                                        const Handle(GEOM_Object)& theBottomRigthPoint,
2551                                                        const GEOMAlgo_State       theState)
2552 {
2553   // Find indices
2554   Handle(TColStd_HSequenceOfInteger) aSeqOfIDs =
2555     getShapesOnQuadrangleIDs( theShape,
2556                               theShapeType,
2557                               theTopLeftPoint,
2558                               theTopRigthPoint,
2559                               theBottomLeftPoint,
2560                               theBottomRigthPoint,
2561                               theState);
2562   if ( aSeqOfIDs.IsNull() || aSeqOfIDs->IsEmpty() )
2563     return NULL;
2564
2565   // Find objects by indices
2566   TCollection_AsciiString anAsciiList;
2567   Handle(TColStd_HSequenceOfTransient) aSeq;
2568   aSeq = getObjectsShapesOn( theShape, aSeqOfIDs, anAsciiList );
2569   if ( aSeq.IsNull() || aSeq->IsEmpty() )
2570     return NULL;
2571
2572   // Make a Python command
2573
2574   Handle(GEOM_Object) anObj = Handle(GEOM_Object)::DownCast( aSeq->Value( 1 ));
2575   Handle(GEOM_Function) aFunction = anObj->GetLastFunction();
2576
2577   GEOM::TPythonDump(aFunction)
2578     << "[" << anAsciiList.ToCString() << "] = geompy.GetShapesOnQuadrangle("
2579     << theShape << ", "
2580     << TopAbs_ShapeEnum(theShapeType) << ", "
2581     << theTopLeftPoint << ", "
2582     << theTopRigthPoint << ", "
2583     << theBottomLeftPoint << ", "
2584     << theBottomRigthPoint << ", "
2585     << theState << ")";
2586
2587   SetErrorCode(OK);
2588   return aSeq;
2589 }
2590
2591 //=======================================================================
2592 //function : GetShapesOnQuadrangleIDs
2593   /*!
2594    * \brief Find IDs of subshapes complying with given status about quadrangle
2595     * \param theShape - the shape to explore
2596     * \param theShapeType - type of subshape of theShape
2597     * \param theTopLeftPoint - top left quadrangle corner
2598     * \param theTopRigthPoint - top right quadrangle corner
2599     * \param theBottomLeftPoint - bottom left quadrangle corner
2600     * \param theBottomRigthPoint - bottom right quadrangle corner
2601     * \param theState - required state
2602     * \retval Handle(TColStd_HSequenceOfInteger) - IDs of found subshapes
2603    */
2604 //=======================================================================
2605 Handle(TColStd_HSequenceOfInteger)
2606   GEOMImpl_IShapesOperations::GetShapesOnQuadrangleIDs (const Handle(GEOM_Object)& theShape,
2607                                                         const Standard_Integer     theShapeType,
2608                                                         const Handle(GEOM_Object)& theTopLeftPoint,
2609                                                         const Handle(GEOM_Object)& theTopRigthPoint,
2610                                                         const Handle(GEOM_Object)& theBottomLeftPoint,
2611                                                         const Handle(GEOM_Object)& theBottomRigthPoint,
2612                                                         const GEOMAlgo_State       theState)
2613 {
2614   // Find indices
2615   Handle(TColStd_HSequenceOfInteger) aSeqOfIDs =
2616     getShapesOnQuadrangleIDs( theShape,
2617                               theShapeType,
2618                               theTopLeftPoint,
2619                               theTopRigthPoint,
2620                               theBottomLeftPoint,
2621                               theBottomRigthPoint,
2622                               theState);
2623   if ( aSeqOfIDs.IsNull() || aSeqOfIDs->IsEmpty() )
2624     return NULL;
2625
2626   // Make a Python command
2627
2628   // The GetShapesOnCylinder() doesn't change object so no new function is required.
2629   Handle(GEOM_Object) lastObj = GEOM::GetCreatedLast(theShape,theTopLeftPoint);
2630   lastObj = GEOM::GetCreatedLast(lastObj,theTopRigthPoint);
2631   lastObj = GEOM::GetCreatedLast(lastObj,theBottomRigthPoint);
2632   lastObj = GEOM::GetCreatedLast(lastObj,theBottomLeftPoint);
2633   Handle(GEOM_Function) aFunction = lastObj->GetLastFunction();
2634
2635   GEOM::TPythonDump(aFunction, /*append=*/true)
2636     << "listShapesOnQuadrangle = geompy.GetShapesOnQuadrangleIDs("
2637     << theShape << ", "
2638     << TopAbs_ShapeEnum(theShapeType) << ", "
2639     << theTopLeftPoint << ", "
2640     << theTopRigthPoint << ", "
2641     << theBottomLeftPoint << ", "
2642     << theBottomRigthPoint << ", "
2643     << theState << ")";
2644
2645   SetErrorCode(OK);
2646   return aSeqOfIDs;
2647 }
2648
2649 //=============================================================================
2650 /*!
2651  *  GetInPlaceOfShape
2652  */
2653 //=============================================================================
2654 static bool GetInPlaceOfShape (const Handle(GEOM_Function)& theWhereFunction,
2655                                const TopTools_IndexedMapOfShape& theWhereIndices,
2656                                const TopoDS_Shape& theWhat,
2657                                TColStd_ListOfInteger& theModifiedList)
2658 {
2659   if (theWhereFunction.IsNull() || theWhat.IsNull()) return false;
2660
2661   if (theWhereIndices.Contains(theWhat)) {
2662     // entity was not changed by the operation
2663     Standard_Integer aWhatIndex = theWhereIndices.FindIndex(theWhat);
2664     theModifiedList.Append(aWhatIndex);
2665     return true;
2666   }
2667
2668   // try to find in history
2669   TDF_Label aHistoryLabel = theWhereFunction->GetHistoryEntry(Standard_False);
2670
2671   // search in history for all argument shapes
2672   Standard_Boolean isFound = Standard_False;
2673   Standard_Boolean isGood = Standard_False;
2674
2675   TDF_LabelSequence aLabelSeq;
2676   theWhereFunction->GetDependency(aLabelSeq);
2677   Standard_Integer nbArg = aLabelSeq.Length();
2678
2679   for (Standard_Integer iarg = 1; iarg <= nbArg && !isFound; iarg++) {
2680
2681     TDF_Label anArgumentRefLabel = aLabelSeq.Value(iarg);
2682
2683     Handle(GEOM_Object) anArgumentObject = GEOM_Object::GetReferencedObject(anArgumentRefLabel);
2684     TopoDS_Shape anArgumentShape = anArgumentObject->GetValue();
2685
2686     TopTools_IndexedMapOfShape anArgumentIndices;
2687     TopExp::MapShapes(anArgumentShape, anArgumentIndices);
2688
2689     if (anArgumentIndices.Contains(theWhat)) {
2690       isFound = Standard_True;
2691       Standard_Integer aWhatIndex = anArgumentIndices.FindIndex(theWhat);
2692
2693       // Find corresponding label in history
2694       TDF_Label anArgumentHistoryLabel =
2695         theWhereFunction->GetArgumentHistoryEntry(anArgumentRefLabel, Standard_False);
2696       if (anArgumentHistoryLabel.IsNull()) {
2697         // Lost History of operation argument. Possibly, all its entities was removed.
2698         isGood = Standard_True;
2699       }
2700       else {
2701         TDF_Label aWhatHistoryLabel = anArgumentHistoryLabel.FindChild(aWhatIndex, Standard_False);
2702
2703         if (aWhatHistoryLabel.IsNull()) {
2704           // Removed entity ? Compound ? Compsolid ? Shell ? Wire
2705           isGood = Standard_False;
2706         } else {
2707           Handle(TDataStd_IntegerArray) anIntegerArray;
2708           if (!aWhatHistoryLabel.FindAttribute(TDataStd_IntegerArray::GetID(), anIntegerArray)) {
2709             //Error: Empty modifications history for the sought shape.
2710             isGood = Standard_False;
2711           }
2712           else {
2713             isGood = Standard_True;
2714             Standard_Integer imod, aModifLen = anIntegerArray->Array()->Length();
2715             for (imod = 1; imod <= aModifLen; imod++) {
2716               theModifiedList.Append(anIntegerArray->Array()->Value(imod));
2717             }
2718           }
2719         }
2720       }
2721     }
2722   }
2723
2724   isFound = isGood;
2725
2726   if (!isFound) {
2727     // try compound/compsolid/shell/wire element by element
2728     bool isFoundAny = false;
2729     TopTools_MapOfShape mapShape;
2730
2731     if (theWhat.ShapeType() == TopAbs_COMPOUND ||
2732         theWhat.ShapeType() == TopAbs_COMPSOLID) {
2733       // recursive processing of compound/compsolid
2734       TopoDS_Iterator anIt (theWhat, Standard_True, Standard_True);
2735       for (; anIt.More(); anIt.Next()) {
2736         if (mapShape.Add(anIt.Value())) {
2737           TopoDS_Shape curWhat = anIt.Value();
2738           isFoundAny = GetInPlaceOfShape(theWhereFunction, theWhereIndices, curWhat, theModifiedList);
2739           if (isFoundAny) isFound = Standard_True;
2740         }
2741       }
2742     }
2743     else if (theWhat.ShapeType() == TopAbs_SHELL) {
2744       // try to replace a shell by its faces images
2745       TopExp_Explorer anExp (theWhat, TopAbs_FACE);
2746       for (; anExp.More(); anExp.Next()) {
2747         if (mapShape.Add(anExp.Current())) {
2748           TopoDS_Shape curWhat = anExp.Current();
2749           isFoundAny = GetInPlaceOfShape(theWhereFunction, theWhereIndices, curWhat, theModifiedList);
2750           if (isFoundAny) isFound = Standard_True;
2751         }
2752       }
2753     }
2754     else if (theWhat.ShapeType() == TopAbs_WIRE) {
2755       // try to replace a wire by its edges images
2756       TopExp_Explorer anExp (theWhat, TopAbs_EDGE);
2757       for (; anExp.More(); anExp.Next()) {
2758         if (mapShape.Add(anExp.Current())) {
2759           TopoDS_Shape curWhat = anExp.Current();
2760           isFoundAny = GetInPlaceOfShape(theWhereFunction, theWhereIndices, curWhat, theModifiedList);
2761           if (isFoundAny) isFound = Standard_True;
2762         }
2763       }
2764     }
2765     else {
2766       // Removed entity
2767     }
2768   }
2769
2770   return isFound;
2771 }
2772
2773 //=============================================================================
2774 /*!
2775  *  GetShapeProperties
2776  */
2777 //=============================================================================
2778 void GEOMImpl_IShapesOperations::GetShapeProperties( const TopoDS_Shape aShape, Standard_Real tab[],
2779                                                      gp_Pnt & aVertex )
2780 {
2781   GProp_GProps theProps;
2782   gp_Pnt aCenterMass;
2783   TopoDS_Shape aPntShape;
2784   Standard_Real aShapeSize;
2785
2786   if      (aShape.ShapeType() == TopAbs_EDGE) BRepGProp::LinearProperties(aShape,  theProps);
2787   else if (aShape.ShapeType() == TopAbs_FACE) BRepGProp::SurfaceProperties(aShape, theProps);
2788   else                                        BRepGProp::VolumeProperties(aShape,  theProps);
2789
2790   aCenterMass = theProps.CentreOfMass();
2791   aShapeSize  = theProps.Mass();
2792
2793   aPntShape = BRepBuilderAPI_MakeVertex(aCenterMass).Shape();
2794   aVertex   = BRep_Tool::Pnt( TopoDS::Vertex( aPntShape ) );
2795   tab[0] = aVertex.X();
2796   tab[1] = aVertex.Y();
2797   tab[2] = aVertex.Z();
2798   tab[3] = aShapeSize;
2799   return;
2800 }
2801
2802 //=============================================================================
2803 /*!
2804  *  GetInPlace
2805  */
2806 //=============================================================================
2807 Handle(GEOM_Object) GEOMImpl_IShapesOperations::GetInPlace (Handle(GEOM_Object) theShapeWhere,
2808                                                             Handle(GEOM_Object) theShapeWhat)
2809 {
2810   SetErrorCode(KO);
2811
2812   if (theShapeWhere.IsNull() || theShapeWhat.IsNull()) return NULL;
2813
2814   TopoDS_Shape aWhere = theShapeWhere->GetValue();
2815   TopoDS_Shape aWhat  = theShapeWhat->GetValue();
2816   TopoDS_Shape aPntShape;
2817   TopoDS_Vertex aVertex;
2818
2819   if (aWhere.IsNull() || aWhat.IsNull()) {
2820     SetErrorCode("Error: aWhere and aWhat TopoDS_Shape are Null.");
2821     return NULL;
2822   }
2823
2824   Handle(GEOM_Function) aWhereFunction = theShapeWhere->GetLastFunction();
2825   if (aWhereFunction.IsNull()) {
2826     SetErrorCode("Error: aWhereFunction is Null.");
2827     return NULL;
2828   }
2829
2830   TopTools_IndexedMapOfShape aWhereIndices;
2831   TopExp::MapShapes(aWhere, aWhereIndices);
2832
2833   TColStd_ListOfInteger aModifiedList;
2834   Standard_Integer aWhereIndex;
2835   Handle(TColStd_HArray1OfInteger) aModifiedArray;
2836   Handle(GEOM_Object) aResult;
2837
2838   bool isFound = false;
2839   Standard_Integer iType = TopAbs_SOLID;
2840   Standard_Integer compType = TopAbs_SOLID;
2841   Standard_Real    aWhat_Mass = 0., aWhere_Mass = 0.;
2842   Standard_Real    tab_aWhat[4],    tab_aWhere[4];
2843   Standard_Real    dl_l = 1e-3;
2844   Standard_Real    min_l, Tol_1D, Tol_2D, Tol_3D, Tol_Mass;
2845   Standard_Real    aXmin, aYmin, aZmin, aXmax, aYmax, aZmax;
2846   Bnd_Box          BoundingBox;
2847   gp_Pnt           aPnt, aPnt_aWhat, tab_Pnt[2];
2848   GProp_GProps     aProps;
2849
2850   // Find the iType of the aWhat shape
2851   if      ( aWhat.ShapeType() == TopAbs_EDGE  || aWhat.ShapeType() == TopAbs_WIRE )      iType = TopAbs_EDGE;
2852   else if ( aWhat.ShapeType() == TopAbs_FACE  || aWhat.ShapeType() == TopAbs_SHELL )     iType = TopAbs_FACE;
2853   else if ( aWhat.ShapeType() == TopAbs_SOLID || aWhat.ShapeType() == TopAbs_COMPSOLID ) iType = TopAbs_SOLID;
2854   else if ( aWhat.ShapeType() == TopAbs_COMPOUND ) {
2855     // Only the iType of the first shape in the compound is taken into account
2856     TopoDS_Iterator It (aWhat, Standard_True, Standard_True);
2857     compType = It.Value().ShapeType();
2858     if      ( compType == TopAbs_EDGE  || compType == TopAbs_WIRE )     iType = TopAbs_EDGE;
2859     else if ( compType == TopAbs_FACE  || compType == TopAbs_SHELL)     iType = TopAbs_FACE;
2860     else if ( compType == TopAbs_SOLID || compType == TopAbs_COMPSOLID) iType = TopAbs_SOLID;
2861   }
2862   else {
2863     SetErrorCode("Error: An attempt to extract a shape of not supported type.");
2864     return NULL;
2865   }
2866
2867   TopExp_Explorer Exp_aWhat( aWhat,   TopAbs_ShapeEnum( iType ) );
2868   TopExp_Explorer Exp_aWhere( aWhere, TopAbs_ShapeEnum( iType ) );
2869   TopExp_Explorer Exp_Edge( aWhere,   TopAbs_EDGE );
2870
2871   // Find the shortest edge in theShapeWhere shape
2872   BRepBndLib::Add(aWhere, BoundingBox);
2873   BoundingBox.Get(aXmin, aYmin, aZmin, aXmax, aYmax, aZmax);
2874   min_l = fabs(aXmax - aXmin);
2875   if( min_l < fabs(aYmax - aYmin) ) min_l = fabs(aYmax - aYmin);
2876   if( min_l < fabs(aZmax - aZmin) ) min_l = fabs(aZmax - aZmin);
2877   min_l /= dl_l;
2878   for ( Standard_Integer nbEdge = 0; Exp_Edge.More(); Exp_Edge.Next(), nbEdge++ ) {
2879     TopExp_Explorer Exp_Vertex( Exp_Edge.Current(), TopAbs_VERTEX);
2880     for ( Standard_Integer nbVertex = 0; Exp_Vertex.More(); Exp_Vertex.Next(), nbVertex++ ) {
2881       aPnt = BRep_Tool::Pnt( TopoDS::Vertex( Exp_Vertex.Current() ) );
2882       tab_Pnt[nbVertex] = aPnt;
2883     }
2884     if ( ! tab_Pnt[0].IsEqual(tab_Pnt[1], dl_l) ) {
2885       BRepGProp::LinearProperties(Exp_Edge.Current(), aProps);
2886       if ( aProps.Mass() < min_l ) min_l = aProps.Mass();
2887     }
2888   }
2889
2890   // Compute tolerances
2891   Tol_1D = dl_l * min_l;
2892   Tol_2D = dl_l * ( min_l * min_l) * ( 2. + dl_l);
2893   Tol_3D = dl_l * ( min_l * min_l * min_l ) * ( 3. + (3 * dl_l) + (dl_l * dl_l) );
2894
2895   if (Tol_1D < Precision::Confusion()) Tol_1D = Precision::Confusion();
2896   if (Tol_2D < Precision::Confusion()) Tol_2D = Precision::Confusion();
2897   if (Tol_3D < Precision::Confusion()) Tol_3D = Precision::Confusion();
2898
2899   Tol_Mass = Tol_3D;
2900   if      ( iType == TopAbs_EDGE ) Tol_Mass = Tol_1D;
2901   else if ( iType == TopAbs_FACE ) Tol_Mass = Tol_2D;
2902
2903   // Compute the ShapeWhat Mass
2904   for ( ; Exp_aWhat.More(); Exp_aWhat.Next() ) {
2905     if      ( iType == TopAbs_EDGE ) BRepGProp::LinearProperties(Exp_aWhat.Current(),  aProps);
2906     else if ( iType == TopAbs_FACE ) BRepGProp::SurfaceProperties(Exp_aWhat.Current(), aProps);
2907     else                             BRepGProp::VolumeProperties(Exp_aWhat.Current(),  aProps);
2908     aWhat_Mass += aProps.Mass();
2909   }
2910
2911   // Searching for the sub-shapes inside the ShapeWhere shape
2912   TopTools_MapOfShape map_aWhere;
2913   for ( Exp_aWhere.ReInit(); Exp_aWhere.More(); Exp_aWhere.Next() ) {
2914     if (!map_aWhere.Add(Exp_aWhere.Current()))
2915       continue; // skip repeated shape to avoid mass addition
2916     GetShapeProperties( Exp_aWhere.Current(), tab_aWhere, aPnt );
2917     for ( Exp_aWhat.ReInit(); Exp_aWhat.More(); Exp_aWhat.Next() ) {
2918       GetShapeProperties( Exp_aWhat.Current(), tab_aWhat, aPnt_aWhat );
2919       if ( fabs(tab_aWhat[3] - tab_aWhere[3]) <= Tol_Mass && aPnt_aWhat.Distance(aPnt) <= Tol_1D )
2920         isFound = true;
2921       else {
2922         if ( (tab_aWhat[3] - tab_aWhere[3]) > Tol_Mass ) {
2923           aPntShape = BRepBuilderAPI_MakeVertex( aPnt ).Shape();
2924           aVertex   = TopoDS::Vertex( aPntShape );
2925           BRepExtrema_DistShapeShape aWhereDistance ( aVertex, Exp_aWhere.Current() );
2926           BRepExtrema_DistShapeShape aWhatDistance  ( aVertex, Exp_aWhat.Current() );
2927           if ( fabs(aWhereDistance.Value() - aWhatDistance.Value()) <= Tol_1D )
2928             isFound = true;
2929         }
2930       }
2931       if ( isFound ) {
2932         aWhereIndex = aWhereIndices.FindIndex(Exp_aWhere.Current());
2933         aModifiedList.Append(aWhereIndex);
2934         aWhere_Mass += tab_aWhere[3];
2935         isFound = false;
2936         break;
2937       }
2938     }
2939     if ( fabs( aWhat_Mass - aWhere_Mass ) <= Tol_Mass ) break;
2940   }
2941
2942   if (aModifiedList.Extent() == 0) { // Not found any Results
2943     SetErrorCode(NOT_FOUND_ANY);
2944     return NULL;
2945   }
2946
2947   aModifiedArray = new TColStd_HArray1OfInteger (1, aModifiedList.Extent());
2948   TColStd_ListIteratorOfListOfInteger anIterModif (aModifiedList);
2949   for (Standard_Integer imod = 1; anIterModif.More(); anIterModif.Next(), imod++)
2950     aModifiedArray->SetValue(imod, anIterModif.Value());
2951
2952   //Add a new object
2953   aResult = GetEngine()->AddSubShape(theShapeWhere, aModifiedArray);
2954   if (aResult.IsNull()) {
2955     SetErrorCode("Error in algorithm: result found, but cannot be returned.");
2956     return NULL;
2957   }
2958
2959   if (aModifiedArray->Length() > 1) {
2960     //Set a GROUP type
2961     aResult->SetType(GEOM_GROUP);
2962
2963     //Set a sub shape type
2964     TopoDS_Shape aFirstFound = aWhereIndices.FindKey(aModifiedArray->Value(1));
2965     TopAbs_ShapeEnum aShapeType = aFirstFound.ShapeType();
2966
2967     TDF_Label aFreeLabel = aResult->GetFreeLabel();
2968     TDataStd_Integer::Set(aFreeLabel, (Standard_Integer)aShapeType);
2969   }
2970
2971   //Make a Python command
2972   Handle(GEOM_Function) aFunction = aResult->GetFunction(1);
2973
2974   GEOM::TPythonDump(aFunction) << aResult << " = geompy.GetInPlace("
2975     << theShapeWhere << ", " << theShapeWhat << ")";
2976
2977   SetErrorCode(OK);
2978   return aResult;
2979 }
2980
2981 //=======================================================================
2982 //function : GetInPlaceByHistory
2983 //purpose  :
2984 //=======================================================================
2985 Handle(GEOM_Object) GEOMImpl_IShapesOperations::GetInPlaceByHistory
2986                                           (Handle(GEOM_Object) theShapeWhere,
2987                                            Handle(GEOM_Object) theShapeWhat)
2988 {
2989   SetErrorCode(KO);
2990
2991   if (theShapeWhere.IsNull() || theShapeWhat.IsNull()) return NULL;
2992
2993   TopoDS_Shape aWhere = theShapeWhere->GetValue();
2994   TopoDS_Shape aWhat  = theShapeWhat->GetValue();
2995
2996   if (aWhere.IsNull() || aWhat.IsNull()) return NULL;
2997
2998   Handle(GEOM_Function) aWhereFunction = theShapeWhere->GetLastFunction();
2999   if (aWhereFunction.IsNull()) return NULL;
3000
3001   //Fill array of indices
3002   TopTools_IndexedMapOfShape aWhereIndices;
3003   TopExp::MapShapes(aWhere, aWhereIndices);
3004
3005   // process shape
3006   TColStd_ListOfInteger aModifiedList;
3007   bool isFound = GetInPlaceOfShape(aWhereFunction, aWhereIndices, aWhat, aModifiedList);
3008
3009   if (!isFound || aModifiedList.Extent() < 1) {
3010     SetErrorCode("Error: No history found for the sought shape or its sub-shapes.");
3011     return NULL;
3012   }
3013
3014   Handle(TColStd_HArray1OfInteger) aModifiedArray =
3015     new TColStd_HArray1OfInteger (1, aModifiedList.Extent());
3016   TColStd_ListIteratorOfListOfInteger anIterModif (aModifiedList);
3017   for (Standard_Integer imod = 1; anIterModif.More(); anIterModif.Next(), imod++) {
3018     aModifiedArray->SetValue(imod, anIterModif.Value());
3019   }
3020
3021   //Add a new object
3022   Handle(GEOM_Object) aResult = GetEngine()->AddSubShape(theShapeWhere, aModifiedArray);
3023   if (aResult.IsNull()) {
3024     SetErrorCode("Error in algorithm: result found, but cannot be returned.");
3025     return NULL;
3026   }
3027
3028   if (aModifiedArray->Length() > 1) {
3029     //Set a GROUP type
3030     aResult->SetType(GEOM_GROUP);
3031
3032     //Set a sub shape type
3033     TopoDS_Shape aFirstFound = aWhereIndices.FindKey(aModifiedArray->Value(1));
3034     TopAbs_ShapeEnum aShapeType = aFirstFound.ShapeType();
3035
3036     TDF_Label aFreeLabel = aResult->GetFreeLabel();
3037     TDataStd_Integer::Set(aFreeLabel, (Standard_Integer)aShapeType);
3038   }
3039
3040   //Make a Python command
3041   Handle(GEOM_Function) aFunction = aResult->GetFunction(1);
3042
3043   GEOM::TPythonDump(aFunction) << aResult << " = geompy.GetInPlaceByHistory("
3044     << theShapeWhere << ", " << theShapeWhat << ")";
3045
3046   SetErrorCode(OK);
3047   return aResult;
3048 }
3049
3050 //=======================================================================
3051 //function : SortShapes
3052 //purpose  :
3053 //=======================================================================
3054 void GEOMImpl_IShapesOperations::SortShapes(TopTools_ListOfShape& SL)
3055 {
3056   Standard_Integer MaxShapes = SL.Extent();
3057   TopTools_Array1OfShape  aShapes (1,MaxShapes);
3058   TColStd_Array1OfInteger OrderInd(1,MaxShapes);
3059   TColStd_Array1OfReal    MidXYZ  (1,MaxShapes); //X,Y,Z;
3060   TColStd_Array1OfReal    Length  (1,MaxShapes); //X,Y,Z;
3061
3062   // Computing of CentreOfMass
3063   Standard_Integer Index;
3064   GProp_GProps GPr;
3065   gp_Pnt GPoint;
3066   TopTools_ListIteratorOfListOfShape it(SL);
3067   for (Index=1;  it.More();  Index++)
3068   {
3069     TopoDS_Shape S = it.Value();
3070     SL.Remove( it ); // == it.Next()
3071     aShapes(Index) = S;
3072     OrderInd.SetValue (Index, Index);
3073     if (S.ShapeType() == TopAbs_VERTEX)
3074     {
3075       GPoint = BRep_Tool::Pnt( TopoDS::Vertex( S ));
3076       Length.SetValue( Index, (Standard_Real) S.Orientation());
3077     }
3078     else
3079     {
3080       BRepGProp::LinearProperties (S, GPr);
3081       GPoint = GPr.CentreOfMass();
3082       Length.SetValue( Index, GPr.Mass() );
3083     }
3084     MidXYZ.SetValue(Index,
3085                     GPoint.X()*999 + GPoint.Y()*99 + GPoint.Z()*0.9);
3086     //cout << Index << " L: " << Length(Index) << "CG: " << MidXYZ(Index) << endl;
3087   }
3088
3089   // Sorting
3090   Standard_Integer aTemp;
3091   Standard_Boolean exchange, Sort = Standard_True;
3092   Standard_Real    tol = Precision::Confusion();
3093   while (Sort)
3094   {
3095     Sort = Standard_False;
3096     for (Index=1; Index < MaxShapes; Index++)
3097     {
3098       exchange = Standard_False;
3099       Standard_Real dMidXYZ = MidXYZ(OrderInd(Index)) - MidXYZ(OrderInd(Index+1));
3100       Standard_Real dLength = Length(OrderInd(Index)) - Length(OrderInd(Index+1));
3101       if ( dMidXYZ >= tol ) {
3102 //         cout << "MidXYZ: " << MidXYZ(OrderInd(Index))<< " > " <<MidXYZ(OrderInd(Index+1))
3103 //              << " d: " << dMidXYZ << endl;
3104         exchange = Standard_True;
3105       }
3106       else if ( Abs(dMidXYZ) < tol && dLength >= tol ) {
3107 //         cout << "Length: " << Length(OrderInd(Index))<< " > " <<Length(OrderInd(Index+1))
3108 //              << " d: " << dLength << endl;
3109         exchange = Standard_True;
3110       }
3111       else if ( Abs(dMidXYZ) < tol && Abs(dLength) < tol &&
3112                 aShapes(OrderInd(Index)).ShapeType() <= TopAbs_FACE) {
3113         // PAL17233
3114         // equal values possible on shapes such as two halves of a sphere and
3115         // a membrane inside the sphere
3116         Bnd_Box box1,box2;
3117         BRepBndLib::Add( aShapes( OrderInd(Index) ), box1 );
3118         if ( box1.IsVoid() ) continue;
3119         BRepBndLib::Add( aShapes( OrderInd(Index+1) ), box2 );
3120         Standard_Real dSquareExtent = box1.SquareExtent() - box2.SquareExtent();
3121         if ( dSquareExtent >= tol ) {
3122 //           cout << "SquareExtent: " << box1.SquareExtent()<<" > "<<box2.SquareExtent() << endl;
3123           exchange = Standard_True;
3124         }
3125         else if ( Abs(dSquareExtent) < tol ) {
3126           Standard_Real aXmin, aYmin, aZmin, aXmax, aYmax, aZmax, val1, val2;
3127           box1.Get(aXmin, aYmin, aZmin, aXmax, aYmax, aZmax);
3128           val1 = (aXmin+aXmax)*999 + (aYmin+aYmax)*99 + (aZmin+aZmax)*0.9;
3129           box2.Get(aXmin, aYmin, aZmin, aXmax, aYmax, aZmax);
3130           val2 = (aXmin+aXmax)*999 + (aYmin+aYmax)*99 + (aZmin+aZmax)*0.9;
3131           //exchange = val1 > val2;
3132           if ((val1 - val2) >= tol) {
3133             exchange = Standard_True;
3134           }
3135           //cout << "box: " << val1<<" > "<<val2 << endl;
3136         }
3137       }
3138
3139       if (exchange)
3140       {
3141 //         cout << "exchange " << Index << " & " << Index+1 << endl;
3142         aTemp = OrderInd(Index);
3143         OrderInd(Index) = OrderInd(Index+1);
3144         OrderInd(Index+1) = aTemp;
3145         Sort = Standard_True;
3146       }
3147     }
3148   }
3149
3150   for (Index=1; Index <= MaxShapes; Index++)
3151     SL.Append( aShapes( OrderInd(Index) ));
3152 }
3153
3154 //=======================================================================
3155 //function : CompsolidToCompound
3156 //purpose  :
3157 //=======================================================================
3158 TopoDS_Shape GEOMImpl_IShapesOperations::CompsolidToCompound (const TopoDS_Shape& theCompsolid)
3159 {
3160   if (theCompsolid.ShapeType() != TopAbs_COMPSOLID) {
3161     return theCompsolid;
3162   }
3163
3164   TopoDS_Compound aCompound;
3165   BRep_Builder B;
3166   B.MakeCompound(aCompound);
3167
3168   TopTools_MapOfShape mapShape;
3169   TopoDS_Iterator It (theCompsolid, Standard_True, Standard_True);
3170
3171   for (; It.More(); It.Next()) {
3172     TopoDS_Shape aShape_i = It.Value();
3173     if (mapShape.Add(aShape_i)) {
3174       B.Add(aCompound, aShape_i);
3175     }
3176   }
3177
3178   return aCompound;
3179 }
3180
3181 //=======================================================================
3182 //function : CheckTriangulation
3183 //purpose  :
3184 //=======================================================================
3185 bool GEOMImpl_IShapesOperations::CheckTriangulation (const TopoDS_Shape& aShape)
3186 {
3187   bool isTriangulation = true;
3188
3189   TopExp_Explorer exp (aShape, TopAbs_FACE);
3190   if (exp.More())
3191   {
3192     TopLoc_Location aTopLoc;
3193     Handle(Poly_Triangulation) aTRF;
3194     aTRF = BRep_Tool::Triangulation(TopoDS::Face(exp.Current()), aTopLoc);
3195     if (aTRF.IsNull()) {
3196       isTriangulation = false;
3197     }
3198   }
3199   else // no faces, try edges
3200   {
3201     TopExp_Explorer expe (aShape, TopAbs_EDGE);
3202     if (!expe.More()) {
3203       return false;
3204     }
3205     TopLoc_Location aLoc;
3206     Handle(Poly_Polygon3D) aPE = BRep_Tool::Polygon3D(TopoDS::Edge(expe.Current()), aLoc);
3207     if (aPE.IsNull()) {
3208       isTriangulation = false;
3209     }
3210   }
3211
3212   if (!isTriangulation) {
3213     // calculate deflection
3214     Standard_Real aDeviationCoefficient = 0.001;
3215
3216     Bnd_Box B;
3217     BRepBndLib::Add(aShape, B);
3218     Standard_Real aXmin, aYmin, aZmin, aXmax, aYmax, aZmax;
3219     B.Get(aXmin, aYmin, aZmin, aXmax, aYmax, aZmax);
3220
3221     Standard_Real dx = aXmax - aXmin, dy = aYmax - aYmin, dz = aZmax - aZmin;
3222     Standard_Real aDeflection = Max(Max(dx, dy), dz) * aDeviationCoefficient * 4;
3223     Standard_Real aHLRAngle = 0.349066;
3224
3225     BRepMesh_IncrementalMesh Inc (aShape, aDeflection, Standard_False, aHLRAngle);
3226   }
3227
3228   return true;
3229 }
3230
3231 #define MAX_TOLERANCE 1.e-7
3232
3233 //=======================================================================
3234 //function : isSameEdge
3235 //purpose  : Returns True if two edges coincide
3236 //=======================================================================
3237 static bool isSameEdge(const TopoDS_Edge& theEdge1, const TopoDS_Edge& theEdge2)
3238 {
3239   TopoDS_Vertex V11, V12, V21, V22;
3240   TopExp::Vertices(theEdge1, V11, V12);
3241   TopExp::Vertices(theEdge2, V21, V22);
3242   gp_Pnt P11 = BRep_Tool::Pnt(V11);
3243   gp_Pnt P12 = BRep_Tool::Pnt(V12);
3244   gp_Pnt P21 = BRep_Tool::Pnt(V21);
3245   gp_Pnt P22 = BRep_Tool::Pnt(V22);
3246   bool coincide = false;
3247
3248   //Check that ends of edges coincide
3249   if(P11.Distance(P21) <= MAX_TOLERANCE) {
3250     if(P12.Distance(P22) <= MAX_TOLERANCE) coincide =  true;
3251   }
3252   else if(P11.Distance(P22) <= MAX_TOLERANCE) {
3253     if(P12.Distance(P21) <= MAX_TOLERANCE) coincide = true;
3254   }
3255
3256   if(!coincide) return false;
3257
3258   if (BRep_Tool::Degenerated(theEdge1))
3259     if (BRep_Tool::Degenerated(theEdge2)) return true;
3260     else return false;
3261   else
3262     if (BRep_Tool::Degenerated(theEdge2)) return false;
3263
3264   double U11, U12, U21, U22;
3265   Handle(Geom_Curve) C1 = BRep_Tool::Curve(theEdge1, U11, U12);
3266   Handle(Geom_Curve) C2 = BRep_Tool::Curve(theEdge2, U21, U22);
3267   if(C1->DynamicType() == C2->DynamicType()) return true;
3268
3269   //Check that both edges has the same geometry
3270   double range = U12-U11;
3271   double U = U11+ range/3.0;
3272   gp_Pnt P1 = C1->Value(U);     //Compute a point on one third of the edge's length
3273   U = U11+range*2.0/3.0;
3274   gp_Pnt P2 = C1->Value(U);     //Compute a point on two thirds of the edge's length
3275
3276   if(!GeomLib_Tool::Parameter(C2, P1, MAX_TOLERANCE, U) ||  U < U21 || U > U22)
3277     return false;
3278
3279   if(P1.Distance(C2->Value(U)) > MAX_TOLERANCE) return false;
3280
3281   if(!GeomLib_Tool::Parameter(C2, P2, MAX_TOLERANCE, U) || U < U21 || U > U22)
3282     return false;
3283
3284   if(P2.Distance(C2->Value(U)) > MAX_TOLERANCE) return false;
3285
3286   return true;
3287 }
3288
3289 #include <TopoDS_TShape.hxx>
3290 //=======================================================================
3291 //function : isSameFace
3292 //purpose  : Returns True if two faces coincide
3293 //=======================================================================
3294 static bool isSameFace(const TopoDS_Face& theFace1, const TopoDS_Face& theFace2)
3295 {
3296   TopExp_Explorer E(theFace1, TopAbs_EDGE);
3297   TopTools_ListOfShape LS1, LS2;
3298   for(; E.More(); E.Next()) LS1.Append(E.Current());
3299
3300   E.Init(theFace2, TopAbs_EDGE);
3301   for(; E.More(); E.Next()) LS2.Append(E.Current());
3302
3303   //Compare the number of edges in the faces
3304   if(LS1.Extent() != LS2.Extent()) return false;
3305
3306   double aMin = RealFirst(), aMax = RealLast();
3307   double xminB1=aMax, yminB1=aMax, zminB1=aMax, xminB2=aMax, yminB2=aMax, zminB2=aMax;
3308   double xmaxB1=aMin, ymaxB1=aMin, zmaxB1=aMin, xmaxB2=aMin, ymaxB2=aMin, zmaxB2=aMin;
3309
3310   for(E.Init(theFace1, TopAbs_VERTEX); E.More(); E.Next()) {
3311     gp_Pnt P = BRep_Tool::Pnt(TopoDS::Vertex(E.Current()));
3312     if(P.X() < xminB1) xminB1 = P.X();
3313     if(P.Y() < yminB1) yminB1 = P.Y();
3314     if(P.Z() < zminB1) zminB1 = P.Z();
3315     if(P.X() > xmaxB1) xmaxB1 = P.X();
3316     if(P.Y() > ymaxB1) ymaxB1 = P.Y();
3317     if(P.Z() > zmaxB1) zmaxB1 = P.Z();
3318   }
3319
3320   for(E.Init(theFace2, TopAbs_VERTEX); E.More(); E.Next()) {
3321     gp_Pnt P = BRep_Tool::Pnt(TopoDS::Vertex(E.Current()));
3322     if(P.X() < xminB2) xminB2 = P.X();
3323     if(P.Y() < yminB2) yminB2 = P.Y();
3324     if(P.Z() < zminB2) zminB2 = P.Z();
3325     if(P.X() > xmaxB2) xmaxB2 = P.X();
3326     if(P.Y() > ymaxB2) ymaxB2 = P.Y();
3327     if(P.Z() > zmaxB2) zmaxB2 = P.Z();
3328   }
3329
3330   //Compare the bounding boxes of both faces
3331   if(gp_Pnt(xminB1, yminB1, zminB1).Distance(gp_Pnt(xminB2, yminB2, zminB2)) > MAX_TOLERANCE)
3332     return false;
3333
3334   if(gp_Pnt(xmaxB1, ymaxB1, zmaxB1).Distance(gp_Pnt(xmaxB2, ymaxB2, zmaxB2)) > MAX_TOLERANCE)
3335     return false;
3336
3337   Handle(Geom_Surface) S1 = BRep_Tool::Surface(theFace1);
3338   Handle(Geom_Surface) S2 = BRep_Tool::Surface(theFace2);
3339
3340   //Check if there a coincidence of two surfaces at least in two points
3341   double U11, U12, V11, V12, U21, U22, V21, V22;
3342   BRepTools::UVBounds(theFace1, U11, U12, V11, V12);
3343   BRepTools::UVBounds(theFace2, U21, U22, V21, V22);
3344
3345   double rangeU = U12-U11;
3346   double rangeV = V12-V11;
3347   double U = U11 + rangeU/3.0;
3348   double V = V11 + rangeV/3.0;
3349   gp_Pnt P1 = S1->Value(U, V);
3350   U = U11+rangeU*2.0/3.0;
3351   V = V11+rangeV*2.0/3.0;
3352   gp_Pnt P2 = S1->Value(U, V);
3353
3354   if (!GeomLib_Tool::Parameters(S2, P1, MAX_TOLERANCE, U, V) || U < U21 || U > U22 || V < V21 || V > V22)
3355     return false;
3356
3357   if (P1.Distance(S2->Value(U,V)) > MAX_TOLERANCE) return false;
3358
3359   if (!GeomLib_Tool::Parameters(S2, P2, MAX_TOLERANCE, U, V) || U < U21 || U > U22 || V < V21 || V > V22)
3360     return false;
3361
3362   if (P2.Distance(S2->Value(U, V)) > MAX_TOLERANCE) return false;
3363
3364   //Check that each edge of the Face1 has a counterpart in the Face2
3365   TopTools_MapOfOrientedShape aMap;
3366   TopTools_ListIteratorOfListOfShape LSI1(LS1);
3367   for(; LSI1.More(); LSI1.Next()) {
3368     TopoDS_Edge E = TopoDS::Edge(LSI1.Value());
3369     bool isFound = false;
3370     TopTools_ListIteratorOfListOfShape LSI2(LS2);
3371     for(; LSI2.More(); LSI2.Next()) {
3372       TopoDS_Shape aValue = LSI2.Value();
3373       if(aMap.Contains(aValue)) continue; //To avoid checking already found edge several times
3374       if(isSameEdge(E, TopoDS::Edge(aValue))) {
3375         aMap.Add(aValue);
3376         isFound = true;
3377         break;
3378       }
3379     }
3380     if(!isFound) return false;
3381   }
3382
3383   return true;
3384 }
3385
3386 //=======================================================================
3387 //function : isSameSolid
3388 //purpose  : Returns True if two solids coincide
3389 //=======================================================================
3390 bool isSameSolid(const TopoDS_Solid& theSolid1, const TopoDS_Solid& theSolid2)
3391 {
3392   TopExp_Explorer E(theSolid1, TopAbs_FACE);
3393   TopTools_ListOfShape LS1, LS2;
3394   for(; E.More(); E.Next()) LS1.Append(E.Current());
3395   E.Init(theSolid2, TopAbs_FACE);
3396   for(; E.More(); E.Next()) LS2.Append(E.Current());
3397
3398   if(LS1.Extent() != LS2.Extent()) return false;
3399
3400   double aMin = RealFirst(), aMax = RealLast();
3401   double xminB1=aMax, yminB1=aMax, zminB1=aMax, xminB2=aMax, yminB2=aMax, zminB2=aMax;
3402   double xmaxB1=aMin, ymaxB1=aMin, zmaxB1=aMin, xmaxB2=aMin, ymaxB2=aMin, zmaxB2=aMin;
3403
3404   for(E.Init(theSolid1, TopAbs_VERTEX); E.More(); E.Next()) {
3405     gp_Pnt P = BRep_Tool::Pnt(TopoDS::Vertex(E.Current()));
3406     if(P.X() < xminB1) xminB1 = P.X();
3407     if(P.Y() < yminB1) yminB1 = P.Y();
3408     if(P.Z() < zminB1) zminB1 = P.Z();
3409     if(P.X() > xmaxB1) xmaxB1 = P.X();
3410     if(P.Y() > ymaxB1) ymaxB1 = P.Y();
3411     if(P.Z() > zmaxB1) zmaxB1 = P.Z();
3412   }
3413
3414   for(E.Init(theSolid2, TopAbs_VERTEX); E.More(); E.Next()) {
3415     gp_Pnt P = BRep_Tool::Pnt(TopoDS::Vertex(E.Current()));
3416     if(P.X() < xminB2) xminB2 = P.X();
3417     if(P.Y() < yminB2) yminB2 = P.Y();
3418     if(P.Z() < zminB2) zminB2 = P.Z();
3419     if(P.X() > xmaxB2) xmaxB2 = P.X();
3420     if(P.Y() > ymaxB2) ymaxB2 = P.Y();
3421     if(P.Z() > zmaxB2) zmaxB2 = P.Z();
3422   }
3423
3424   //Compare the bounding boxes of both solids
3425   if(gp_Pnt(xminB1, yminB1, zminB1).Distance(gp_Pnt(xminB2, yminB2, zminB2)) > MAX_TOLERANCE)
3426     return false;
3427
3428   if(gp_Pnt(xmaxB1, ymaxB1, zmaxB1).Distance(gp_Pnt(xmaxB2, ymaxB2, zmaxB2)) > MAX_TOLERANCE)
3429     return false;
3430
3431   //Check that each face of the Solid1 has a counterpart in the Solid2
3432   TopTools_MapOfOrientedShape aMap;
3433   TopTools_ListIteratorOfListOfShape LSI1(LS1);
3434   for(; LSI1.More(); LSI1.Next()) {
3435     TopoDS_Face F = TopoDS::Face(LSI1.Value());
3436     bool isFound = false;
3437     TopTools_ListIteratorOfListOfShape LSI2(LS2);
3438     for(; LSI2.More(); LSI2.Next()) {
3439       if(aMap.Contains(LSI2.Value())) continue; //To avoid checking already found faces several times
3440       if(isSameFace(F, TopoDS::Face(LSI2.Value()))) {
3441         aMap.Add(LSI2.Value());
3442         isFound = true;
3443         break;
3444       }
3445     }
3446     if(!isFound) return false;
3447   }
3448
3449   return true;
3450 }
3451
3452 //=======================================================================
3453 //function : GetSame
3454 //purpose  :
3455 //=======================================================================
3456 Handle(GEOM_Object) GEOMImpl_IShapesOperations::GetSame(const Handle(GEOM_Object)& theShapeWhere,
3457                                                         const Handle(GEOM_Object)& theShapeWhat)
3458 {
3459   SetErrorCode(KO);
3460   if (theShapeWhere.IsNull() || theShapeWhat.IsNull()) return NULL;
3461
3462   TopoDS_Shape aWhere = theShapeWhere->GetValue();
3463   TopoDS_Shape aWhat  = theShapeWhat->GetValue();
3464
3465   if (aWhere.IsNull() || aWhat.IsNull()) return NULL;
3466
3467   int anIndex = -1;
3468   bool isFound = false;
3469   TopoDS_Shape aSubShape;
3470   TopTools_MapOfShape aMap;
3471
3472   switch(aWhat.ShapeType()) {
3473     case TopAbs_VERTEX: {
3474       gp_Pnt P = BRep_Tool::Pnt(TopoDS::Vertex(aWhat));
3475       TopExp_Explorer E(aWhere, TopAbs_VERTEX);
3476       for(; E.More(); E.Next()) {
3477         if(!aMap.Add(E.Current())) continue;
3478         gp_Pnt P2 = BRep_Tool::Pnt(TopoDS::Vertex(E.Current()));
3479         if(P.Distance(P2) <= MAX_TOLERANCE) {
3480           isFound = true;
3481           aSubShape = E.Current();
3482           break;
3483         }
3484       }
3485       break;
3486                         }
3487     case TopAbs_FACE: {
3488       TopoDS_Face aFace = TopoDS::Face(aWhat);
3489       TopExp_Explorer E(aWhere, TopAbs_FACE);
3490       for(; E.More(); E.Next()) {
3491         if(!aMap.Add(E.Current())) continue;
3492         if(isSameFace(aFace, TopoDS::Face(E.Current()))) {
3493           aSubShape = E.Current();
3494           isFound = true;
3495           break;
3496         }
3497       }
3498       break;
3499                       }
3500     case TopAbs_EDGE: {
3501       TopoDS_Edge anEdge = TopoDS::Edge(aWhat);
3502       TopExp_Explorer E(aWhere, TopAbs_EDGE);
3503       for(; E.More(); E.Next()) {
3504         if(!aMap.Add(E.Current())) continue;
3505         if(isSameEdge(anEdge, TopoDS::Edge(E.Current()))) {
3506           aSubShape = E.Current();
3507           isFound = true;
3508           break;
3509         }
3510       }
3511       break;
3512                       }
3513     case TopAbs_SOLID: {
3514       TopoDS_Solid aSolid = TopoDS::Solid(aWhat);
3515       TopExp_Explorer E(aWhere, TopAbs_SOLID);
3516       for(; E.More(); E.Next()) {
3517         if(!aMap.Add(E.Current())) continue;
3518         if(isSameSolid(aSolid, TopoDS::Solid(E.Current()))) {
3519           aSubShape = E.Current();
3520           isFound = true;
3521           break;
3522         }
3523       }
3524       break;
3525                        }
3526     default:
3527       return NULL;
3528   }
3529
3530   if(isFound) {
3531     TopTools_IndexedMapOfShape anIndices;
3532     TopExp::MapShapes(aWhere, anIndices);
3533     if (anIndices.Contains(aSubShape))
3534       anIndex = anIndices.FindIndex(aSubShape);
3535   }
3536
3537   if(anIndex < 0) return NULL;
3538
3539   Handle(TColStd_HArray1OfInteger) anArray = new TColStd_HArray1OfInteger(1,1);
3540
3541   anArray->SetValue(1, anIndex);
3542
3543   Handle(GEOM_Object) aResult = GetEngine()->AddSubShape(theShapeWhere, anArray);
3544   Handle(GEOM_Function) aFunction = aResult->GetLastFunction();
3545
3546   GEOM::TPythonDump(aFunction) << aResult << " = geompy.GetSame("
3547     << theShapeWhere << ", " << theShapeWhat << ")";
3548
3549   SetErrorCode(OK);
3550
3551   return aResult;
3552 }