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