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