]> SALOME platform Git repositories - modules/geom.git/blob - src/GEOMImpl/GEOMImpl_IShapesOperations.cxx
Salome HOME
0022747: [EDF] Improvement of Get Shared Shapes operation
[modules/geom.git] / src / GEOMImpl / GEOMImpl_IShapesOperations.cxx
1 // Copyright (C) 2007-2014  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, or (at your option) any later version.
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
23 //  File      : GEOMImpl_IShapesOperations.cxx
24 //  Created   :
25 //  Author    : modified by Lioka RAZAFINDRAZAKA (CEA) 22/06/2007
26 //  Project   : SALOME
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_GlueDriver.hxx"
37
38 #include "GEOMImpl_IVector.hxx"
39 #include "GEOMImpl_IShapes.hxx"
40 #include "GEOMImpl_IGlue.hxx"
41
42 #include "GEOMImpl_Block6Explorer.hxx"
43 #include "GEOMImpl_IHealingOperations.hxx"
44
45 #include "GEOMImpl_Gen.hxx"
46
47 #include "GEOM_Function.hxx"
48 #include "GEOM_ISubShape.hxx"
49 #include "GEOM_PythonDump.hxx"
50
51 #include "GEOMUtils.hxx"
52
53 #include "GEOMAlgo_ClsfBox.hxx"
54 #include "GEOMAlgo_ClsfSolid.hxx"
55 #include "GEOMAlgo_CoupleOfShapes.hxx"
56 #include "GEOMAlgo_FinderShapeOn1.hxx"
57 #include "GEOMAlgo_FinderShapeOnQuad.hxx"
58 #include "GEOMAlgo_FinderShapeOn2.hxx"
59 #include "GEOMAlgo_GetInPlace.hxx"
60 #include "GEOMAlgo_GlueDetector.hxx"
61 #include "GEOMAlgo_ListIteratorOfListOfCoupleOfShapes.hxx"
62 #include "GEOMAlgo_ListOfCoupleOfShapes.hxx"
63
64 #include <Basics_OCCTVersion.hxx>
65
66 #include <utilities.h>
67 #include <OpUtil.hxx>
68 #include <Utils_ExceptHandlers.hxx>
69
70 #include <BRepAdaptor_Curve.hxx>
71 #include <BRepAdaptor_Surface.hxx>
72 #include <BRepBndLib.hxx>
73 #include <BRepBuilderAPI_MakeVertex.hxx>
74 #include <BRepClass3d_SolidClassifier.hxx>
75 #include <BRepClass_FaceClassifier.hxx>
76 #include <BRepExtrema_DistShapeShape.hxx>
77 #include <BRepExtrema_ExtCF.hxx>
78 #include <BRepGProp.hxx>
79 #include <BRepMesh_IncrementalMesh.hxx>
80 #include <BRepTools.hxx>
81 #include <BRep_Builder.hxx>
82 #include <BRep_Tool.hxx>
83 #include <Bnd_Box.hxx>
84 #include <GEOMImpl_IMeasure.hxx>
85 #include <GEOMImpl_MeasureDriver.hxx>
86 #include <GProp_GProps.hxx>
87 #include <Geom2d_Curve.hxx>
88 #include <GeomAdaptor_Surface.hxx>
89 #include <GeomLib_Tool.hxx>
90 #include <Geom_CylindricalSurface.hxx>
91 #include <Geom_Plane.hxx>
92 #include <Geom_SphericalSurface.hxx>
93 #include <Geom_Surface.hxx>
94 #include <Precision.hxx>
95 #include <TColStd_Array1OfReal.hxx>
96 #include <TColStd_HArray1OfInteger.hxx>
97 #include <TColStd_ListIteratorOfListOfInteger.hxx>
98 #include <TColStd_ListOfInteger.hxx>
99 #include <TDF_Tool.hxx>
100 #include <TDataStd_Integer.hxx>
101 #include <TDataStd_IntegerArray.hxx>
102 #include <TDataStd_ListIteratorOfListOfExtendedString.hxx>
103 #include <TFunction_Driver.hxx>
104 #include <TFunction_DriverTable.hxx>
105 #include <TFunction_Logbook.hxx>
106 #include <TopAbs.hxx>
107 #include <TopExp.hxx>
108 #include <TopExp_Explorer.hxx>
109 #include <TopLoc_Location.hxx>
110 #include <TopTools_Array1OfShape.hxx>
111 #include <TopTools_DataMapIteratorOfDataMapOfShapeListOfShape.hxx>
112 #include <TopTools_IndexedMapOfShape.hxx>
113 #include <TopTools_ListIteratorOfListOfShape.hxx>
114 #include <TopTools_MapOfOrientedShape.hxx>
115 #include <TopTools_MapOfShape.hxx>
116 #include <TopTools_SequenceOfShape.hxx>
117 #include <TopoDS.hxx>
118 #include <TopoDS_Compound.hxx>
119 #include <TopoDS_Edge.hxx>
120 #include <TopoDS_Face.hxx>
121 #include <TopoDS_Iterator.hxx>
122 #include <TopoDS_Shape.hxx>
123 #include <TopoDS_Solid.hxx>
124 #include <TopoDS_Vertex.hxx>
125 #include <gp_Cylinder.hxx>
126 #include <gp_Lin.hxx>
127 #include <gp_Pnt.hxx>
128
129 #include <vector>
130 #include <algorithm>
131 #include <functional>
132
133 #include <Standard_NullObject.hxx>
134 #include <Standard_Failure.hxx>
135 #include <Standard_ErrorHandler.hxx> // CAREFUL ! position of this file is critic : see Lucien PIGNOLONI / OCC
136
137
138 //=============================================================================
139 /*!
140  *   constructor:
141  */
142 //=============================================================================
143 GEOMImpl_IShapesOperations::GEOMImpl_IShapesOperations (GEOM_Engine* theEngine, int theDocID)
144 : GEOM_IOperations(theEngine, theDocID)
145 {
146   MESSAGE("GEOMImpl_IShapesOperations::GEOMImpl_IShapesOperations");
147 }
148
149 //=============================================================================
150 /*!
151  *  destructor
152  */
153 //=============================================================================
154 GEOMImpl_IShapesOperations::~GEOMImpl_IShapesOperations()
155 {
156   MESSAGE("GEOMImpl_IShapesOperations::~GEOMImpl_IShapesOperations");
157 }
158
159 //=============================================================================
160 /*!
161  *  MakeEdge
162  */
163 //=============================================================================
164 Handle(GEOM_Object) GEOMImpl_IShapesOperations::MakeEdge
165                      (Handle(GEOM_Object) thePnt1, Handle(GEOM_Object) thePnt2)
166 {
167   SetErrorCode(KO);
168
169   if (thePnt1.IsNull() || thePnt2.IsNull()) return NULL;
170
171   //Add a new Edge object
172   Handle(GEOM_Object) anEdge = GetEngine()->AddObject(GetDocID(), GEOM_EDGE);
173
174   //Add a new Vector function
175   Handle(GEOM_Function) aFunction =
176     anEdge->AddFunction(GEOMImpl_VectorDriver::GetID(), VECTOR_TWO_PNT);
177
178   //Check if the function is set correctly
179   if (aFunction->GetDriverGUID() != GEOMImpl_VectorDriver::GetID()) return NULL;
180
181   GEOMImpl_IVector aPI (aFunction);
182
183   Handle(GEOM_Function) aRef1 = thePnt1->GetLastFunction();
184   Handle(GEOM_Function) aRef2 = thePnt2->GetLastFunction();
185   if (aRef1.IsNull() || aRef2.IsNull()) return NULL;
186
187   aPI.SetPoint1(aRef1);
188   aPI.SetPoint2(aRef2);
189
190   //Compute the Edge value
191   try {
192     OCC_CATCH_SIGNALS;
193     if (!GetSolver()->ComputeFunction(aFunction)) {
194       SetErrorCode("Vector driver failed");
195       return NULL;
196     }
197   }
198   catch (Standard_Failure) {
199     Handle(Standard_Failure) aFail = Standard_Failure::Caught();
200     SetErrorCode(aFail->GetMessageString());
201     return NULL;
202   }
203
204   //Make a Python command
205   GEOM::TPythonDump(aFunction) << anEdge << " = geompy.MakeEdge("
206                                << thePnt1 << ", " << thePnt2 << ")";
207
208   SetErrorCode(OK);
209   return anEdge;
210 }
211
212 //=============================================================================
213 /*!
214  *  MakeEdgeOnCurveByLength
215  */
216 //=============================================================================
217 Handle(GEOM_Object) GEOMImpl_IShapesOperations::MakeEdgeOnCurveByLength
218                      (Handle(GEOM_Object) theRefCurve,
219                       const Standard_Real theLength,
220                       Handle(GEOM_Object) theStartPoint)
221 {
222   SetErrorCode(KO);
223
224   if (theRefCurve.IsNull()) return NULL;
225
226   //Add a new Edge object
227   Handle(GEOM_Object) anEdge = GetEngine()->AddObject(GetDocID(), GEOM_EDGE);
228
229   //Add a new Vector function
230   Handle(GEOM_Function) aFunction =
231     anEdge->AddFunction(GEOMImpl_ShapeDriver::GetID(), EDGE_CURVE_LENGTH);
232
233   //Check if the function is set correctly
234   if (aFunction->GetDriverGUID() != GEOMImpl_ShapeDriver::GetID()) return NULL;
235
236   GEOMImpl_IVector aPI (aFunction);
237
238   Handle(GEOM_Function) aRef1 = theRefCurve->GetLastFunction();
239   if (aRef1.IsNull()) return NULL;
240   aPI.SetPoint1(aRef1);
241
242   if (!theStartPoint.IsNull()) {
243     Handle(GEOM_Function) aRef2 = theStartPoint->GetLastFunction();
244     aPI.SetPoint2(aRef2);
245   }
246
247   aPI.SetParameter(theLength);
248
249   //Compute the Edge value
250   try {
251     OCC_CATCH_SIGNALS;
252     if (!GetSolver()->ComputeFunction(aFunction)) {
253       SetErrorCode("Vector driver failed");
254       return NULL;
255     }
256   }
257   catch (Standard_Failure) {
258     Handle(Standard_Failure) aFail = Standard_Failure::Caught();
259     SetErrorCode(aFail->GetMessageString());
260     return NULL;
261   }
262
263   //Make a Python command
264   GEOM::TPythonDump(aFunction) << anEdge << " = geompy.MakeEdgeOnCurveByLength("
265                                << theRefCurve << ", " << theLength << ", " << theStartPoint << ")";
266
267   SetErrorCode(OK);
268   return anEdge;
269 }
270
271 //=============================================================================
272 /*!
273  *  MakeEdgeWire
274  */
275 //=============================================================================
276 Handle(GEOM_Object) GEOMImpl_IShapesOperations::MakeEdgeWire
277                     (Handle(GEOM_Object) theWire,
278                      const Standard_Real theLinearTolerance,
279                      const Standard_Real theAngularTolerance)
280 {
281   SetErrorCode(KO);
282
283   if (theWire.IsNull()) return NULL;
284
285   //Add a new Edge object
286   Handle(GEOM_Object) anEdge = GetEngine()->AddObject(GetDocID(), GEOM_EDGE);
287
288   //Add a new Vector function
289   Handle(GEOM_Function) aFunction =
290     anEdge->AddFunction(GEOMImpl_ShapeDriver::GetID(), EDGE_WIRE);
291
292   //Check if the function is set correctly
293   if (aFunction->GetDriverGUID() != GEOMImpl_ShapeDriver::GetID()) return NULL;
294
295   GEOMImpl_IShapes aCI (aFunction);
296
297   Handle(GEOM_Function) aWire = theWire->GetLastFunction();
298
299   if (aWire.IsNull()) return NULL;
300
301   aCI.SetBase(aWire);
302   aCI.SetTolerance(theLinearTolerance);
303   aCI.SetAngularTolerance(theAngularTolerance);
304
305   //Compute the Edge value
306   try {
307     OCC_CATCH_SIGNALS;
308     if (!GetSolver()->ComputeFunction(aFunction)) {
309       SetErrorCode("Shape driver failed");
310       return NULL;
311     }
312   }
313   catch (Standard_Failure) {
314     Handle(Standard_Failure) aFail = Standard_Failure::Caught();
315     SetErrorCode(aFail->GetMessageString());
316     return NULL;
317   }
318
319   const double DEF_LIN_TOL = Precision::Confusion();
320   const double DEF_ANG_TOL = Precision::Angular();
321   //Make a Python command
322   if ( theAngularTolerance == DEF_ANG_TOL ) {
323     if ( theLinearTolerance == DEF_LIN_TOL )
324       GEOM::TPythonDump(aFunction) << anEdge  << " = geompy.MakeEdgeWire("
325                                    << theWire << ")";
326     else
327       GEOM::TPythonDump(aFunction) << anEdge  << " = geompy.MakeEdgeWire("
328                                    << theWire << ", " << theLinearTolerance << ")";
329   }
330   else {
331     GEOM::TPythonDump(aFunction) << anEdge  << " = geompy.MakeEdgeWire("
332                                  << theWire << ", " << theLinearTolerance << ", "
333                                  << theAngularTolerance << ")";
334   }
335
336   SetErrorCode(OK);
337   return anEdge;
338 }
339
340 //=============================================================================
341 /*!
342  *  MakeWire
343  */
344 //=============================================================================
345 Handle(GEOM_Object) GEOMImpl_IShapesOperations::MakeWire
346                              (std::list<Handle(GEOM_Object)> theShapes,
347                               const Standard_Real            theTolerance)
348 {
349   SetErrorCode(KO);
350
351   //Add a new object
352   Handle(GEOM_Object) aWire = GetEngine()->AddObject(GetDocID(), GEOM_WIRE);
353
354   //Add a new function
355   Handle(GEOM_Function) aFunction =
356     aWire->AddFunction(GEOMImpl_ShapeDriver::GetID(), WIRE_EDGES);
357   if (aFunction.IsNull()) return NULL;
358
359   //Check if the function is set correctly
360   if (aFunction->GetDriverGUID() != GEOMImpl_ShapeDriver::GetID()) return NULL;
361
362   GEOMImpl_IShapes aCI (aFunction);
363   aCI.SetTolerance(theTolerance);
364
365   Handle(TColStd_HSequenceOfTransient) aShapesSeq = new TColStd_HSequenceOfTransient;
366
367   // Shapes
368   std::list<Handle(GEOM_Object)>::iterator it = theShapes.begin();
369   for (; it != theShapes.end(); it++) {
370     Handle(GEOM_Function) aRefSh = (*it)->GetLastFunction();
371     if (aRefSh.IsNull()) {
372       SetErrorCode("NULL argument shape for the shape construction");
373       return NULL;
374     }
375     aShapesSeq->Append(aRefSh);
376   }
377   aCI.SetShapes(aShapesSeq);
378
379   //Compute the shape
380   try {
381     OCC_CATCH_SIGNALS;
382     if (!GetSolver()->ComputeFunction(aFunction)) {
383       SetErrorCode("Shape driver failed");
384       return NULL;
385     }
386   }
387   catch (Standard_Failure) {
388     Handle(Standard_Failure) aFail = Standard_Failure::Caught();
389     SetErrorCode(aFail->GetMessageString());
390     return NULL;
391   }
392
393   //Make a Python command
394   GEOM::TPythonDump pd (aFunction);
395   pd << aWire << " = geompy.MakeWire([";
396
397   // Shapes
398   it = theShapes.begin();
399   if (it != theShapes.end()) {
400     pd << (*it++);
401     while (it != theShapes.end()) {
402       pd << ", " << (*it++);
403     }
404   }
405   pd << "], " << theTolerance << ")";
406
407   SetErrorCode(OK);
408   return aWire;
409 }
410
411 //=============================================================================
412 /*!
413  *  MakeFace
414  */
415 //=============================================================================
416 Handle(GEOM_Object) GEOMImpl_IShapesOperations::MakeFace (Handle(GEOM_Object) theWire,
417                                                           const bool isPlanarWanted)
418 {
419   SetErrorCode(KO);
420
421   if (theWire.IsNull()) return NULL;
422
423   //Add a new Face object
424   Handle(GEOM_Object) aFace = GetEngine()->AddObject(GetDocID(), GEOM_FACE);
425
426   //Add a new Shape function for creation of a face from a wire
427   Handle(GEOM_Function) aFunction =
428     aFace->AddFunction(GEOMImpl_ShapeDriver::GetID(), FACE_WIRE);
429   if (aFunction.IsNull()) return NULL;
430
431   //Check if the function is set correctly
432   if (aFunction->GetDriverGUID() != GEOMImpl_ShapeDriver::GetID()) return NULL;
433
434   GEOMImpl_IShapes aCI (aFunction);
435
436   Handle(GEOM_Function) aRefWire = theWire->GetLastFunction();
437
438   if (aRefWire.IsNull()) return NULL;
439
440   aCI.SetBase(aRefWire);
441   aCI.SetIsPlanar(isPlanarWanted);
442
443   //Compute the Face value
444   Standard_Boolean isWarning = Standard_False;
445   try {
446     OCC_CATCH_SIGNALS;
447     if (!GetSolver()->ComputeFunction(aFunction)) {
448       SetErrorCode("Shape driver failed to compute a face");
449       return NULL;
450     }
451   }
452   catch (Standard_Failure) {
453     Handle(Standard_Failure) aFail = Standard_Failure::Caught();
454     SetErrorCode(aFail->GetMessageString());
455     // to provide warning
456     if (!aFunction->GetValue().IsNull()) {
457       isWarning = Standard_True;
458     } else {
459       return NULL;
460     }
461   }
462
463   //Make a Python command
464   GEOM::TPythonDump(aFunction) << aFace << " = geompy.MakeFace("
465     << theWire << ", " << (int)isPlanarWanted << ")";
466
467   // to provide warning
468   if (!isWarning) SetErrorCode(OK);
469   return aFace;
470 }
471
472 //=============================================================================
473 /*!
474  *  MakeFaceWires
475  */
476 //=============================================================================
477 Handle(GEOM_Object) GEOMImpl_IShapesOperations::MakeFaceWires
478                              (std::list<Handle(GEOM_Object)> theShapes,
479                               const bool isPlanarWanted)
480 {
481   SetErrorCode(KO);
482
483   //Add a new object
484   Handle(GEOM_Object) aShape = GetEngine()->AddObject(GetDocID(), GEOM_FACE);
485
486   //Add a new function
487   Handle(GEOM_Function) aFunction =
488     aShape->AddFunction(GEOMImpl_ShapeDriver::GetID(), FACE_WIRES);
489   if (aFunction.IsNull()) return NULL;
490
491   //Check if the function is set correctly
492   if (aFunction->GetDriverGUID() != GEOMImpl_ShapeDriver::GetID()) return NULL;
493
494   GEOMImpl_IShapes aCI (aFunction);
495
496   Handle(TColStd_HSequenceOfTransient) aShapesSeq = new TColStd_HSequenceOfTransient;
497
498   // Shapes
499   std::list<Handle(GEOM_Object)>::iterator it = theShapes.begin();
500   for (; it != theShapes.end(); it++) {
501     Handle(GEOM_Function) aRefSh = (*it)->GetLastFunction();
502     if (aRefSh.IsNull()) {
503       SetErrorCode("NULL argument shape for the face construction");
504       return NULL;
505     }
506     aShapesSeq->Append(aRefSh);
507   }
508   aCI.SetShapes(aShapesSeq);
509
510   aCI.SetIsPlanar(isPlanarWanted);
511
512   //Compute the shape
513   Standard_Boolean isWarning = Standard_False;
514   try {
515     OCC_CATCH_SIGNALS;
516     if (!GetSolver()->ComputeFunction(aFunction)) {
517       SetErrorCode("Shape driver failed");
518       return NULL;
519     }
520   }
521   catch (Standard_Failure) {
522     Handle(Standard_Failure) aFail = Standard_Failure::Caught();
523     SetErrorCode(aFail->GetMessageString());
524     // to provide warning
525     if (!aFunction->GetValue().IsNull()) {
526       isWarning = Standard_True;
527     } else {
528       return NULL;
529     }
530   }
531
532   //Make a Python command
533   GEOM::TPythonDump pd (aFunction);
534   pd << aShape << " = geompy.MakeFaceWires([";
535
536   // Shapes
537   it = theShapes.begin();
538   if (it != theShapes.end()) {
539     pd << (*it++);
540     while (it != theShapes.end()) {
541       pd << ", " << (*it++);
542     }
543   }
544   pd << "], " << (int)isPlanarWanted << ")";
545
546   // to provide warning
547   if (!isWarning) SetErrorCode(OK);
548   return aShape;
549 }
550
551 //=============================================================================
552 /*!
553  *  MakeShell
554  */
555 //=============================================================================
556 Handle(GEOM_Object) GEOMImpl_IShapesOperations::MakeShell
557                              (std::list<Handle(GEOM_Object)> theShapes)
558 {
559   return MakeShape(theShapes, GEOM_SHELL, SHELL_FACES, "MakeShell");
560 }
561
562 //=============================================================================
563 /*!
564  *  MakeSolidShells
565  */
566 //=============================================================================
567 Handle(GEOM_Object) GEOMImpl_IShapesOperations::MakeSolidShells
568                              (std::list<Handle(GEOM_Object)> theShapes)
569 {
570   return MakeShape(theShapes, GEOM_SOLID, SOLID_SHELLS, "MakeSolid");
571 }
572
573 //=============================================================================
574 /*!
575  *  MakeCompound
576  */
577 //=============================================================================
578 Handle(GEOM_Object) GEOMImpl_IShapesOperations::MakeCompound
579                              (std::list<Handle(GEOM_Object)> theShapes)
580 {
581   return MakeShape(theShapes, GEOM_COMPOUND, COMPOUND_SHAPES, "MakeCompound");
582 }
583
584 //=============================================================================
585 /*!
586  *  MakeShape
587  */
588 //=============================================================================
589 Handle(GEOM_Object) GEOMImpl_IShapesOperations::MakeShape
590                              (std::list<Handle(GEOM_Object)> theShapes,
591                               const Standard_Integer         theObjectType,
592                               const Standard_Integer         theFunctionType,
593                               const TCollection_AsciiString& theMethodName)
594 {
595   SetErrorCode(KO);
596
597   //Add a new object
598   Handle(GEOM_Object) aShape = GetEngine()->AddObject(GetDocID(), theObjectType);
599
600   //Add a new function
601   Handle(GEOM_Function) aFunction =
602     aShape->AddFunction(GEOMImpl_ShapeDriver::GetID(), theFunctionType);
603   if (aFunction.IsNull()) return NULL;
604
605   //Check if the function is set correctly
606   if (aFunction->GetDriverGUID() != GEOMImpl_ShapeDriver::GetID()) return NULL;
607
608   GEOMImpl_IShapes aCI (aFunction);
609
610   Handle(TColStd_HSequenceOfTransient) aShapesSeq = new TColStd_HSequenceOfTransient;
611
612   // Shapes
613   std::list<Handle(GEOM_Object)>::iterator it = theShapes.begin();
614   for (; it != theShapes.end(); it++) {
615     Handle(GEOM_Function) aRefSh = (*it)->GetLastFunction();
616     if (aRefSh.IsNull()) {
617       SetErrorCode("NULL argument shape for the shape construction");
618       return NULL;
619     }
620     aShapesSeq->Append(aRefSh);
621   }
622   aCI.SetShapes(aShapesSeq);
623
624   //Compute the shape
625   try {
626     OCC_CATCH_SIGNALS;
627     if (!GetSolver()->ComputeFunction(aFunction)) {
628       SetErrorCode("Shape driver failed");
629       return NULL;
630     }
631   }
632   catch (Standard_Failure) {
633     Handle(Standard_Failure) aFail = Standard_Failure::Caught();
634     SetErrorCode(aFail->GetMessageString());
635     return NULL;
636   }
637
638   //Make a Python command
639   GEOM::TPythonDump pd (aFunction);
640   pd << aShape << " = geompy." << theMethodName.ToCString() << "([";
641
642   // Shapes
643   it = theShapes.begin();
644   if (it != theShapes.end()) {
645     pd << (*it++);
646     while (it != theShapes.end()) {
647       pd << ", " << (*it++);
648     }
649   }
650   pd << "])";
651
652   SetErrorCode(OK);
653   return aShape;
654 }
655
656 //=============================================================================
657 /*!
658  *  MakeGlueFaces
659  */
660 //=============================================================================
661 Handle(GEOM_Object)
662 GEOMImpl_IShapesOperations::MakeGlueFaces (std::list< Handle(GEOM_Object) >& theShapes,
663                                            const Standard_Real               theTolerance,
664                                            const Standard_Boolean            doKeepNonSolids)
665 {
666   SetErrorCode(KO);
667
668   Handle(TColStd_HSequenceOfTransient) objects = GEOM_Object::GetLastFunctions( theShapes );
669   if ( objects.IsNull() || objects->IsEmpty() ) {
670     SetErrorCode("NULL argument shape");
671     return NULL;
672   }
673
674   //Add a new Glued object
675   Handle(GEOM_Object) aGlued = GetEngine()->AddObject(GetDocID(), GEOM_GLUED);
676
677   //Add a new Glue function
678   Handle(GEOM_Function) aFunction;
679   aFunction = aGlued->AddFunction(GEOMImpl_GlueDriver::GetID(), GLUE_FACES);
680   if (aFunction.IsNull()) return NULL;
681
682   //Check if the function is set correctly
683   if (aFunction->GetDriverGUID() != GEOMImpl_GlueDriver::GetID()) return NULL;
684
685   GEOMImpl_IGlue aCI (aFunction);
686
687   aCI.SetBase( objects );
688   aCI.SetTolerance(theTolerance);
689   aCI.SetKeepNonSolids(doKeepNonSolids);
690
691   //Compute the sub-shape value
692   Standard_Boolean isWarning = Standard_False;
693   try {
694     OCC_CATCH_SIGNALS;
695     if (!GetSolver()->ComputeFunction(aFunction)) {
696       SetErrorCode("Shape driver failed to glue faces");
697       return NULL;
698     }
699   }
700   catch (Standard_Failure) {
701     Handle(Standard_Failure) aFail = Standard_Failure::Caught();
702     SetErrorCode(aFail->GetMessageString());
703     // to provide warning
704     if (!aFunction->GetValue().IsNull()) {
705       isWarning = Standard_True;
706     } else {
707       return NULL;
708     }
709   }
710
711   //Make a Python command
712   GEOM::TPythonDump(aFunction) << aGlued << " = geompy.MakeGlueFaces("
713     << theShapes << ", " << theTolerance << ")";
714
715   // to provide warning
716   if (!isWarning) SetErrorCode(OK);
717   return aGlued;
718 }
719
720 //=============================================================================
721 /*!
722  *  GetGlueFaces
723  */
724 //=============================================================================
725 /*
726 Handle(TColStd_HSequenceOfTransient) GEOMImpl_IShapesOperations::GetGlueFaces
727                                                 (Handle(GEOM_Object) theShape,
728                                                  const Standard_Real theTolerance)
729 {
730   SetErrorCode(KO);
731
732   if (theShape.IsNull()) return NULL;
733   TopoDS_Shape aShape = theShape->GetValue();
734   if (aShape.IsNull()) return NULL;
735
736   Handle(TColStd_HSequenceOfTransient) aSeq = new TColStd_HSequenceOfTransient;
737
738   Standard_Integer iErr;
739   TopoDS_Shape aS;
740   GEOMAlgo_Gluer1 aGluer;
741   GEOMAlgo_ListIteratorOfListOfCoupleOfShapes aItCS;
742   GEOMAlgo_CoupleOfShapes aCS;
743   GEOMAlgo_ListOfCoupleOfShapes aLCS;
744
745   //aGluer = new GEOMAlgo_Gluer1;
746   aGluer.SetShape(aShape);
747   aGluer.SetTolerance(theTolerance);
748   aGluer.Perform();
749   iErr = aGluer.ErrorStatus();
750   if (iErr) return NULL;
751
752   TopTools_ListOfShape listShape;
753   const GEOMAlgo_ListOfCoupleOfShapes& aLCSG = aGluer.GluedFaces();
754   // Access to faces
755   aItCS.Initialize(aLCSG);
756   for (; aItCS.More(); aItCS.Next()) {
757     const GEOMAlgo_CoupleOfShapes& aCSG = aItCS.Value();
758     listShape.Append(aCSG.Shape1());
759   }
760
761   TopTools_ListIteratorOfListOfShape itSub (listShape);
762   TCollection_AsciiString anAsciiList, anEntry;
763   TopTools_IndexedMapOfShape anIndices;
764   TopExp::MapShapes(aShape, anIndices);
765   Handle(TColStd_HArray1OfInteger) anArray;
766   Handle(GEOM_Object) anObj;
767   for (int index = 1; itSub.More(); itSub.Next(), ++index) {
768     TopoDS_Shape aValue = itSub.Value();
769     anArray = new TColStd_HArray1OfInteger(1,1);
770     anArray->SetValue(1, anIndices.FindIndex(aValue));
771     anObj = GetEngine()->AddSubShape(theShape, anArray);
772     if (!anObj.IsNull()) {
773       aSeq->Append(anObj);
774
775       // for python command
776       TDF_Tool::Entry(anObj->GetEntry(), anEntry);
777       anAsciiList += anEntry;
778       anAsciiList += ",";
779     }
780   }
781
782   //Make a Python command
783   if( anAsciiList.Length() > 0 ) {
784     anAsciiList.Trunc(anAsciiList.Length() - 1);
785     Handle(GEOM_Function) aFunction = theShape->GetLastFunction();
786     GEOM::TPythonDump pd (aFunction, true);
787     pd << "[" << anAsciiList.ToCString();
788     pd << "] = geompy.GetGlueFaces(" << theShape << ", " << theTolerance << ")";
789   }
790
791   SetErrorCode(OK);
792
793   return aSeq;
794 }
795 */
796
797 //=============================================================================
798 /*!
799  *  MakeGlueFacesByList
800  */
801 //=============================================================================
802 Handle(GEOM_Object)
803 GEOMImpl_IShapesOperations::MakeGlueFacesByList(std::list< Handle(GEOM_Object) >& theShapes,
804                                                 const Standard_Real               theTolerance,
805                                                 std::list<Handle(GEOM_Object)> &  theFaces,
806                                                 const Standard_Boolean            doKeepNonSolids,
807                                                 const Standard_Boolean            doGlueAllEdges)
808 {
809   SetErrorCode(KO);
810
811   Handle(TColStd_HSequenceOfTransient) objects = GEOM_Object::GetLastFunctions( theShapes );
812   if ( objects.IsNull() || objects->IsEmpty() ) {
813     SetErrorCode("NULL argument shape");
814     return NULL;
815   }
816   Handle(TColStd_HSequenceOfTransient) aFaces = GEOM_Object::GetLastFunctions( theFaces );
817   if ( aFaces.IsNull() ) {
818     SetErrorCode("NULL argument shape for the shape construction");
819     return NULL;
820   }
821
822   //Add a new Glued object
823   Handle(GEOM_Object) aGlued = GetEngine()->AddObject(GetDocID(), GEOM_GLUED);
824
825   //Add a new Glue function
826   Handle(GEOM_Function) aFunction;
827   aFunction = aGlued->AddFunction(GEOMImpl_GlueDriver::GetID(), GLUE_FACES_BY_LIST);
828   if (aFunction.IsNull()) return NULL;
829
830   //Check if the function is set correctly
831   if (aFunction->GetDriverGUID() != GEOMImpl_GlueDriver::GetID()) return NULL;
832
833   GEOMImpl_IGlue aCI (aFunction);
834
835   aCI.SetBase( objects );
836   aCI.SetTolerance(theTolerance);
837   aCI.SetKeepNonSolids(doKeepNonSolids);
838   aCI.SetGlueAllEdges(doGlueAllEdges);
839   aCI.SetFaces(aFaces);
840
841   //Compute the sub-shape value
842   Standard_Boolean isWarning = Standard_False;
843   try {
844     OCC_CATCH_SIGNALS;
845     if (!GetSolver()->ComputeFunction(aFunction)) {
846       SetErrorCode("Shape driver failed to glue faces");
847       return NULL;
848     }
849   }
850   catch (Standard_Failure) {
851     Handle(Standard_Failure) aFail = Standard_Failure::Caught();
852     SetErrorCode(aFail->GetMessageString());
853     // to provide warning
854     if (!aFunction->GetValue().IsNull()) {
855       isWarning = Standard_True;
856     } else {
857       return NULL;
858     }
859   }
860
861   //Make a Python command
862
863   GEOM::TPythonDump pd(aFunction);
864   pd << aGlued << " = geompy.MakeGlueFacesByList("
865      << theShapes << ", " << theTolerance << ", " << theFaces << ", "
866      << (bool)doKeepNonSolids << ", " << (bool)doGlueAllEdges << ")";
867
868   // to provide warning
869   if (!isWarning) SetErrorCode(OK);
870   return aGlued;
871 }
872
873 //=============================================================================
874 /*!
875  *  MakeGlueEdges
876  */
877 //=============================================================================
878 Handle(GEOM_Object)
879 GEOMImpl_IShapesOperations::MakeGlueEdges (std::list< Handle(GEOM_Object) >& theShapes,
880                                            const Standard_Real               theTolerance)
881 {
882   SetErrorCode(KO);
883
884   Handle(TColStd_HSequenceOfTransient) objects = GEOM_Object::GetLastFunctions( theShapes );
885   if ( objects.IsNull() || objects->IsEmpty() ) {
886     SetErrorCode("NULL argument shape");
887     return NULL;
888   }
889
890   //Add a new Glued object
891   Handle(GEOM_Object) aGlued = GetEngine()->AddObject(GetDocID(), GEOM_GLUED);
892
893   //Add a new Glue function
894   Handle(GEOM_Function) aFunction;
895   aFunction = aGlued->AddFunction(GEOMImpl_GlueDriver::GetID(), GLUE_EDGES);
896   if (aFunction.IsNull()) return NULL;
897
898   //Check if the function is set correctly
899   if (aFunction->GetDriverGUID() != GEOMImpl_GlueDriver::GetID()) return NULL;
900
901   GEOMImpl_IGlue aCI (aFunction);
902
903   aCI.SetBase( objects );
904   aCI.SetTolerance(theTolerance);
905   aCI.SetKeepNonSolids(true);
906
907   //Compute the sub-shape value
908   Standard_Boolean isWarning = Standard_False;
909   try {
910     OCC_CATCH_SIGNALS;
911     if (!GetSolver()->ComputeFunction(aFunction)) {
912       SetErrorCode("Shape driver failed to glue edges");
913       return NULL;
914     }
915   }
916   catch (Standard_Failure) {
917     Handle(Standard_Failure) aFail = Standard_Failure::Caught();
918     SetErrorCode(aFail->GetMessageString());
919     // to provide warning
920     if (!aFunction->GetValue().IsNull()) {
921       isWarning = Standard_True;
922     } else {
923       return NULL;
924     }
925   }
926
927   //Make a Python command
928   GEOM::TPythonDump(aFunction) << aGlued << " = geompy.MakeGlueEdges("
929     << theShapes << ", " << theTolerance << ")";
930
931   // to provide warning
932   if (!isWarning) SetErrorCode(OK);
933   return aGlued;
934 }
935
936 //=============================================================================
937 /*!
938  *  GetGlueShapes
939  */
940 //=============================================================================
941 Handle(TColStd_HSequenceOfTransient)
942 GEOMImpl_IShapesOperations::GetGlueShapes (std::list< Handle(GEOM_Object) >& theShapes,
943                                            const Standard_Real               theTolerance,
944                                            const TopAbs_ShapeEnum            theType)
945 {
946   SetErrorCode(KO);
947
948   TopoDS_Shape aShape;
949   TopTools_SequenceOfShape shapes;
950   std::list< Handle(GEOM_Object) >::iterator s = theShapes.begin();
951   Handle(GEOM_Object) lastCreatedGO;
952   for ( ; s != theShapes.end(); ++s )
953   {
954     Handle(GEOM_Object) go = *s;
955     if ( go.IsNull() ) return NULL;
956     aShape = go->GetValue();
957     if ( aShape.IsNull() ) return NULL;
958     shapes.Append( aShape );
959     lastCreatedGO = GEOM::GetCreatedLast( lastCreatedGO, go );
960   }
961   if ( shapes.Length() > 1 )
962   {
963     TopoDS_Compound compound;
964     BRep_Builder builder;
965     builder.MakeCompound( compound );
966     for ( int i = 1; i <= shapes.Length(); ++i )
967       builder.Add( compound, shapes( i ) );
968
969     aShape = compound;
970   }
971
972   Handle(TColStd_HSequenceOfTransient) aSeq = new TColStd_HSequenceOfTransient;
973
974   GEOMAlgo_GlueDetector aGluer;
975   aGluer.SetArgument(aShape);
976   aGluer.SetTolerance(theTolerance);
977   aGluer.Perform();
978   Standard_Integer iErr = aGluer.ErrorStatus();
979   if (iErr) return NULL;
980
981   std::vector< TopTools_IndexedMapOfShape* > anIndices( shapes.Length(), NULL );
982   Handle(TColStd_HArray1OfInteger) anArray;
983   Handle(GEOM_Object) anObj;
984
985   TopTools_ListOfShape listOnePerSet;
986
987   const TopTools_DataMapOfShapeListOfShape& aImages = aGluer.Images();
988   TopTools_DataMapIteratorOfDataMapOfShapeListOfShape aItDMSLS (aImages);
989   for (int index = 1; aItDMSLS.More(); aItDMSLS.Next(), ++index) {
990     // some key shape
991     //const TopoDS_Shape& aSkey = aItDMSLS.Key();
992
993     // list of shapes of the argument that can be glued
994     const TopTools_ListOfShape& aLSD = aItDMSLS.Value();
995
996     //listShape.Append(aLSD.First());
997     TopoDS_Shape aValue = aLSD.First();
998
999     if (aValue.ShapeType() == theType) {
1000       listOnePerSet.Append(aValue);
1001     }
1002   }
1003
1004   // for stable order of returned entities
1005   GEOMUtils::SortShapes(listOnePerSet, Standard_False);
1006
1007   TopTools_ListIteratorOfListOfShape aListIt (listOnePerSet);
1008   for (; aListIt.More(); aListIt.Next())
1009   {
1010     TopoDS_Shape aValue = aListIt.Value();
1011     // find a shape to add aValue as a sub-shape
1012     anObj.Nullify();
1013     s = theShapes.begin();
1014     for ( int i = 0; i < shapes.Length(); ++i, ++s )
1015     {
1016       Handle(GEOM_Object) object = *s;
1017       if ( !anIndices[i] ) {
1018         anIndices[i] = new TopTools_IndexedMapOfShape;
1019         TopExp::MapShapes( object->GetValue(), *anIndices[i]);
1020       }
1021       if (int index = anIndices[i]->FindIndex( aValue )) {
1022         anArray = new TColStd_HArray1OfInteger(1,1);
1023         anArray->SetValue(1, index);
1024         anObj = GetEngine()->AddSubShape( object, anArray);
1025         break;
1026       }
1027     }
1028     if (!anObj.IsNull())
1029       aSeq->Append(anObj);
1030   }
1031   for ( size_t i = 0 ; i < anIndices.size(); ++i )
1032     delete anIndices[i];
1033
1034   // Make a Python command
1035   if ( aSeq->Length() > 0)
1036   {
1037     Handle(GEOM_Function) aFunction = lastCreatedGO->GetLastFunction();
1038     GEOM::TPythonDump pd (aFunction, /*append=*/true);
1039     pd << aSeq
1040        << " = geompy." << (theType == TopAbs_FACE ? "GetGlueFaces" : "GetGlueEdges" )
1041        << "( " << theShapes << ", " << theTolerance << ")";
1042   }
1043
1044   SetErrorCode(OK);
1045
1046   return aSeq;
1047 }
1048
1049 //=============================================================================
1050 /*!
1051  *  MakeGlueEdgesByList
1052  */
1053 //=============================================================================
1054 Handle(GEOM_Object)
1055 GEOMImpl_IShapesOperations::MakeGlueEdgesByList (std::list< Handle(GEOM_Object) >& theShapes,
1056                                                  const Standard_Real               theTolerance,
1057                                                  std::list<Handle(GEOM_Object)>&   theEdges)
1058 {
1059   SetErrorCode(KO);
1060
1061   Handle(TColStd_HSequenceOfTransient) objects = GEOM_Object::GetLastFunctions( theShapes );
1062   if ( objects.IsNull() || objects->IsEmpty() ) {
1063     SetErrorCode("NULL argument shape");
1064     return NULL;
1065   }
1066   Handle(TColStd_HSequenceOfTransient) anEdges = GEOM_Object::GetLastFunctions( theEdges );
1067   if ( anEdges.IsNull() ) {
1068     SetErrorCode("NULL argument shape for the shape construction");
1069     return NULL;
1070   }
1071   //Add a new Glued object
1072   Handle(GEOM_Object) aGlued = GetEngine()->AddObject(GetDocID(), GEOM_GLUED);
1073
1074   //Add a new Glue function
1075   Handle(GEOM_Function) aFunction;
1076   aFunction = aGlued->AddFunction(GEOMImpl_GlueDriver::GetID(), GLUE_EDGES_BY_LIST);
1077   if (aFunction.IsNull()) return NULL;
1078
1079   //Check if the function is set correctly
1080   if (aFunction->GetDriverGUID() != GEOMImpl_GlueDriver::GetID()) return NULL;
1081
1082   GEOMImpl_IGlue aCI (aFunction);
1083
1084   aCI.SetBase( objects );
1085   aCI.SetTolerance(theTolerance);
1086   aCI.SetKeepNonSolids(true);
1087   aCI.SetFaces(anEdges);
1088
1089   //Compute the sub-shape value
1090   Standard_Boolean isWarning = Standard_False;
1091   try {
1092     OCC_CATCH_SIGNALS;
1093     if (!GetSolver()->ComputeFunction(aFunction)) {
1094       SetErrorCode("Shape driver failed to glue edges");
1095       return NULL;
1096     }
1097   }
1098   catch (Standard_Failure) {
1099     Handle(Standard_Failure) aFail = Standard_Failure::Caught();
1100     SetErrorCode(aFail->GetMessageString());
1101     // to provide warning
1102     if (!aFunction->GetValue().IsNull()) {
1103       isWarning = Standard_True;
1104     } else {
1105       return NULL;
1106     }
1107   }
1108
1109   //Make a Python command
1110
1111   GEOM::TPythonDump pd (aFunction);
1112   pd << aGlued << " = geompy.MakeGlueEdgesByList("
1113      << theShapes << ", " << theTolerance << ", " << theEdges << " )";
1114
1115   // to provide warning
1116   if (!isWarning) SetErrorCode(OK);
1117   return aGlued;
1118 }
1119
1120 //=============================================================================
1121 /*!
1122  *  GetExistingSubObjects
1123  */
1124 //=============================================================================
1125 Handle(TColStd_HSequenceOfTransient)
1126 GEOMImpl_IShapesOperations::GetExistingSubObjects(Handle(GEOM_Object)    theShape,
1127                                                   const Standard_Boolean theGroupsOnly)
1128 {
1129   // note: this method does not return fields
1130
1131   Standard_Integer types = theGroupsOnly ? Groups : Groups|SubShapes;
1132   Handle(TColStd_HSequenceOfTransient) results = GetExistingSubObjects(theShape, types);
1133
1134   if (results->Length() > 0) {
1135     //Make a Python command
1136     TCollection_AsciiString anAsciiList;
1137     for (int i = 1; i <= results->Length(); i++)
1138     {
1139       Handle(GEOM_BaseObject) obj = Handle(GEOM_BaseObject)::DownCast( results->Value(i));
1140       obj->GetEntryString();
1141       if ( i < results->Length() )
1142         anAsciiList += ",";
1143     }
1144     
1145     GEOM::TPythonDump pd (theShape->GetLastFunction(), /*append=*/true);
1146     pd << "[" << anAsciiList.ToCString();
1147     pd << "] = geompy.GetExistingSubObjects(";
1148     pd << theShape << ", " << (bool)theGroupsOnly << ")";
1149   }
1150
1151   return results;
1152 }
1153
1154 Handle(TColStd_HSequenceOfTransient)
1155 GEOMImpl_IShapesOperations::GetExistingSubObjects(Handle(GEOM_Object)    theShape,
1156                                                   const Standard_Integer theTypes)
1157 {
1158   SetErrorCode(KO);
1159
1160   if (theShape.IsNull()) return NULL;
1161
1162   Handle(GEOM_Function) aMainShape = theShape->GetLastFunction();
1163   if (aMainShape.IsNull()) return NULL;
1164
1165   Handle(TColStd_HSequenceOfTransient) aSeq = new TColStd_HSequenceOfTransient;
1166   SetErrorCode(NOT_FOUND_ANY);
1167
1168   if (!aMainShape->HasSubShapeReferences()) return aSeq;
1169   const TDataStd_ListOfExtendedString& aListEntries = aMainShape->GetSubShapeReferences();
1170   if (aListEntries.IsEmpty()) return aSeq;
1171
1172   SetErrorCode(KO);
1173
1174   TDataStd_ListIteratorOfListOfExtendedString anIt (aListEntries);
1175   for (; anIt.More(); anIt.Next()) {
1176     TCollection_ExtendedString anEntry = anIt.Value();
1177     Standard_Integer aStrLen = anEntry.LengthOfCString();
1178     char* anEntryStr = new char[aStrLen+1];
1179     anEntry.ToUTF8CString(anEntryStr);
1180     Handle(GEOM_BaseObject) anObj = GetEngine()->GetObject(GetDocID(), anEntryStr, false);
1181     if (!anObj.IsNull() ) {
1182       bool isGroup    = anObj->IsKind(STANDARD_TYPE(GEOM_Object)) && anObj->GetType() == GEOM_GROUP;
1183       bool isSubShape = anObj->IsKind(STANDARD_TYPE(GEOM_Object)) && anObj->GetType() != GEOM_GROUP;
1184       bool isField    = anObj->IsKind(STANDARD_TYPE(GEOM_Field));
1185       if (theTypes & Groups    && isGroup ||
1186           theTypes & SubShapes && isSubShape ||
1187           theTypes & Fields    && isField) {
1188         aSeq->Append(anObj);
1189       }
1190     }
1191     delete [] anEntryStr;
1192   }
1193
1194   if (aSeq->Length() == 0) {
1195     SetErrorCode(NOT_FOUND_ANY);
1196     return aSeq;
1197   }
1198
1199   SetErrorCode(OK);
1200
1201   return aSeq;
1202 }
1203
1204 //=============================================================================
1205 /*!
1206  *  MakeExplode
1207  */
1208 //=============================================================================
1209 Handle(TColStd_HSequenceOfTransient) GEOMImpl_IShapesOperations::MakeExplode
1210                                           (Handle(GEOM_Object)    theShape,
1211                                            const Standard_Integer theShapeType,
1212                                            const Standard_Boolean isSorted,
1213                                            const ExplodeType      theExplodeType)
1214 {
1215   SetErrorCode(KO);
1216
1217   if (theShape.IsNull()) return NULL;
1218   TopoDS_Shape aShape = theShape->GetValue();
1219   if (aShape.IsNull()) return NULL;
1220
1221   Handle(GEOM_Function) aMainShape = theShape->GetLastFunction();
1222
1223   Handle(TColStd_HSequenceOfTransient) aSeq = new TColStd_HSequenceOfTransient;
1224   Handle(GEOM_Object) anObj;
1225   TopTools_MapOfShape mapShape;
1226   TopTools_ListOfShape listShape;
1227
1228   if (aShape.ShapeType() == TopAbs_COMPOUND &&
1229       (TopAbs_ShapeEnum(theShapeType) == TopAbs_SHAPE ||
1230        TopAbs_ShapeEnum(theShapeType) == TopAbs_COMPSOLID ||
1231        TopAbs_ShapeEnum(theShapeType) == TopAbs_COMPOUND))
1232   {
1233     TopoDS_Iterator It (aShape, Standard_True, Standard_True);
1234     for (; It.More(); It.Next()) {
1235       if (mapShape.Add(It.Value())) {
1236         if (TopAbs_ShapeEnum(theShapeType) == TopAbs_SHAPE ||
1237             TopAbs_ShapeEnum(theShapeType) == It.Value().ShapeType()) {
1238           listShape.Append(It.Value());
1239         }
1240       }
1241     }
1242   }
1243   else if (theExplodeType != EXPLODE_NEW_EXCLUDE_MAIN || aShape.ShapeType() != theShapeType) // issue 0021079
1244   {
1245     TopExp_Explorer exp (aShape, TopAbs_ShapeEnum(theShapeType));
1246     for (; exp.More(); exp.Next())
1247       if (mapShape.Add(exp.Current()))
1248         listShape.Append(exp.Current());
1249   }
1250
1251   if (listShape.IsEmpty()) {
1252     //SetErrorCode("The given shape has no sub-shapes of the requested type");
1253     SetErrorCode(NOT_FOUND_ANY); // NPAL18017
1254     return aSeq;
1255   }
1256
1257   if (isSorted) {
1258     bool isOldSorting = false;
1259     if (theExplodeType == EXPLODE_OLD_INCLUDE_MAIN)
1260       isOldSorting = true;
1261     GEOMUtils::SortShapes(listShape, isOldSorting);
1262   }
1263
1264   TopTools_IndexedMapOfShape anIndices;
1265   TopExp::MapShapes(aShape, anIndices);
1266   Handle(TColStd_HArray1OfInteger) anArray;
1267
1268   TopTools_ListIteratorOfListOfShape itSub (listShape);
1269   TCollection_AsciiString anAsciiList, anEntry;
1270   for (int index = 1; itSub.More(); itSub.Next(), ++index)
1271   {
1272     TopoDS_Shape aValue = itSub.Value();
1273     anArray = new TColStd_HArray1OfInteger(1,1);
1274     anArray->SetValue(1, anIndices.FindIndex(aValue));
1275
1276     //anObj = GetEngine()->AddSubShape(theShape, anArray);
1277     {
1278       anObj = GetEngine()->AddObject(GetDocID(), GEOM_SUBSHAPE);
1279       Handle(GEOM_Function) aFunction = anObj->AddFunction(GEOM_Object::GetSubShapeID(), 1);
1280       if (aFunction.IsNull()) return aSeq;
1281
1282       GEOM_ISubShape aSSI (aFunction);
1283       aSSI.SetMainShape(aMainShape);
1284       aSSI.SetIndices(anArray);
1285
1286       // Set function value directly, as we know it.
1287       // Usage of Solver here would lead to significant loss of time,
1288       // because GEOM_SubShapeDriver will build TopTools_IndexedMapOfShape
1289       // on the main shape for each being calculated sub-shape separately.
1290       aFunction->SetValue(aValue);
1291
1292       // Put this subshape in the list of sub-shapes of theMainShape
1293       aMainShape->AddSubShapeReference(aFunction);
1294     }
1295
1296     if (!anObj.IsNull()) {
1297       aSeq->Append(anObj);
1298
1299       // for python command
1300       TDF_Tool::Entry(anObj->GetEntry(), anEntry);
1301       anAsciiList += anEntry;
1302       anAsciiList += ",";
1303     }
1304   }
1305
1306   //Make a Python command
1307   anAsciiList.Trunc(anAsciiList.Length() - 1);
1308
1309   GEOM::TPythonDump pd (aMainShape, /*append=*/true);
1310   pd << "[" << anAsciiList.ToCString() << "] = geompy.";
1311   switch (theExplodeType) {
1312   case EXPLODE_NEW_EXCLUDE_MAIN:
1313     pd << "ExtractShapes(" << theShape << ", "
1314        << TopAbs_ShapeEnum(theShapeType) << ", " << (isSorted ? "True" : "False") << ")";
1315     break;
1316   case EXPLODE_NEW_INCLUDE_MAIN:
1317     pd << "SubShapeAll" << (isSorted ? "SortedCentres(" : "(")
1318        << theShape << ", " << TopAbs_ShapeEnum(theShapeType) << ")";
1319     break;
1320   case EXPLODE_OLD_INCLUDE_MAIN:
1321     pd << "SubShapeAll" << (isSorted ? "Sorted(" : "(")
1322        << theShape << ", " << TopAbs_ShapeEnum(theShapeType) << ")";
1323     break;
1324   default: ;
1325   }
1326   SetErrorCode(OK);
1327
1328   return aSeq;
1329 }
1330
1331 //=============================================================================
1332 /*!
1333  *  SubShapeAllIDs
1334  */
1335 //=============================================================================
1336 Handle(TColStd_HSequenceOfInteger) GEOMImpl_IShapesOperations::SubShapeAllIDs
1337                                           (Handle(GEOM_Object)    theShape,
1338                                            const Standard_Integer theShapeType,
1339                                            const Standard_Boolean isSorted,
1340                                            const ExplodeType      theExplodeType)
1341 {
1342   SetErrorCode(KO);
1343
1344   if (theShape.IsNull()) return NULL;
1345   TopoDS_Shape aShape = theShape->GetValue();
1346   if (aShape.IsNull()) return NULL;
1347
1348   Handle(TColStd_HSequenceOfInteger) aSeq = new TColStd_HSequenceOfInteger;
1349   TopTools_MapOfShape mapShape;
1350   TopTools_ListOfShape listShape;
1351
1352   if (aShape.ShapeType() == TopAbs_COMPOUND &&
1353       (TopAbs_ShapeEnum(theShapeType) == TopAbs_SHAPE ||
1354        TopAbs_ShapeEnum(theShapeType) == TopAbs_COMPSOLID ||
1355        TopAbs_ShapeEnum(theShapeType) == TopAbs_COMPOUND))
1356   {
1357     TopoDS_Iterator It (aShape, Standard_True, Standard_True);
1358     for (; It.More(); It.Next()) {
1359       if (mapShape.Add(It.Value())) {
1360         if (TopAbs_ShapeEnum(theShapeType) == TopAbs_SHAPE ||
1361             TopAbs_ShapeEnum(theShapeType) == It.Value().ShapeType()) {
1362           listShape.Append(It.Value());
1363         }
1364       }
1365     }
1366   }
1367   else if (theExplodeType != EXPLODE_NEW_EXCLUDE_MAIN || aShape.ShapeType() != theShapeType) // issue 0021079
1368   {
1369     TopExp_Explorer exp (aShape, TopAbs_ShapeEnum(theShapeType));
1370     for (; exp.More(); exp.Next())
1371       if (mapShape.Add(exp.Current()))
1372         listShape.Append(exp.Current());
1373   }
1374
1375   if (listShape.IsEmpty()) {
1376     //SetErrorCode("The given shape has no sub-shapes of the requested type");
1377     SetErrorCode(NOT_FOUND_ANY); // NPAL18017
1378     return aSeq;
1379   }
1380
1381   if (isSorted) {
1382     bool isOldSorting = false;
1383     if (theExplodeType == EXPLODE_OLD_INCLUDE_MAIN)
1384       isOldSorting = true;
1385     GEOMUtils::SortShapes(listShape, isOldSorting);
1386   }
1387
1388   TopTools_IndexedMapOfShape anIndices;
1389   TopExp::MapShapes(aShape, anIndices);
1390   Handle(TColStd_HArray1OfInteger) anArray;
1391
1392   TopTools_ListIteratorOfListOfShape itSub (listShape);
1393   for (int index = 1; itSub.More(); itSub.Next(), ++index) {
1394     TopoDS_Shape aValue = itSub.Value();
1395     aSeq->Append(anIndices.FindIndex(aValue));
1396   }
1397
1398   Handle(GEOM_Function) aFunction = theShape->GetLastFunction();
1399
1400   //Make a Python command
1401   GEOM::TPythonDump pd (aFunction, /*append=*/true);
1402   pd << "listSubShapeIDs = geompy.SubShapeAll";
1403   switch (theExplodeType) {
1404   case EXPLODE_NEW_EXCLUDE_MAIN:
1405     break;
1406   case EXPLODE_NEW_INCLUDE_MAIN:
1407     pd << (isSorted ? "SortedCentresIDs(" : "IDs(")
1408        << theShape << ", " << TopAbs_ShapeEnum(theShapeType) << ")";
1409     break;
1410   case EXPLODE_OLD_INCLUDE_MAIN:
1411     pd << (isSorted ? "SortedIDs(" : "IDs(")
1412        << theShape << ", " << TopAbs_ShapeEnum(theShapeType) << ")";
1413     break;
1414   default: ;
1415   }
1416
1417   SetErrorCode(OK);
1418   return aSeq;
1419 }
1420
1421 //=============================================================================
1422 /*!
1423  *  GetSubShape
1424  */
1425 //=============================================================================
1426 Handle(GEOM_Object) GEOMImpl_IShapesOperations::GetSubShape
1427                                           (Handle(GEOM_Object)    theMainShape,
1428                                            const Standard_Integer theID)
1429 {
1430   SetErrorCode(KO);
1431
1432   if (theMainShape.IsNull()) return NULL;
1433
1434   Handle(TColStd_HArray1OfInteger) anArray = new TColStd_HArray1OfInteger(1,1);
1435   anArray->SetValue(1, theID);
1436   Handle(GEOM_Object) anObj = GetEngine()->AddSubShape(theMainShape, anArray,true);
1437   if (anObj.IsNull()) {
1438     SetErrorCode("Can not get a sub-shape with the given ID");
1439     return NULL;
1440   }
1441
1442   Handle(GEOM_Function) aFunction = anObj->GetLastFunction();
1443
1444   //Make a Python command
1445   GEOM::TPythonDump(aFunction) << anObj << " = geompy.GetSubShape("
1446                                << theMainShape << ", [" << theID << "])";
1447
1448   SetErrorCode(OK);
1449   return anObj;
1450 }
1451
1452 //=============================================================================
1453 /*!
1454  *  MakeSubShapes
1455  */
1456 //=============================================================================
1457 Handle(TColStd_HSequenceOfTransient) GEOMImpl_IShapesOperations::MakeSubShapes
1458                                 (Handle(GEOM_Object)              theMainShape,
1459                                  Handle(TColStd_HArray1OfInteger) theIndices)
1460 {
1461   SetErrorCode(KO);
1462
1463   Handle(TColStd_HSequenceOfTransient) aSeq = new TColStd_HSequenceOfTransient;
1464
1465   if (!theIndices->Length()) {
1466     SetErrorCode(NOT_FOUND_ANY);
1467     return aSeq;
1468   }
1469
1470   if (theMainShape.IsNull()) return NULL;
1471   TopoDS_Shape aShape = theMainShape->GetValue();
1472   if (aShape.IsNull()) return NULL;
1473
1474   Handle(GEOM_Function) aMainShape = theMainShape->GetLastFunction();
1475
1476   TopTools_IndexedMapOfShape anIndices;
1477   TopExp::MapShapes(aShape, anIndices);
1478
1479   Handle(TColStd_HArray1OfInteger) anArray;
1480   Handle(GEOM_Object) anObj;
1481
1482   TCollection_AsciiString anAsciiList, anEntry;
1483   Standard_Integer i, low = theIndices->Lower(), up = theIndices->Upper();
1484   for (i = low; i <= up; i++) {
1485     int id = theIndices->Value(i);
1486     if (1 <= id && id <= anIndices.Extent()) {
1487       TopoDS_Shape aValue = anIndices.FindKey(id);
1488       anArray = new TColStd_HArray1OfInteger(1,1);
1489       anArray->SetValue(1, id);
1490
1491       anObj = GetEngine()->AddObject(GetDocID(), GEOM_SUBSHAPE);
1492       if (!anObj.IsNull()) {
1493         Handle(GEOM_Function) aFunction = anObj->AddFunction(GEOM_Object::GetSubShapeID(), 1);
1494         if (aFunction.IsNull()) return aSeq;
1495
1496         GEOM_ISubShape aSSI (aFunction);
1497         aSSI.SetMainShape(aMainShape);
1498         aSSI.SetIndices(anArray);
1499
1500         // Set function value directly, as we know it.
1501         // Usage of Solver here would lead to significant loss of time,
1502         // because GEOM_SubShapeDriver will build TopTools_IndexedMapOfShape
1503         // on the main shape for each being calculated sub-shape separately.
1504         aFunction->SetValue(aValue);
1505
1506         // Put this sub-shape in the list of sub-shapes of theMainShape
1507         aMainShape->AddSubShapeReference(aFunction);
1508
1509         aSeq->Append(anObj);
1510
1511         // for python command
1512         TDF_Tool::Entry(anObj->GetEntry(), anEntry);
1513         anAsciiList += anEntry;
1514         anAsciiList += ",";
1515       }
1516     }
1517   }
1518
1519   //Make a Python command
1520   anAsciiList.Trunc(anAsciiList.Length() - 1);
1521
1522   GEOM::TPythonDump pd (aMainShape, /*append=*/true);
1523   pd << "[" << anAsciiList.ToCString() << "] = geompy.SubShapes("
1524      << theMainShape << ", [" ;
1525   for (i = low; i <= up - 1; i++) {
1526     pd << theIndices->Value(i) << ", ";
1527   }
1528   pd << theIndices->Value(up) << "])";
1529
1530   SetErrorCode(OK);
1531
1532   return aSeq;
1533 }
1534
1535 //=============================================================================
1536 /*!
1537  *  GetSubShapeIndex
1538  */
1539 //=============================================================================
1540 Standard_Integer GEOMImpl_IShapesOperations::GetSubShapeIndex (Handle(GEOM_Object) theMainShape,
1541                                                                Handle(GEOM_Object) theSubShape)
1542 {
1543   SetErrorCode(KO);
1544
1545   TopoDS_Shape aMainShape = theMainShape->GetValue();
1546   TopoDS_Shape aSubShape = theSubShape->GetValue();
1547
1548   if (aMainShape.IsNull() || aSubShape.IsNull()) return -1;
1549
1550   TopTools_IndexedMapOfShape anIndices;
1551   TopExp::MapShapes(aMainShape, anIndices);
1552 //   if (anIndices.Contains(aSubShape)) {
1553 //     SetErrorCode(OK);
1554 //     return anIndices.FindIndex(aSubShape);
1555 //   }
1556   int id = anIndices.FindIndex(aSubShape);
1557   if (id > 0)
1558   {
1559     SetErrorCode(OK);
1560     return id;
1561   }
1562   return -1;
1563 }
1564
1565
1566
1567 //=============================================================================
1568 /*!
1569  *  GetSubShapeIndices
1570  */
1571 //=============================================================================
1572 Handle(TColStd_HSequenceOfInteger) GEOMImpl_IShapesOperations::GetSubShapesIndices (Handle(GEOM_Object) theMainShape,
1573                                                                                     std::list<Handle(GEOM_Object)> theSubShapes)
1574 {
1575   MESSAGE("GEOMImpl_IShapesOperations::GetSubShapesIndices")
1576   SetErrorCode(KO);
1577   
1578   Handle(TColStd_HSequenceOfInteger) aSeq = new TColStd_HSequenceOfInteger;
1579   
1580   TopoDS_Shape aMainShape = theMainShape->GetValue();
1581   if (aMainShape.IsNull())
1582   {
1583     MESSAGE("NULL main shape")
1584     return NULL;
1585   }
1586   
1587   TopTools_IndexedMapOfShape anIndices;
1588   TopExp::MapShapes(aMainShape, anIndices);
1589   
1590   std::list<Handle(GEOM_Object)>::iterator it;
1591   for (it=theSubShapes.begin(); it != theSubShapes.end(); ++it)
1592   {
1593     TopoDS_Shape aSubShape = (*it)->GetValue(); 
1594     if (aSubShape.IsNull())
1595     {
1596       MESSAGE("NULL subshape")
1597       return NULL;
1598     }
1599     int id = anIndices.FindIndex(aSubShape);
1600     aSeq->Append(id);
1601   }  
1602   
1603   SetErrorCode(OK);
1604   return aSeq;
1605 }
1606
1607
1608 //=============================================================================
1609 /*!
1610  *  GetTopologyIndex
1611  */
1612 //=============================================================================
1613 Standard_Integer GEOMImpl_IShapesOperations::GetTopologyIndex (Handle(GEOM_Object) theMainShape,
1614                                                                Handle(GEOM_Object) theSubShape)
1615 {
1616   SetErrorCode(OK);
1617
1618   TopoDS_Shape aMainShape = theMainShape->GetValue();
1619   TopoDS_Shape aSubShape = theSubShape->GetValue();
1620
1621   if (aMainShape.IsNull() || aSubShape.IsNull()) {
1622     SetErrorCode("Null argument shape given");
1623     return -1;
1624   }
1625
1626   int index = 1;
1627   if (aSubShape.ShapeType() == TopAbs_COMPOUND) {
1628     TopoDS_Iterator it;
1629     TopTools_ListOfShape CL;
1630     CL.Append(aMainShape);
1631     TopTools_ListIteratorOfListOfShape itC;
1632     for (itC.Initialize(CL); itC.More(); itC.Next()) {
1633       for (it.Initialize(itC.Value()); it.More(); it.Next()) {
1634         if (it.Value().ShapeType() == TopAbs_COMPOUND) {
1635           if (it.Value().IsSame(aSubShape))
1636             return index;
1637           else
1638             index++;
1639           CL.Append(it.Value());
1640         }
1641       }
1642     }
1643   } else {
1644     TopExp_Explorer anExp (aMainShape, aSubShape.ShapeType());
1645     TopTools_MapOfShape M;
1646     for (; anExp.More(); anExp.Next()) {
1647       if (M.Add(anExp.Current())) {
1648         if (anExp.Current().IsSame(aSubShape))
1649           return index;
1650         index++;
1651       }
1652     }
1653   }
1654
1655   SetErrorCode("The sub-shape does not belong to the main shape");
1656   return -1;
1657 }
1658
1659 //=============================================================================
1660 /*!
1661  *  GetShapeTypeString
1662  */
1663 //=============================================================================
1664 TCollection_AsciiString GEOMImpl_IShapesOperations::GetShapeTypeString (Handle(GEOM_Object) theShape)
1665 {
1666   SetErrorCode(KO);
1667
1668   TCollection_AsciiString aTypeName ("Null Shape");
1669
1670   TopoDS_Shape aShape = theShape->GetValue();
1671   if (aShape.IsNull())
1672     return aTypeName;
1673
1674   switch (aShape.ShapeType() )
1675   {
1676   case TopAbs_COMPOUND:
1677     aTypeName = "Compound";
1678     break;
1679   case  TopAbs_COMPSOLID:
1680     aTypeName = "Compound Solid";
1681     break;
1682   case TopAbs_SOLID:
1683     aTypeName = "Solid";
1684     break;
1685   case TopAbs_SHELL:
1686     aTypeName = "Shell";
1687     break;
1688   case TopAbs_FACE:
1689     {
1690       BRepAdaptor_Surface surf (TopoDS::Face(aShape));
1691       if (surf.GetType() == GeomAbs_Plane)
1692         aTypeName = "Plane";
1693       else if (surf.GetType() == GeomAbs_Cylinder)
1694         aTypeName = "Cylindrical Face";
1695       else if (surf.GetType() == GeomAbs_Sphere)
1696         aTypeName = "Spherical Face";
1697       else if (surf.GetType() == GeomAbs_Torus)
1698         aTypeName = "Toroidal Face";
1699       else if (surf.GetType() == GeomAbs_Cone)
1700         aTypeName = "Conical Face";
1701       else
1702         aTypeName = "GEOM::FACE";
1703     }
1704     break;
1705   case TopAbs_WIRE:
1706     aTypeName = "Wire";
1707     break;
1708   case TopAbs_EDGE:
1709     {
1710       BRepAdaptor_Curve curv (TopoDS::Edge(aShape));
1711       if (curv.GetType() == GeomAbs_Line) {
1712         if ((Abs(curv.FirstParameter()) >= 1E6) ||
1713             (Abs(curv.LastParameter()) >= 1E6))
1714           aTypeName = "Line";
1715         else
1716           aTypeName = "Edge";
1717       } else if (curv.GetType() == GeomAbs_Circle) {
1718         if (curv.IsClosed())
1719           aTypeName = "Circle";
1720         else
1721           aTypeName = "Arc";
1722       } else {
1723         aTypeName = "Edge";
1724       }
1725     }
1726     break;
1727   case TopAbs_VERTEX:
1728     aTypeName = "Vertex";
1729     break;
1730   case TopAbs_SHAPE:
1731     aTypeName = "Shape";
1732     break;
1733   default:
1734     aTypeName = "Shape of unknown type";
1735   }
1736
1737   return aTypeName;
1738 }
1739
1740 //=============================================================================
1741 /*!
1742  *  NumberOfSubShapes
1743  */
1744 //=============================================================================
1745 Standard_Integer GEOMImpl_IShapesOperations::NumberOfSubShapes
1746                                           (Handle(GEOM_Object)    theShape,
1747                                            const Standard_Integer theShapeType)
1748 {
1749   SetErrorCode(KO);
1750   Standard_Integer nbShapes = 0;
1751
1752   if (theShape.IsNull()) return -1;
1753   TopoDS_Shape aShape = theShape->GetValue();
1754   if (aShape.IsNull()) return -1;
1755
1756   /*
1757   TopTools_MapOfShape mapShape;
1758
1759   if (aShape.ShapeType() == TopAbs_COMPOUND &&
1760       (TopAbs_ShapeEnum(theShapeType) == TopAbs_SHAPE ||
1761        TopAbs_ShapeEnum(theShapeType) == TopAbs_COMPSOLID ||
1762        TopAbs_ShapeEnum(theShapeType) == TopAbs_COMPOUND)) {
1763     TopoDS_Iterator It (aShape, Standard_True, Standard_True);
1764     for (; It.More(); It.Next()) {
1765       if (mapShape.Add(It.Value())) {
1766         if (TopAbs_ShapeEnum(theShapeType) == TopAbs_SHAPE ||
1767             TopAbs_ShapeEnum(theShapeType) == It.Value().ShapeType()) {
1768           nbShapes++;
1769         }
1770       }
1771     }
1772   } else {
1773     TopExp_Explorer exp (aShape, TopAbs_ShapeEnum(theShapeType));
1774     for (; exp.More(); exp.Next())
1775       if (mapShape.Add(exp.Current()))
1776         nbShapes++;
1777   }
1778   */
1779
1780   try {
1781     OCC_CATCH_SIGNALS;
1782     int iType, nbTypes [TopAbs_SHAPE];
1783     for (iType = 0; iType < TopAbs_SHAPE; ++iType)
1784       nbTypes[iType] = 0;
1785     nbTypes[aShape.ShapeType()]++;
1786
1787     TopTools_MapOfShape aMapOfShape;
1788     aMapOfShape.Add(aShape);
1789     TopTools_ListOfShape aListOfShape;
1790     aListOfShape.Append(aShape);
1791
1792     TopTools_ListIteratorOfListOfShape itL (aListOfShape);
1793     for (; itL.More(); itL.Next()) {
1794       TopoDS_Iterator it (itL.Value());
1795       for (; it.More(); it.Next()) {
1796         TopoDS_Shape s = it.Value();
1797         if (aMapOfShape.Add(s)) {
1798           aListOfShape.Append(s);
1799           nbTypes[s.ShapeType()]++;
1800         }
1801       }
1802     }
1803
1804     if (TopAbs_ShapeEnum(theShapeType) == TopAbs_SHAPE)
1805       nbShapes = aMapOfShape.Extent();
1806     else
1807       nbShapes = nbTypes[theShapeType];
1808   }
1809   catch (Standard_Failure) {
1810     Handle(Standard_Failure) aFail = Standard_Failure::Caught();
1811     SetErrorCode(aFail->GetMessageString());
1812     return -1;
1813   }
1814
1815   SetErrorCode(OK);
1816   return nbShapes;
1817 }
1818
1819 //=============================================================================
1820 /*!
1821  *  ReverseShape
1822  */
1823 //=============================================================================
1824 Handle(GEOM_Object) GEOMImpl_IShapesOperations::ReverseShape(Handle(GEOM_Object) theShape)
1825 {
1826   SetErrorCode(KO);
1827
1828   if (theShape.IsNull()) return NULL;
1829
1830   /*
1831   //Add a new reversed object
1832   Handle(GEOM_Object) aReversed = GetEngine()->AddObject(GetDocID(), theShape->GetType());
1833
1834   //Add a new Revese function
1835   Handle(GEOM_Function) aFunction;
1836   aFunction = aReversed->AddFunction(GEOMImpl_ShapeDriver::GetID(), REVERSE_ORIENTATION);
1837   if (aFunction.IsNull()) return NULL;
1838
1839   //Check if the function is set correctly
1840   if (aFunction->GetDriverGUID() != GEOMImpl_ShapeDriver::GetID()) return NULL;
1841
1842   GEOMImpl_IShapes aSI (aFunction);
1843
1844   Handle(GEOM_Function) aRefShape = theShape->GetLastFunction();
1845   if (aRefShape.IsNull()) return NULL;
1846
1847   aSI.SetBase(aRefShape);
1848
1849   //Compute the sub-shape value
1850   try {
1851     OCC_CATCH_SIGNALS;
1852     if (!GetSolver()->ComputeFunction(aFunction)) {
1853       SetErrorCode("Shape driver failed to reverse shape");
1854       return NULL;
1855     }
1856   }
1857   catch (Standard_Failure) {
1858     Handle(Standard_Failure) aFail = Standard_Failure::Caught();
1859     SetErrorCode(aFail->GetMessageString());
1860     return NULL;
1861   }
1862
1863   //Make a Python command
1864   GEOM::TPythonDump(aFunction) << aReversed
1865     << " = geompy.ChangeOrientation(" << theShape << ")";
1866
1867   SetErrorCode(OK);
1868   */
1869
1870   Handle(GEOM_Object) aReversed;
1871
1872   GEOM_Engine* anEngine = GetEngine();
1873   //GEOMImpl_Gen* aGen = dynamic_cast<GEOMImpl_Gen*>(anEngine);
1874   GEOMImpl_Gen* aGen = (GEOMImpl_Gen*)anEngine;
1875
1876   if (aGen) {
1877     GEOMImpl_IHealingOperations* anIHealingOperations =
1878       aGen->GetIHealingOperations(GetDocID());
1879     aReversed = anIHealingOperations->ChangeOrientationCopy(theShape);
1880     SetErrorCode(anIHealingOperations->GetErrorCode());
1881   }
1882
1883   return aReversed;
1884 }
1885
1886 //=============================================================================
1887 /*!
1888  *  GetFreeFacesIDs
1889  */
1890 //=============================================================================
1891 Handle(TColStd_HSequenceOfInteger) GEOMImpl_IShapesOperations::GetFreeFacesIDs
1892                                                  (Handle(GEOM_Object) theShape)
1893 {
1894   SetErrorCode(KO);
1895
1896   if (theShape.IsNull()) return NULL;
1897   TopoDS_Shape aShape = theShape->GetValue();
1898   if (aShape.IsNull()) return NULL;
1899
1900   Handle(TColStd_HSequenceOfInteger) aSeq = new TColStd_HSequenceOfInteger;
1901
1902   TopTools_IndexedDataMapOfShapeListOfShape mapFaceBlocks;
1903   GEOMImpl_Block6Explorer::MapShapesAndAncestors
1904     (aShape, TopAbs_FACE, TopAbs_SOLID, mapFaceBlocks);
1905
1906   Standard_Integer ind = 1, nbFaces = mapFaceBlocks.Extent();
1907
1908   if (nbFaces == 0) {
1909     SetErrorCode("The given shape has no faces");
1910     return aSeq;
1911   }
1912
1913   TopTools_IndexedMapOfShape anIndices;
1914   TopExp::MapShapes(aShape, anIndices);
1915
1916   Standard_Integer id;
1917   for (; ind <= nbFaces; ind++) {
1918     if (mapFaceBlocks.FindFromIndex(ind).Extent() != 2) {
1919       id = anIndices.FindIndex(mapFaceBlocks.FindKey(ind));
1920       aSeq->Append(id);
1921     }
1922   }
1923
1924   //The explode doesn't change object so no new function is required.
1925   Handle(GEOM_Function) aFunction = theShape->GetLastFunction();
1926
1927   //Make a Python command
1928   GEOM::TPythonDump(aFunction, /*append=*/true)
1929     << "listFreeFacesIDs = geompy.GetFreeFacesIDs(" << theShape << ")";
1930
1931   SetErrorCode(OK);
1932   return aSeq;
1933 }
1934
1935 //=======================================================================
1936 //function : GetSharedShapes
1937 //purpose  :
1938 //=======================================================================
1939 Handle(TColStd_HSequenceOfTransient) GEOMImpl_IShapesOperations::GetSharedShapes
1940                                                 (Handle(GEOM_Object)    theShape1,
1941                                                  Handle(GEOM_Object)    theShape2,
1942                                                  const Standard_Integer theShapeType)
1943 {
1944   SetErrorCode(KO);
1945
1946   if (theShape1.IsNull() || theShape2.IsNull()) return NULL;
1947
1948   TopoDS_Shape aShape1 = theShape1->GetValue();
1949   TopoDS_Shape aShape2 = theShape2->GetValue();
1950
1951   if (aShape1.IsNull() || aShape2.IsNull()) return NULL;
1952
1953   TopTools_IndexedMapOfShape anIndices;
1954   TopExp::MapShapes(aShape1, anIndices);
1955   Handle(TColStd_HArray1OfInteger) anArray;
1956
1957   TopTools_IndexedMapOfShape mapShape1;
1958   TopExp::MapShapes(aShape1, TopAbs_ShapeEnum(theShapeType), mapShape1);
1959
1960   Handle(GEOM_Object) anObj;
1961   Handle(TColStd_HSequenceOfTransient) aSeq = new TColStd_HSequenceOfTransient;
1962   TCollection_AsciiString anAsciiList, anEntry;
1963
1964   TopTools_MapOfShape mapShape2;
1965   TopExp_Explorer exp (aShape2, TopAbs_ShapeEnum(theShapeType));
1966   for (; exp.More(); exp.Next()) {
1967     TopoDS_Shape aSS = exp.Current();
1968     if (mapShape2.Add(aSS) && mapShape1.Contains(aSS)) {
1969       anArray = new TColStd_HArray1OfInteger(1,1);
1970       anArray->SetValue(1, anIndices.FindIndex(aSS));
1971       anObj = GetEngine()->AddSubShape(theShape1, anArray);
1972       aSeq->Append(anObj);
1973
1974       // for python command
1975       TDF_Tool::Entry(anObj->GetEntry(), anEntry);
1976       anAsciiList += anEntry;
1977       anAsciiList += ",";
1978     }
1979   }
1980
1981   if (aSeq->IsEmpty()) {
1982     SetErrorCode("The given shapes have no shared sub-shapes of the requested type");
1983     return aSeq;
1984   }
1985
1986   //Make a Python command
1987   anAsciiList.Trunc(anAsciiList.Length() - 1);
1988
1989   Handle(GEOM_Function) aFunction = anObj->GetLastFunction();
1990
1991   GEOM::TPythonDump(aFunction) << "[" << anAsciiList.ToCString()
1992     << "] = geompy.GetSharedShapes(" << theShape1 << ", "
1993       << theShape2 << ", " << TopAbs_ShapeEnum(theShapeType) << ")";
1994
1995   SetErrorCode(OK);
1996   return aSeq;
1997 }
1998
1999 //=======================================================================
2000 //function : GetSharedShapes
2001 //purpose  :
2002 //=======================================================================
2003 Handle(TColStd_HSequenceOfTransient) GEOMImpl_IShapesOperations::GetSharedShapes
2004                                      (std::list<Handle(GEOM_Object)> & theShapes,
2005                                       const Standard_Integer           theShapeType)
2006 {
2007   SetErrorCode(KO);
2008
2009   int aLen = theShapes.size();
2010   if (aLen < 1) return NULL;
2011
2012   int ind = 1;
2013   std::list<Handle(GEOM_Object)>::iterator it = theShapes.begin();
2014
2015   Handle(GEOM_Object) aMainObj = *it;
2016   Handle(GEOM_Function) aMainShape = aMainObj->GetLastFunction();
2017
2018   TopTools_SequenceOfShape shapeSeq;
2019   for (; it != theShapes.end(); it++, ind++) {
2020     Handle(GEOM_Function) aRefShape = (*it)->GetLastFunction();
2021     if (aRefShape.IsNull()) {
2022       SetErrorCode("NULL shape for GetSharedShapes");
2023       return NULL;
2024     }
2025     TopoDS_Shape aShape2 = aRefShape->GetValue();
2026     if (aShape2.IsNull()) return NULL;
2027     shapeSeq.Append( aShape2 );
2028   }
2029
2030   TopoDS_Shape aShape1 = shapeSeq.First();
2031
2032   if ( shapeSeq.Length() == 1 )
2033   {
2034     shapeSeq.Clear();
2035     for ( TopoDS_Iterator it( aShape1); it.More(); it.Next() )
2036       shapeSeq.Append( it.Value() );
2037     aShape1 = shapeSeq.First();
2038   }
2039
2040   TopTools_IndexedMapOfShape anIndices;
2041   TopExp::MapShapes(aMainShape->GetValue(), anIndices);
2042
2043   TopTools_IndexedMapOfShape mapSelected;
2044   TopExp::MapShapes(aShape1, TopAbs_ShapeEnum(theShapeType), mapSelected);
2045
2046   // Find shared shapes
2047   BRep_Builder B;
2048   TopoDS_Compound aCurrSelection;
2049
2050   for ( ind = 2; ind <= shapeSeq.Length(); ind++) {
2051
2052     TopoDS_Compound aCompound;
2053     B.MakeCompound(aCompound);
2054
2055     const TopoDS_Shape& aShape2 = shapeSeq.Value( ind );
2056
2057     TopTools_MapOfShape mapShape2;
2058     TopExp_Explorer exp (aShape2, TopAbs_ShapeEnum(theShapeType));
2059     for (; exp.More(); exp.Next()) {
2060       const TopoDS_Shape& aSS = exp.Current();
2061       if (mapShape2.Add(aSS) && mapSelected.Contains(aSS)) {
2062         B.Add(aCompound, aSS);
2063       }
2064     }
2065
2066     mapSelected.Clear();
2067     TopExp::MapShapes(aCompound, TopAbs_ShapeEnum(theShapeType), mapSelected);
2068     aCurrSelection = aCompound;
2069   }
2070
2071   // Create GEOM_Object for each found shared shape (collected in aCurrSelection)
2072   Handle(GEOM_Object) anObj, aLastCreated;
2073   Handle(TColStd_HArray1OfInteger) anArray;
2074   Handle(TColStd_HSequenceOfTransient) aSeq = new TColStd_HSequenceOfTransient;
2075   TCollection_AsciiString anAsciiList, anEntry;
2076
2077   TopoDS_Iterator itSel (aCurrSelection, Standard_True, Standard_True);
2078   for (; itSel.More(); itSel.Next()) {
2079     anArray = new TColStd_HArray1OfInteger(1,1);
2080     anArray->SetValue(1, anIndices.FindIndex(itSel.Value()));
2081     anObj = GetEngine()->AddSubShape(aMainObj, anArray);
2082     aSeq->Append(anObj);
2083
2084     aLastCreated = GEOM::GetCreatedLast( aLastCreated, anObj );
2085
2086     // for python command
2087     TDF_Tool::Entry(anObj->GetEntry(), anEntry);
2088     anAsciiList += anEntry;
2089     anAsciiList += ",";
2090   }
2091
2092   if (aSeq->IsEmpty()) {
2093     SetErrorCode("The given shapes have no shared sub-shapes of the requested type");
2094     return aSeq;
2095   }
2096
2097   // Make a Python command
2098   anAsciiList.Trunc(anAsciiList.Length() - 1);
2099
2100   // IPAL22904: TC6.5.0: order of python commands is wrong after dump study
2101   // Get the function of the latest published object
2102   Handle(GEOM_Function) aFunction = aLastCreated->GetLastFunction();
2103   if( aFunction.IsNull() ) // just in case
2104     aFunction = aMainShape;
2105
2106   GEOM::TPythonDump pd (aFunction, /*append=*/true);
2107   pd << "[" << anAsciiList.ToCString()
2108      << "] = geompy.GetSharedShapesMulti([";
2109
2110   it = theShapes.begin();
2111   pd << (*it++);
2112   while (it != theShapes.end()) {
2113     pd << ", " << (*it++);
2114   }
2115
2116   pd << "], " << TopAbs_ShapeEnum(theShapeType) << ")";
2117
2118   SetErrorCode(OK);
2119   return aSeq;
2120 }
2121
2122 //=============================================================================
2123 /*!
2124  *
2125  */
2126 //=============================================================================
2127 static GEOM::TPythonDump& operator<< (GEOM::TPythonDump&   theDump,
2128                                       const GEOMAlgo_State theState)
2129 {
2130   switch (theState) {
2131   case GEOMAlgo_ST_IN:
2132     theDump << "GEOM.ST_IN";
2133     break;
2134   case GEOMAlgo_ST_OUT:
2135     theDump << "GEOM.ST_OUT";
2136     break;
2137   case GEOMAlgo_ST_ON:
2138     theDump << "GEOM.ST_ON";
2139     break;
2140   case GEOMAlgo_ST_ONIN:
2141     theDump << "GEOM.ST_ONIN";
2142     break;
2143   case GEOMAlgo_ST_ONOUT:
2144     theDump << "GEOM.ST_ONOUT";
2145     break;
2146   default:
2147     theDump << "GEOM.ST_UNKNOWN";
2148     break;
2149   }
2150   return theDump;
2151 }
2152
2153 //=======================================================================
2154 //function : checkTypeShapesOn
2155 /*!
2156  * \brief Checks if theShapeType parameter of GetShapesOnXXX() is OK
2157  * \param theShapeType - the shape type to check
2158  * \retval bool  - result of the check
2159  */
2160 //=======================================================================
2161 bool GEOMImpl_IShapesOperations::checkTypeShapesOn(const Standard_Integer theShapeType)
2162 {
2163   if (theShapeType != TopAbs_VERTEX &&
2164       theShapeType != TopAbs_EDGE &&
2165       theShapeType != TopAbs_FACE &&
2166       theShapeType != TopAbs_SOLID) {
2167     SetErrorCode("Only solids, vertices, edges or faces can be found by this method");
2168     return false;
2169   }
2170   return true;
2171 }
2172
2173 //=======================================================================
2174 //function : makePlane
2175   /*!
2176    * \brief Creates Geom_Plane
2177     * \param theAx1 - shape object defining plane parameters
2178     * \retval Handle(Geom_Surface) - resulting surface
2179    */
2180 //=======================================================================
2181 Handle(Geom_Surface) GEOMImpl_IShapesOperations::makePlane(const TopoDS_Shape& anAx1)
2182 {
2183   if (anAx1.ShapeType() != TopAbs_EDGE) return NULL;
2184   TopoDS_Edge anEdge = TopoDS::Edge(anAx1);
2185   TopoDS_Vertex V1, V2;
2186   TopExp::Vertices(anEdge, V1, V2, Standard_True);
2187   if (V1.IsNull() || V2.IsNull()) {
2188     SetErrorCode("Bad edge given for the plane normal vector");
2189     return NULL;
2190   }
2191   gp_Pnt aLoc = BRep_Tool::Pnt(V1);
2192   gp_Vec aVec (aLoc, BRep_Tool::Pnt(V2));
2193   if (aVec.Magnitude() < Precision::Confusion()) {
2194     SetErrorCode("Vector with null magnitude given");
2195     return NULL;
2196   }
2197   return new Geom_Plane(aLoc, aVec);
2198 }
2199
2200 //=======================================================================
2201 //function : makeCylinder
2202   /*!
2203    * \brief Creates Geom_CylindricalSurface
2204     * \param theAx1 - edge defining cylinder axis
2205     * \param theRadius - cylinder radius
2206     * \retval Handle(Geom_Surface) - resulting surface
2207    */
2208 //=======================================================================
2209 Handle(Geom_Surface) GEOMImpl_IShapesOperations::makeCylinder(const TopoDS_Shape& anAxis,
2210                                                               const Standard_Real theRadius)
2211 {
2212   //Axis of the cylinder
2213   if (anAxis.ShapeType() != TopAbs_EDGE) {
2214     SetErrorCode("Not an edge given for the axis");
2215     return NULL;
2216   }
2217   TopoDS_Edge anEdge = TopoDS::Edge(anAxis);
2218   TopoDS_Vertex V1, V2;
2219   TopExp::Vertices(anEdge, V1, V2, Standard_True);
2220   if (V1.IsNull() || V2.IsNull()) {
2221     SetErrorCode("Bad edge given for the axis");
2222     return NULL;
2223   }
2224   gp_Pnt aLoc = BRep_Tool::Pnt(V1);
2225   gp_Vec aVec (aLoc, BRep_Tool::Pnt(V2));
2226   if (aVec.Magnitude() < Precision::Confusion()) {
2227     SetErrorCode("Vector with null magnitude given");
2228     return NULL;
2229   }
2230
2231   gp_Ax3 anAx3 (aLoc, aVec);
2232   return new Geom_CylindricalSurface(anAx3, theRadius);
2233 }
2234
2235 //=======================================================================
2236 //function : getShapesOnBoxIDs
2237   /*!
2238    * \brief Find IDs of sub-shapes complying with given status about surface
2239     * \param theBox - the box to check state of sub-shapes against
2240     * \param theShape - the shape to explore
2241     * \param theShapeType - type of sub-shape of theShape
2242     * \param theState - required state
2243     * \retval Handle(TColStd_HSequenceOfInteger) - IDs of found sub-shapes
2244    */
2245 //=======================================================================
2246 Handle(TColStd_HSequenceOfInteger)
2247   GEOMImpl_IShapesOperations::getShapesOnBoxIDs(const Handle(GEOM_Object)& theBox,
2248                                                 const Handle(GEOM_Object)& theShape,
2249                                                 const Standard_Integer theShapeType,
2250                                                 GEOMAlgo_State theState)
2251 {
2252   Handle(TColStd_HSequenceOfInteger) aSeqOfIDs;
2253
2254   TopoDS_Shape aBox = theBox->GetValue();
2255   TopoDS_Shape aShape = theShape->GetValue();
2256
2257   // Check presence of triangulation, build if need
2258   if (!GEOMUtils::CheckTriangulation(aShape)) {
2259     SetErrorCode("Cannot build triangulation on the shape");
2260     return aSeqOfIDs;
2261   }
2262
2263   // Call algo
2264   GEOMAlgo_FinderShapeOn2 aFinder;
2265   Standard_Real aTol = 0.0001; // default value
2266
2267   Handle(GEOMAlgo_ClsfBox) aClsfBox = new GEOMAlgo_ClsfBox;
2268   aClsfBox->SetBox(aBox);
2269
2270   aFinder.SetShape(aShape);
2271   aFinder.SetTolerance(aTol);
2272   aFinder.SetClsf(aClsfBox);
2273   aFinder.SetShapeType( (TopAbs_ShapeEnum)theShapeType );
2274   aFinder.SetState(theState);
2275   aFinder.Perform();
2276
2277   // Interprete results
2278   Standard_Integer iErr = aFinder.ErrorStatus();
2279   // the detailed description of error codes is in GEOMAlgo_FinderShapeOn1.cxx
2280   if (iErr) {
2281     MESSAGE(" iErr : " << iErr);
2282     TCollection_AsciiString aMsg (" iErr : ");
2283     aMsg += TCollection_AsciiString(iErr);
2284     SetErrorCode(aMsg);
2285     return aSeqOfIDs;
2286   }
2287   Standard_Integer iWrn = aFinder.WarningStatus();
2288   // the detailed description of warning codes is in GEOMAlgo_FinderShapeOn1.cxx
2289   if (iWrn) {
2290     MESSAGE(" *** iWrn : " << iWrn);
2291   }
2292
2293   const TopTools_ListOfShape& listSS = aFinder.Shapes(); // the result
2294
2295   if (listSS.Extent() < 1) {
2296     //SetErrorCode("Not a single sub-shape of the requested type found on the given surface");
2297     SetErrorCode(NOT_FOUND_ANY); // NPAL18017
2298     return aSeqOfIDs;
2299   }
2300
2301   // Fill sequence of object IDs
2302   aSeqOfIDs = new TColStd_HSequenceOfInteger;
2303
2304   TopTools_IndexedMapOfShape anIndices;
2305   TopExp::MapShapes(aShape, anIndices);
2306
2307   TopTools_ListIteratorOfListOfShape itSub (listSS);
2308   for (int index = 1; itSub.More(); itSub.Next(), ++index) {
2309     int id = anIndices.FindIndex(itSub.Value());
2310     aSeqOfIDs->Append(id);
2311   }
2312
2313   return aSeqOfIDs;
2314 }
2315
2316 //=======================================================================
2317 //function : GetShapesOnBoxIDs
2318 /*!
2319    * \brief Find sub-shapes complying with given status about surface
2320     * \param theBox - the box to check state of sub-shapes against
2321     * \param theShape - the shape to explore
2322     * \param theShapeType - type of sub-shape of theShape
2323     * \param theState - required state
2324     * \retval Handle(TColStd_HSequenceOfInteger) - IDs of found sub-shapes
2325  */
2326 //=======================================================================
2327 Handle(TColStd_HSequenceOfInteger)
2328     GEOMImpl_IShapesOperations::GetShapesOnBoxIDs(const Handle(GEOM_Object)& theBox,
2329                                                   const Handle(GEOM_Object)& theShape,
2330                                                   const Standard_Integer theShapeType,
2331                                                   GEOMAlgo_State theState)
2332 {
2333   // Find sub-shapes ids
2334   Handle(TColStd_HSequenceOfInteger) aSeqOfIDs =
2335     getShapesOnBoxIDs (theBox, theShape, theShapeType, theState);
2336   if ( aSeqOfIDs.IsNull()  || aSeqOfIDs->Length() == 0 )
2337     return NULL;
2338
2339   // The GetShapesOnBox() doesn't change object so no new function is required.
2340   Handle(GEOM_Function) aFunction = GEOM::GetCreatedLast(theShape,theBox)->GetLastFunction();
2341
2342   // Make a Python command
2343   GEOM::TPythonDump(aFunction, /*append=*/true)
2344     << "listShapesOnBoxIDs = geompy.GetShapesOnBoxIDs("
2345     << theBox << ", "
2346     << theShape << ", "
2347     << TopAbs_ShapeEnum(theShapeType) << ", "
2348     << theState << ")";
2349
2350   SetErrorCode(OK);
2351   return aSeqOfIDs;
2352 }
2353
2354 //=======================================================================
2355 //function : GetShapesOnBox
2356 /*!
2357    * \brief Find sub-shapes complying with given status about surface
2358     * \param theBox - the box to check state of sub-shapes against
2359     * \param theShape - the shape to explore
2360     * \param theShapeType - type of sub-shape of theShape
2361     * \param theState - required state
2362     * \retval Handle(TColStd_HSequenceOfTransient) - found sub-shapes
2363  */
2364 //=======================================================================
2365 Handle(TColStd_HSequenceOfTransient)
2366     GEOMImpl_IShapesOperations::GetShapesOnBox(const Handle(GEOM_Object)& theBox,
2367                                                const Handle(GEOM_Object)&  theShape,
2368                                                const Standard_Integer theShapeType,
2369                                                GEOMAlgo_State theState)
2370 {
2371   // Find sub-shapes ids
2372   Handle(TColStd_HSequenceOfInteger) aSeqOfIDs =
2373     getShapesOnBoxIDs (theBox, theShape, theShapeType, theState);
2374   if ( aSeqOfIDs.IsNull()  || aSeqOfIDs->Length() == 0 )
2375     return NULL;
2376
2377   // Find objects by indices
2378   TCollection_AsciiString anAsciiList;
2379   Handle(TColStd_HSequenceOfTransient) aSeq;
2380   aSeq = getObjectsShapesOn( theShape, aSeqOfIDs, anAsciiList );
2381   if ( aSeq.IsNull() || aSeq->IsEmpty() )
2382     return NULL;
2383
2384   // Make a Python command
2385
2386   Handle(GEOM_Object) anObj = Handle(GEOM_Object)::DownCast( aSeq->Value( 1 ));
2387   Handle(GEOM_Function) aFunction = anObj->GetLastFunction();
2388
2389   GEOM::TPythonDump(aFunction)
2390     << "[" << anAsciiList.ToCString() << "] = geompy.GetShapesOnBox("
2391     << theBox << ", "
2392     << theShape << ", "
2393     << TopAbs_ShapeEnum(theShapeType) << ", "
2394     << theState << ")";
2395
2396   SetErrorCode(OK);
2397   return aSeq;
2398 }
2399
2400 //=======================================================================
2401 //function : getShapesOnShapeIDs
2402 /*!
2403  * \brief Find IDs of sub-shapes complying with given status about surface
2404  * \param theCheckShape - the shape to check state of sub-shapes against
2405  * \param theShape - the shape to explore
2406  * \param theShapeType - type of sub-shape of theShape
2407  * \param theState - required state
2408  * \retval Handle(TColStd_HSequenceOfInteger) - IDs of found sub-shapes
2409  */
2410 //=======================================================================
2411 Handle(TColStd_HSequenceOfInteger)
2412   GEOMImpl_IShapesOperations::getShapesOnShapeIDs
2413                                  (const Handle(GEOM_Object)& theCheckShape,
2414                                   const Handle(GEOM_Object)& theShape,
2415                                   const Standard_Integer theShapeType,
2416                                   GEOMAlgo_State theState)
2417 {
2418   Handle(TColStd_HSequenceOfInteger) aSeqOfIDs;
2419
2420   TopoDS_Shape aCheckShape = theCheckShape->GetValue();
2421   TopoDS_Shape aShape = theShape->GetValue();
2422   TopTools_ListOfShape res;
2423
2424   // Check presence of triangulation, build if need
2425   if (!GEOMUtils::CheckTriangulation(aShape)) {
2426     SetErrorCode("Cannot build triangulation on the shape");
2427     return aSeqOfIDs;
2428   }
2429
2430   // Call algo
2431   GEOMAlgo_FinderShapeOn2 aFinder;
2432   Standard_Real aTol = 0.0001; // default value
2433
2434   Handle(GEOMAlgo_ClsfSolid) aClsfSolid = new GEOMAlgo_ClsfSolid;
2435   aClsfSolid->SetShape(aCheckShape);
2436
2437   aFinder.SetShape(aShape);
2438   aFinder.SetTolerance(aTol);
2439   aFinder.SetClsf(aClsfSolid);
2440   aFinder.SetShapeType( (TopAbs_ShapeEnum)theShapeType );
2441   aFinder.SetState(theState);
2442   aFinder.Perform();
2443
2444   // Interprete results
2445   Standard_Integer iErr = aFinder.ErrorStatus();
2446   // the detailed description of error codes is in GEOMAlgo_FinderShapeOn1.cxx
2447   if (iErr) {
2448     if (iErr == 41) {
2449       SetErrorCode("theCheckShape must be a solid");
2450     }
2451     else {
2452       MESSAGE(" iErr : " << iErr);
2453       TCollection_AsciiString aMsg (" iErr : ");
2454       aMsg += TCollection_AsciiString(iErr);
2455       SetErrorCode(aMsg);
2456     }
2457     return aSeqOfIDs;
2458   }
2459   Standard_Integer iWrn = aFinder.WarningStatus();
2460   // the detailed description of warning codes is in GEOMAlgo_FinderShapeOn1.cxx
2461   if (iWrn) {
2462     MESSAGE(" *** iWrn : " << iWrn);
2463   }
2464
2465   const TopTools_ListOfShape& listSS = aFinder.Shapes(); // the result
2466
2467   if (listSS.Extent() < 1) {
2468     //SetErrorCode("Not a single sub-shape of the requested type found on the given surface");
2469     SetErrorCode(NOT_FOUND_ANY); // NPAL18017
2470   }
2471
2472   // Fill sequence of object IDs
2473   aSeqOfIDs = new TColStd_HSequenceOfInteger;
2474
2475   TopTools_IndexedMapOfShape anIndices;
2476   TopExp::MapShapes(aShape, anIndices);
2477
2478   TopTools_ListIteratorOfListOfShape itSub (listSS);
2479   for (int index = 1; itSub.More(); itSub.Next(), ++index) {
2480     int id = anIndices.FindIndex(itSub.Value());
2481     aSeqOfIDs->Append(id);
2482   }
2483
2484   return aSeqOfIDs;
2485 }
2486
2487 //=======================================================================
2488 //function : GetShapesOnShapeIDs
2489 /*!
2490  * \brief Find sub-shapes complying with given status about surface
2491  * \param theCheckShape - the shape to check state of sub-shapes against
2492  * \param theShape - the shape to explore
2493  * \param theShapeType - type of sub-shape of theShape
2494  * \param theState - required state
2495  * \retval Handle(TColStd_HSequenceOfInteger) - IDs of found sub-shapes
2496  */
2497 //=======================================================================
2498 Handle(TColStd_HSequenceOfInteger)
2499     GEOMImpl_IShapesOperations::GetShapesOnShapeIDs
2500                             (const Handle(GEOM_Object)& theCheckShape,
2501                              const Handle(GEOM_Object)& theShape,
2502                              const Standard_Integer theShapeType,
2503                              GEOMAlgo_State theState)
2504 {
2505   Handle(TColStd_HSequenceOfInteger) aSeqOfIDs =
2506     getShapesOnShapeIDs (theCheckShape, theShape, theShapeType, theState);
2507
2508   if ( aSeqOfIDs.IsNull()  || aSeqOfIDs->Length() == 0 )
2509     return NULL;
2510
2511   // The GetShapesOnShape() doesn't change object so no new function is required.
2512   Handle(GEOM_Function) aFunction =
2513     GEOM::GetCreatedLast(theShape,theCheckShape)->GetLastFunction();
2514
2515   // Make a Python command
2516   GEOM::TPythonDump(aFunction, /*append=*/true)
2517     << "listShapesOnBoxIDs = geompy.GetShapesOnShapeIDs("
2518     << theCheckShape << ", "
2519     << theShape << ", "
2520     << TopAbs_ShapeEnum(theShapeType) << ", "
2521     << theState << ")";
2522
2523   SetErrorCode(OK);
2524   return aSeqOfIDs;
2525 }
2526
2527 //=======================================================================
2528 //function : GetShapesOnShape
2529 /*!
2530  * \brief Find sub-shapes complying with given status about surface
2531  * \param theCheckShape - the shape to check state of sub-shapes against
2532  * \param theShape - the shape to explore
2533  * \param theShapeType - type of sub-shape of theShape
2534  * \param theState - required state
2535  * \retval Handle(TColStd_HSequenceOfTransient) - found sub-shapes
2536  */
2537 //=======================================================================
2538 Handle(TColStd_HSequenceOfTransient)
2539   GEOMImpl_IShapesOperations::GetShapesOnShape
2540                              (const Handle(GEOM_Object)& theCheckShape,
2541                               const Handle(GEOM_Object)&  theShape,
2542                               const Standard_Integer theShapeType,
2543                               GEOMAlgo_State theState)
2544 {
2545   Handle(TColStd_HSequenceOfInteger) aSeqOfIDs =
2546     getShapesOnShapeIDs (theCheckShape, theShape, theShapeType, theState);
2547   if ( aSeqOfIDs.IsNull()  || aSeqOfIDs->Length() == 0 )
2548     return NULL;
2549
2550   // Find objects by indices
2551   TCollection_AsciiString anAsciiList;
2552   Handle(TColStd_HSequenceOfTransient) aSeq;
2553   aSeq = getObjectsShapesOn( theShape, aSeqOfIDs, anAsciiList );
2554
2555   if ( aSeq.IsNull() || aSeq->IsEmpty() )
2556     return NULL;
2557
2558   // Make a Python command
2559
2560   Handle(GEOM_Object) anObj = Handle(GEOM_Object)::DownCast( aSeq->Value( 1 ));
2561   Handle(GEOM_Function) aFunction = anObj->GetLastFunction();
2562
2563   GEOM::TPythonDump(aFunction)
2564     << "[" << anAsciiList.ToCString() << "] = geompy.GetShapesOnShape("
2565     << theCheckShape << ", "
2566     << theShape << ", "
2567     << TopAbs_ShapeEnum(theShapeType) << ", "
2568     << theState << ")";
2569
2570   SetErrorCode(OK);
2571   return aSeq;
2572 }
2573
2574 //=======================================================================
2575 //function : GetShapesOnShapeAsCompound
2576 //=======================================================================
2577 Handle(GEOM_Object) GEOMImpl_IShapesOperations::GetShapesOnShapeAsCompound
2578                              (const Handle(GEOM_Object)& theCheckShape,
2579                               const Handle(GEOM_Object)&  theShape,
2580                               const Standard_Integer theShapeType,
2581                               GEOMAlgo_State theState)
2582 {
2583   Handle(TColStd_HSequenceOfInteger) aSeqOfIDs =
2584     getShapesOnShapeIDs (theCheckShape, theShape, theShapeType, theState);
2585
2586   if ( aSeqOfIDs.IsNull()  || aSeqOfIDs->Length() == 0 )
2587     return NULL;
2588
2589   // Find objects by indices
2590   TCollection_AsciiString anAsciiList;
2591   Handle(TColStd_HSequenceOfTransient) aSeq;
2592   aSeq = getObjectsShapesOn( theShape, aSeqOfIDs, anAsciiList );
2593
2594   if ( aSeq.IsNull() || aSeq->IsEmpty() )
2595     return NULL;
2596
2597   TopoDS_Compound aCompound;
2598   BRep_Builder B;
2599   B.MakeCompound(aCompound);
2600   int i = 1;
2601   for(; i<=aSeq->Length(); i++) {
2602     Handle(GEOM_Object) anObj = Handle(GEOM_Object)::DownCast(aSeq->Value(i));
2603     TopoDS_Shape aShape_i = anObj->GetValue();
2604     B.Add(aCompound,aShape_i);
2605   }
2606
2607   //Add a new result object
2608   Handle(GEOM_Object) aRes = GetEngine()->AddObject(GetDocID(), GEOM_SHAPES_ON_SHAPE);
2609   Handle(GEOM_Function) aFunction =
2610     aRes->AddFunction(GEOMImpl_ShapeDriver::GetID(), SHAPES_ON_SHAPE);
2611   aFunction->SetValue(aCompound);
2612
2613   aSeq->Clear();
2614   aSeq->Append( theCheckShape->GetLastFunction() );
2615   aSeq->Append( theShape->GetLastFunction() );
2616
2617   GEOMImpl_IShapes aCI( aFunction );
2618   aCI.SetShapes( aSeq );
2619   aCI.SetSubShapeType( theShapeType );
2620   aCI.SetTolerance( theState );
2621
2622   GEOM::TPythonDump(aFunction)
2623     << aRes << " = geompy.GetShapesOnShapeAsCompound("
2624     << theCheckShape << ", "
2625     << theShape << ", "
2626     << TopAbs_ShapeEnum(theShapeType) << ", "
2627     << theState << ")";
2628
2629   SetErrorCode(OK);
2630
2631   return aRes;
2632 }
2633
2634 //=======================================================================
2635 //function : getShapesOnSurfaceIDs
2636   /*!
2637    * \brief Find IDs of sub-shapes complying with given status about surface
2638     * \param theSurface - the surface to check state of sub-shapes against
2639     * \param theShape - the shape to explore
2640     * \param theShapeType - type of sub-shape of theShape
2641     * \param theState - required state
2642     * \retval Handle(TColStd_HSequenceOfInteger) - IDs of found sub-shapes
2643    */
2644 //=======================================================================
2645 Handle(TColStd_HSequenceOfInteger)
2646   GEOMImpl_IShapesOperations::getShapesOnSurfaceIDs(const Handle(Geom_Surface)& theSurface,
2647                                                     const TopoDS_Shape&         theShape,
2648                                                     TopAbs_ShapeEnum            theShapeType,
2649                                                     GEOMAlgo_State              theState)
2650 {
2651   Handle(TColStd_HSequenceOfInteger) aSeqOfIDs;
2652
2653   // Check presence of triangulation, build if need
2654   if (!GEOMUtils::CheckTriangulation(theShape)) {
2655     SetErrorCode("Cannot build triangulation on the shape");
2656     return aSeqOfIDs;
2657   }
2658
2659   // BEGIN: Mantis issue 0020961: Error on a pipe T-Shape
2660   // Compute tolerance
2661   Standard_Real T, VertMax = -RealLast();
2662   try {
2663     OCC_CATCH_SIGNALS;
2664     for (TopExp_Explorer ExV (theShape, TopAbs_VERTEX); ExV.More(); ExV.Next()) {
2665       TopoDS_Vertex Vertex = TopoDS::Vertex(ExV.Current());
2666       T = BRep_Tool::Tolerance(Vertex);
2667       if (T > VertMax)
2668         VertMax = T;
2669     }
2670   }
2671   catch (Standard_Failure) {
2672     Handle(Standard_Failure) aFail = Standard_Failure::Caught();
2673     SetErrorCode(aFail->GetMessageString());
2674     return aSeqOfIDs;
2675   }
2676   // END: Mantis issue 0020961
2677
2678   // Call algo
2679   GEOMAlgo_FinderShapeOn1 aFinder;
2680   //Standard_Real aTol = 0.0001; // default value
2681   Standard_Real aTol = VertMax; // Mantis issue 0020961
2682
2683   aFinder.SetShape(theShape);
2684   aFinder.SetTolerance(aTol);
2685   aFinder.SetSurface(theSurface);
2686   aFinder.SetShapeType(theShapeType);
2687   aFinder.SetState(theState);
2688
2689   // Sets the minimal number of inner points for the faces that do not have own
2690   // inner points at all (for e.g. rectangular planar faces have just 2 triangles).
2691   // Default value=3
2692   aFinder.SetNbPntsMin(3);
2693   // Sets the maximal number of inner points for edges or faces.
2694   // It is usefull for the cases when this number is very big (e.g =2000) to improve
2695   // the performance. If this value =0, all inner points will be taken into account.
2696   // Default value=0
2697   aFinder.SetNbPntsMax(100);
2698
2699   aFinder.Perform();
2700
2701   // Interprete results
2702   Standard_Integer iErr = aFinder.ErrorStatus();
2703   // the detailed description of error codes is in GEOMAlgo_FinderShapeOn1.cxx
2704   if (iErr) {
2705     MESSAGE(" iErr : " << iErr);
2706     TCollection_AsciiString aMsg (" iErr : ");
2707     aMsg += TCollection_AsciiString(iErr);
2708     SetErrorCode(aMsg);
2709     return aSeqOfIDs;
2710   }
2711   Standard_Integer iWrn = aFinder.WarningStatus();
2712   // the detailed description of warning codes is in GEOMAlgo_FinderShapeOn1.cxx
2713   if (iWrn) {
2714     MESSAGE(" *** iWrn : " << iWrn);
2715   }
2716
2717   const TopTools_ListOfShape& listSS = aFinder.Shapes(); // the result
2718
2719   if (listSS.Extent() < 1) {
2720     //SetErrorCode("Not a single sub-shape of the requested type found on the given surface");
2721     SetErrorCode(NOT_FOUND_ANY); // NPAL18017
2722     return aSeqOfIDs;
2723   }
2724
2725   // Fill sequence of object IDs
2726   aSeqOfIDs = new TColStd_HSequenceOfInteger;
2727
2728   TopTools_IndexedMapOfShape anIndices;
2729   TopExp::MapShapes(theShape, anIndices);
2730
2731   TopTools_ListIteratorOfListOfShape itSub (listSS);
2732   for (int index = 1; itSub.More(); itSub.Next(), ++index) {
2733     int id = anIndices.FindIndex(itSub.Value());
2734     aSeqOfIDs->Append(id);
2735   }
2736
2737   return aSeqOfIDs;
2738 }
2739
2740 //=======================================================================
2741 //function : getObjectsShapesOn
2742 /*!
2743  * \brief Find shape objects and their entries by their ids
2744  * \param theShapeIDs - incoming shape ids
2745  * \param theShapeEntries - outgoing entries like "entry1, entry2, ..."
2746  * \retval Handle(TColStd_HSequenceOfTransient) - found shape objects
2747  */
2748 //=======================================================================
2749 Handle(TColStd_HSequenceOfTransient) GEOMImpl_IShapesOperations::
2750  getObjectsShapesOn(const Handle(GEOM_Object)&                theShape,
2751                     const Handle(TColStd_HSequenceOfInteger)& theShapeIDs,
2752                     TCollection_AsciiString &                 theShapeEntries)
2753 {
2754   Handle(TColStd_HSequenceOfTransient) aSeq;
2755
2756   if ( !theShapeIDs.IsNull() && theShapeIDs->Length() > 0 )
2757   {
2758     aSeq = new TColStd_HSequenceOfTransient;
2759     Handle(TColStd_HArray1OfInteger) anArray = new TColStd_HArray1OfInteger(1,1);
2760     TCollection_AsciiString anEntry;
2761     for ( int i = 1; i <= theShapeIDs->Length(); ++i )
2762     {
2763       anArray->SetValue(1, theShapeIDs->Value( i ));
2764       Handle(GEOM_Object) anObj = GetEngine()->AddSubShape(theShape, anArray);
2765       aSeq->Append( anObj );
2766
2767       TDF_Tool::Entry(anObj->GetEntry(), anEntry);
2768       if ( i != 1 ) theShapeEntries += ",";
2769       theShapeEntries += anEntry;
2770     }
2771   }
2772   return aSeq;
2773 }
2774
2775 //=======================================================================
2776 //function : getShapesOnSurface
2777 /*!
2778    * \brief Find sub-shapes complying with given status about surface
2779     * \param theSurface - the surface to check state of sub-shapes against
2780     * \param theShape - the shape to explore
2781     * \param theShapeType - type of sub-shape of theShape
2782     * \param theState - required state
2783     * \param theShapeEntries - outgoing entries like "entry1, entry2, ..."
2784     * \retval Handle(TColStd_HSequenceOfInteger) - IDs of found sub-shapes
2785  */
2786 //=======================================================================
2787 Handle(TColStd_HSequenceOfTransient)
2788     GEOMImpl_IShapesOperations::getShapesOnSurface(const Handle(Geom_Surface)& theSurface,
2789                                                    const Handle(GEOM_Object)&  theShape,
2790                                                    TopAbs_ShapeEnum            theShapeType,
2791                                                    GEOMAlgo_State              theState,
2792                                                    TCollection_AsciiString &   theShapeEntries)
2793 {
2794   // Find sub-shapes ids
2795   Handle(TColStd_HSequenceOfInteger) aSeqOfIDs =
2796     getShapesOnSurfaceIDs (theSurface, theShape->GetValue(), theShapeType, theState);
2797   if ( aSeqOfIDs.IsNull()  || aSeqOfIDs->Length() == 0 )
2798     return NULL;
2799
2800   return getObjectsShapesOn( theShape, aSeqOfIDs, theShapeEntries );
2801 }
2802
2803 //=============================================================================
2804 /*!
2805  *  GetShapesOnPlane
2806  */
2807 //=============================================================================
2808 Handle(TColStd_HSequenceOfTransient) GEOMImpl_IShapesOperations::GetShapesOnPlane
2809                                         (const Handle(GEOM_Object)& theShape,
2810                                          const Standard_Integer     theShapeType,
2811                                          const Handle(GEOM_Object)& theAx1,
2812                                          const GEOMAlgo_State       theState)
2813 {
2814   SetErrorCode(KO);
2815
2816   if (theShape.IsNull() || theAx1.IsNull()) return NULL;
2817
2818   TopoDS_Shape aShape = theShape->GetValue();
2819   TopoDS_Shape anAx1  = theAx1->GetValue();
2820
2821   if (aShape.IsNull() || anAx1.IsNull()) return NULL;
2822
2823   TopAbs_ShapeEnum aShapeType = TopAbs_ShapeEnum(theShapeType);
2824   if ( !checkTypeShapesOn( theShapeType ))
2825     return NULL;
2826
2827   // Create plane
2828   Handle(Geom_Surface) aPlane = makePlane( anAx1 );
2829   if ( aPlane.IsNull() )
2830     return NULL;
2831
2832   // Find objects
2833   TCollection_AsciiString anAsciiList;
2834   Handle(TColStd_HSequenceOfTransient) aSeq;
2835   aSeq = getShapesOnSurface( aPlane, theShape, aShapeType, theState, anAsciiList );
2836   if ( aSeq.IsNull() || aSeq->Length() == 0 )
2837     return NULL;
2838
2839   // Make a Python command
2840
2841   Handle(GEOM_Object) anObj = Handle(GEOM_Object)::DownCast( aSeq->Value( 1 ));
2842   Handle(GEOM_Function) aFunction = anObj->GetLastFunction();
2843
2844   GEOM::TPythonDump(aFunction) << "[" << anAsciiList.ToCString()
2845     << "] = geompy.GetShapesOnPlane(" << theShape << ", "
2846       << aShapeType << ", " << theAx1 << ", " << theState << ")";
2847
2848   SetErrorCode(OK);
2849   return aSeq;
2850 }
2851
2852 //=============================================================================
2853 /*!
2854  *  GetShapesOnPlaneWithLocation
2855  */
2856 //=============================================================================
2857 Handle(TColStd_HSequenceOfTransient) GEOMImpl_IShapesOperations::GetShapesOnPlaneWithLocation
2858                                         (const Handle(GEOM_Object)& theShape,
2859                                          const Standard_Integer     theShapeType,
2860                                          const Handle(GEOM_Object)& theAx1,
2861                                          const Handle(GEOM_Object)& thePnt,
2862                                          const GEOMAlgo_State       theState)
2863 {
2864   SetErrorCode(KO);
2865
2866   if (theShape.IsNull() || theAx1.IsNull() || thePnt.IsNull()) return NULL;
2867
2868   TopoDS_Shape aShape = theShape->GetValue();
2869   TopoDS_Shape anAx1  = theAx1->GetValue();
2870   TopoDS_Shape anPnt = thePnt->GetValue();
2871
2872   if (aShape.IsNull() || anAx1.IsNull() || anPnt.IsNull()) return NULL;
2873
2874   TopAbs_ShapeEnum aShapeType = TopAbs_ShapeEnum(theShapeType);
2875   if ( !checkTypeShapesOn( theShapeType ))
2876     return NULL;
2877
2878   // Create plane
2879   if ( anAx1.ShapeType() != TopAbs_EDGE || anPnt.ShapeType() != TopAbs_VERTEX ) return NULL;
2880   TopoDS_Vertex V1, V2, V3;
2881   TopoDS_Edge anEdge = TopoDS::Edge(anAx1);
2882   TopExp::Vertices(anEdge, V1, V2, Standard_True);
2883
2884   if (V1.IsNull() || V2.IsNull()) {
2885     SetErrorCode("Bad edge given for the plane normal vector");
2886     return NULL;
2887   }
2888   V3 = TopoDS::Vertex(anPnt);
2889
2890   if(V3.IsNull()) {
2891     SetErrorCode("Bad vertex given for the plane location");
2892       return NULL;
2893   }
2894   gp_Pnt aLoc = BRep_Tool::Pnt(V3);
2895   gp_Vec aVec(BRep_Tool::Pnt(V1),BRep_Tool::Pnt(V2));
2896
2897   if (aVec.Magnitude() < Precision::Confusion()) {
2898     SetErrorCode("Vector with null magnitude given");
2899     return NULL;
2900   }
2901   Handle(Geom_Surface) aPlane = new Geom_Plane(aLoc, aVec);
2902
2903   if ( aPlane.IsNull() )
2904     return NULL;
2905
2906   // Find objects
2907   TCollection_AsciiString anAsciiList;
2908   Handle(TColStd_HSequenceOfTransient) aSeq;
2909   aSeq = getShapesOnSurface( aPlane, theShape, aShapeType, theState, anAsciiList );
2910   if ( aSeq.IsNull() || aSeq->Length() == 0 )
2911     return NULL;
2912
2913   // Make a Python command
2914
2915   Handle(GEOM_Object) anObj = Handle(GEOM_Object)::DownCast( aSeq->Value( 1 ));
2916   Handle(GEOM_Function) aFunction = anObj->GetLastFunction();
2917
2918   GEOM::TPythonDump(aFunction) << "[" << anAsciiList.ToCString()
2919     << "] = geompy.GetShapesOnPlaneWithLocation(" << theShape << ", "
2920     << aShapeType << ", " << theAx1 << ", "<< thePnt <<", " << theState << ")";
2921
2922   SetErrorCode(OK);
2923   return aSeq;
2924 }
2925
2926 //=============================================================================
2927 /*!
2928  *  GetShapesOnCylinder
2929  */
2930 //=============================================================================
2931 Handle(TColStd_HSequenceOfTransient) GEOMImpl_IShapesOperations::GetShapesOnCylinder
2932                                           (const Handle(GEOM_Object)& theShape,
2933                                            const Standard_Integer     theShapeType,
2934                                            const Handle(GEOM_Object)& theAxis,
2935                                            const Standard_Real        theRadius,
2936                                            const GEOMAlgo_State       theState)
2937 {
2938   SetErrorCode(KO);
2939
2940   if (theShape.IsNull() || theAxis.IsNull()) return NULL;
2941
2942   TopoDS_Shape aShape = theShape->GetValue();
2943   TopoDS_Shape anAxis = theAxis->GetValue();
2944
2945   if (aShape.IsNull() || anAxis.IsNull()) return NULL;
2946
2947   TopAbs_ShapeEnum aShapeType = TopAbs_ShapeEnum(theShapeType);
2948   if ( !checkTypeShapesOn( aShapeType ))
2949     return NULL;
2950
2951   // Create a cylinder surface
2952   Handle(Geom_Surface) aCylinder = makeCylinder( anAxis, theRadius );
2953   if ( aCylinder.IsNull() )
2954     return NULL;
2955
2956   // Find objects
2957   TCollection_AsciiString anAsciiList;
2958   Handle(TColStd_HSequenceOfTransient) aSeq;
2959   aSeq = getShapesOnSurface( aCylinder, theShape, aShapeType, theState, anAsciiList );
2960   if ( aSeq.IsNull() || aSeq->Length() == 0 )
2961     return NULL;
2962
2963   // Make a Python command
2964
2965   Handle(GEOM_Object) anObj = Handle(GEOM_Object)::DownCast( aSeq->Value( 1 ));
2966   Handle(GEOM_Function) aFunction = anObj->GetLastFunction();
2967
2968   GEOM::TPythonDump(aFunction) << "[" << anAsciiList.ToCString()
2969     << "] = geompy.GetShapesOnCylinder(" << theShape << ", " << aShapeType
2970       << ", " << theAxis << ", " << theRadius << ", " << theState << ")";
2971
2972   SetErrorCode(OK);
2973   return aSeq;
2974 }
2975
2976 //=============================================================================
2977 /*!
2978  *  GetShapesOnCylinderWithLocation
2979  */
2980 //=============================================================================
2981 Handle(TColStd_HSequenceOfTransient) GEOMImpl_IShapesOperations::GetShapesOnCylinderWithLocation
2982                                           (const Handle(GEOM_Object)& theShape,
2983                                            const Standard_Integer     theShapeType,
2984                                            const Handle(GEOM_Object)& theAxis,
2985                                            const Handle(GEOM_Object)& thePnt,
2986                                            const Standard_Real        theRadius,
2987                                            const GEOMAlgo_State       theState)
2988 {
2989   SetErrorCode(KO);
2990
2991   if (theShape.IsNull() || theAxis.IsNull() || thePnt.IsNull()) return NULL;
2992
2993   TopoDS_Shape aShape = theShape->GetValue();
2994   TopoDS_Shape anAxis = theAxis->GetValue();
2995   TopoDS_Shape aPnt   = thePnt->GetValue();
2996
2997   if (aShape.IsNull() || anAxis.IsNull() || aPnt.IsNull()) return NULL;
2998
2999   if (aPnt.ShapeType() != TopAbs_VERTEX )
3000   {
3001     SetErrorCode("Bottom location point must be vertex");
3002     return NULL;
3003   }
3004
3005   TopAbs_ShapeEnum aShapeType = TopAbs_ShapeEnum(theShapeType);
3006   if ( !checkTypeShapesOn( aShapeType ))
3007     return NULL;
3008
3009   // Create a cylinder surface
3010   Handle(Geom_Surface) aCylinder = makeCylinder( anAxis, theRadius );
3011   if ( aCylinder.IsNull() )
3012     return NULL;
3013
3014   // translate the surface
3015   Handle(Geom_CylindricalSurface) aCylSurface =
3016     Handle(Geom_CylindricalSurface)::DownCast( aCylinder );
3017   if ( aCylSurface.IsNull() )
3018   {
3019     SetErrorCode("Unexpected surface type instead of Geom_CylindricalSurface");
3020     return NULL;
3021   }
3022   gp_Pnt fromLoc = aCylSurface->Cylinder().Location();
3023   gp_Pnt toLoc   = BRep_Tool::Pnt( TopoDS::Vertex( aPnt ));
3024   aCylinder->Translate( fromLoc, toLoc );
3025
3026   // Find objects
3027   TCollection_AsciiString anAsciiList;
3028   Handle(TColStd_HSequenceOfTransient) aSeq;
3029   aSeq = getShapesOnSurface( aCylinder, theShape, aShapeType, theState, anAsciiList );
3030   if ( aSeq.IsNull() || aSeq->Length() == 0 )
3031     return NULL;
3032
3033   // Make a Python command
3034
3035   Handle(GEOM_Object) anObj = Handle(GEOM_Object)::DownCast( aSeq->Value( 1 ));
3036   Handle(GEOM_Function) aFunction = anObj->GetLastFunction();
3037
3038   GEOM::TPythonDump(aFunction)
3039     << "[" << anAsciiList.ToCString()
3040     << "] = geompy.GetShapesOnCylinderWithLocation(" << theShape << ", " << aShapeType << ", "
3041     << theAxis << ", " << thePnt << ", " << theRadius << ", " << theState << ")";
3042
3043   SetErrorCode(OK);
3044   return aSeq;
3045 }
3046
3047 //=============================================================================
3048 /*!
3049  *  GetShapesOnSphere
3050  */
3051 //=============================================================================
3052 Handle(TColStd_HSequenceOfTransient) GEOMImpl_IShapesOperations::GetShapesOnSphere
3053                                           (const Handle(GEOM_Object)& theShape,
3054                                            const Standard_Integer     theShapeType,
3055                                            const Handle(GEOM_Object)& theCenter,
3056                                            const Standard_Real        theRadius,
3057                                            const GEOMAlgo_State       theState)
3058 {
3059   SetErrorCode(KO);
3060
3061   if (theShape.IsNull() || theCenter.IsNull()) return NULL;
3062
3063   TopoDS_Shape aShape  = theShape->GetValue();
3064   TopoDS_Shape aCenter = theCenter->GetValue();
3065
3066   if (aShape.IsNull() || aCenter.IsNull()) return NULL;
3067
3068   TopAbs_ShapeEnum aShapeType = TopAbs_ShapeEnum(theShapeType);
3069   if ( !checkTypeShapesOn( aShapeType ))
3070     return NULL;
3071
3072   // Center of the sphere
3073   if (aCenter.ShapeType() != TopAbs_VERTEX) return NULL;
3074   gp_Pnt aLoc = BRep_Tool::Pnt(TopoDS::Vertex(aCenter));
3075
3076   gp_Ax3 anAx3 (aLoc, gp::DZ());
3077   Handle(Geom_SphericalSurface) aSphere =
3078     new Geom_SphericalSurface(anAx3, theRadius);
3079
3080   // Find objects
3081   TCollection_AsciiString anAsciiList;
3082   Handle(TColStd_HSequenceOfTransient) aSeq;
3083   aSeq = getShapesOnSurface( aSphere, theShape, aShapeType, theState, anAsciiList );
3084   if ( aSeq.IsNull() || aSeq->Length() == 0 )
3085     return NULL;
3086
3087   // Make a Python command
3088
3089   Handle(GEOM_Object) anObj = Handle(GEOM_Object)::DownCast( aSeq->Value( 1 ));
3090   Handle(GEOM_Function) aFunction = anObj->GetLastFunction();
3091
3092   GEOM::TPythonDump(aFunction) << "[" << anAsciiList.ToCString()
3093     << "] = geompy.GetShapesOnSphere(" << theShape << ", " << aShapeType
3094       << ", " << theCenter << ", " << theRadius << ", " << theState << ")";
3095
3096   SetErrorCode(OK);
3097   return aSeq;
3098 }
3099
3100 //=============================================================================
3101 /*!
3102  *  GetShapesOnPlaneIDs
3103  */
3104 //=============================================================================
3105 Handle(TColStd_HSequenceOfInteger) GEOMImpl_IShapesOperations::GetShapesOnPlaneIDs
3106                                         (const Handle(GEOM_Object)& theShape,
3107                                          const Standard_Integer     theShapeType,
3108                                          const Handle(GEOM_Object)& theAx1,
3109                                          const GEOMAlgo_State       theState)
3110 {
3111   SetErrorCode(KO);
3112
3113   if (theShape.IsNull() || theAx1.IsNull()) return NULL;
3114
3115   TopoDS_Shape aShape = theShape->GetValue();
3116   TopoDS_Shape anAx1  = theAx1->GetValue();
3117
3118   if (aShape.IsNull() || anAx1.IsNull()) return NULL;
3119
3120   TopAbs_ShapeEnum aShapeType = TopAbs_ShapeEnum(theShapeType);
3121   if ( !checkTypeShapesOn( aShapeType ))
3122     return NULL;
3123
3124   // Create plane
3125   Handle(Geom_Surface) aPlane = makePlane( anAx1 );
3126   if ( aPlane.IsNull() )
3127     return NULL;
3128
3129   // Find object IDs
3130   Handle(TColStd_HSequenceOfInteger) aSeq;
3131   aSeq = getShapesOnSurfaceIDs( aPlane, aShape, aShapeType, theState );
3132
3133   // The GetShapesOnPlaneIDs() doesn't change object so no new function is required.
3134   Handle(GEOM_Function) aFunction = GEOM::GetCreatedLast(theShape,theAx1)->GetLastFunction();
3135
3136   // Make a Python command
3137   GEOM::TPythonDump(aFunction, /*append=*/true)
3138     << "listShapesOnPlane = geompy.GetShapesOnPlaneIDs"
3139     << "(" << theShape << "," << aShapeType << "," << theAx1 << "," << theState << ")";
3140
3141   SetErrorCode(OK);
3142   return aSeq;
3143 }
3144
3145 //=============================================================================
3146 /*!
3147  *  GetShapesOnPlaneWithLocationIDs
3148  */
3149 //=============================================================================
3150 Handle(TColStd_HSequenceOfInteger) GEOMImpl_IShapesOperations::GetShapesOnPlaneWithLocationIDs
3151                                         (const Handle(GEOM_Object)& theShape,
3152                                          const Standard_Integer     theShapeType,
3153                                          const Handle(GEOM_Object)& theAx1,
3154                                          const Handle(GEOM_Object)& thePnt,
3155                                          const GEOMAlgo_State       theState)
3156 {
3157   SetErrorCode(KO);
3158
3159   if (theShape.IsNull() || theAx1.IsNull() || thePnt.IsNull()) return NULL;
3160
3161   TopoDS_Shape aShape = theShape->GetValue();
3162   TopoDS_Shape anAx1  = theAx1->GetValue();
3163   TopoDS_Shape anPnt  = thePnt->GetValue();
3164
3165   if (aShape.IsNull() || anAx1.IsNull() || anPnt.IsNull()) return NULL;
3166
3167   TopAbs_ShapeEnum aShapeType = TopAbs_ShapeEnum(theShapeType);
3168   if ( !checkTypeShapesOn( aShapeType ))
3169     return NULL;
3170
3171   // Create plane
3172   if (anAx1.ShapeType() != TopAbs_EDGE || anPnt.ShapeType() != TopAbs_VERTEX) return NULL;
3173   TopoDS_Edge anEdge = TopoDS::Edge(anAx1);
3174   TopoDS_Vertex V1, V2, V3;
3175   TopExp::Vertices(anEdge, V1, V2, Standard_True);
3176   if (V1.IsNull() || V2.IsNull()) {
3177     SetErrorCode("Bad edge given for the plane normal vector");
3178     return NULL;
3179   }
3180   V3 = TopoDS::Vertex(anPnt);
3181   if(V3.IsNull()) {
3182     SetErrorCode("Bad vertex given for the plane location");
3183       return NULL;
3184   }
3185   gp_Pnt aLoc = BRep_Tool::Pnt(V3);
3186   gp_Vec aVec(BRep_Tool::Pnt(V1),BRep_Tool::Pnt(V2));
3187   if (aVec.Magnitude() < Precision::Confusion()) {
3188     SetErrorCode("Vector with null magnitude given");
3189     return NULL;
3190   }
3191
3192   Handle(Geom_Surface) aPlane = new Geom_Plane(aLoc, aVec);
3193   if ( aPlane.IsNull() )
3194     return NULL;
3195
3196   // Find object IDs
3197   Handle(TColStd_HSequenceOfInteger) aSeq;
3198   aSeq = getShapesOnSurfaceIDs( aPlane, aShape, aShapeType, theState );
3199
3200   // The GetShapesOnPlaneIDs() doesn't change object so no new function is required.
3201   Handle(GEOM_Function) aFunction = GEOM::GetCreatedLast(theShape,theAx1)->GetLastFunction();
3202
3203   // Make a Python command
3204   GEOM::TPythonDump(aFunction, /*append=*/true)
3205     << "listShapesOnPlane = geompy.GetShapesOnPlaneWithLocationIDs"
3206     << "(" << theShape << ", " << aShapeType << ", " << theAx1 << ", "<< thePnt << ", "  << theState << ")";
3207
3208   SetErrorCode(OK);
3209   return aSeq;
3210 }
3211
3212 //=============================================================================
3213 /*!
3214  *  GetShapesOnCylinderIDs
3215  */
3216 //=============================================================================
3217 Handle(TColStd_HSequenceOfInteger) GEOMImpl_IShapesOperations::GetShapesOnCylinderIDs
3218                                           (const Handle(GEOM_Object)& theShape,
3219                                            const Standard_Integer     theShapeType,
3220                                            const Handle(GEOM_Object)& theAxis,
3221                                            const Standard_Real        theRadius,
3222                                            const GEOMAlgo_State       theState)
3223 {
3224   SetErrorCode(KO);
3225
3226   if (theShape.IsNull() || theAxis.IsNull()) return NULL;
3227
3228   TopoDS_Shape aShape = theShape->GetValue();
3229   TopoDS_Shape anAxis = theAxis->GetValue();
3230
3231   if (aShape.IsNull() || anAxis.IsNull()) return NULL;
3232
3233   TopAbs_ShapeEnum aShapeType = TopAbs_ShapeEnum(theShapeType);
3234   if ( !checkTypeShapesOn( aShapeType ))
3235     return NULL;
3236
3237   // Create a cylinder surface
3238   Handle(Geom_Surface) aCylinder = makeCylinder( anAxis, theRadius );
3239   if ( aCylinder.IsNull() )
3240     return NULL;
3241
3242   // Find object IDs
3243   Handle(TColStd_HSequenceOfInteger) aSeq;
3244   aSeq = getShapesOnSurfaceIDs( aCylinder, aShape, aShapeType, theState );
3245
3246   // The GetShapesOnCylinder() doesn't change object so no new function is required.
3247   Handle(GEOM_Function) aFunction = GEOM::GetCreatedLast(theShape,theAxis)->GetLastFunction();
3248
3249   // Make a Python command
3250   GEOM::TPythonDump(aFunction, /*append=*/true)
3251     << "listShapesOnCylinder = geompy.GetShapesOnCylinderIDs"
3252     << "(" << theShape << ", " << aShapeType << ", " << theAxis << ", "
3253     << theRadius << ", " << theState << ")";
3254
3255   SetErrorCode(OK);
3256   return aSeq;
3257 }
3258
3259 //=============================================================================
3260 /*!
3261  *  GetShapesOnCylinderWithLocationIDs
3262  */
3263 //=============================================================================
3264 Handle(TColStd_HSequenceOfInteger) GEOMImpl_IShapesOperations::GetShapesOnCylinderWithLocationIDs
3265                                           (const Handle(GEOM_Object)& theShape,
3266                                            const Standard_Integer     theShapeType,
3267                                            const Handle(GEOM_Object)& theAxis,
3268                                            const Handle(GEOM_Object)& thePnt,
3269                                            const Standard_Real        theRadius,
3270                                            const GEOMAlgo_State       theState)
3271 {
3272   SetErrorCode(KO);
3273
3274   if (theShape.IsNull() || theAxis.IsNull() || thePnt.IsNull()) return NULL;
3275
3276   TopoDS_Shape aShape = theShape->GetValue();
3277   TopoDS_Shape anAxis = theAxis->GetValue();
3278   TopoDS_Shape aPnt   = thePnt->GetValue();
3279
3280   if (aShape.IsNull() || anAxis.IsNull() || aPnt.IsNull()) return NULL;
3281
3282   if (aPnt.ShapeType() != TopAbs_VERTEX )
3283   {
3284     SetErrorCode("Bottom location point must be vertex");
3285     return NULL;
3286   }
3287
3288   TopAbs_ShapeEnum aShapeType = TopAbs_ShapeEnum(theShapeType);
3289   if ( !checkTypeShapesOn( aShapeType ))
3290     return NULL;
3291
3292   // Create a cylinder surface
3293   Handle(Geom_Surface) aCylinder = makeCylinder( anAxis, theRadius );
3294   if ( aCylinder.IsNull() )
3295     return NULL;
3296
3297   // translate the surface
3298   Handle(Geom_CylindricalSurface) aCylSurface =
3299     Handle(Geom_CylindricalSurface)::DownCast( aCylinder );
3300   if ( aCylSurface.IsNull() )
3301   {
3302     SetErrorCode("Unexpected surface type instead of Geom_CylindricalSurface");
3303     return NULL;
3304   }
3305   gp_Pnt fromLoc = aCylSurface->Cylinder().Location();
3306   gp_Pnt toLoc   = BRep_Tool::Pnt( TopoDS::Vertex( aPnt ));
3307   aCylinder->Translate( fromLoc, toLoc );
3308
3309   // Find object IDs
3310   Handle(TColStd_HSequenceOfInteger) aSeq;
3311   aSeq = getShapesOnSurfaceIDs( aCylinder, aShape, aShapeType, theState );
3312
3313   // The GetShapesOnCylinder() doesn't change object so no new function is required.
3314   Handle(GEOM_Function) aFunction =
3315     GEOM::GetCreatedLast(theShape, GEOM::GetCreatedLast(thePnt,theAxis))->GetLastFunction();
3316
3317   // Make a Python command
3318   GEOM::TPythonDump(aFunction, /*append=*/true)
3319     << "listShapesOnCylinder = geompy.GetShapesOnCylinderWithLocationIDs"
3320     << "(" << theShape << ", " << aShapeType << ", " << theAxis << ", "
3321     << thePnt << ", " << theRadius << ", " << theState << ")";
3322
3323   SetErrorCode(OK);
3324   return aSeq;
3325 }
3326
3327 //=============================================================================
3328 /*!
3329  *  GetShapesOnSphereIDs
3330  */
3331 //=============================================================================
3332 Handle(TColStd_HSequenceOfInteger) GEOMImpl_IShapesOperations::GetShapesOnSphereIDs
3333                                           (const Handle(GEOM_Object)& theShape,
3334                                            const Standard_Integer     theShapeType,
3335                                            const Handle(GEOM_Object)& theCenter,
3336                                            const Standard_Real        theRadius,
3337                                            const GEOMAlgo_State       theState)
3338 {
3339   SetErrorCode(KO);
3340
3341   if (theShape.IsNull() || theCenter.IsNull()) return NULL;
3342
3343   TopoDS_Shape aShape  = theShape->GetValue();
3344   TopoDS_Shape aCenter = theCenter->GetValue();
3345
3346   if (aShape.IsNull() || aCenter.IsNull()) return NULL;
3347
3348   TopAbs_ShapeEnum aShapeType = TopAbs_ShapeEnum(theShapeType);
3349   if ( !checkTypeShapesOn( aShapeType ))
3350     return NULL;
3351
3352   // Center of the sphere
3353   if (aCenter.ShapeType() != TopAbs_VERTEX) return NULL;
3354   gp_Pnt aLoc = BRep_Tool::Pnt(TopoDS::Vertex(aCenter));
3355
3356   gp_Ax3 anAx3 (aLoc, gp::DZ());
3357   Handle(Geom_SphericalSurface) aSphere =
3358     new Geom_SphericalSurface(anAx3, theRadius);
3359
3360   // Find object IDs
3361   Handle(TColStd_HSequenceOfInteger) aSeq;
3362   aSeq = getShapesOnSurfaceIDs( aSphere, aShape, aShapeType, theState );
3363
3364   // The GetShapesOnSphere() doesn't change object so no new function is required.
3365   Handle(GEOM_Function) aFunction = GEOM::GetCreatedLast(theShape,theCenter)->GetLastFunction();
3366
3367   // Make a Python command
3368   GEOM::TPythonDump(aFunction, /*append=*/true)
3369     << "listShapesOnCylinder = geompy.GetShapesOnSphereIDs"
3370     << "(" << theShape << ", " << aShapeType << ", " << theCenter << ", "
3371     << theRadius << ", " << theState << ")";
3372
3373   SetErrorCode(OK);
3374   return aSeq;
3375 }
3376
3377 //=======================================================================
3378 //function : getShapesOnQuadrangleIDs
3379   /*!
3380    * \brief Find IDs of sub-shapes complying with given status about quadrangle
3381     * \param theShape - the shape to explore
3382     * \param theShapeType - type of sub-shape of theShape
3383     * \param theTopLeftPoint - top left quadrangle corner
3384     * \param theTopRigthPoint - top right quadrangle corner
3385     * \param theBottomLeftPoint - bottom left quadrangle corner
3386     * \param theBottomRigthPoint - bottom right quadrangle corner
3387     * \param theState - required state
3388     * \retval Handle(TColStd_HSequenceOfInteger) - IDs of found sub-shapes
3389    */
3390 //=======================================================================
3391 Handle(TColStd_HSequenceOfInteger)
3392   GEOMImpl_IShapesOperations::getShapesOnQuadrangleIDs (const Handle(GEOM_Object)& theShape,
3393                                                         const Standard_Integer     theShapeType,
3394                                                         const Handle(GEOM_Object)& theTopLeftPoint,
3395                                                         const Handle(GEOM_Object)& theTopRigthPoint,
3396                                                         const Handle(GEOM_Object)& theBottomLeftPoint,
3397                                                         const Handle(GEOM_Object)& theBottomRigthPoint,
3398                                                         const GEOMAlgo_State       theState)
3399 {
3400   SetErrorCode(KO);
3401
3402   if ( theShape.IsNull() ||
3403        theTopLeftPoint.IsNull() ||
3404        theTopRigthPoint.IsNull() ||
3405        theBottomLeftPoint.IsNull() ||
3406        theBottomRigthPoint.IsNull() )
3407     return NULL;
3408
3409   TopoDS_Shape aShape = theShape->GetValue();
3410   TopoDS_Shape aTL = theTopLeftPoint->GetValue();
3411   TopoDS_Shape aTR = theTopRigthPoint->GetValue();
3412   TopoDS_Shape aBL = theBottomLeftPoint->GetValue();
3413   TopoDS_Shape aBR = theBottomRigthPoint->GetValue();
3414
3415   if (aShape.IsNull() ||
3416       aTL.IsNull() ||
3417       aTR.IsNull() ||
3418       aBL.IsNull() ||
3419       aBR.IsNull() ||
3420       aTL.ShapeType() != TopAbs_VERTEX ||
3421       aTR.ShapeType() != TopAbs_VERTEX ||
3422       aBL.ShapeType() != TopAbs_VERTEX ||
3423       aBR.ShapeType() != TopAbs_VERTEX )
3424     return NULL;
3425
3426   TopAbs_ShapeEnum aShapeType = TopAbs_ShapeEnum(theShapeType);
3427   if ( !checkTypeShapesOn( aShapeType ))
3428     return NULL;
3429
3430   Handle(TColStd_HSequenceOfInteger) aSeqOfIDs;
3431
3432   // Check presence of triangulation, build if need
3433   if (!GEOMUtils::CheckTriangulation(aShape)) {
3434     SetErrorCode("Cannot build triangulation on the shape");
3435     return aSeqOfIDs;
3436   }
3437
3438   // Call algo
3439   gp_Pnt aPntTL = BRep_Tool::Pnt(TopoDS::Vertex(aTL));
3440   gp_Pnt aPntTR = BRep_Tool::Pnt(TopoDS::Vertex(aTR));
3441   gp_Pnt aPntBL = BRep_Tool::Pnt(TopoDS::Vertex(aBL));
3442   gp_Pnt aPntBR = BRep_Tool::Pnt(TopoDS::Vertex(aBR));
3443
3444   GEOMAlgo_FinderShapeOnQuad aFinder( aPntTL, aPntTR, aPntBL, aPntBR );
3445   Standard_Real aTol = 0.0001; // default value
3446
3447   aFinder.SetShape(aShape);
3448   aFinder.SetTolerance(aTol);
3449   //aFinder.SetSurface(theSurface);
3450   aFinder.SetShapeType(aShapeType);
3451   aFinder.SetState(theState);
3452
3453   // Sets the minimal number of inner points for the faces that do not have own
3454   // inner points at all (for e.g. rectangular planar faces have just 2 triangles).
3455   // Default value=3
3456   aFinder.SetNbPntsMin(3);
3457   // Sets the maximal number of inner points for edges or faces.
3458   // It is usefull for the cases when this number is very big (e.g =2000) to improve
3459   // the performance. If this value =0, all inner points will be taken into account.
3460   // Default value=0
3461   aFinder.SetNbPntsMax(100);
3462
3463   aFinder.Perform();
3464
3465   // Interprete results
3466   Standard_Integer iErr = aFinder.ErrorStatus();
3467   // the detailed description of error codes is in GEOMAlgo_FinderShapeOn1.cxx
3468   if (iErr) {
3469     MESSAGE(" iErr : " << iErr);
3470     TCollection_AsciiString aMsg (" iErr : ");
3471     aMsg += TCollection_AsciiString(iErr);
3472     SetErrorCode(aMsg);
3473     return aSeqOfIDs;
3474   }
3475   Standard_Integer iWrn = aFinder.WarningStatus();
3476   // the detailed description of warning codes is in GEOMAlgo_FinderShapeOn1.cxx
3477   if (iWrn) {
3478     MESSAGE(" *** iWrn : " << iWrn);
3479   }
3480
3481   const TopTools_ListOfShape& listSS = aFinder.Shapes(); // the result
3482
3483   if (listSS.Extent() < 1) {
3484     //SetErrorCode("Not a single sub-shape of the requested type found on the given surface");
3485     SetErrorCode(NOT_FOUND_ANY); // NPAL18017
3486     return aSeqOfIDs;
3487   }
3488
3489   // Fill sequence of object IDs
3490   aSeqOfIDs = new TColStd_HSequenceOfInteger;
3491
3492   TopTools_IndexedMapOfShape anIndices;
3493   TopExp::MapShapes(aShape, anIndices);
3494
3495   TopTools_ListIteratorOfListOfShape itSub (listSS);
3496   for (int index = 1; itSub.More(); itSub.Next(), ++index) {
3497     int id = anIndices.FindIndex(itSub.Value());
3498     aSeqOfIDs->Append(id);
3499   }
3500   return aSeqOfIDs;
3501 }
3502
3503 //=======================================================================
3504 //function : GetShapesOnQuadrangle
3505   /*!
3506    * \brief Find sub-shapes complying with given status about quadrangle
3507     * \param theShape - the shape to explore
3508     * \param theShapeType - type of sub-shape of theShape
3509     * \param theTopLeftPoint - top left quadrangle corner
3510     * \param theTopRigthPoint - top right quadrangle corner
3511     * \param theBottomLeftPoint - bottom left quadrangle corner
3512     * \param theBottomRigthPoint - bottom right quadrangle corner
3513     * \param theState - required state
3514     * \retval Handle(TColStd_HSequenceOfInteger) - IDs of found sub-shapes
3515    */
3516 //=======================================================================
3517 Handle(TColStd_HSequenceOfTransient)
3518     GEOMImpl_IShapesOperations::GetShapesOnQuadrangle (const Handle(GEOM_Object)& theShape,
3519                                                        const Standard_Integer     theShapeType,
3520                                                        const Handle(GEOM_Object)& theTopLeftPoint,
3521                                                        const Handle(GEOM_Object)& theTopRigthPoint,
3522                                                        const Handle(GEOM_Object)& theBottomLeftPoint,
3523                                                        const Handle(GEOM_Object)& theBottomRigthPoint,
3524                                                        const GEOMAlgo_State       theState)
3525 {
3526   // Find indices
3527   Handle(TColStd_HSequenceOfInteger) aSeqOfIDs =
3528     getShapesOnQuadrangleIDs( theShape,
3529                               theShapeType,
3530                               theTopLeftPoint,
3531                               theTopRigthPoint,
3532                               theBottomLeftPoint,
3533                               theBottomRigthPoint,
3534                               theState);
3535   if ( aSeqOfIDs.IsNull() || aSeqOfIDs->IsEmpty() )
3536     return NULL;
3537
3538   // Find objects by indices
3539   TCollection_AsciiString anAsciiList;
3540   Handle(TColStd_HSequenceOfTransient) aSeq;
3541   aSeq = getObjectsShapesOn( theShape, aSeqOfIDs, anAsciiList );
3542   if ( aSeq.IsNull() || aSeq->IsEmpty() )
3543     return NULL;
3544
3545   // Make a Python command
3546
3547   Handle(GEOM_Object) anObj = Handle(GEOM_Object)::DownCast( aSeq->Value( 1 ));
3548   Handle(GEOM_Function) aFunction = anObj->GetLastFunction();
3549
3550   GEOM::TPythonDump(aFunction)
3551     << "[" << anAsciiList.ToCString() << "] = geompy.GetShapesOnQuadrangle("
3552     << theShape << ", "
3553     << TopAbs_ShapeEnum(theShapeType) << ", "
3554     << theTopLeftPoint << ", "
3555     << theTopRigthPoint << ", "
3556     << theBottomLeftPoint << ", "
3557     << theBottomRigthPoint << ", "
3558     << theState << ")";
3559
3560   SetErrorCode(OK);
3561   return aSeq;
3562 }
3563
3564 //=======================================================================
3565 //function : GetShapesOnQuadrangleIDs
3566   /*!
3567    * \brief Find IDs of sub-shapes complying with given status about quadrangle
3568     * \param theShape - the shape to explore
3569     * \param theShapeType - type of sub-shape of theShape
3570     * \param theTopLeftPoint - top left quadrangle corner
3571     * \param theTopRigthPoint - top right quadrangle corner
3572     * \param theBottomLeftPoint - bottom left quadrangle corner
3573     * \param theBottomRigthPoint - bottom right quadrangle corner
3574     * \param theState - required state
3575     * \retval Handle(TColStd_HSequenceOfInteger) - IDs of found sub-shapes
3576    */
3577 //=======================================================================
3578 Handle(TColStd_HSequenceOfInteger)
3579   GEOMImpl_IShapesOperations::GetShapesOnQuadrangleIDs (const Handle(GEOM_Object)& theShape,
3580                                                         const Standard_Integer     theShapeType,
3581                                                         const Handle(GEOM_Object)& theTopLeftPoint,
3582                                                         const Handle(GEOM_Object)& theTopRigthPoint,
3583                                                         const Handle(GEOM_Object)& theBottomLeftPoint,
3584                                                         const Handle(GEOM_Object)& theBottomRigthPoint,
3585                                                         const GEOMAlgo_State       theState)
3586 {
3587   // Find indices
3588   Handle(TColStd_HSequenceOfInteger) aSeqOfIDs =
3589     getShapesOnQuadrangleIDs( theShape,
3590                               theShapeType,
3591                               theTopLeftPoint,
3592                               theTopRigthPoint,
3593                               theBottomLeftPoint,
3594                               theBottomRigthPoint,
3595                               theState);
3596   if ( aSeqOfIDs.IsNull() || aSeqOfIDs->IsEmpty() )
3597     return NULL;
3598
3599   // Make a Python command
3600
3601   // The GetShapesOnCylinder() doesn't change object so no new function is required.
3602   Handle(GEOM_Object) lastObj = GEOM::GetCreatedLast(theShape,theTopLeftPoint);
3603   lastObj = GEOM::GetCreatedLast(lastObj,theTopRigthPoint);
3604   lastObj = GEOM::GetCreatedLast(lastObj,theBottomRigthPoint);
3605   lastObj = GEOM::GetCreatedLast(lastObj,theBottomLeftPoint);
3606   Handle(GEOM_Function) aFunction = lastObj->GetLastFunction();
3607
3608   GEOM::TPythonDump(aFunction, /*append=*/true)
3609     << "listShapesOnQuadrangle = geompy.GetShapesOnQuadrangleIDs("
3610     << theShape << ", "
3611     << TopAbs_ShapeEnum(theShapeType) << ", "
3612     << theTopLeftPoint << ", "
3613     << theTopRigthPoint << ", "
3614     << theBottomLeftPoint << ", "
3615     << theBottomRigthPoint << ", "
3616     << theState << ")";
3617
3618   SetErrorCode(OK);
3619   return aSeqOfIDs;
3620 }
3621
3622 //=============================================================================
3623 /*!
3624  *  GetInPlaceOfShape
3625  */
3626 //=============================================================================
3627 static bool GetInPlaceOfShape (const Handle(GEOM_Function)& theWhereFunction,
3628                                const TopTools_IndexedMapOfShape& theWhereIndices,
3629                                const TopoDS_Shape& theWhat,
3630                                TColStd_ListOfInteger& theModifiedList)
3631 {
3632   if (theWhereFunction.IsNull() || theWhat.IsNull()) return false;
3633
3634   if (theWhereIndices.Contains(theWhat)) {
3635     // entity was not changed by the operation
3636     Standard_Integer aWhatIndex = theWhereIndices.FindIndex(theWhat);
3637     theModifiedList.Append(aWhatIndex);
3638     return true;
3639   }
3640
3641   // try to find in history
3642   TDF_Label aHistoryLabel = theWhereFunction->GetHistoryEntry(Standard_False);
3643
3644   // search in history for all argument shapes
3645   Standard_Boolean isFound = Standard_False;
3646   Standard_Boolean isGood = Standard_False;
3647
3648   TDF_LabelSequence aLabelSeq;
3649   theWhereFunction->GetDependency(aLabelSeq);
3650   Standard_Integer nbArg = aLabelSeq.Length();
3651
3652   for (Standard_Integer iarg = 1; iarg <= nbArg && !isFound; iarg++) {
3653
3654     TDF_Label anArgumentRefLabel = aLabelSeq.Value(iarg);
3655
3656     Handle(GEOM_Object) anArgumentObject = GEOM_Object::GetReferencedObject(anArgumentRefLabel);
3657     TopoDS_Shape anArgumentShape = anArgumentObject->GetValue();
3658
3659     TopTools_IndexedMapOfShape anArgumentIndices;
3660     TopExp::MapShapes(anArgumentShape, anArgumentIndices);
3661
3662     if (anArgumentIndices.Contains(theWhat)) {
3663       isFound = Standard_True;
3664       Standard_Integer aWhatIndex = anArgumentIndices.FindIndex(theWhat);
3665
3666       // Find corresponding label in history
3667       TDF_Label anArgumentHistoryLabel =
3668         theWhereFunction->GetArgumentHistoryEntry(anArgumentRefLabel, Standard_False);
3669       if (anArgumentHistoryLabel.IsNull()) {
3670         // Lost History of operation argument. Possibly, all its entities was removed.
3671         isGood = Standard_True;
3672       }
3673       else {
3674         TDF_Label aWhatHistoryLabel = anArgumentHistoryLabel.FindChild(aWhatIndex, Standard_False);
3675
3676         if (aWhatHistoryLabel.IsNull()) {
3677           // Removed entity ? Compound ? Compsolid ? Shell ? Wire
3678           isGood = Standard_False;
3679         } else {
3680           Handle(TDataStd_IntegerArray) anIntegerArray;
3681           if (!aWhatHistoryLabel.FindAttribute(TDataStd_IntegerArray::GetID(), anIntegerArray)) {
3682             //Error: Empty modifications history for the sought shape.
3683             isGood = Standard_False;
3684           }
3685           else {
3686             isGood = Standard_True;
3687             Standard_Integer imod, aModifLen = anIntegerArray->Array()->Length();
3688             for (imod = 1; imod <= aModifLen; imod++) {
3689               theModifiedList.Append(anIntegerArray->Array()->Value(imod));
3690             }
3691           }
3692         }
3693       }
3694     }
3695   }
3696
3697   isFound = isGood;
3698
3699   if (!isFound) {
3700     // try compound/compsolid/shell/wire element by element
3701     bool isFoundAny = false;
3702     TopTools_MapOfShape mapShape;
3703
3704     if (theWhat.ShapeType() == TopAbs_COMPOUND ||
3705         theWhat.ShapeType() == TopAbs_COMPSOLID) {
3706       // recursive processing of compound/compsolid
3707       TopoDS_Iterator anIt (theWhat, Standard_True, Standard_True);
3708       for (; anIt.More(); anIt.Next()) {
3709         if (mapShape.Add(anIt.Value())) {
3710           TopoDS_Shape curWhat = anIt.Value();
3711           isFoundAny = GetInPlaceOfShape(theWhereFunction, theWhereIndices, curWhat, theModifiedList);
3712           if (isFoundAny) isFound = Standard_True;
3713         }
3714       }
3715     }
3716     else if (theWhat.ShapeType() == TopAbs_SHELL) {
3717       // try to replace a shell by its faces images
3718       TopExp_Explorer anExp (theWhat, TopAbs_FACE);
3719       for (; anExp.More(); anExp.Next()) {
3720         if (mapShape.Add(anExp.Current())) {
3721           TopoDS_Shape curWhat = anExp.Current();
3722           isFoundAny = GetInPlaceOfShape(theWhereFunction, theWhereIndices, curWhat, theModifiedList);
3723           if (isFoundAny) isFound = Standard_True;
3724         }
3725       }
3726     }
3727     else if (theWhat.ShapeType() == TopAbs_WIRE) {
3728       // try to replace a wire by its edges images
3729       TopExp_Explorer anExp (theWhat, TopAbs_EDGE);
3730       for (; anExp.More(); anExp.Next()) {
3731         if (mapShape.Add(anExp.Current())) {
3732           TopoDS_Shape curWhat = anExp.Current();
3733           isFoundAny = GetInPlaceOfShape(theWhereFunction, theWhereIndices, curWhat, theModifiedList);
3734           if (isFoundAny) isFound = Standard_True;
3735         }
3736       }
3737     }
3738     else {
3739       // Removed entity
3740     }
3741   }
3742
3743   return isFound;
3744 }
3745
3746 //=============================================================================
3747 /*!
3748  *  GetShapeProperties
3749  */
3750 //=============================================================================
3751 void GEOMImpl_IShapesOperations::GetShapeProperties( const TopoDS_Shape aShape, Standard_Real tab[],
3752                                                      gp_Pnt & aVertex )
3753 {
3754   GProp_GProps theProps;
3755   gp_Pnt aCenterMass;
3756   //TopoDS_Shape aPntShape;
3757   Standard_Real aShapeSize;
3758
3759   if    (aShape.ShapeType() == TopAbs_VERTEX) aCenterMass = BRep_Tool::Pnt( TopoDS::Vertex( aShape ) );
3760   else if (aShape.ShapeType() == TopAbs_EDGE) BRepGProp::LinearProperties(aShape,  theProps);
3761   else if (aShape.ShapeType() == TopAbs_FACE) BRepGProp::SurfaceProperties(aShape, theProps);
3762   else                                        BRepGProp::VolumeProperties(aShape,  theProps);
3763
3764   if (aShape.ShapeType() == TopAbs_VERTEX)
3765     aShapeSize = 1;
3766   else {
3767     aCenterMass = theProps.CentreOfMass();
3768     aShapeSize  = theProps.Mass();
3769   }
3770
3771 //   aPntShape = BRepBuilderAPI_MakeVertex(aCenterMass).Shape();
3772 //   aVertex   = BRep_Tool::Pnt( TopoDS::Vertex( aPntShape ) );
3773   aVertex = aCenterMass;
3774   tab[0] = aVertex.X();
3775   tab[1] = aVertex.Y();
3776   tab[2] = aVertex.Z();
3777   tab[3] = aShapeSize;
3778   return;
3779 }
3780
3781 namespace {
3782
3783   //================================================================================
3784   /*!
3785    * \brief Return normal to face at extrema point
3786    */
3787   //================================================================================
3788
3789   gp_Vec GetNormal (const TopoDS_Face& face, const BRepExtrema_DistShapeShape& extrema)
3790   {
3791     gp_Vec defaultNorm(1,0,0); // to have same normals on different faces
3792     try {
3793       // get UV at extrema point
3794       Standard_Real u,v, f,l;
3795       switch ( extrema.SupportTypeShape2(1) ) {
3796       case BRepExtrema_IsInFace: {
3797         extrema.ParOnFaceS2(1, u, v );
3798         break;
3799       }
3800       case BRepExtrema_IsOnEdge: {
3801         TopoDS_Edge edge = TopoDS::Edge( extrema.SupportOnShape2(1));
3802         Handle(Geom2d_Curve) pcurve = BRep_Tool::CurveOnSurface( edge, face, f,l );
3803         extrema.ParOnEdgeS2( 1, u );
3804         gp_Pnt2d uv = pcurve->Value( u );
3805         u = uv.Coord(1);
3806         v = uv.Coord(2);
3807         break;
3808       }
3809       case BRepExtrema_IsVertex: return defaultNorm;
3810       }
3811       // get derivatives
3812       BRepAdaptor_Surface surface( face, false );
3813       gp_Vec du, dv; gp_Pnt p;
3814       surface.D1( u, v, p, du, dv );
3815
3816       return du ^ dv;
3817
3818     } catch (Standard_Failure ) {
3819     }
3820     return defaultNorm;
3821   }
3822 }
3823
3824 //=============================================================================
3825 /*!
3826  *  case GetInPlace:
3827  *  default:
3828  */
3829 //=============================================================================
3830 Handle(GEOM_Object) GEOMImpl_IShapesOperations::GetInPlace (Handle(GEOM_Object) theShapeWhere,
3831                                                             Handle(GEOM_Object) theShapeWhat)
3832 {
3833   SetErrorCode(KO);
3834
3835   if (theShapeWhere.IsNull() || theShapeWhat.IsNull()) return NULL;
3836
3837   TopoDS_Shape aWhere = theShapeWhere->GetValue();
3838   TopoDS_Shape aWhat  = theShapeWhat->GetValue();
3839
3840   if (aWhere.IsNull() || aWhat.IsNull()) {
3841     SetErrorCode("Error: aWhere and aWhat TopoDS_Shape are Null.");
3842     return NULL;
3843   }
3844
3845   // Compute confusion tolerance.
3846   Standard_Real    aTolConf = Precision::Confusion();
3847   Standard_Integer i;
3848
3849   for (i = 0; i < 2; ++i) {
3850     TopExp_Explorer anExp(i == 0 ? aWhere : aWhat, TopAbs_VERTEX);
3851
3852     for (; anExp.More(); anExp.Next()) {
3853       const TopoDS_Vertex aVtx = TopoDS::Vertex(anExp.Current());
3854       const Standard_Real aTolVtx = BRep_Tool::Tolerance(aVtx);
3855
3856       if (aTolVtx > aTolConf) {
3857         aTolConf = aTolVtx;
3858       }
3859     }
3860   }
3861
3862   // Compute mass tolerance.
3863   Bnd_Box       aBoundingBox;
3864   Standard_Real aXmin, aYmin, aZmin, aXmax, aYmax, aZmax;
3865   Standard_Real aMassTol;
3866
3867   BRepBndLib::Add(aWhere, aBoundingBox);
3868   BRepBndLib::Add(aWhat,  aBoundingBox);
3869   aBoundingBox.Get(aXmin, aYmin, aZmin, aXmax, aYmax, aZmax);
3870   aMassTol = Max(aXmax - aXmin, aYmax - aYmin);
3871   aMassTol = Max(aMassTol, aZmax - aZmin);
3872   aMassTol *= aTolConf;
3873
3874   // Searching for the sub-shapes inside the ShapeWhere shape
3875   GEOMAlgo_GetInPlace aGIP;
3876   aGIP.SetTolerance(aTolConf);
3877   aGIP.SetTolMass(aMassTol);
3878   aGIP.SetTolCG(aTolConf);
3879
3880   aGIP.SetArgument(aWhat);
3881   aGIP.SetShapeWhere(aWhere);
3882
3883   aGIP.Perform();
3884   int iErr = aGIP.ErrorStatus();
3885   if (iErr) {
3886     SetErrorCode("Error in GEOMAlgo_GetInPlace");
3887     return NULL;
3888   }
3889
3890   // Add direct result.
3891   TopTools_ListOfShape        aLSA;
3892   const TopoDS_Shape         &aShapeResult = aGIP.Result();
3893   TopTools_MapOfShape         aMFence;
3894   TopTools_IndexedMapOfShape  aWhereIndices;
3895
3896   TopExp::MapShapes(aWhere, aWhereIndices);
3897
3898   if (aShapeResult.IsNull() == Standard_False) {
3899     TopoDS_Iterator anIt(aShapeResult);
3900
3901     for (; anIt.More(); anIt.Next()) {
3902       const TopoDS_Shape &aPart = anIt.Value();
3903
3904       if(aWhereIndices.Contains(aPart) && aMFence.Add(aPart)) {
3905         aLSA.Append(aPart);
3906       }
3907     }
3908   }
3909
3910   if (aLSA.Extent() == 0) {
3911     SetErrorCode(NOT_FOUND_ANY); // Not found any Results
3912     return NULL;
3913   }
3914
3915   Handle(TColStd_HArray1OfInteger) aModifiedArray = new TColStd_HArray1OfInteger (1, aLSA.Extent());
3916   TopTools_ListIteratorOfListOfShape anIterModif (aLSA);
3917   for (Standard_Integer imod = 1; anIterModif.More(); anIterModif.Next(), imod++) {
3918     if (aWhereIndices.Contains(anIterModif.Value())) {
3919       aModifiedArray->SetValue(imod, aWhereIndices.FindIndex(anIterModif.Value()));
3920     }
3921     else {
3922       SetErrorCode("Error: wrong sub-shape returned");
3923       return NULL;
3924     }
3925   }
3926
3927   //Add a new object
3928   Handle(GEOM_Object) aResult = GetEngine()->AddSubShape(theShapeWhere, aModifiedArray);
3929   if (aResult.IsNull()) {
3930     SetErrorCode("Error in algorithm: result found, but cannot be returned.");
3931     return NULL;
3932   }
3933
3934   if (aModifiedArray->Length() > 1 || theShapeWhat->GetType() == GEOM_GROUP) {
3935     //Set a GROUP type
3936     aResult->SetType(GEOM_GROUP);
3937
3938     //Set a sub-shape type
3939     TopoDS_Shape aFirstFound = aLSA.First();
3940     TopAbs_ShapeEnum aShapeType = aFirstFound.ShapeType();
3941
3942     TDF_Label aFreeLabel = aResult->GetFreeLabel();
3943     TDataStd_Integer::Set(aFreeLabel, (Standard_Integer)aShapeType);
3944   }
3945
3946   //Make a Python command
3947   Handle(GEOM_Function) aFunction = aResult->GetFunction(1);
3948
3949   GEOM::TPythonDump(aFunction) << aResult << " = geompy.GetInPlace("
3950     << theShapeWhere << ", " << theShapeWhat << ", True)";
3951
3952   SetErrorCode(OK);
3953   return aResult;
3954 }
3955
3956 //=============================================================================
3957 /*!
3958  *  case GetInPlaceOld:
3959  *  default:
3960  */
3961 //=============================================================================
3962 Handle(GEOM_Object) GEOMImpl_IShapesOperations::GetInPlaceOld (Handle(GEOM_Object) theShapeWhere,
3963                                                                Handle(GEOM_Object) theShapeWhat)
3964 {
3965   SetErrorCode(KO);
3966
3967   if (theShapeWhere.IsNull() || theShapeWhat.IsNull()) return NULL;
3968
3969   TopoDS_Shape aWhere = theShapeWhere->GetValue();
3970   TopoDS_Shape aWhat  = theShapeWhat->GetValue();
3971   TopoDS_Shape aPntShape;
3972   TopoDS_Vertex aVertex;
3973
3974   if (aWhere.IsNull() || aWhat.IsNull()) {
3975     SetErrorCode("Error: aWhere and aWhat TopoDS_Shape are Null.");
3976     return NULL;
3977   }
3978
3979   Handle(GEOM_Function) aWhereFunction = theShapeWhere->GetLastFunction();
3980   if (aWhereFunction.IsNull()) {
3981     SetErrorCode("Error: aWhereFunction is Null.");
3982     return NULL;
3983   }
3984
3985   TopTools_IndexedMapOfShape aWhereIndices;
3986   TopExp::MapShapes(aWhere, aWhereIndices);
3987
3988   TColStd_ListOfInteger aModifiedList;
3989   Standard_Integer aWhereIndex;
3990   Handle(TColStd_HArray1OfInteger) aModifiedArray;
3991   Handle(GEOM_Object) aResult;
3992
3993   bool isFound = false;
3994   TopAbs_ShapeEnum iType = TopAbs_SOLID;
3995   //Standard_Real    aWhat_Mass = 0., aWhere_Mass = 0.;
3996   Standard_Real    tab_aWhat[4],    tab_aWhere[4];
3997   Standard_Real    dl_l = 1e-3;
3998   Standard_Real    min_l, Tol_0D, Tol_1D, Tol_2D, Tol_3D, Tol_Mass;
3999   Standard_Real    aXmin, aYmin, aZmin, aXmax, aYmax, aZmax;
4000   Bnd_Box          BoundingBox;
4001   gp_Pnt           aPnt, aPnt_aWhat, tab_Pnt[2];
4002   GProp_GProps     aProps;
4003
4004   // Find the iType of the aWhat shape
4005   /*
4006   if      ( aWhat.ShapeType() == TopAbs_VERTEX )                                         iType = TopAbs_VERTEX;
4007   else if ( aWhat.ShapeType() == TopAbs_EDGE  || aWhat.ShapeType() == TopAbs_WIRE )      iType = TopAbs_EDGE;
4008   else if ( aWhat.ShapeType() == TopAbs_FACE  || aWhat.ShapeType() == TopAbs_SHELL )     iType = TopAbs_FACE;
4009   else if ( aWhat.ShapeType() == TopAbs_SOLID || aWhat.ShapeType() == TopAbs_COMPSOLID ) iType = TopAbs_SOLID;
4010   else if ( aWhat.ShapeType() == TopAbs_COMPOUND ) {
4011     // Only the iType of the first shape in the compound is taken into account
4012     TopoDS_Iterator It (aWhat, Standard_False, Standard_False);
4013     if ( !It.More() ) {
4014       SetErrorCode("Error: theShapeWhat is an empty COMPOUND.");
4015       return NULL;
4016     }
4017     TopAbs_ShapeEnum compType = It.Value().ShapeType();
4018     if      ( compType == TopAbs_VERTEX )                               iType = TopAbs_VERTEX;
4019     else if ( compType == TopAbs_EDGE  || compType == TopAbs_WIRE )     iType = TopAbs_EDGE;
4020     else if ( compType == TopAbs_FACE  || compType == TopAbs_SHELL)     iType = TopAbs_FACE;
4021     else if ( compType == TopAbs_SOLID || compType == TopAbs_COMPSOLID) iType = TopAbs_SOLID;
4022   }
4023   else {
4024     SetErrorCode("Error: An attempt to extract a shape of not supported type.");
4025     return NULL;
4026   }
4027   */
4028   iType = GEOMUtils::GetTypeOfSimplePart(aWhat);
4029   if (iType == TopAbs_SHAPE) {
4030     SetErrorCode("Error: An attempt to extract a shape of not supported type.");
4031     return NULL;
4032   }
4033
4034   TopExp_Explorer Exp_aWhat  ( aWhat,  iType );
4035   TopExp_Explorer Exp_aWhere ( aWhere, iType );
4036   TopExp_Explorer Exp_Edge   ( aWhere, TopAbs_EDGE );
4037
4038   // Find the shortest edge in theShapeWhere shape
4039   BRepBndLib::Add(aWhere, BoundingBox);
4040   BoundingBox.Get(aXmin, aYmin, aZmin, aXmax, aYmax, aZmax);
4041   min_l = fabs(aXmax - aXmin);
4042   if( min_l < fabs(aYmax - aYmin) ) min_l = fabs(aYmax - aYmin);
4043   if( min_l < fabs(aZmax - aZmin) ) min_l = fabs(aZmax - aZmin);
4044   min_l /= dl_l;
4045   // Mantis issue 0020908 BEGIN
4046   if (!Exp_Edge.More()) {
4047     min_l = Precision::Confusion();
4048   }
4049   // Mantis issue 0020908 END
4050   for ( Standard_Integer nbEdge = 0; Exp_Edge.More(); Exp_Edge.Next(), nbEdge++ ) {
4051     TopExp_Explorer Exp_Vertex( Exp_Edge.Current(), TopAbs_VERTEX);
4052     for ( Standard_Integer nbVertex = 0; Exp_Vertex.More(); Exp_Vertex.Next(), nbVertex++ ) {
4053       aPnt = BRep_Tool::Pnt( TopoDS::Vertex( Exp_Vertex.Current() ) );
4054       tab_Pnt[nbVertex] = aPnt;
4055     }
4056     if ( ! tab_Pnt[0].IsEqual(tab_Pnt[1], dl_l) ) {
4057       BRepGProp::LinearProperties(Exp_Edge.Current(), aProps);
4058       if ( aProps.Mass() < min_l ) min_l = aProps.Mass();
4059     }
4060   }
4061
4062   // Compute tolerances
4063   Tol_0D = dl_l;
4064   Tol_1D = dl_l * min_l;
4065   Tol_2D = dl_l * ( min_l * min_l) * ( 2. + dl_l);
4066   Tol_3D = dl_l * ( min_l * min_l * min_l ) * ( 3. + (3 * dl_l) + (dl_l * dl_l) );
4067
4068   if (Tol_0D < Precision::Confusion()) Tol_0D = Precision::Confusion();
4069   if (Tol_1D < Precision::Confusion()) Tol_1D = Precision::Confusion();
4070   if (Tol_2D < Precision::Confusion()) Tol_2D = Precision::Confusion();
4071   if (Tol_3D < Precision::Confusion()) Tol_3D = Precision::Confusion();
4072
4073   //if (Tol_1D > 1.0) Tol_1D = 1.0;
4074   //if (Tol_2D > 1.0) Tol_2D = 1.0;
4075   //if (Tol_3D > 1.0) Tol_3D = 1.0;
4076
4077   Tol_Mass = Tol_3D;
4078   if ( iType == TopAbs_VERTEX )    Tol_Mass = Tol_0D;
4079   else if ( iType == TopAbs_EDGE ) Tol_Mass = Tol_1D;
4080   else if ( iType == TopAbs_FACE ) Tol_Mass = Tol_2D;
4081
4082   // Compute the ShapeWhat Mass
4083   /*
4084   for ( ; Exp_aWhat.More(); Exp_aWhat.Next() ) {
4085     if ( iType == TopAbs_VERTEX ) {
4086       aWhat_Mass += 1;
4087       continue;
4088     }
4089     else if ( iType == TopAbs_EDGE ) BRepGProp::LinearProperties(Exp_aWhat.Current(),  aProps);
4090     else if ( iType == TopAbs_FACE ) BRepGProp::SurfaceProperties(Exp_aWhat.Current(), aProps);
4091     else                             BRepGProp::VolumeProperties(Exp_aWhat.Current(),  aProps);
4092     aWhat_Mass += aProps.Mass();
4093   }
4094   */
4095
4096   // Searching for the sub-shapes inside the ShapeWhere shape
4097   TopTools_MapOfShape map_aWhere;
4098   for ( Exp_aWhere.ReInit(); Exp_aWhere.More(); Exp_aWhere.Next() ) {
4099     if (!map_aWhere.Add(Exp_aWhere.Current()))
4100       continue; // skip repeated shape to avoid mass addition
4101     GetShapeProperties( Exp_aWhere.Current(), tab_aWhere, aPnt );
4102     for ( Exp_aWhat.ReInit(); Exp_aWhat.More(); Exp_aWhat.Next() ) {
4103       GetShapeProperties( Exp_aWhat.Current(), tab_aWhat, aPnt_aWhat );
4104       if ( fabs(tab_aWhat[3] - tab_aWhere[3]) <= Tol_Mass && aPnt_aWhat.Distance(aPnt) <= Tol_1D )
4105         isFound = true;
4106       else {
4107         if ( (tab_aWhat[3] - tab_aWhere[3]) > Tol_Mass ) {
4108           aPntShape = BRepBuilderAPI_MakeVertex( aPnt ).Shape();
4109           aVertex   = TopoDS::Vertex( aPntShape );
4110           BRepExtrema_DistShapeShape aWhereDistance ( aVertex, Exp_aWhere.Current() );
4111           BRepExtrema_DistShapeShape aWhatDistance  ( aVertex, Exp_aWhat.Current() );
4112           if ( aWhereDistance.IsDone() && aWhatDistance.IsDone() &&
4113                fabs(aWhereDistance.Value() - aWhatDistance.Value()) <= Tol_1D )
4114           {
4115             // 0020162: "EDF 961 GEOM : Getinplace is getting additionnal orthogonal faces"
4116             // aVertex must be projected to the same point on Where and on What
4117             gp_Pnt pOnWhat  = aWhatDistance.PointOnShape2(1);
4118             gp_Pnt pOnWhere = aWhereDistance.PointOnShape2(1);
4119             isFound = ( pOnWhat.Distance(pOnWhere) <= Tol_1D );
4120             if ( isFound && iType == TopAbs_FACE )
4121             {
4122               // check normals at pOnWhat and pOnWhere
4123               const double angleTol = M_PI/180.;
4124               gp_Vec normToWhat  = GetNormal( TopoDS::Face(Exp_aWhat.Current()), aWhatDistance);
4125               gp_Vec normToWhere = GetNormal( TopoDS::Face(Exp_aWhere.Current()), aWhereDistance);
4126               if ( normToWhat * normToWhere < 0 )
4127                 normToWhat.Reverse();
4128               isFound = ( normToWhat.Angle( normToWhere ) < angleTol );
4129             }
4130           }
4131         }
4132       }
4133       if ( isFound ) {
4134         aWhereIndex = aWhereIndices.FindIndex(Exp_aWhere.Current());
4135         aModifiedList.Append(aWhereIndex);
4136         //aWhere_Mass += tab_aWhere[3];
4137         isFound = false;
4138         break;
4139       }
4140     }
4141     //if ( fabs( aWhat_Mass - aWhere_Mass ) <= Tol_Mass )
4142       //break;
4143   }
4144
4145   if (aModifiedList.Extent() == 0) { // Not found any Results
4146     SetErrorCode(NOT_FOUND_ANY);
4147     return NULL;
4148   }
4149
4150   aModifiedArray = new TColStd_HArray1OfInteger (1, aModifiedList.Extent());
4151   TColStd_ListIteratorOfListOfInteger anIterModif (aModifiedList);
4152   for (Standard_Integer imod = 1; anIterModif.More(); anIterModif.Next(), imod++)
4153     aModifiedArray->SetValue(imod, anIterModif.Value());
4154
4155   //Add a new object
4156   aResult = GetEngine()->AddSubShape(theShapeWhere, aModifiedArray);
4157   if (aResult.IsNull()) {
4158     SetErrorCode("Error in algorithm: result found, but cannot be returned.");
4159     return NULL;
4160   }
4161
4162   if (aModifiedArray->Length() > 1 || theShapeWhat->GetType() == GEOM_GROUP) {
4163     //Set a GROUP type
4164     aResult->SetType(GEOM_GROUP);
4165
4166     //Set a sub-shape type
4167     TopoDS_Shape aFirstFound = aWhereIndices.FindKey(aModifiedArray->Value(1));
4168     TopAbs_ShapeEnum aShapeType = aFirstFound.ShapeType();
4169
4170     TDF_Label aFreeLabel = aResult->GetFreeLabel();
4171     TDataStd_Integer::Set(aFreeLabel, (Standard_Integer)aShapeType);
4172   }
4173
4174   //Make a Python command
4175   Handle(GEOM_Function) aFunction = aResult->GetFunction(1);
4176
4177   GEOM::TPythonDump(aFunction) << aResult << " = geompy.GetInPlace("
4178     << theShapeWhere << ", " << theShapeWhat << ", False)";
4179
4180   SetErrorCode(OK);
4181   return aResult;
4182 }
4183
4184 //=======================================================================
4185 //function : GetInPlaceByHistory
4186 //purpose  :
4187 //=======================================================================
4188 Handle(GEOM_Object) GEOMImpl_IShapesOperations::GetInPlaceByHistory
4189                                           (Handle(GEOM_Object) theShapeWhere,
4190                                            Handle(GEOM_Object) theShapeWhat)
4191 {
4192   SetErrorCode(KO);
4193
4194   if (theShapeWhere.IsNull() || theShapeWhat.IsNull()) return NULL;
4195
4196   TopoDS_Shape aWhere = theShapeWhere->GetValue();
4197   TopoDS_Shape aWhat  = theShapeWhat->GetValue();
4198
4199   if (aWhere.IsNull() || aWhat.IsNull()) return NULL;
4200
4201   Handle(GEOM_Function) aWhereFunction = theShapeWhere->GetLastFunction();
4202   if (aWhereFunction.IsNull()) return NULL;
4203
4204   //Fill array of indices
4205   TopTools_IndexedMapOfShape aWhereIndices;
4206   TopExp::MapShapes(aWhere, aWhereIndices);
4207
4208   // process shape
4209   TColStd_ListOfInteger aModifiedList;
4210   bool isFound = GetInPlaceOfShape(aWhereFunction, aWhereIndices, aWhat, aModifiedList);
4211
4212   if (!isFound || aModifiedList.Extent() < 1) {
4213     SetErrorCode("Error: No history found for the sought shape or its sub-shapes.");
4214     return NULL;
4215   }
4216
4217   Standard_Integer nbFound = aModifiedList.Extent();
4218   TColStd_ListIteratorOfListOfInteger anIterModif (aModifiedList);
4219   if ( nbFound > 1 )
4220   {
4221     // remove sub-shapes inappropriate for group creation
4222     TopAbs_ShapeEnum subType = TopAbs_SHAPE;
4223     while ( anIterModif.More() ) {
4224       TopAbs_ShapeEnum type = aWhereIndices( anIterModif.Value() ).ShapeType();
4225       bool okForGroup = ( type == TopAbs_VERTEX || type == TopAbs_EDGE ||
4226                           type == TopAbs_FACE   || type == TopAbs_SOLID );
4227       if ( okForGroup ) {
4228         if ( subType == TopAbs_SHAPE )
4229           subType = type;
4230         else
4231           okForGroup = ( subType == type );
4232       }
4233       if ( okForGroup )
4234         anIterModif.Next();
4235       else
4236         aModifiedList.Remove( anIterModif );
4237       nbFound -= ( !okForGroup );
4238     }
4239     if ( nbFound == 0 ) {
4240       SetErrorCode("Error: result found but it's type is inappropriate for group creation.");
4241       return NULL;
4242     }
4243   }
4244
4245   Handle(TColStd_HArray1OfInteger) aModifiedArray =
4246     new TColStd_HArray1OfInteger( 1, nbFound );
4247   anIterModif.Initialize(aModifiedList);
4248   for (Standard_Integer imod = 1; anIterModif.More(); anIterModif.Next(), imod++)
4249     aModifiedArray->SetValue(imod, anIterModif.Value());
4250
4251   //Add a new object
4252   Handle(GEOM_Object) aResult = GetEngine()->AddSubShape(theShapeWhere, aModifiedArray);
4253   if (aResult.IsNull()) {
4254     SetErrorCode("Error in algorithm: result found, but cannot be returned.");
4255     return NULL;
4256   }
4257
4258   if (aModifiedArray->Length() > 1) {
4259     //Set a GROUP type
4260     aResult->SetType(GEOM_GROUP);
4261
4262     //Set a sub-shape type
4263     TopoDS_Shape aFirstFound = aWhereIndices.FindKey(aModifiedArray->Value(1));
4264     TopAbs_ShapeEnum aShapeType = aFirstFound.ShapeType();
4265
4266     TDF_Label aFreeLabel = aResult->GetFreeLabel();
4267     TDataStd_Integer::Set(aFreeLabel, (Standard_Integer)aShapeType);
4268   }
4269
4270   //Make a Python command
4271   Handle(GEOM_Function) aFunction = aResult->GetFunction(1);
4272
4273   GEOM::TPythonDump(aFunction) << aResult << " = geompy.GetInPlaceByHistory("
4274                                << theShapeWhere << ", " << theShapeWhat << ")";
4275
4276   SetErrorCode(OK);
4277   return aResult;
4278 }
4279
4280 #define MAX_TOLERANCE 1.e-7
4281
4282 //=======================================================================
4283 //function : isSameEdge
4284 //purpose  : Returns True if two edges coincide
4285 //=======================================================================
4286 static bool isSameEdge(const TopoDS_Edge& theEdge1, const TopoDS_Edge& theEdge2)
4287 {
4288   TopoDS_Vertex V11, V12, V21, V22;
4289   TopExp::Vertices(theEdge1, V11, V12);
4290   TopExp::Vertices(theEdge2, V21, V22);
4291   gp_Pnt P11 = BRep_Tool::Pnt(V11);
4292   gp_Pnt P12 = BRep_Tool::Pnt(V12);
4293   gp_Pnt P21 = BRep_Tool::Pnt(V21);
4294   gp_Pnt P22 = BRep_Tool::Pnt(V22);
4295   bool coincide = false;
4296
4297   //Check that ends of edges coincide
4298   if(P11.Distance(P21) <= MAX_TOLERANCE) {
4299     if(P12.Distance(P22) <= MAX_TOLERANCE) coincide =  true;
4300   }
4301   else if(P11.Distance(P22) <= MAX_TOLERANCE) {
4302     if(P12.Distance(P21) <= MAX_TOLERANCE) coincide = true;
4303   }
4304
4305   if(!coincide) return false;
4306
4307   if (BRep_Tool::Degenerated(theEdge1))
4308     if (BRep_Tool::Degenerated(theEdge2)) return true;
4309     else return false;
4310   else
4311     if (BRep_Tool::Degenerated(theEdge2)) return false;
4312
4313   double U11, U12, U21, U22;
4314   Handle(Geom_Curve) C1 = BRep_Tool::Curve(theEdge1, U11, U12);
4315   Handle(Geom_Curve) C2 = BRep_Tool::Curve(theEdge2, U21, U22);
4316   if(C1->DynamicType() == C2->DynamicType()) return true;
4317
4318   //Check that both edges has the same geometry
4319   double range = U12-U11;
4320   double U = U11+ range/3.0;
4321   gp_Pnt P1 = C1->Value(U);     //Compute a point on one third of the edge's length
4322   U = U11+range*2.0/3.0;
4323   gp_Pnt P2 = C1->Value(U);     //Compute a point on two thirds of the edge's length
4324
4325   if(!GeomLib_Tool::Parameter(C2, P1, MAX_TOLERANCE, U) ||  U < U21 || U > U22)
4326     return false;
4327
4328   if(P1.Distance(C2->Value(U)) > MAX_TOLERANCE) return false;
4329
4330   if(!GeomLib_Tool::Parameter(C2, P2, MAX_TOLERANCE, U) || U < U21 || U > U22)
4331     return false;
4332
4333   if(P2.Distance(C2->Value(U)) > MAX_TOLERANCE) return false;
4334
4335   return true;
4336 }
4337
4338 #include <TopoDS_TShape.hxx>
4339 //=======================================================================
4340 //function : isSameFace
4341 //purpose  : Returns True if two faces coincide
4342 //=======================================================================
4343 static bool isSameFace(const TopoDS_Face& theFace1, const TopoDS_Face& theFace2)
4344 {
4345   TopExp_Explorer E(theFace1, TopAbs_EDGE);
4346   TopTools_ListOfShape LS1, LS2;
4347   for(; E.More(); E.Next()) LS1.Append(E.Current());
4348
4349   E.Init(theFace2, TopAbs_EDGE);
4350   for(; E.More(); E.Next()) LS2.Append(E.Current());
4351
4352   //Compare the number of edges in the faces
4353   if(LS1.Extent() != LS2.Extent()) return false;
4354
4355   double aMin = RealFirst(), aMax = RealLast();
4356   double xminB1=aMax, yminB1=aMax, zminB1=aMax, xminB2=aMax, yminB2=aMax, zminB2=aMax;
4357   double xmaxB1=aMin, ymaxB1=aMin, zmaxB1=aMin, xmaxB2=aMin, ymaxB2=aMin, zmaxB2=aMin;
4358
4359   for(E.Init(theFace1, TopAbs_VERTEX); E.More(); E.Next()) {
4360     gp_Pnt P = BRep_Tool::Pnt(TopoDS::Vertex(E.Current()));
4361     if(P.X() < xminB1) xminB1 = P.X();
4362     if(P.Y() < yminB1) yminB1 = P.Y();
4363     if(P.Z() < zminB1) zminB1 = P.Z();
4364     if(P.X() > xmaxB1) xmaxB1 = P.X();
4365     if(P.Y() > ymaxB1) ymaxB1 = P.Y();
4366     if(P.Z() > zmaxB1) zmaxB1 = P.Z();
4367   }
4368
4369   for(E.Init(theFace2, TopAbs_VERTEX); E.More(); E.Next()) {
4370     gp_Pnt P = BRep_Tool::Pnt(TopoDS::Vertex(E.Current()));
4371     if(P.X() < xminB2) xminB2 = P.X();
4372     if(P.Y() < yminB2) yminB2 = P.Y();
4373     if(P.Z() < zminB2) zminB2 = P.Z();
4374     if(P.X() > xmaxB2) xmaxB2 = P.X();
4375     if(P.Y() > ymaxB2) ymaxB2 = P.Y();
4376     if(P.Z() > zmaxB2) zmaxB2 = P.Z();
4377   }
4378
4379   //Compare the bounding boxes of both faces
4380   if(gp_Pnt(xminB1, yminB1, zminB1).Distance(gp_Pnt(xminB2, yminB2, zminB2)) > MAX_TOLERANCE)
4381     return false;
4382
4383   if(gp_Pnt(xmaxB1, ymaxB1, zmaxB1).Distance(gp_Pnt(xmaxB2, ymaxB2, zmaxB2)) > MAX_TOLERANCE)
4384     return false;
4385
4386   Handle(Geom_Surface) S1 = BRep_Tool::Surface(theFace1);
4387   Handle(Geom_Surface) S2 = BRep_Tool::Surface(theFace2);
4388
4389   //Check if there a coincidence of two surfaces at least in two points
4390   double U11, U12, V11, V12, U21, U22, V21, V22;
4391   BRepTools::UVBounds(theFace1, U11, U12, V11, V12);
4392   BRepTools::UVBounds(theFace2, U21, U22, V21, V22);
4393
4394   double rangeU = U12-U11;
4395   double rangeV = V12-V11;
4396   double U = U11 + rangeU/3.0;
4397   double V = V11 + rangeV/3.0;
4398   gp_Pnt P1 = S1->Value(U, V);
4399   U = U11+rangeU*2.0/3.0;
4400   V = V11+rangeV*2.0/3.0;
4401   gp_Pnt P2 = S1->Value(U, V);
4402
4403   if (!GeomLib_Tool::Parameters(S2, P1, MAX_TOLERANCE, U, V) || U < U21 || U > U22 || V < V21 || V > V22)
4404     return false;
4405
4406   if (P1.Distance(S2->Value(U,V)) > MAX_TOLERANCE) return false;
4407
4408   if (!GeomLib_Tool::Parameters(S2, P2, MAX_TOLERANCE, U, V) || U < U21 || U > U22 || V < V21 || V > V22)
4409     return false;
4410
4411   if (P2.Distance(S2->Value(U, V)) > MAX_TOLERANCE) return false;
4412
4413   //Check that each edge of the Face1 has a counterpart in the Face2
4414   TopTools_MapOfOrientedShape aMap;
4415   TopTools_ListIteratorOfListOfShape LSI1(LS1);
4416   for(; LSI1.More(); LSI1.Next()) {
4417     TopoDS_Edge E = TopoDS::Edge(LSI1.Value());
4418     bool isFound = false;
4419     TopTools_ListIteratorOfListOfShape LSI2(LS2);
4420     for(; LSI2.More(); LSI2.Next()) {
4421       TopoDS_Shape aValue = LSI2.Value();
4422       if(aMap.Contains(aValue)) continue; //To avoid checking already found edge several times
4423       if(isSameEdge(E, TopoDS::Edge(aValue))) {
4424         aMap.Add(aValue);
4425         isFound = true;
4426         break;
4427       }
4428     }
4429     if(!isFound) return false;
4430   }
4431
4432   return true;
4433 }
4434
4435 //=======================================================================
4436 //function : isSameSolid
4437 //purpose  : Returns True if two solids coincide
4438 //=======================================================================
4439 bool isSameSolid(const TopoDS_Solid& theSolid1, const TopoDS_Solid& theSolid2)
4440 {
4441   TopExp_Explorer E(theSolid1, TopAbs_FACE);
4442   TopTools_ListOfShape LS1, LS2;
4443   for(; E.More(); E.Next()) LS1.Append(E.Current());
4444   E.Init(theSolid2, TopAbs_FACE);
4445   for(; E.More(); E.Next()) LS2.Append(E.Current());
4446
4447   if(LS1.Extent() != LS2.Extent()) return false;
4448
4449   double aMin = RealFirst(), aMax = RealLast();
4450   double xminB1=aMax, yminB1=aMax, zminB1=aMax, xminB2=aMax, yminB2=aMax, zminB2=aMax;
4451   double xmaxB1=aMin, ymaxB1=aMin, zmaxB1=aMin, xmaxB2=aMin, ymaxB2=aMin, zmaxB2=aMin;
4452
4453   for(E.Init(theSolid1, TopAbs_VERTEX); E.More(); E.Next()) {
4454     gp_Pnt P = BRep_Tool::Pnt(TopoDS::Vertex(E.Current()));
4455     if(P.X() < xminB1) xminB1 = P.X();
4456     if(P.Y() < yminB1) yminB1 = P.Y();
4457     if(P.Z() < zminB1) zminB1 = P.Z();
4458     if(P.X() > xmaxB1) xmaxB1 = P.X();
4459     if(P.Y() > ymaxB1) ymaxB1 = P.Y();
4460     if(P.Z() > zmaxB1) zmaxB1 = P.Z();
4461   }
4462
4463   for(E.Init(theSolid2, TopAbs_VERTEX); E.More(); E.Next()) {
4464     gp_Pnt P = BRep_Tool::Pnt(TopoDS::Vertex(E.Current()));
4465     if(P.X() < xminB2) xminB2 = P.X();
4466     if(P.Y() < yminB2) yminB2 = P.Y();
4467     if(P.Z() < zminB2) zminB2 = P.Z();
4468     if(P.X() > xmaxB2) xmaxB2 = P.X();
4469     if(P.Y() > ymaxB2) ymaxB2 = P.Y();
4470     if(P.Z() > zmaxB2) zmaxB2 = P.Z();
4471   }
4472
4473   //Compare the bounding boxes of both solids
4474   if(gp_Pnt(xminB1, yminB1, zminB1).Distance(gp_Pnt(xminB2, yminB2, zminB2)) > MAX_TOLERANCE)
4475     return false;
4476
4477   if(gp_Pnt(xmaxB1, ymaxB1, zmaxB1).Distance(gp_Pnt(xmaxB2, ymaxB2, zmaxB2)) > MAX_TOLERANCE)
4478     return false;
4479
4480   //Check that each face of the Solid1 has a counterpart in the Solid2
4481   TopTools_MapOfOrientedShape aMap;
4482   TopTools_ListIteratorOfListOfShape LSI1(LS1);
4483   for(; LSI1.More(); LSI1.Next()) {
4484     TopoDS_Face F = TopoDS::Face(LSI1.Value());
4485     bool isFound = false;
4486     TopTools_ListIteratorOfListOfShape LSI2(LS2);
4487     for(; LSI2.More(); LSI2.Next()) {
4488       if(aMap.Contains(LSI2.Value())) continue; //To avoid checking already found faces several times
4489       if(isSameFace(F, TopoDS::Face(LSI2.Value()))) {
4490         aMap.Add(LSI2.Value());
4491         isFound = true;
4492         break;
4493       }
4494     }
4495     if(!isFound) return false;
4496   }
4497
4498   return true;
4499 }
4500
4501 //=======================================================================
4502 //function : GetSame
4503 //purpose  :
4504 //=======================================================================
4505 Handle(GEOM_Object) GEOMImpl_IShapesOperations::GetSame(const Handle(GEOM_Object)& theShapeWhere,
4506                                                         const Handle(GEOM_Object)& theShapeWhat)
4507 {
4508   SetErrorCode(KO);
4509   if (theShapeWhere.IsNull() || theShapeWhat.IsNull()) return NULL;
4510
4511   TopoDS_Shape aWhere = theShapeWhere->GetValue();
4512   TopoDS_Shape aWhat  = theShapeWhat->GetValue();
4513
4514   if (aWhere.IsNull() || aWhat.IsNull()) return NULL;
4515
4516   int anIndex = -1;
4517   bool isFound = false;
4518   TopoDS_Shape aSubShape;
4519   TopTools_MapOfShape aMap;
4520
4521   if (aWhat.ShapeType() == TopAbs_COMPOUND || aWhat.ShapeType() == TopAbs_COMPSOLID) {
4522     TopoDS_Iterator It (aWhat, Standard_True, Standard_True);
4523     if (It.More()) aWhat = It.Value();
4524     It.Next();
4525     if (It.More()) {
4526       SetErrorCode("Compounds of two or more shapes are not allowed for aWhat argument");
4527       return NULL;
4528     }
4529   }
4530
4531   switch (aWhat.ShapeType()) {
4532     case TopAbs_VERTEX: {
4533       gp_Pnt P = BRep_Tool::Pnt(TopoDS::Vertex(aWhat));
4534       TopExp_Explorer E(aWhere, TopAbs_VERTEX);
4535       for(; E.More(); E.Next()) {
4536         if(!aMap.Add(E.Current())) continue;
4537         gp_Pnt P2 = BRep_Tool::Pnt(TopoDS::Vertex(E.Current()));
4538         if(P.Distance(P2) <= MAX_TOLERANCE) {
4539           isFound = true;
4540           aSubShape = E.Current();
4541           break;
4542         }
4543       }
4544       break;
4545                         }
4546     case TopAbs_EDGE: {
4547       TopoDS_Edge anEdge = TopoDS::Edge(aWhat);
4548       TopExp_Explorer E(aWhere, TopAbs_EDGE);
4549       for(; E.More(); E.Next()) {
4550         if(!aMap.Add(E.Current())) continue;
4551         if(isSameEdge(anEdge, TopoDS::Edge(E.Current()))) {
4552           aSubShape = E.Current();
4553           isFound = true;
4554           break;
4555         }
4556       }
4557       break;
4558                       }
4559     case TopAbs_FACE: {
4560       TopoDS_Face aFace = TopoDS::Face(aWhat);
4561       TopExp_Explorer E(aWhere, TopAbs_FACE);
4562       for(; E.More(); E.Next()) {
4563         if(!aMap.Add(E.Current())) continue;
4564         if(isSameFace(aFace, TopoDS::Face(E.Current()))) {
4565           aSubShape = E.Current();
4566           isFound = true;
4567           break;
4568         }
4569       }
4570       break;
4571                       }
4572     case TopAbs_SOLID: {
4573       TopoDS_Solid aSolid = TopoDS::Solid(aWhat);
4574       TopExp_Explorer E(aWhere, TopAbs_SOLID);
4575       for(; E.More(); E.Next()) {
4576         if(!aMap.Add(E.Current())) continue;
4577         if(isSameSolid(aSolid, TopoDS::Solid(E.Current()))) {
4578           aSubShape = E.Current();
4579           isFound = true;
4580           break;
4581         }
4582       }
4583       break;
4584                        }
4585     default:
4586       return NULL;
4587   }
4588
4589   if (isFound) {
4590     TopTools_IndexedMapOfShape anIndices;
4591     TopExp::MapShapes(aWhere, anIndices);
4592     if (anIndices.Contains(aSubShape))
4593       anIndex = anIndices.FindIndex(aSubShape);
4594   }
4595
4596   if (anIndex < 0) return NULL;
4597
4598   Handle(TColStd_HArray1OfInteger) anArray = new TColStd_HArray1OfInteger(1,1);
4599
4600   anArray->SetValue(1, anIndex);
4601
4602   Handle(GEOM_Object) aResult = GetEngine()->AddSubShape(theShapeWhere, anArray);
4603   Handle(GEOM_Function) aFunction = aResult->GetLastFunction();
4604
4605   GEOM::TPythonDump(aFunction) << aResult << " = geompy.GetSame("
4606     << theShapeWhere << ", " << theShapeWhat << ")";
4607
4608   SetErrorCode(OK);
4609
4610   return aResult;
4611 }
4612
4613
4614 //=======================================================================
4615 //function : GetSameIDs
4616 //purpose  :
4617 //=======================================================================
4618 Handle(TColStd_HSequenceOfInteger) GEOMImpl_IShapesOperations::GetSameIDs
4619                                                        (const Handle(GEOM_Object)& theShapeWhere,
4620                                                         const Handle(GEOM_Object)& theShapeWhat)
4621 {
4622   SetErrorCode(KO);
4623   if (theShapeWhere.IsNull() || theShapeWhat.IsNull()) return NULL;
4624
4625   TopoDS_Shape aWhere = theShapeWhere->GetValue();
4626   TopoDS_Shape aWhat  = theShapeWhat->GetValue();
4627
4628   if (aWhere.IsNull() || aWhat.IsNull()) return NULL;
4629
4630   TopTools_ListOfShape listShape;
4631   TopTools_MapOfShape aMap;
4632
4633   if (aWhat.ShapeType() == TopAbs_COMPOUND || aWhat.ShapeType() == TopAbs_COMPSOLID) {
4634     TopoDS_Iterator It (aWhat, Standard_True, Standard_True);
4635     if (It.More()) aWhat = It.Value();
4636     It.Next();
4637     if (It.More()) {
4638       SetErrorCode("Compounds of two or more shapes are not allowed for aWhat argument");
4639       return NULL;
4640     }
4641   }
4642
4643   switch (aWhat.ShapeType()) {
4644     case TopAbs_VERTEX: {
4645       gp_Pnt P = BRep_Tool::Pnt(TopoDS::Vertex(aWhat));
4646       TopExp_Explorer E(aWhere, TopAbs_VERTEX);
4647       for(; E.More(); E.Next()) {
4648         if(!aMap.Add(E.Current())) continue;
4649         gp_Pnt P2 = BRep_Tool::Pnt(TopoDS::Vertex(E.Current()));
4650         if(P.Distance(P2) <= MAX_TOLERANCE) {
4651           listShape.Append(E.Current());
4652         }
4653       }
4654       break;
4655                         }
4656     case TopAbs_EDGE: {
4657       TopoDS_Edge anEdge = TopoDS::Edge(aWhat);
4658       TopExp_Explorer E(aWhere, TopAbs_EDGE);
4659       for(; E.More(); E.Next()) {
4660         if(!aMap.Add(E.Current())) continue;
4661         if(isSameEdge(anEdge, TopoDS::Edge(E.Current()))) {
4662           listShape.Append(E.Current());
4663         }
4664       }
4665       break;
4666                       }
4667     case TopAbs_FACE: {
4668       TopoDS_Face aFace = TopoDS::Face(aWhat);
4669       TopExp_Explorer E(aWhere, TopAbs_FACE);
4670       for(; E.More(); E.Next()) {
4671         if(!aMap.Add(E.Current())) continue;
4672         if(isSameFace(aFace, TopoDS::Face(E.Current()))) {
4673           listShape.Append(E.Current());
4674         }
4675       }
4676       break;
4677                       }
4678     case TopAbs_SOLID: {
4679       TopoDS_Solid aSolid = TopoDS::Solid(aWhat);
4680       TopExp_Explorer E(aWhere, TopAbs_SOLID);
4681       for(; E.More(); E.Next()) {
4682         if(!aMap.Add(E.Current())) continue;
4683         if(isSameSolid(aSolid, TopoDS::Solid(E.Current()))) {
4684           listShape.Append(E.Current());
4685         }
4686       }
4687       break;
4688                        }
4689     default:
4690       return NULL;
4691   }
4692
4693   if ( !listShape.IsEmpty() ) {
4694     TopTools_IndexedMapOfShape anIndices;
4695     TopExp::MapShapes(aWhere, anIndices);
4696     TopTools_ListIteratorOfListOfShape itSub (listShape);
4697     Handle(TColStd_HSequenceOfInteger) aSeq = new TColStd_HSequenceOfInteger;
4698     for (; itSub.More(); itSub.Next()) {
4699       if (anIndices.Contains(itSub.Value()))
4700         aSeq->Append(anIndices.FindIndex(itSub.Value()));
4701     }
4702     SetErrorCode(OK);
4703     // The GetSameIDs() doesn't change object so no new function is required.
4704     Handle(GEOM_Function) aFunction = GEOM::GetCreatedLast(theShapeWhere,theShapeWhat)->GetLastFunction();
4705
4706   // Make a Python command
4707   GEOM::TPythonDump(aFunction, /*append=*/true)
4708     << "listSameIDs = geompy.GetSameIDs("
4709     << theShapeWhere << ", "
4710     << theShapeWhat << ")";
4711     return aSeq;
4712   } else {
4713     SetErrorCode(NOT_FOUND_ANY);
4714     return NULL;
4715   }
4716 }