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