Salome HOME
f222863f51c8f5dcf8fdbc396e1062c59d92dad1
[modules/geom.git] / src / GEOMImpl / GEOMImpl_IShapesOperations.cxx
1 // Copyright (C) 2007-2023  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 coincident 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)
180 : GEOM_IOperations(theEngine)
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(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(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(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(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(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(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(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(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(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(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(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(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(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(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(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     delete [] anEntryStr;
1460   }
1461
1462   if (aSeq->Length() == 0) {
1463     SetErrorCode(NOT_FOUND_ANY);
1464     return aSeq;
1465   }
1466
1467   SetErrorCode(OK);
1468
1469   return aSeq;
1470 }
1471
1472 //=============================================================================
1473 /*!
1474  *  MakeExplode
1475  */
1476 //=============================================================================
1477 Handle(TColStd_HSequenceOfTransient) GEOMImpl_IShapesOperations::MakeExplode
1478                                           (Handle(GEOM_Object)    theShape,
1479                                            const Standard_Integer theShapeType,
1480                                            const Standard_Boolean isSorted,
1481                                            const ExplodeType      theExplodeType)
1482 {
1483   SetErrorCode(KO);
1484
1485   if (theShape.IsNull()) return NULL;
1486   TopoDS_Shape aShape = theShape->GetValue();
1487   if (aShape.IsNull()) return NULL;
1488
1489   Handle(GEOM_Function) aMainShape = theShape->GetLastFunction();
1490
1491   Handle(TColStd_HSequenceOfTransient) aSeq = new TColStd_HSequenceOfTransient;
1492   Handle(GEOM_Object) anObj;
1493   TopTools_MapOfShape mapShape;
1494   TopTools_ListOfShape listShape;
1495
1496   if (aShape.ShapeType() == TopAbs_COMPOUND &&
1497       (theShapeType == TopAbs_SHAPE || theShapeType == TopAbs_FLAT || theShapeType == TopAbs_COMPOUND))
1498   {
1499     TopoDS_Iterator It (aShape, Standard_True, Standard_True);
1500     for (; It.More(); It.Next()) {
1501       TopoDS_Shape SS = It.Value();
1502       if (mapShape.Add(SS)) {
1503         if (theShapeType == TopAbs_FLAT) {
1504           AddFlatSubShapes(SS, listShape, mapShape);
1505         }
1506         else if (theShapeType == TopAbs_SHAPE || theShapeType == SS.ShapeType()) {
1507           listShape.Append(SS);
1508         }
1509         // VSR: for EXPLODE_NEW_INCLUDE_MAIN and EXPLODE_OLD_INCLUDE_MAIN:
1510         // it seems it is necessary to add top-level shape if theShapeType == TopAbs_COMPOUND
1511       }
1512     }
1513   }
1514   else if (theExplodeType != EXPLODE_NEW_EXCLUDE_MAIN || aShape.ShapeType() != theShapeType) // issue 0021079
1515   {
1516     TopExp_Explorer exp (aShape, TopAbs_ShapeEnum(theShapeType));
1517     for (; exp.More(); exp.Next())
1518       if (mapShape.Add(exp.Current()))
1519         listShape.Append(exp.Current());
1520   }
1521
1522   if (listShape.IsEmpty()){
1523     //SetErrorCode("The given shape has no sub-shapes of the requested type");
1524     SetErrorCode(NOT_FOUND_ANY); // NPAL18017
1525     return aSeq;
1526   }
1527
1528   if (isSorted) {
1529     bool isOldSorting = false;
1530     if (theExplodeType == EXPLODE_OLD_INCLUDE_MAIN)
1531       isOldSorting = true;
1532     GEOMUtils::SortShapes(listShape, isOldSorting);
1533   }
1534
1535   TopTools_IndexedMapOfShape anIndices;
1536   TopExp::MapShapes(aShape, anIndices);
1537   Handle(TColStd_HArray1OfInteger) anArray;
1538
1539   TopTools_ListIteratorOfListOfShape itSub (listShape);
1540   TCollection_AsciiString anAsciiList, anEntry;
1541   for (int index = 1; itSub.More(); itSub.Next(), ++index)
1542   {
1543     TopoDS_Shape aValue = itSub.Value();
1544     anArray = new TColStd_HArray1OfInteger(1,1);
1545     anArray->SetValue(1, anIndices.FindIndex(aValue));
1546
1547     //anObj = GetEngine()->AddSubShape(theShape, anArray);
1548     {
1549       anObj = GetEngine()->AddObject(GEOM_SUBSHAPE);
1550       Handle(GEOM_Function) aFunction = anObj->AddFunction(GEOM_Object::GetSubShapeID(), 1);
1551       if (aFunction.IsNull()) return aSeq;
1552
1553       GEOM_ISubShape aSSI (aFunction);
1554       aSSI.SetMainShape(aMainShape);
1555       aSSI.SetIndices(anArray);
1556
1557       // Set function value directly, as we know it.
1558       // Usage of Solver here would lead to significant loss of time,
1559       // because GEOM_SubShapeDriver will build TopTools_IndexedMapOfShape
1560       // on the main shape for each being calculated sub-shape separately.
1561       aFunction->SetValue(aValue);
1562
1563       // Put this subshape in the list of sub-shapes of theMainShape
1564       aMainShape->AddSubShapeReference(aFunction);
1565     }
1566     if (!anObj.IsNull()) {
1567           aSeq->Append(anObj);
1568
1569           // for python command
1570           TDF_Tool::Entry(anObj->GetEntry(), anEntry);
1571           anAsciiList += anEntry;
1572           anAsciiList += ",";
1573         }
1574       }
1575
1576   //Make a Python command
1577   anAsciiList.Trunc(anAsciiList.Length() - 1);
1578
1579   GEOM::TPythonDump pd (aMainShape, /*append=*/true);
1580   pd << "[" << anAsciiList.ToCString() << "] = geompy.";
1581   switch (theExplodeType) {
1582   case EXPLODE_NEW_EXCLUDE_MAIN:
1583     pd << "ExtractShapes(" << theShape << ", "
1584        << TopAbs_ShapeEnum(theShapeType) << ", " << (isSorted ? "True" : "False") << ")";
1585     break;
1586   case EXPLODE_NEW_INCLUDE_MAIN:
1587     pd << "SubShapeAll" << (isSorted ? "SortedCentres(" : "(")
1588        << theShape << ", " << TopAbs_ShapeEnum(theShapeType) << ")";
1589     break;
1590   case EXPLODE_OLD_INCLUDE_MAIN:
1591     pd << "SubShapeAll" << (isSorted ? "Sorted(" : "(")
1592        << theShape << ", " << TopAbs_ShapeEnum(theShapeType) << ")";
1593     break;
1594   default: ;
1595   }
1596   SetErrorCode(OK);
1597
1598   return aSeq;
1599 }
1600
1601 //=============================================================================
1602 /*!
1603  *  SubShapeAllIDs
1604  */
1605 //=============================================================================
1606 Handle(TColStd_HSequenceOfInteger) GEOMImpl_IShapesOperations::SubShapeAllIDs
1607                                           (Handle(GEOM_Object)    theShape,
1608                                            const Standard_Integer theShapeType,
1609                                            const Standard_Boolean isSorted,
1610                                            const ExplodeType      theExplodeType)
1611 {
1612   SetErrorCode(KO);
1613
1614   if (theShape.IsNull()) return NULL;
1615   TopoDS_Shape aShape = theShape->GetValue();
1616   if (aShape.IsNull()) return NULL;
1617
1618   Handle(TColStd_HSequenceOfInteger) aSeq = new TColStd_HSequenceOfInteger;
1619   TopTools_MapOfShape mapShape;
1620   TopTools_ListOfShape listShape;
1621
1622   if (aShape.ShapeType() == TopAbs_COMPOUND &&
1623       (theShapeType == TopAbs_SHAPE || theShapeType == TopAbs_FLAT || theShapeType == TopAbs_COMPOUND))
1624   {
1625     TopoDS_Iterator It (aShape, Standard_True, Standard_True);
1626     for (; It.More(); It.Next()) {
1627       TopoDS_Shape SS = It.Value();
1628       if (mapShape.Add(SS)) {
1629         if (theShapeType == TopAbs_FLAT) {
1630           AddFlatSubShapes(SS, listShape, mapShape);
1631         }
1632         else if (theShapeType == TopAbs_SHAPE || theShapeType == SS.ShapeType()) {
1633           listShape.Append(SS);
1634         }
1635       }
1636     }
1637   }
1638   else if (theExplodeType != EXPLODE_NEW_EXCLUDE_MAIN || aShape.ShapeType() != theShapeType) // issue 0021079
1639   {
1640     TopExp_Explorer exp (aShape, TopAbs_ShapeEnum(theShapeType));
1641     for (; exp.More(); exp.Next())
1642       if (mapShape.Add(exp.Current()))
1643         listShape.Append(exp.Current());
1644   }
1645
1646   if (listShape.IsEmpty()) {
1647     //SetErrorCode("The given shape has no sub-shapes of the requested type");
1648     SetErrorCode(NOT_FOUND_ANY); // NPAL18017
1649     return aSeq;
1650   }
1651
1652   if (isSorted) {
1653     bool isOldSorting = false;
1654     if (theExplodeType == EXPLODE_OLD_INCLUDE_MAIN)
1655       isOldSorting = true;
1656     GEOMUtils::SortShapes(listShape, isOldSorting);
1657   }
1658
1659   TopTools_IndexedMapOfShape anIndices;
1660   TopExp::MapShapes(aShape, anIndices);
1661   Handle(TColStd_HArray1OfInteger) anArray;
1662
1663   TopTools_ListIteratorOfListOfShape itSub (listShape);
1664   for (int index = 1; itSub.More(); itSub.Next(), ++index) {
1665     TopoDS_Shape aValue = itSub.Value();
1666     aSeq->Append(anIndices.FindIndex(aValue));
1667   }
1668
1669   Handle(GEOM_Function) aFunction = theShape->GetLastFunction();
1670
1671   // VSR 29/08/2017: 0023327, 0023428: eliminate unnecessary lines in Python dump
1672 #ifdef DUMP_SUBSHAPE_IDS
1673   //Make a Python command
1674   GEOM::TPythonDump pd (aFunction, /*append=*/true);
1675   pd << "listSubShapeIDs = geompy.SubShapeAll";
1676   switch (theExplodeType) {
1677   case EXPLODE_NEW_EXCLUDE_MAIN:
1678     break;
1679   case EXPLODE_NEW_INCLUDE_MAIN:
1680     pd << (isSorted ? "SortedCentresIDs(" : "IDs(")
1681        << theShape << ", " << TopAbs_ShapeEnum(theShapeType) << ")";
1682     break;
1683   case EXPLODE_OLD_INCLUDE_MAIN:
1684     pd << (isSorted ? "SortedIDs(" : "IDs(")
1685        << theShape << ", " << TopAbs_ShapeEnum(theShapeType) << ")";
1686     break;
1687   default: ;
1688   }
1689 #endif // DUMP_SUBSHAPE_IDS
1690
1691   SetErrorCode(OK);
1692   return aSeq;
1693 }
1694
1695 //=============================================================================
1696 /*!
1697  *  GetSubShape
1698  */
1699 //=============================================================================
1700 Handle(GEOM_Object) GEOMImpl_IShapesOperations::GetSubShape
1701                                           (Handle(GEOM_Object)    theMainShape,
1702                                            const Standard_Integer theID)
1703 {
1704   SetErrorCode(KO);
1705
1706   if (theMainShape.IsNull()) return NULL;
1707
1708   Handle(TColStd_HArray1OfInteger) anArray = new TColStd_HArray1OfInteger(1,1);
1709   anArray->SetValue(1, theID);
1710   Handle(GEOM_Object) anObj = GetEngine()->AddSubShape(theMainShape, anArray,true);
1711   if (anObj.IsNull()) {
1712     SetErrorCode("Can not get a sub-shape with the given ID");
1713     return NULL;
1714   }
1715
1716   Handle(GEOM_Function) aFunction = anObj->GetLastFunction();
1717
1718   //Make a Python command
1719   GEOM::TPythonDump(aFunction) << anObj << " = geompy.GetSubShape("
1720                                << theMainShape << ", [" << theID << "])";
1721
1722   SetErrorCode(OK);
1723   return anObj;
1724 }
1725
1726 //=============================================================================
1727 /*!
1728  *  MakeSubShapes
1729  */
1730 //=============================================================================
1731 Handle(TColStd_HSequenceOfTransient) GEOMImpl_IShapesOperations::MakeSubShapes
1732                                 (Handle(GEOM_Object)              theMainShape,
1733                                  Handle(TColStd_HArray1OfInteger) theIndices)
1734 {
1735   SetErrorCode(KO);
1736
1737   Handle(TColStd_HSequenceOfTransient) aSeq = new TColStd_HSequenceOfTransient;
1738
1739   if (!theIndices->Length()) {
1740     SetErrorCode(NOT_FOUND_ANY);
1741     return aSeq;
1742   }
1743
1744   if (theMainShape.IsNull()) return NULL;
1745   TopoDS_Shape aShape = theMainShape->GetValue();
1746   if (aShape.IsNull()) return NULL;
1747
1748   Handle(GEOM_Function) aMainShape = theMainShape->GetLastFunction();
1749
1750   TopTools_IndexedMapOfShape anIndices;
1751   TopExp::MapShapes(aShape, anIndices);
1752
1753   Handle(TColStd_HArray1OfInteger) anArray;
1754   Handle(GEOM_Object) anObj;
1755
1756   TCollection_AsciiString anAsciiList, anEntry;
1757   Standard_Integer i, low = theIndices->Lower(), up = theIndices->Upper();
1758   for (i = low; i <= up; i++) {
1759     int id = theIndices->Value(i);
1760     if (1 <= id && id <= anIndices.Extent()) {
1761       TopoDS_Shape aValue = anIndices.FindKey(id);
1762       anArray = new TColStd_HArray1OfInteger(1,1);
1763       anArray->SetValue(1, id);
1764
1765       anObj = GetEngine()->AddObject(GEOM_SUBSHAPE);
1766       if (!anObj.IsNull()) {
1767         Handle(GEOM_Function) aFunction = anObj->AddFunction(GEOM_Object::GetSubShapeID(), 1);
1768         if (aFunction.IsNull()) return aSeq;
1769
1770         GEOM_ISubShape aSSI (aFunction);
1771         aSSI.SetMainShape(aMainShape);
1772         aSSI.SetIndices(anArray);
1773
1774         // Set function value directly, as we know it.
1775         // Usage of Solver here would lead to significant loss of time,
1776         // because GEOM_SubShapeDriver will build TopTools_IndexedMapOfShape
1777         // on the main shape for each being calculated sub-shape separately.
1778         aFunction->SetValue(aValue);
1779
1780         // Put this sub-shape in the list of sub-shapes of theMainShape
1781         aMainShape->AddSubShapeReference(aFunction);
1782
1783         aSeq->Append(anObj);
1784
1785         // for python command
1786         TDF_Tool::Entry(anObj->GetEntry(), anEntry);
1787         anAsciiList += anEntry;
1788         anAsciiList += ",";
1789       }
1790     }
1791   }
1792
1793   //Make a Python command
1794   anAsciiList.Trunc(anAsciiList.Length() - 1);
1795
1796   GEOM::TPythonDump pd (aMainShape, /*append=*/true);
1797   pd << "[" << anAsciiList.ToCString() << "] = geompy.SubShapes("
1798      << theMainShape << ", [" ;
1799   for (i = low; i <= up - 1; i++) {
1800     pd << theIndices->Value(i) << ", ";
1801   }
1802   pd << theIndices->Value(up) << "])";
1803
1804   SetErrorCode(OK);
1805
1806   return aSeq;
1807 }
1808
1809 //=============================================================================
1810 /*!
1811  *  GetSubShapeIndex
1812  */
1813 //=============================================================================
1814 Standard_Integer GEOMImpl_IShapesOperations::GetSubShapeIndex (Handle(GEOM_Object) theMainShape,
1815                                                                Handle(GEOM_Object) theSubShape)
1816 {
1817   SetErrorCode(KO);
1818
1819   TopoDS_Shape aMainShape = theMainShape->GetValue();
1820   TopoDS_Shape aSubShape = theSubShape->GetValue();
1821
1822   if (aMainShape.IsNull() || aSubShape.IsNull()) return -1;
1823
1824   TopTools_IndexedMapOfShape anIndices;
1825   TopExp::MapShapes(aMainShape, anIndices);
1826 //   if (anIndices.Contains(aSubShape)) {
1827 //     SetErrorCode(OK);
1828 //     return anIndices.FindIndex(aSubShape);
1829 //   }
1830   int id = anIndices.FindIndex(aSubShape);
1831   if (id > 0)
1832   {
1833     SetErrorCode(OK);
1834     return id;
1835   }
1836   return -1;
1837 }
1838
1839
1840
1841 //=============================================================================
1842 /*!
1843  *  GetSubShapeIndices
1844  */
1845 //=============================================================================
1846 Handle(TColStd_HSequenceOfInteger) GEOMImpl_IShapesOperations::GetSubShapesIndices (Handle(GEOM_Object) theMainShape,
1847                                                                                     std::list<Handle(GEOM_Object)> theSubShapes)
1848 {
1849   MESSAGE("GEOMImpl_IShapesOperations::GetSubShapesIndices");
1850   SetErrorCode(KO);
1851   
1852   Handle(TColStd_HSequenceOfInteger) aSeq = new TColStd_HSequenceOfInteger;
1853   
1854   TopoDS_Shape aMainShape = theMainShape->GetValue();
1855   if (aMainShape.IsNull())
1856   {
1857     MESSAGE("NULL main shape");
1858     return NULL;
1859   }
1860   
1861   TopTools_IndexedMapOfShape anIndices;
1862   TopExp::MapShapes(aMainShape, anIndices);
1863   
1864   std::list<Handle(GEOM_Object)>::iterator it;
1865   for (it=theSubShapes.begin(); it != theSubShapes.end(); ++it)
1866   {
1867     TopoDS_Shape aSubShape = (*it)->GetValue(); 
1868     if (aSubShape.IsNull())
1869     {
1870       MESSAGE("NULL subshape");
1871       return NULL;
1872     }
1873     int id = anIndices.FindIndex(aSubShape);
1874     aSeq->Append(id);
1875   }  
1876   
1877   SetErrorCode(OK);
1878   return aSeq;
1879 }
1880
1881
1882 //=============================================================================
1883 /*!
1884  *  GetTopologyIndex
1885  */
1886 //=============================================================================
1887 Standard_Integer GEOMImpl_IShapesOperations::GetTopologyIndex (Handle(GEOM_Object) theMainShape,
1888                                                                Handle(GEOM_Object) theSubShape)
1889 {
1890   SetErrorCode(OK);
1891
1892   TopoDS_Shape aMainShape = theMainShape->GetValue();
1893   TopoDS_Shape aSubShape = theSubShape->GetValue();
1894
1895   if (aMainShape.IsNull() || aSubShape.IsNull()) {
1896     SetErrorCode("Null argument shape given");
1897     return -1;
1898   }
1899
1900   int index = 1;
1901   if (aSubShape.ShapeType() == TopAbs_COMPOUND) {
1902     TopoDS_Iterator it;
1903     TopTools_ListOfShape CL;
1904     CL.Append(aMainShape);
1905     TopTools_ListIteratorOfListOfShape itC;
1906     for (itC.Initialize(CL); itC.More(); itC.Next()) {
1907       for (it.Initialize(itC.Value()); it.More(); it.Next()) {
1908         if (it.Value().ShapeType() == TopAbs_COMPOUND) {
1909           if (it.Value().IsSame(aSubShape))
1910             return index;
1911           else
1912             index++;
1913           CL.Append(it.Value());
1914         }
1915       }
1916     }
1917   } else {
1918     TopExp_Explorer anExp (aMainShape, aSubShape.ShapeType());
1919     TopTools_MapOfShape M;
1920     for (; anExp.More(); anExp.Next()) {
1921       if (M.Add(anExp.Current())) {
1922         if (anExp.Current().IsSame(aSubShape))
1923           return index;
1924         index++;
1925       }
1926     }
1927   }
1928
1929   SetErrorCode("The sub-shape does not belong to the main shape");
1930   return -1;
1931 }
1932
1933 //=============================================================================
1934 /*!
1935  *  GetShapeTypeString
1936  */
1937 //=============================================================================
1938 TCollection_AsciiString GEOMImpl_IShapesOperations::GetShapeTypeString (Handle(GEOM_Object) theShape)
1939 {
1940   SetErrorCode(KO);
1941
1942   TCollection_AsciiString aTypeName ("Null Shape");
1943
1944   TopoDS_Shape aShape = theShape->GetValue();
1945   if (aShape.IsNull())
1946     return aTypeName;
1947
1948   switch (aShape.ShapeType() )
1949   {
1950   case TopAbs_COMPOUND:
1951     aTypeName = "Compound";
1952     break;
1953   case  TopAbs_COMPSOLID:
1954     aTypeName = "Compound Solid";
1955     break;
1956   case TopAbs_SOLID:
1957     aTypeName = "Solid";
1958     break;
1959   case TopAbs_SHELL:
1960     aTypeName = "Shell";
1961     break;
1962   case TopAbs_FACE:
1963     {
1964       BRepAdaptor_Surface surf (TopoDS::Face(aShape));
1965       if (surf.GetType() == GeomAbs_Plane)
1966         aTypeName = "Plane";
1967       else if (surf.GetType() == GeomAbs_Cylinder)
1968         aTypeName = "Cylindrical Face";
1969       else if (surf.GetType() == GeomAbs_Sphere)
1970         aTypeName = "Spherical Face";
1971       else if (surf.GetType() == GeomAbs_Torus)
1972         aTypeName = "Toroidal Face";
1973       else if (surf.GetType() == GeomAbs_Cone)
1974         aTypeName = "Conical Face";
1975       else
1976         aTypeName = "GEOM::FACE";
1977     }
1978     break;
1979   case TopAbs_WIRE:
1980     aTypeName = "Wire";
1981     break;
1982   case TopAbs_EDGE:
1983     {
1984       BRepAdaptor_Curve curv (TopoDS::Edge(aShape));
1985       if (curv.GetType() == GeomAbs_Line) {
1986         if ((Abs(curv.FirstParameter()) >= 1E6) ||
1987             (Abs(curv.LastParameter()) >= 1E6))
1988           aTypeName = "Line";
1989         else
1990           aTypeName = "Edge";
1991       } else if (curv.GetType() == GeomAbs_Circle) {
1992         if (curv.IsClosed())
1993           aTypeName = "Circle";
1994         else
1995           aTypeName = "Arc";
1996       } else {
1997         aTypeName = "Edge";
1998       }
1999     }
2000     break;
2001   case TopAbs_VERTEX:
2002     aTypeName = "Vertex";
2003     break;
2004   case TopAbs_SHAPE:
2005     aTypeName = "Shape";
2006     break;
2007   default:
2008     aTypeName = "Shape of unknown type";
2009   }
2010
2011   return aTypeName;
2012 }
2013
2014 //=============================================================================
2015 /*!
2016  *  IsSubShapeBelongsTo
2017  */
2018 //=============================================================================
2019 Standard_Boolean GEOMImpl_IShapesOperations::IsSubShapeBelongsTo( Handle(GEOM_Object) theSubObject,
2020                                                                   const Standard_Integer theSubObjectIndex,
2021                                                                   Handle(GEOM_Object) theObject,
2022                                                                   const Standard_Integer theObjectIndex)
2023 {
2024   SetErrorCode(KO);
2025
2026   if ( theObject.IsNull() || theSubObject.IsNull() )
2027     return false;
2028
2029   TopoDS_Shape shape    = theObject->GetValue();
2030   TopoDS_Shape subShape = theSubObject->GetValue();
2031
2032   if ( shape.IsNull() || subShape.IsNull() )
2033     return false;
2034
2035   TopTools_IndexedMapOfShape anIndices;
2036   if ( theObjectIndex > 0 ) {
2037     TopExp::MapShapes( shape, anIndices );
2038     shape = anIndices.FindKey(theObjectIndex);
2039     anIndices.Clear();
2040   }
2041   if ( theSubObjectIndex > 0 ) {
2042     TopExp::MapShapes( subShape, anIndices );
2043     subShape = anIndices.FindKey(theSubObjectIndex);
2044     anIndices.Clear();
2045   }
2046
2047   TopExp::MapShapes( shape, anIndices );
2048
2049   const Standard_Boolean isBelongTo = anIndices.Contains(subShape);
2050
2051   SetErrorCode(OK);
2052
2053   return isBelongTo;
2054 }
2055
2056 //=============================================================================
2057 /*!
2058  *  NumberOfSubShapes
2059  */
2060 //=============================================================================
2061 Standard_Integer GEOMImpl_IShapesOperations::NumberOfSubShapes
2062                                           (Handle(GEOM_Object)    theShape,
2063                                            const Standard_Integer theShapeType)
2064 {
2065   SetErrorCode(KO);
2066   Standard_Integer nbShapes = 0;
2067
2068   if (theShape.IsNull()) return -1;
2069   TopoDS_Shape aShape = theShape->GetValue();
2070   if (aShape.IsNull()) return -1;
2071
2072   /*
2073   TopTools_MapOfShape mapShape;
2074
2075   if (aShape.ShapeType() == TopAbs_COMPOUND &&
2076       (TopAbs_ShapeEnum(theShapeType) == TopAbs_SHAPE ||
2077        TopAbs_ShapeEnum(theShapeType) == TopAbs_COMPSOLID ||
2078        TopAbs_ShapeEnum(theShapeType) == TopAbs_COMPOUND)) {
2079     TopoDS_Iterator It (aShape, Standard_True, Standard_True);
2080     for (; It.More(); It.Next()) {
2081       if (mapShape.Add(It.Value())) {
2082         if (TopAbs_ShapeEnum(theShapeType) == TopAbs_SHAPE ||
2083             TopAbs_ShapeEnum(theShapeType) == It.Value().ShapeType()) {
2084           nbShapes++;
2085         }
2086       }
2087     }
2088   } else {
2089     TopExp_Explorer exp (aShape, TopAbs_ShapeEnum(theShapeType));
2090     for (; exp.More(); exp.Next())
2091       if (mapShape.Add(exp.Current()))
2092         nbShapes++;
2093   }
2094   */
2095
2096   try {
2097     if (theShapeType == TopAbs_FLAT) {
2098       TopTools_MapOfShape aMapOfShape;
2099       TopTools_ListOfShape aListOfShape;
2100       AddFlatSubShapes(aShape, aListOfShape, aMapOfShape);
2101       nbShapes = aListOfShape.Extent();
2102     }
2103     else {
2104       OCC_CATCH_SIGNALS;
2105       int iType, nbTypes [TopAbs_SHAPE];
2106       for (iType = 0; iType < TopAbs_SHAPE; ++iType)
2107         nbTypes[iType] = 0;
2108       nbTypes[aShape.ShapeType()]++;
2109       
2110       TopTools_MapOfShape aMapOfShape;
2111       aMapOfShape.Add(aShape);
2112       TopTools_ListOfShape aListOfShape;
2113       aListOfShape.Append(aShape);
2114       
2115       TopTools_ListIteratorOfListOfShape itL (aListOfShape);
2116       for (; itL.More(); itL.Next()) {
2117         TopoDS_Iterator it (itL.Value());
2118         for (; it.More(); it.Next()) {
2119           TopoDS_Shape s = it.Value();
2120           if (aMapOfShape.Add(s)) {
2121             aListOfShape.Append(s);
2122             nbTypes[s.ShapeType()]++;
2123           }
2124         }
2125       }
2126       
2127       if (TopAbs_ShapeEnum(theShapeType) == TopAbs_SHAPE)
2128         nbShapes = aMapOfShape.Extent();
2129       else
2130         nbShapes = nbTypes[theShapeType];
2131     }
2132   }
2133   catch (Standard_Failure& aFail) {
2134     SetErrorCode(aFail.GetMessageString());
2135     return -1;
2136   }
2137
2138   SetErrorCode(OK);
2139   return nbShapes;
2140 }
2141
2142 //=============================================================================
2143 /*!
2144  *  ReverseShape
2145  */
2146 //=============================================================================
2147 Handle(GEOM_Object) GEOMImpl_IShapesOperations::ReverseShape(Handle(GEOM_Object) theShape)
2148 {
2149   SetErrorCode(KO);
2150
2151   if (theShape.IsNull()) return NULL;
2152
2153   /*
2154   //Add a new reversed object
2155   Handle(GEOM_Object) aReversed = GetEngine()->AddObject(theShape->GetType());
2156
2157   //Add a new Revese function
2158   Handle(GEOM_Function) aFunction;
2159   aFunction = aReversed->AddFunction(GEOMImpl_ShapeDriver::GetID(), REVERSE_ORIENTATION);
2160   if (aFunction.IsNull()) return NULL;
2161
2162   //Check if the function is set correctly
2163   if (aFunction->GetDriverGUID() != GEOMImpl_ShapeDriver::GetID()) return NULL;
2164
2165   GEOMImpl_IShapes aSI (aFunction);
2166
2167   Handle(GEOM_Function) aRefShape = theShape->GetLastFunction();
2168   if (aRefShape.IsNull()) return NULL;
2169
2170   aSI.SetBase(aRefShape);
2171
2172   //Compute the sub-shape value
2173   try {
2174     OCC_CATCH_SIGNALS;
2175     if (!GetSolver()->ComputeFunction(aFunction)) {
2176       SetErrorCode("Shape driver failed to reverse shape");
2177       return NULL;
2178     }
2179   }
2180   catch (Standard_Failure& aFail) {
2181     SetErrorCode(aFail.GetMessageString());
2182     return NULL;
2183   }
2184
2185   //Make a Python command
2186   GEOM::TPythonDump(aFunction) << aReversed
2187     << " = geompy.ChangeOrientation(" << theShape << ")";
2188
2189   SetErrorCode(OK);
2190   */
2191
2192   Handle(GEOM_Object) aReversed;
2193
2194   GEOM_Engine* anEngine = GetEngine();
2195   //GEOMImpl_Gen* aGen = dynamic_cast<GEOMImpl_Gen*>(anEngine);
2196   GEOMImpl_Gen* aGen = (GEOMImpl_Gen*)anEngine;
2197
2198   if (aGen) {
2199     GEOMImpl_IHealingOperations* anIHealingOperations =
2200       aGen->GetIHealingOperations();
2201     aReversed = anIHealingOperations->ChangeOrientationCopy(theShape);
2202     SetErrorCode(anIHealingOperations->GetErrorCode());
2203   }
2204
2205   return aReversed;
2206 }
2207
2208 //=============================================================================
2209 /*!
2210  *  GetFreeFacesIDs
2211  */
2212 //=============================================================================
2213 Handle(TColStd_HSequenceOfInteger) GEOMImpl_IShapesOperations::GetFreeFacesIDs
2214                                                  (Handle(GEOM_Object) theShape)
2215 {
2216   SetErrorCode(KO);
2217
2218   if (theShape.IsNull()) return NULL;
2219   TopoDS_Shape aShape = theShape->GetValue();
2220   if (aShape.IsNull()) return NULL;
2221
2222   Handle(TColStd_HSequenceOfInteger) aSeq = new TColStd_HSequenceOfInteger;
2223
2224   TopTools_IndexedDataMapOfShapeListOfShape mapFaceBlocks;
2225   GEOMImpl_Block6Explorer::MapShapesAndAncestors
2226     (aShape, TopAbs_FACE, TopAbs_SOLID, mapFaceBlocks);
2227
2228   Standard_Integer ind = 1, nbFaces = mapFaceBlocks.Extent();
2229
2230   if (nbFaces == 0) {
2231     SetErrorCode("The given shape has no faces");
2232     return aSeq;
2233   }
2234
2235   TopTools_IndexedMapOfShape anIndices;
2236   TopExp::MapShapes(aShape, anIndices);
2237
2238   Standard_Integer id;
2239   for (; ind <= nbFaces; ind++) {
2240     if (mapFaceBlocks.FindFromIndex(ind).Extent() != 2) {
2241       id = anIndices.FindIndex(mapFaceBlocks.FindKey(ind));
2242       aSeq->Append(id);
2243     }
2244   }
2245
2246   //The explode doesn't change object so no new function is required.
2247   Handle(GEOM_Function) aFunction = theShape->GetLastFunction();
2248
2249   // VSR 29/08/2017: 0023327, 0023428: eliminate unnecessary lines in Python dump
2250 #ifdef DUMP_SUBSHAPE_IDS
2251   //Make a Python command
2252   GEOM::TPythonDump(aFunction, /*append=*/true)
2253     << "listFreeFacesIDs = geompy.GetFreeFacesIDs(" << theShape << ")";
2254 #endif // DUMP_SUBSHAPE_IDS
2255
2256   SetErrorCode(OK);
2257   return aSeq;
2258 }
2259
2260 //=======================================================================
2261 //function : GetSharedShapes
2262 //purpose  :
2263 //=======================================================================
2264 Handle(TColStd_HSequenceOfTransient) GEOMImpl_IShapesOperations::GetSharedShapes
2265                                                 (Handle(GEOM_Object)    theShape1,
2266                                                  Handle(GEOM_Object)    theShape2,
2267                                                  const Standard_Integer theShapeType)
2268 {
2269   SetErrorCode(KO);
2270
2271   if (theShape1.IsNull() || theShape2.IsNull()) return NULL;
2272
2273   TopoDS_Shape aShape1 = theShape1->GetValue();
2274   TopoDS_Shape aShape2 = theShape2->GetValue();
2275
2276   if (aShape1.IsNull() || aShape2.IsNull()) return NULL;
2277
2278   TopTools_IndexedMapOfShape anIndices;
2279   TopExp::MapShapes(aShape1, anIndices);
2280   Handle(TColStd_HArray1OfInteger) anArray;
2281
2282   TopTools_IndexedMapOfShape mapShape1;
2283   TopExp::MapShapes(aShape1, TopAbs_ShapeEnum(theShapeType), mapShape1);
2284
2285   Handle(GEOM_Object) anObj;
2286   Handle(TColStd_HSequenceOfTransient) aSeq = new TColStd_HSequenceOfTransient;
2287   TCollection_AsciiString anAsciiList, anEntry;
2288
2289   TopTools_MapOfShape mapShape2;
2290   TopExp_Explorer exp (aShape2, TopAbs_ShapeEnum(theShapeType));
2291   for (; exp.More(); exp.Next()) {
2292     TopoDS_Shape aSS = exp.Current();
2293     if (mapShape2.Add(aSS) && mapShape1.Contains(aSS)) {
2294       anArray = new TColStd_HArray1OfInteger(1,1);
2295       anArray->SetValue(1, anIndices.FindIndex(aSS));
2296       anObj = GetEngine()->AddSubShape(theShape1, anArray);
2297       aSeq->Append(anObj);
2298
2299       // for python command
2300       TDF_Tool::Entry(anObj->GetEntry(), anEntry);
2301       anAsciiList += anEntry;
2302       anAsciiList += ",";
2303     }
2304   }
2305
2306   if (aSeq->IsEmpty()) {
2307     SetErrorCode(NOT_FOUND_ANY);
2308     return aSeq;
2309   }
2310
2311   //Make a Python command
2312   anAsciiList.Trunc(anAsciiList.Length() - 1);
2313
2314   Handle(GEOM_Function) aFunction = anObj->GetLastFunction();
2315
2316   GEOM::TPythonDump(aFunction) << "[" << anAsciiList.ToCString()
2317     << "] = geompy.GetSharedShapes(" << theShape1 << ", "
2318       << theShape2 << ", " << TopAbs_ShapeEnum(theShapeType) << ")";
2319
2320   SetErrorCode(OK);
2321   return aSeq;
2322 }
2323
2324 //=======================================================================
2325 //function : GetSharedShapes
2326 //purpose  :
2327 //
2328 // NOTE on the implementation
2329 // 
2330 // 1) Resulting sub-shapes are published as a children of the 1st input shape
2331 //    from theShapes list. Due to this reason only direct sub-shapes of the 1st
2332 //    shape can be contained in the result of the operation (i.e. shares between
2333 //    2nd/3rd, etc couples cannot be retrieved.
2334 // 2) An exception from above case is when a single compound is specified as an
2335 //    input. In this case we search shares between its top-level content, so we
2336 //    are able to search shares between all possible couples of shapes.
2337 // 3) Parameter theMultiShare controls what types of shares to search:
2338 //    - True: get sub-shapes that are shared between ALL input shapes;
2339 //    - False: get shares between couples of input sub-shapes (see points 1 and 2).
2340 //
2341 // Thus, we have the following cases:
2342 // [1] theShapes = N shapes (N>1), theMultiShare = True
2343 //     Result: sub-shapes that are shared by all theShapes
2344 // [2] theShapes = N shapes (N>1), theMultiShare = False
2345 //     Result: sub-shapes of 1st shape from theShapes that are shared with any shape
2346 //     from theShapes
2347 // [3] theShapes = 1 shape, theMultiShare = True
2348 //     Result: sub-shapes that are shared by all top-level sub-objects of theShapes[0]
2349 // [4] theShapes = 1 shape, theMultiShare = False
2350 //     Result: sub-shapes of all possible couples of all top-level sub-objects of
2351 //     theShapes[0].
2352 //=======================================================================
2353 Handle(TColStd_HSequenceOfTransient) GEOMImpl_IShapesOperations::GetSharedShapes
2354                                      (std::list<Handle(GEOM_Object)> & theShapes,
2355                                       const Standard_Integer           theShapeType,
2356                                       const bool                       theMultiShare)
2357 {
2358   SetErrorCode(KO);
2359
2360   int aLen = theShapes.size();
2361   if (aLen < 1) return NULL;
2362
2363   std::list<Handle(GEOM_Object)>::iterator it = theShapes.begin();
2364
2365   // main object is always first in the input list
2366   // it is the object from which sub-shapes indices are taken
2367   // and where results are published
2368   Handle(GEOM_Object) aMainObj = *it;
2369   Handle(GEOM_Function) aMainShape = aMainObj->GetLastFunction();
2370
2371   // collect all shapes from the input list (including first one) for processing
2372   TopTools_SequenceOfShape shapeSeq;
2373   for (; it != theShapes.end(); it++) {
2374     Handle(GEOM_Function) aRefShape = (*it)->GetLastFunction();
2375     if (aRefShape.IsNull()) {
2376       SetErrorCode("NULL shape for GetSharedShapes");
2377       return NULL;
2378     }
2379     TopoDS_Shape aShape = aRefShape->GetValue();
2380     if (aShape.IsNull()) {
2381       SetErrorCode("NULL shape for GetSharedShapes");
2382       return NULL;
2383     }
2384     shapeSeq.Append( aShape );
2385   }
2386
2387   // if only single shape is specified as input
2388   // collect all ites top-level sub-shapes for processing
2389   if ( shapeSeq.Length() == 1 )
2390   {
2391     TopoDS_Shape aShape = shapeSeq.First();
2392     shapeSeq.Clear();
2393     for ( TopoDS_Iterator it( aShape ); it.More(); it.Next() )
2394       shapeSeq.Append( it.Value() );
2395   }
2396
2397   // map all sub-shapes in a main shape to their indices
2398   TopTools_IndexedMapOfShape anIndices;
2399   TopExp::MapShapes(aMainShape->GetValue(), anIndices);
2400   TopTools_MapOfShape mapShape;
2401
2402   // find shared shapes
2403
2404   // here we will collect all shares
2405   TopTools_ListOfShape aShared;
2406
2407   // number of iterations
2408   int nbIters  =  theMultiShare || theShapes.size() > 1 ? 1 : shapeSeq.Length()-1;
2409   // numShares factor to search (i.e. by what nb of shapes each found sub-shape should be shared)
2410   int nbShares =  theMultiShare ? shapeSeq.Length()-1 : 1;
2411     
2412   for ( int iter = 1; iter <= nbIters; iter++) {
2413     for ( int ind = iter+1; ind <= shapeSeq.Length(); ind++) {
2414       if ( ind-1+nbShares > shapeSeq.Length() ) break;
2415       TopoDS_Compound aCurrSelection;
2416       TopoDS_Shape aShape1 = shapeSeq.Value( iter );
2417       TopTools_IndexedMapOfShape mapSelected;
2418       TopExp::MapShapes(aShape1, TopAbs_ShapeEnum(theShapeType), mapSelected);
2419       for ( int s = 0; s < nbShares; s++ ) {
2420         BRep_Builder B;
2421         TopoDS_Compound aCompound;
2422         B.MakeCompound(aCompound);
2423         const TopoDS_Shape& aShape2 = shapeSeq.Value( ind+s );
2424         TopTools_MapOfShape mapShape2;
2425         TopExp_Explorer exp (aShape2, TopAbs_ShapeEnum(theShapeType));
2426         for (; exp.More(); exp.Next()) {
2427           const TopoDS_Shape& aSS = exp.Current();
2428           if (mapShape2.Add(aSS) && mapSelected.Contains(aSS)) {
2429             B.Add(aCompound, aSS);
2430           }
2431         }
2432         mapSelected.Clear();
2433         aCurrSelection = aCompound;
2434         TopExp::MapShapes(aCurrSelection, TopAbs_ShapeEnum(theShapeType), mapSelected);
2435       }
2436       TopoDS_Iterator itSel(aCurrSelection, Standard_True, Standard_True);
2437       for (; itSel.More(); itSel.Next()) {
2438         const TopoDS_Shape& aSS = itSel.Value();
2439         if (mapShape.Add(aSS) )
2440           aShared.Append(aSS);
2441       }
2442     }
2443   }
2444
2445   Handle(TColStd_HSequenceOfTransient) aSeq = new TColStd_HSequenceOfTransient;
2446
2447   if (aShared.IsEmpty()){
2448     SetErrorCode(NOT_FOUND_ANY);
2449     return aSeq;
2450   }
2451
2452   // create GEOM_Object for each found shared shape (collected in aShared)
2453   TCollection_AsciiString anAsciiList;
2454   Handle(GEOM_Object) anObj;
2455   TopTools_ListIteratorOfListOfShape itSub (aShared);
2456   for (; itSub.More(); itSub.Next()) {
2457     TopoDS_Shape aValue = itSub.Value();
2458     Handle(TColStd_HArray1OfInteger) anArray = new TColStd_HArray1OfInteger(1,1);
2459     anArray->SetValue(1, anIndices.FindIndex(aValue));
2460     anObj = GetEngine()->AddSubShape(aMainObj, anArray);
2461     aSeq->Append(anObj);
2462
2463     // for python command
2464     TCollection_AsciiString anEntry;
2465     TDF_Tool::Entry(anObj->GetEntry(), anEntry);
2466     anAsciiList += anEntry;
2467     anAsciiList += ",";
2468   }
2469
2470   // make a Python command
2471   anAsciiList.Trunc(anAsciiList.Length() - 1);
2472
2473   GEOM::TPythonDump pd (anObj->GetLastFunction());
2474   pd << "[" << anAsciiList.ToCString()
2475      << "] = geompy.GetSharedShapesMulti(";
2476
2477   if ( aLen > 1 )
2478     pd << "[";
2479
2480   it = theShapes.begin();
2481   pd << (*it++);
2482   while (it != theShapes.end()) {
2483     pd << ", " << (*it++);
2484   }
2485   if ( aLen > 1 )
2486     pd << "]";
2487
2488   pd << ", " << TopAbs_ShapeEnum(theShapeType) << ", " << theMultiShare << ")";
2489
2490   SetErrorCode(OK);
2491   return aSeq;
2492 }
2493
2494 //=============================================================================
2495 /*!
2496  *
2497  */
2498 //=============================================================================
2499 static GEOM::TPythonDump& operator<< (GEOM::TPythonDump&   theDump,
2500                                       const GEOMAlgo_State theState)
2501 {
2502   switch (theState) {
2503   case GEOMAlgo_ST_IN:
2504     theDump << "GEOM.ST_IN";
2505     break;
2506   case GEOMAlgo_ST_OUT:
2507     theDump << "GEOM.ST_OUT";
2508     break;
2509   case GEOMAlgo_ST_ON:
2510     theDump << "GEOM.ST_ON";
2511     break;
2512   case GEOMAlgo_ST_ONIN:
2513     theDump << "GEOM.ST_ONIN";
2514     break;
2515   case GEOMAlgo_ST_ONOUT:
2516     theDump << "GEOM.ST_ONOUT";
2517     break;
2518   default:
2519     theDump << "GEOM.ST_UNKNOWN";
2520     break;
2521   }
2522   return theDump;
2523 }
2524
2525 //=======================================================================
2526 //function : checkTypeShapesOn
2527 /*!
2528  * \brief Checks if theShapeType parameter of GetShapesOnXXX() is OK
2529  * \param theShapeType - the shape type to check
2530  * \retval bool  - result of the check
2531  */
2532 //=======================================================================
2533 bool GEOMImpl_IShapesOperations::checkTypeShapesOn(const Standard_Integer theShapeType)
2534 {
2535   if (theShapeType != TopAbs_VERTEX &&
2536       theShapeType != TopAbs_EDGE &&
2537       theShapeType != TopAbs_FACE &&
2538       theShapeType != TopAbs_SOLID) {
2539     SetErrorCode("Only solids, vertices, edges or faces can be found by this method");
2540     return false;
2541   }
2542   return true;
2543 }
2544
2545 //=======================================================================
2546 //function : makePlane
2547   /*!
2548    * \brief Creates Geom_Plane
2549     * \param theAx1 - shape object defining plane parameters
2550     * \retval Handle(Geom_Surface) - resulting surface
2551    */
2552 //=======================================================================
2553 Handle(Geom_Surface) GEOMImpl_IShapesOperations::makePlane(const TopoDS_Shape& anAx1)
2554 {
2555   if (anAx1.ShapeType() != TopAbs_EDGE) return NULL;
2556   TopoDS_Edge anEdge = TopoDS::Edge(anAx1);
2557   TopoDS_Vertex V1, V2;
2558   TopExp::Vertices(anEdge, V1, V2, Standard_True);
2559   if (V1.IsNull() || V2.IsNull()) {
2560     SetErrorCode("Bad edge given for the plane normal vector");
2561     return NULL;
2562   }
2563   gp_Pnt aLoc = BRep_Tool::Pnt(V1);
2564   gp_Vec aVec (aLoc, BRep_Tool::Pnt(V2));
2565   if (aVec.Magnitude() < Precision::Confusion()) {
2566     SetErrorCode("Vector with null magnitude given");
2567     return NULL;
2568   }
2569   return new Geom_Plane(aLoc, aVec);
2570 }
2571
2572 //=======================================================================
2573 //function : makeCylinder
2574   /*!
2575    * \brief Creates Geom_CylindricalSurface
2576     * \param theAx1 - edge defining cylinder axis
2577     * \param theRadius - cylinder radius
2578     * \retval Handle(Geom_Surface) - resulting surface
2579    */
2580 //=======================================================================
2581 Handle(Geom_Surface) GEOMImpl_IShapesOperations::makeCylinder(const TopoDS_Shape& anAxis,
2582                                                               const Standard_Real theRadius)
2583 {
2584   //Axis of the cylinder
2585   if (anAxis.ShapeType() != TopAbs_EDGE) {
2586     SetErrorCode("Not an edge given for the axis");
2587     return NULL;
2588   }
2589   TopoDS_Edge anEdge = TopoDS::Edge(anAxis);
2590   TopoDS_Vertex V1, V2;
2591   TopExp::Vertices(anEdge, V1, V2, Standard_True);
2592   if (V1.IsNull() || V2.IsNull()) {
2593     SetErrorCode("Bad edge given for the axis");
2594     return NULL;
2595   }
2596   gp_Pnt aLoc = BRep_Tool::Pnt(V1);
2597   gp_Vec aVec (aLoc, BRep_Tool::Pnt(V2));
2598   if (aVec.Magnitude() < Precision::Confusion()) {
2599     SetErrorCode("Vector with null magnitude given");
2600     return NULL;
2601   }
2602
2603   gp_Ax3 anAx3 (aLoc, aVec);
2604   return new Geom_CylindricalSurface(anAx3, theRadius);
2605 }
2606
2607 //=======================================================================
2608 //function : getShapesOnBoxIDs
2609   /*!
2610    * \brief Find IDs of sub-shapes complying with given status about surface
2611     * \param theBox - the box to check state of sub-shapes against
2612     * \param theShape - the shape to explore
2613     * \param theShapeType - type of sub-shape of theShape
2614     * \param theState - required state
2615     * \retval Handle(TColStd_HSequenceOfInteger) - IDs of found sub-shapes
2616    */
2617 //=======================================================================
2618 Handle(TColStd_HSequenceOfInteger)
2619   GEOMImpl_IShapesOperations::getShapesOnBoxIDs(const Handle(GEOM_Object)& theBox,
2620                                                 const Handle(GEOM_Object)& theShape,
2621                                                 const Standard_Integer theShapeType,
2622                                                 GEOMAlgo_State theState)
2623 {
2624   Handle(TColStd_HSequenceOfInteger) aSeqOfIDs;
2625
2626   TopoDS_Shape aBox = theBox->GetValue();
2627   TopoDS_Shape aShape = theShape->GetValue();
2628
2629   // Check presence of triangulation, build if need
2630   if (theShapeType != TopAbs_VERTEX && !GEOMUtils::CheckTriangulation(aShape)) {
2631     SetErrorCode("Cannot build triangulation on the shape");
2632     return aSeqOfIDs;
2633   }
2634
2635   // Call algo
2636   GEOMAlgo_FinderShapeOn2 aFinder;
2637   Standard_Real aTol = 0.0001; // default value
2638
2639   Handle(GEOMAlgo_ClsfBox) aClsfBox = new GEOMAlgo_ClsfBox;
2640   aClsfBox->SetBox(aBox);
2641
2642   aFinder.SetShape(aShape);
2643   aFinder.SetTolerance(aTol);
2644   aFinder.SetClsf(aClsfBox);
2645   aFinder.SetShapeType( (TopAbs_ShapeEnum)theShapeType );
2646   aFinder.SetState(theState);
2647   aFinder.Perform();
2648
2649   // Interpret results
2650   Standard_Integer iErr = aFinder.ErrorStatus();
2651   // the detailed description of error codes is in GEOMAlgo_FinderShapeOn2.cxx
2652   if (iErr) {
2653     MESSAGE(" iErr : " << iErr);
2654     TCollection_AsciiString aMsg (" iErr : ");
2655     aMsg += TCollection_AsciiString(iErr);
2656     SetErrorCode(aMsg);
2657     return aSeqOfIDs;
2658   }
2659   Standard_Integer iWrn = aFinder.WarningStatus();
2660   // the detailed description of warning codes is in GEOMAlgo_FinderShapeOn2.cxx
2661   if (iWrn) {
2662     MESSAGE(" *** iWrn : " << iWrn);
2663   }
2664
2665   const TopTools_ListOfShape& listSS = aFinder.Shapes(); // the result
2666
2667   if (listSS.Extent() < 1) {
2668     //SetErrorCode("Not a single sub-shape of the requested type found on the given surface");
2669     SetErrorCode(NOT_FOUND_ANY); // NPAL18017
2670     return aSeqOfIDs;
2671   }
2672
2673   // Fill sequence of object IDs
2674   aSeqOfIDs = new TColStd_HSequenceOfInteger;
2675
2676   TopTools_IndexedMapOfShape anIndices;
2677   TopExp::MapShapes(aShape, anIndices);
2678
2679   TopTools_ListIteratorOfListOfShape itSub (listSS);
2680   for (int index = 1; itSub.More(); itSub.Next(), ++index) {
2681     int id = anIndices.FindIndex(itSub.Value());
2682     aSeqOfIDs->Append(id);
2683   }
2684
2685   return aSeqOfIDs;
2686 }
2687
2688 //=======================================================================
2689 //function : GetShapesOnBoxIDs
2690 /*!
2691    * \brief Find sub-shapes complying with given status about surface
2692     * \param theBox - the box to check state of sub-shapes against
2693     * \param theShape - the shape to explore
2694     * \param theShapeType - type of sub-shape of theShape
2695     * \param theState - required state
2696     * \retval Handle(TColStd_HSequenceOfInteger) - IDs of found sub-shapes
2697  */
2698 //=======================================================================
2699 Handle(TColStd_HSequenceOfInteger)
2700     GEOMImpl_IShapesOperations::GetShapesOnBoxIDs(const Handle(GEOM_Object)& theBox,
2701                                                   const Handle(GEOM_Object)& theShape,
2702                                                   const Standard_Integer theShapeType,
2703                                                   GEOMAlgo_State theState)
2704 {
2705   // Find sub-shapes ids
2706   Handle(TColStd_HSequenceOfInteger) aSeqOfIDs =
2707     getShapesOnBoxIDs (theBox, theShape, theShapeType, theState);
2708   if ( aSeqOfIDs.IsNull()  || aSeqOfIDs->Length() == 0 )
2709     return NULL;
2710
2711   // The GetShapesOnBox() doesn't change object so no new function is required.
2712   Handle(GEOM_Function) aFunction = GEOM::GetCreatedLast(theShape,theBox)->GetLastFunction();
2713
2714   // VSR 29/08/2017: 0023327, 0023428: eliminate unnecessary lines in Python dump
2715 #ifdef DUMP_SUBSHAPE_IDS
2716   // Make a Python command
2717   GEOM::TPythonDump(aFunction, /*append=*/true)
2718     << "listShapesOnBoxIDs = geompy.GetShapesOnBoxIDs("
2719     << theBox << ", "
2720     << theShape << ", "
2721     << TopAbs_ShapeEnum(theShapeType) << ", "
2722     << theState << ")";
2723 #endif // DUMP_SUBSHAPE_IDS
2724
2725   SetErrorCode(OK);
2726   return aSeqOfIDs;
2727 }
2728
2729 //=======================================================================
2730 //function : GetShapesOnBox
2731 /*!
2732    * \brief Find sub-shapes complying with given status about surface
2733     * \param theBox - the box to check state of sub-shapes against
2734     * \param theShape - the shape to explore
2735     * \param theShapeType - type of sub-shape of theShape
2736     * \param theState - required state
2737     * \retval Handle(TColStd_HSequenceOfTransient) - found sub-shapes
2738  */
2739 //=======================================================================
2740 Handle(TColStd_HSequenceOfTransient)
2741     GEOMImpl_IShapesOperations::GetShapesOnBox(const Handle(GEOM_Object)& theBox,
2742                                                const Handle(GEOM_Object)&  theShape,
2743                                                const Standard_Integer theShapeType,
2744                                                GEOMAlgo_State theState)
2745 {
2746   // Find sub-shapes ids
2747   Handle(TColStd_HSequenceOfInteger) aSeqOfIDs =
2748     getShapesOnBoxIDs (theBox, theShape, theShapeType, theState);
2749   if ( aSeqOfIDs.IsNull()  || aSeqOfIDs->Length() == 0 )
2750     return NULL;
2751
2752   // Find objects by indices
2753   TCollection_AsciiString anAsciiList;
2754   Handle(TColStd_HSequenceOfTransient) aSeq;
2755   aSeq = getObjectsShapesOn( theShape, aSeqOfIDs, anAsciiList );
2756   if ( aSeq.IsNull() || aSeq->IsEmpty() )
2757     return NULL;
2758
2759   // Make a Python command
2760
2761   Handle(GEOM_Object) anObj = Handle(GEOM_Object)::DownCast( aSeq->Value( 1 ));
2762   Handle(GEOM_Function) aFunction = anObj->GetLastFunction();
2763
2764   GEOM::TPythonDump(aFunction)
2765     << "[" << anAsciiList.ToCString() << "] = geompy.GetShapesOnBox("
2766     << theBox << ", "
2767     << theShape << ", "
2768     << TopAbs_ShapeEnum(theShapeType) << ", "
2769     << theState << ")";
2770
2771   SetErrorCode(OK);
2772   return aSeq;
2773 }
2774
2775 //=======================================================================
2776 //function : getShapesOnShapeIDs
2777 /*!
2778  * \brief Find IDs of sub-shapes complying with given status about surface
2779  * \param theCheckShape - the shape to check state of sub-shapes against
2780  * \param theShape - the shape to explore
2781  * \param theShapeType - type of sub-shape of theShape
2782  * \param theState - required state
2783  * \retval Handle(TColStd_HSequenceOfInteger) - IDs of found sub-shapes
2784  */
2785 //=======================================================================
2786 Handle(TColStd_HSequenceOfInteger)
2787   GEOMImpl_IShapesOperations::getShapesOnShapeIDs
2788                                  (const Handle(GEOM_Object)& theCheckShape,
2789                                   const Handle(GEOM_Object)& theShape,
2790                                   const Standard_Integer theShapeType,
2791                                   GEOMAlgo_State theState)
2792 {
2793   Handle(TColStd_HSequenceOfInteger) aSeqOfIDs;
2794
2795   TopoDS_Shape aCheckShape = theCheckShape->GetValue();
2796   TopoDS_Shape aShape = theShape->GetValue();
2797   TopTools_ListOfShape res;
2798
2799   // Check presence of triangulation, build if need
2800   if (theShapeType != TopAbs_VERTEX && !GEOMUtils::CheckTriangulation(aShape)) {
2801     SetErrorCode("Cannot build triangulation on the shape");
2802     return aSeqOfIDs;
2803   }
2804
2805   // Compute classification tolerance.
2806   TopTools_IndexedMapOfShape aMapVtx;
2807   Standard_Real              aTol = Precision::Confusion();
2808
2809   TopExp::MapShapes(aShape, TopAbs_VERTEX, aMapVtx);
2810
2811   Standard_Integer i;
2812   Standard_Integer aNbVtx = aMapVtx.Extent();
2813
2814   for (i = 1; i <= aNbVtx; ++i) {
2815     const TopoDS_Vertex aVtx    = TopoDS::Vertex(aMapVtx.FindKey(i));
2816     const Standard_Real aVtxTol = BRep_Tool::Tolerance(aVtx);
2817
2818     if (aTol < aVtxTol) {
2819       aTol = aVtxTol;
2820     }
2821   }
2822
2823   // Bound the tolerance value.
2824   if (aTol > 0.0001) {
2825     aTol = 0.0001;
2826   }
2827
2828   // Call algo
2829   GEOMAlgo_FinderShapeOn2 aFinder;
2830
2831   Handle(GEOMAlgo_ClsfSolid) aClsfSolid = new GEOMAlgo_ClsfSolid;
2832   aClsfSolid->SetShape(aCheckShape);
2833
2834   aFinder.SetShape(aShape);
2835   aFinder.SetTolerance(aTol);
2836   aFinder.SetClsf(aClsfSolid);
2837   aFinder.SetShapeType( (TopAbs_ShapeEnum)theShapeType );
2838   aFinder.SetState(theState);
2839   aFinder.Perform();
2840
2841   // Interpret results
2842   Standard_Integer iErr = aFinder.ErrorStatus();
2843   // the detailed description of error codes is in GEOMAlgo_FinderShapeOn2.cxx
2844   if (iErr) {
2845     if (iErr == 41) {
2846       SetErrorCode("theCheckShape must be a solid");
2847     }
2848     else {
2849       MESSAGE(" iErr : " << iErr);
2850       TCollection_AsciiString aMsg (" iErr : ");
2851       aMsg += TCollection_AsciiString(iErr);
2852       SetErrorCode(aMsg);
2853     }
2854     return aSeqOfIDs;
2855   }
2856   Standard_Integer iWrn = aFinder.WarningStatus();
2857   // the detailed description of warning codes is in GEOMAlgo_FinderShapeOn2.cxx
2858   if (iWrn) {
2859     MESSAGE(" *** iWrn : " << iWrn);
2860   }
2861
2862   const TopTools_ListOfShape& listSS = aFinder.Shapes(); // the result
2863
2864   if (listSS.Extent() < 1) {
2865     //SetErrorCode("Not a single sub-shape of the requested type found on the given surface");
2866     SetErrorCode(NOT_FOUND_ANY); // NPAL18017
2867   }
2868
2869   // Fill sequence of object IDs
2870   aSeqOfIDs = new TColStd_HSequenceOfInteger;
2871
2872   TopTools_IndexedMapOfShape anIndices;
2873   TopExp::MapShapes(aShape, anIndices);
2874
2875   TopTools_ListIteratorOfListOfShape itSub (listSS);
2876   for (int index = 1; itSub.More(); itSub.Next(), ++index) {
2877     int id = anIndices.FindIndex(itSub.Value());
2878     aSeqOfIDs->Append(id);
2879   }
2880
2881   return aSeqOfIDs;
2882 }
2883
2884 //=======================================================================
2885 //function : GetShapesOnShapeIDs
2886 /*!
2887  * \brief Find sub-shapes complying with given status about surface
2888  * \param theCheckShape - the shape to check state of sub-shapes against
2889  * \param theShape - the shape to explore
2890  * \param theShapeType - type of sub-shape of theShape
2891  * \param theState - required state
2892  * \retval Handle(TColStd_HSequenceOfInteger) - IDs of found sub-shapes
2893  */
2894 //=======================================================================
2895 Handle(TColStd_HSequenceOfInteger)
2896     GEOMImpl_IShapesOperations::GetShapesOnShapeIDs
2897                             (const Handle(GEOM_Object)& theCheckShape,
2898                              const Handle(GEOM_Object)& theShape,
2899                              const Standard_Integer theShapeType,
2900                              GEOMAlgo_State theState)
2901 {
2902   Handle(TColStd_HSequenceOfInteger) aSeqOfIDs =
2903     getShapesOnShapeIDs (theCheckShape, theShape, theShapeType, theState);
2904
2905   if ( aSeqOfIDs.IsNull()  || aSeqOfIDs->Length() == 0 )
2906     return NULL;
2907
2908   // The GetShapesOnShape() doesn't change object so no new function is required.
2909   Handle(GEOM_Function) aFunction =
2910     GEOM::GetCreatedLast(theShape,theCheckShape)->GetLastFunction();
2911
2912   // VSR 29/08/2017: 0023327, 0023428: eliminate unnecessary lines in Python dump
2913 #ifdef DUMP_SUBSHAPE_IDS
2914   // Make a Python command
2915   GEOM::TPythonDump(aFunction, /*append=*/true)
2916     << "listShapesOnShapeIDs = geompy.GetShapesOnShapeIDs("
2917     << theCheckShape << ", "
2918     << theShape << ", "
2919     << TopAbs_ShapeEnum(theShapeType) << ", "
2920     << theState << ")";
2921 #endif // DUMP_SUBSHAPE_IDS
2922
2923   SetErrorCode(OK);
2924   return aSeqOfIDs;
2925 }
2926
2927 //=======================================================================
2928 //function : GetShapesOnShape
2929 /*!
2930  * \brief Find sub-shapes complying with given status about surface
2931  * \param theCheckShape - the shape to check state of sub-shapes against
2932  * \param theShape - the shape to explore
2933  * \param theShapeType - type of sub-shape of theShape
2934  * \param theState - required state
2935  * \retval Handle(TColStd_HSequenceOfTransient) - found sub-shapes
2936  */
2937 //=======================================================================
2938 Handle(TColStd_HSequenceOfTransient)
2939   GEOMImpl_IShapesOperations::GetShapesOnShape
2940                              (const Handle(GEOM_Object)& theCheckShape,
2941                               const Handle(GEOM_Object)&  theShape,
2942                               const Standard_Integer theShapeType,
2943                               GEOMAlgo_State theState)
2944 {
2945   Handle(TColStd_HSequenceOfInteger) aSeqOfIDs =
2946     getShapesOnShapeIDs (theCheckShape, theShape, theShapeType, theState);
2947   if ( aSeqOfIDs.IsNull()  || aSeqOfIDs->Length() == 0 )
2948     return NULL;
2949
2950   // Find objects by indices
2951   TCollection_AsciiString anAsciiList;
2952   Handle(TColStd_HSequenceOfTransient) aSeq;
2953   aSeq = getObjectsShapesOn( theShape, aSeqOfIDs, anAsciiList );
2954
2955   if ( aSeq.IsNull() || aSeq->IsEmpty() )
2956     return NULL;
2957
2958   // Make a Python command
2959
2960   Handle(GEOM_Object) anObj = Handle(GEOM_Object)::DownCast( aSeq->Value( 1 ));
2961   Handle(GEOM_Function) aFunction = anObj->GetLastFunction();
2962
2963   GEOM::TPythonDump(aFunction)
2964     << "[" << anAsciiList.ToCString() << "] = geompy.GetShapesOnShape("
2965     << theCheckShape << ", "
2966     << theShape << ", "
2967     << TopAbs_ShapeEnum(theShapeType) << ", "
2968     << theState << ")";
2969
2970   SetErrorCode(OK);
2971   return aSeq;
2972 }
2973
2974 //=======================================================================
2975 //function : GetShapesOnShapeAsCompound
2976 //=======================================================================
2977 Handle(GEOM_Object) GEOMImpl_IShapesOperations::GetShapesOnShapeAsCompound
2978                              (const Handle(GEOM_Object)& theCheckShape,
2979                               const Handle(GEOM_Object)&  theShape,
2980                               const Standard_Integer theShapeType,
2981                               GEOMAlgo_State theState)
2982 {
2983   Handle(TColStd_HSequenceOfInteger) aSeqOfIDs =
2984     getShapesOnShapeIDs (theCheckShape, theShape, theShapeType, theState);
2985
2986   if ( aSeqOfIDs.IsNull()  || aSeqOfIDs->Length() == 0 )
2987     return NULL;
2988
2989   // Find objects by indices
2990   TCollection_AsciiString anAsciiList;
2991   Handle(TColStd_HSequenceOfTransient) aSeq;
2992   aSeq = getObjectsShapesOn( theShape, aSeqOfIDs, anAsciiList );
2993
2994   if ( aSeq.IsNull() || aSeq->IsEmpty() )
2995     return NULL;
2996
2997   TopoDS_Compound aCompound;
2998   BRep_Builder B;
2999   B.MakeCompound(aCompound);
3000   int i = 1;
3001   for(; i<=aSeq->Length(); i++) {
3002     Handle(GEOM_Object) anObj = Handle(GEOM_Object)::DownCast(aSeq->Value(i));
3003     TopoDS_Shape aShape_i = anObj->GetValue();
3004     B.Add(aCompound,aShape_i);
3005   }
3006
3007   //Add a new result object
3008   Handle(GEOM_Object) aRes = GetEngine()->AddObject(GEOM_SHAPES_ON_SHAPE);
3009   Handle(GEOM_Function) aFunction =
3010     aRes->AddFunction(GEOMImpl_ShapeDriver::GetID(), SHAPES_ON_SHAPE);
3011   aFunction->SetValue(aCompound);
3012
3013   aSeq->Clear();
3014   aSeq->Append( theCheckShape->GetLastFunction() );
3015   aSeq->Append( theShape->GetLastFunction() );
3016
3017   GEOMImpl_IShapes aCI( aFunction );
3018   aCI.SetShapes( aSeq );
3019   aCI.SetSubShapeType( theShapeType );
3020   aCI.SetTolerance( theState );
3021
3022   GEOM::TPythonDump(aFunction)
3023     << aRes << " = geompy.GetShapesOnShapeAsCompound("
3024     << theCheckShape << ", "
3025     << theShape << ", "
3026     << TopAbs_ShapeEnum(theShapeType) << ", "
3027     << theState << ")";
3028
3029   SetErrorCode(OK);
3030
3031   return aRes;
3032 }
3033
3034 //=============================================================================
3035 /*!
3036  *  GetSubShapeEdgeSorted
3037  */
3038 //=============================================================================
3039 Handle(TColStd_HSequenceOfTransient)
3040     GEOMImpl_IShapesOperations::GetSubShapeEdgeSorted
3041                           (const Handle(GEOM_Object) &theShape,
3042                            const Handle(GEOM_Object) &theStartPoint)
3043 {
3044   // Get the sorted edges indices.
3045   Handle(TColStd_HSequenceOfInteger) aSortedIDs =
3046     getSubShapeEdgeSortedIDs(theShape, theStartPoint);
3047
3048   // Get object by indices.
3049   TCollection_AsciiString              anAsciiList;
3050   Handle(TColStd_HSequenceOfTransient) aSeq =
3051     getObjectsShapesOn(theShape, aSortedIDs, anAsciiList);
3052
3053   if (aSeq.IsNull() || aSeq->IsEmpty()) {
3054     SetErrorCode("Empty sequence of edges");
3055     return NULL;
3056   }
3057
3058   // Make a Python command
3059   Handle(GEOM_Object)   anObj     =
3060     Handle(GEOM_Object)::DownCast(aSeq->Value(1));
3061   Handle(GEOM_Function) aFunction = anObj->GetLastFunction();
3062
3063   GEOM::TPythonDump(aFunction)
3064     << "[" << anAsciiList.ToCString() << "] = geompy.GetSubShapeEdgeSorted("
3065     << theShape << ", " << theStartPoint << ")";
3066
3067   SetErrorCode(OK);
3068
3069   return aSeq;
3070 }
3071
3072 //=============================================================================
3073 /*!
3074  *  GetSubShapesWithTolerance
3075  */
3076 //=============================================================================
3077 Handle(TColStd_HSequenceOfTransient)
3078     GEOMImpl_IShapesOperations::GetSubShapesWithTolerance
3079                      (const Handle(GEOM_Object)            &theShape,
3080                       const Standard_Integer                theShapeType,
3081                       const GEOMUtils::ComparisonCondition  theCondition,
3082                       const Standard_Real                   theTolerance)
3083 {
3084   if (theShape.IsNull()) {
3085     SetErrorCode("NULL GEOM object");
3086     return NULL;
3087   }
3088
3089   TopoDS_Shape aShape = theShape->GetValue();
3090
3091   if (aShape.IsNull()) {
3092     SetErrorCode("NULL Shape");
3093     return NULL;
3094   }
3095
3096   if (theShapeType != TopAbs_FACE && theShapeType != TopAbs_EDGE &&
3097       theShapeType != TopAbs_VERTEX && aShape.ShapeType() >= theShapeType) {
3098     SetErrorCode("Invalid shape type");
3099     return NULL;
3100   }
3101
3102   TopTools_IndexedMapOfShape         anIndices;
3103   TopTools_MapOfShape                aMapFence;
3104   TopExp_Explorer                    anExp(aShape,
3105                                            (TopAbs_ShapeEnum) theShapeType);
3106   Handle(TColStd_HSequenceOfInteger) anIDs = new TColStd_HSequenceOfInteger;
3107
3108   TopExp::MapShapes(aShape, anIndices);
3109
3110   for (; anExp.More(); anExp.Next()) {
3111     const TopoDS_Shape &aSubShape = anExp.Current();
3112
3113     if (aMapFence.Add(aSubShape)) {
3114       // Compute tolerance
3115       Standard_Real aTolerance = -1.;
3116
3117       switch (aSubShape.ShapeType()) {
3118         case TopAbs_FACE:
3119           aTolerance = BRep_Tool::Tolerance(TopoDS::Face(aSubShape));
3120           break;
3121         case TopAbs_EDGE:
3122           aTolerance = BRep_Tool::Tolerance(TopoDS::Edge(aSubShape));
3123           break;
3124         case TopAbs_VERTEX:
3125           aTolerance = BRep_Tool::Tolerance(TopoDS::Vertex(aSubShape));
3126           break;
3127         default:
3128           break;
3129       }
3130
3131       if (aTolerance < 0.) {
3132         continue;
3133       }
3134
3135       // Compare the tolerance with reference value.
3136       if (GEOMUtils::IsFitCondition (theCondition, aTolerance, theTolerance)) {
3137         anIDs->Append(anIndices.FindIndex(aSubShape));
3138       }
3139     }
3140   }
3141
3142   if (anIDs->IsEmpty()) {
3143     SetErrorCode("Empty sequence of sub-shapes");
3144     return NULL;
3145   }
3146
3147   // Get objects by indices.
3148   TCollection_AsciiString              anAsciiList;
3149   Handle(TColStd_HSequenceOfTransient) aSeq =
3150     getObjectsShapesOn(theShape, anIDs, anAsciiList);
3151
3152   if (aSeq.IsNull() || aSeq->IsEmpty()) {
3153     SetErrorCode("Empty sequence of edges");
3154     return NULL;
3155   }
3156
3157   // Make a Python command
3158   Handle(GEOM_Object)   anObj     =
3159     Handle(GEOM_Object)::DownCast(aSeq->Value(1));
3160   Handle(GEOM_Function) aFunction = anObj->GetLastFunction();
3161
3162   GEOM::TPythonDump(aFunction)
3163     << "[" << anAsciiList.ToCString() << "] = geompy.GetSubShapesWithTolerance("
3164     << theShape << ", " << theShapeType << ", " << theCondition << ", "
3165     << theTolerance << ")";
3166
3167   SetErrorCode(OK);
3168
3169   return aSeq;
3170 }
3171
3172 //=============================================================================
3173 /*!
3174  *  MakeExtraction
3175  */
3176 //=============================================================================
3177 Handle(GEOM_Object) GEOMImpl_IShapesOperations::MakeExtraction
3178                      (const Handle(GEOM_Object)              &theShape,
3179                       const Handle(TColStd_HArray1OfInteger) &theSubShapeIDs,
3180                       std::list<ExtractionStat>              &theStats)
3181 {
3182   SetErrorCode(KO);
3183
3184   if (theShape.IsNull()) {
3185     return NULL;
3186   }
3187
3188   //Add a new Result object
3189   Handle(GEOM_Object) aResult =
3190               GetEngine()->AddObject(GEOM_EXTRACTION);
3191
3192   //Add a new Extraction function
3193   Handle(GEOM_Function) aFunction =
3194     aResult->AddFunction(GEOMImpl_ShapeDriver::GetID(), EXTRACTION);
3195
3196   //Check if the function is set correctly
3197   if (aFunction->GetDriverGUID() != GEOMImpl_ShapeDriver::GetID()) {
3198     return NULL;
3199   }
3200
3201   Handle(GEOM_Function) aShape = theShape->GetLastFunction();
3202
3203   if (aShape.IsNull()) {
3204     return NULL;
3205   }
3206
3207   GEOMImpl_IExtract aCI (aFunction);
3208
3209   aCI.SetShape(aShape);
3210   aCI.SetSubShapeIDs(theSubShapeIDs);
3211
3212   //Compute the Edge value
3213   try {
3214     OCC_CATCH_SIGNALS;
3215     if (!GetSolver()->ComputeFunction(aFunction)) {
3216       SetErrorCode("Shape driver failed");
3217
3218       return NULL;
3219     }
3220   }
3221   catch (Standard_Failure& aFail) {
3222     SetErrorCode(aFail.GetMessageString());
3223
3224     return NULL;
3225   }
3226
3227   // Fill in statistics.
3228   theStats.clear();
3229
3230   Handle(TColStd_HArray1OfInteger) aStatIDsArray[3] = 
3231     { aCI.GetRemovedIDs(), aCI.GetModifiedIDs(), aCI.GetAddedIDs() };
3232   int                              i;
3233   int                              j;
3234
3235   for (j = 0; j < 3; ++j) {
3236     if (!aStatIDsArray[j].IsNull()) {
3237       const int      anUpperID = aStatIDsArray[j]->Upper();
3238       ExtractionStat aStat;
3239
3240       for (i = aStatIDsArray[j]->Lower(); i <= anUpperID; ++i) {
3241         aStat.indices.push_back(aStatIDsArray[j]->Value(i));
3242       }
3243
3244       aStat.type = (ExtractionStatType) j;
3245       theStats.push_back(aStat);
3246     }
3247   }
3248
3249   //Make a Python command
3250   GEOM::TPythonDump pd(aFunction);
3251
3252   pd << aResult  << " = geompy.MakeExtraction(" << theShape << ", [";
3253
3254   if (!theSubShapeIDs.IsNull()) {
3255     const int aNbIDs = theSubShapeIDs->Upper();
3256
3257     for (i = theSubShapeIDs->Lower(); i < aNbIDs; ++i) {
3258       pd << theSubShapeIDs->Value(i) << ", ";
3259     }
3260
3261     // Dump the last value without a comma.
3262     pd << theSubShapeIDs->Value(i);
3263   }
3264
3265   pd << "])";
3266
3267   SetErrorCode(OK);
3268
3269   return aResult;
3270 }
3271
3272 //=======================================================================
3273 //function : getShapesOnSurfaceIDs
3274   /*!
3275    * \brief Find IDs of sub-shapes complying with given status about surface
3276     * \param theSurface - the surface to check state of sub-shapes against
3277     * \param theShape - the shape to explore
3278     * \param theShapeType - type of sub-shape of theShape
3279     * \param theState - required state
3280     * \retval Handle(TColStd_HSequenceOfInteger) - IDs of found sub-shapes
3281    */
3282 //=======================================================================
3283 Handle(TColStd_HSequenceOfInteger)
3284   GEOMImpl_IShapesOperations::getShapesOnSurfaceIDs(const Handle(Geom_Surface)& theSurface,
3285                                                     const TopoDS_Shape&         theShape,
3286                                                     TopAbs_ShapeEnum            theShapeType,
3287                                                     GEOMAlgo_State              theState)
3288 {
3289   Handle(TColStd_HSequenceOfInteger) aSeqOfIDs;
3290
3291   // Check presence of triangulation, build if need
3292   if (theShapeType != TopAbs_VERTEX &&
3293       !GEOMUtils::CheckTriangulation(theShape)) {
3294     SetErrorCode("Cannot build triangulation on the shape");
3295     return aSeqOfIDs;
3296   }
3297
3298   // BEGIN: Mantis issue 0020961: Error on a pipe T-Shape
3299   // Compute tolerance
3300   Standard_Real T, VertMax = -RealLast();
3301   try {
3302     OCC_CATCH_SIGNALS;
3303     for (TopExp_Explorer ExV (theShape, TopAbs_VERTEX); ExV.More(); ExV.Next()) {
3304       TopoDS_Vertex Vertex = TopoDS::Vertex(ExV.Current());
3305       T = BRep_Tool::Tolerance(Vertex);
3306       if (T > VertMax)
3307         VertMax = T;
3308     }
3309   }
3310   catch (Standard_Failure& aFail) {
3311     SetErrorCode(aFail.GetMessageString());
3312     return aSeqOfIDs;
3313   }
3314   // END: Mantis issue 0020961
3315
3316   // Call algo
3317   GEOMAlgo_FinderShapeOn2   aFinder;
3318   Handle(GEOMAlgo_ClsfSurf) aClsfSurf = new GEOMAlgo_ClsfSurf;
3319   Standard_Real             aTol      = VertMax; // Mantis issue 0020961
3320
3321   aClsfSurf->SetSurface(theSurface);
3322   aFinder.SetShape(theShape);
3323   aFinder.SetTolerance(aTol);
3324   aFinder.SetClsf(aClsfSurf);
3325   aFinder.SetShapeType(theShapeType);
3326   aFinder.SetState(theState);
3327
3328   // Sets the minimal number of inner points for the faces that do not have own
3329   // inner points at all (for e.g. rectangular planar faces have just 2 triangles).
3330   // Default value=3
3331   aFinder.SetNbPntsMin(3);
3332   // Sets the maximal number of inner points for edges or faces.
3333   // It is useful for the cases when this number is very big (e.g =2000) to improve
3334   // the performance. If this value =0, all inner points will be taken into account.
3335   // Default value=0
3336   aFinder.SetNbPntsMax(100);
3337
3338   aFinder.Perform();
3339
3340   // Interpret results
3341   Standard_Integer iErr = aFinder.ErrorStatus();
3342   // the detailed description of error codes is in GEOMAlgo_FinderShapeOn2.cxx
3343   if (iErr) {
3344     MESSAGE(" iErr : " << iErr);
3345     TCollection_AsciiString aMsg (" iErr : ");
3346     aMsg += TCollection_AsciiString(iErr);
3347     SetErrorCode(aMsg);
3348     return aSeqOfIDs;
3349   }
3350   Standard_Integer iWrn = aFinder.WarningStatus();
3351   // the detailed description of warning codes is in GEOMAlgo_FinderShapeOn2.cxx
3352   if (iWrn) {
3353     MESSAGE(" *** iWrn : " << iWrn);
3354   }
3355
3356   const TopTools_ListOfShape& listSS = aFinder.Shapes(); // the result
3357
3358   if (listSS.Extent() < 1) {
3359     //SetErrorCode("Not a single sub-shape of the requested type found on the given surface");
3360     SetErrorCode(NOT_FOUND_ANY); // NPAL18017
3361     return aSeqOfIDs;
3362   }
3363
3364   // Fill sequence of object IDs
3365   aSeqOfIDs = new TColStd_HSequenceOfInteger;
3366
3367   TopTools_IndexedMapOfShape anIndices;
3368   TopExp::MapShapes(theShape, anIndices);
3369
3370   TopTools_ListIteratorOfListOfShape itSub (listSS);
3371   for (int index = 1; itSub.More(); itSub.Next(), ++index) {
3372     int id = anIndices.FindIndex(itSub.Value());
3373     aSeqOfIDs->Append(id);
3374   }
3375
3376   return aSeqOfIDs;
3377 }
3378
3379 //=======================================================================
3380 //function : getObjectsShapesOn
3381 /*!
3382  * \brief Find shape objects and their entries by their ids
3383  * \param theShapeIDs - incoming shape ids
3384  * \param theShapeEntries - outgoing entries like "entry1, entry2, ..."
3385  * \retval Handle(TColStd_HSequenceOfTransient) - found shape objects
3386  */
3387 //=======================================================================
3388 Handle(TColStd_HSequenceOfTransient) GEOMImpl_IShapesOperations::
3389  getObjectsShapesOn(const Handle(GEOM_Object)&                theShape,
3390                     const Handle(TColStd_HSequenceOfInteger)& theShapeIDs,
3391                     TCollection_AsciiString &                 theShapeEntries)
3392 {
3393   Handle(TColStd_HSequenceOfTransient) aSeq;
3394
3395   if ( !theShapeIDs.IsNull() && theShapeIDs->Length() > 0 )
3396   {
3397     aSeq = new TColStd_HSequenceOfTransient;
3398     Handle(TColStd_HArray1OfInteger) anArray = new TColStd_HArray1OfInteger(1,1);
3399     TCollection_AsciiString anEntry;
3400     for ( int i = 1; i <= theShapeIDs->Length(); ++i )
3401     {
3402       anArray->SetValue(1, theShapeIDs->Value( i ));
3403       Handle(GEOM_Object) anObj = GetEngine()->AddSubShape(theShape, anArray);
3404       aSeq->Append( anObj );
3405
3406       TDF_Tool::Entry(anObj->GetEntry(), anEntry);
3407       if ( i != 1 ) theShapeEntries += ",";
3408       theShapeEntries += anEntry;
3409     }
3410   }
3411   return aSeq;
3412 }
3413
3414 //=============================================================================
3415 /*!
3416  *  getSubShapeEdgeSortedIDs
3417  */
3418 //=============================================================================
3419 Handle(TColStd_HSequenceOfInteger)
3420     GEOMImpl_IShapesOperations::getSubShapeEdgeSortedIDs
3421                                (const Handle(GEOM_Object) &theShape,
3422                                 const Handle(GEOM_Object) &theStartPoint)
3423 {
3424   Handle(TColStd_HSequenceOfInteger) aResult;
3425
3426   if (theShape.IsNull() || theStartPoint.IsNull()) {
3427     SetErrorCode("NULL GEOM object");
3428     return aResult;
3429   }
3430
3431   const TopoDS_Shape aShape      = theShape->GetValue();
3432   const TopoDS_Shape aStartPoint = theStartPoint->GetValue();
3433
3434   if (aShape.IsNull() || aStartPoint.IsNull()) {
3435     SetErrorCode("NULL Shape");
3436     return aResult;
3437   }
3438
3439   if (aStartPoint.ShapeType() != TopAbs_VERTEX) {
3440     SetErrorCode("Starting point is not a vertex");
3441     return aResult;
3442   }
3443
3444   TopExp_Explorer      anExp(aShape, TopAbs_EDGE);
3445   TopTools_MapOfShape  aMapFence;
3446   TopTools_ListOfShape anEdges;
3447
3448   for (; anExp.More(); anExp.Next()) {
3449     const TopoDS_Shape &anEdge = anExp.Current();
3450
3451     if (aMapFence.Add(anEdge)) {
3452       anEdges.Append(anEdge);
3453     }
3454   }
3455
3456   if (anEdges.IsEmpty()) {
3457     SetErrorCode("Shape doesn't contain edges");
3458     return aResult;
3459   }
3460
3461   // Step 1: Sort edges
3462   GEOMUtils::SortShapes(anEdges, Standard_False);
3463
3464   TopTools_ListIteratorOfListOfShape anIter(anEdges);
3465   TopoDS_Vertex                      aV[2];
3466   TopTools_DataMapOfShapeListOfShape aMapVE;
3467
3468   // Step 2: Fill the map vertex - list of edges.
3469   for (; anIter.More(); anIter.Next()) {
3470     TopoDS_Edge anEdge = TopoDS::Edge(anIter.Value());
3471
3472     TopExp::Vertices(anEdge, aV[0], aV[1]);
3473
3474     const Standard_Integer aNbV = aV[0].IsSame(aV[1]) ? 1 : 2;
3475     Standard_Integer       i;
3476
3477     for (i = 0; i < aNbV; ++i) {
3478       if (aV[i].IsNull() == Standard_False) {
3479         if (!aMapVE.IsBound(aV[i])) {
3480           // There is no this vertex in the map.
3481           aMapVE.Bind(aV[i], TopTools_ListOfShape());
3482         }
3483
3484         // Add the edge to the list bound with the vertex aV[i].
3485         TopTools_ListOfShape &aLEdges = aMapVE.ChangeFind(aV[i]);
3486
3487         aLEdges.Append(anEdge);
3488       }
3489     }
3490   }
3491
3492   // Step 3: Find starting point in aMapVE.
3493   TopoDS_Vertex aStartVtx = TopoDS::Vertex(aStartPoint);
3494
3495   if (!aMapVE.IsBound(aStartVtx)) {
3496     aStartVtx = getSameVertex(aShape, aStartVtx);
3497
3498     if (aStartVtx.IsNull()) {
3499       SetErrorCode("Invalid Starting point");
3500       return aResult;
3501     }
3502   }
3503
3504   TopTools_IndexedMapOfShape anIndices;
3505   TopTools_MapOfShape        aMapVFence;
3506   TopoDS_Shape               aCurVtx  = aStartVtx;
3507   TopoDS_Edge                aCurEdge =
3508     TopoDS::Edge(aMapVE.Find(aCurVtx).First());
3509
3510   aResult = new TColStd_HSequenceOfInteger;
3511   TopExp::MapShapes(aShape, anIndices);
3512
3513   // Step 4: Fill the list of sorted edges.
3514   while (aMapVFence.Add(aCurVtx)) {
3515     // Append the ID of the current edge to the list of sorted.
3516     aResult->Append(anIndices.FindIndex(aCurEdge));
3517     TopExp::Vertices(aCurEdge, aV[0], aV[1]);
3518
3519     // Get the next vertex.
3520     if (aCurVtx.IsSame(aV[0])) {
3521       if (aCurVtx.IsSame(aV[1])) {
3522         // There is no next vertex.
3523         break;
3524       } else {
3525         aCurVtx = aV[1];
3526       }
3527     } else {
3528       aCurVtx = aV[0];
3529     }
3530
3531     if (aCurVtx.IsNull()) {
3532       // There is no next vertex.
3533       break;
3534     }
3535
3536     // Get the next edge.
3537     const TopTools_ListOfShape         &aLEdges = aMapVE.Find(aCurVtx);
3538     TopTools_ListIteratorOfListOfShape  anEIter(aLEdges);
3539
3540     for (; anEIter.More(); anEIter.Next()) {
3541       const TopoDS_Shape &aLocalEdge = anEIter.Value();
3542
3543       if (aLocalEdge.IsNull() == Standard_False) {
3544         if (!aCurEdge.IsSame(aLocalEdge)) {
3545           aCurEdge = TopoDS::Edge(aLocalEdge);
3546           break;
3547         }
3548       }
3549     }
3550
3551     if (!anEIter.More()) {
3552       // There is no next edge.
3553       break;
3554     }
3555   }
3556
3557   return aResult;
3558 }
3559
3560 //=======================================================================
3561 //function : getShapesOnSurface
3562 /*!
3563    * \brief Find sub-shapes complying with given status about surface
3564     * \param theSurface - the surface to check state of sub-shapes against
3565     * \param theShape - the shape to explore
3566     * \param theShapeType - type of sub-shape of theShape
3567     * \param theState - required state
3568     * \param theShapeEntries - outgoing entries like "entry1, entry2, ..."
3569     * \retval Handle(TColStd_HSequenceOfInteger) - IDs of found sub-shapes
3570  */
3571 //=======================================================================
3572 Handle(TColStd_HSequenceOfTransient)
3573     GEOMImpl_IShapesOperations::getShapesOnSurface(const Handle(Geom_Surface)& theSurface,
3574                                                    const Handle(GEOM_Object)&  theShape,
3575                                                    TopAbs_ShapeEnum            theShapeType,
3576                                                    GEOMAlgo_State              theState,
3577                                                    TCollection_AsciiString &   theShapeEntries)
3578 {
3579   // Find sub-shapes ids
3580   Handle(TColStd_HSequenceOfInteger) aSeqOfIDs =
3581     getShapesOnSurfaceIDs (theSurface, theShape->GetValue(), theShapeType, theState);
3582   if ( aSeqOfIDs.IsNull()  || aSeqOfIDs->Length() == 0 )
3583     return NULL;
3584
3585   return getObjectsShapesOn( theShape, aSeqOfIDs, theShapeEntries );
3586 }
3587
3588 //=============================================================================
3589 /*!
3590  *  GetShapesOnPlane
3591  */
3592 //=============================================================================
3593 Handle(TColStd_HSequenceOfTransient) GEOMImpl_IShapesOperations::GetShapesOnPlane
3594                                         (const Handle(GEOM_Object)& theShape,
3595                                          const Standard_Integer     theShapeType,
3596                                          const Handle(GEOM_Object)& theAx1,
3597                                          const GEOMAlgo_State       theState)
3598 {
3599   SetErrorCode(KO);
3600
3601   if (theShape.IsNull() || theAx1.IsNull()) return NULL;
3602
3603   TopoDS_Shape aShape = theShape->GetValue();
3604   TopoDS_Shape anAx1  = theAx1->GetValue();
3605
3606   if (aShape.IsNull() || anAx1.IsNull()) return NULL;
3607
3608   TopAbs_ShapeEnum aShapeType = TopAbs_ShapeEnum(theShapeType);
3609   if ( !checkTypeShapesOn( theShapeType ))
3610     return NULL;
3611
3612   // Create plane
3613   Handle(Geom_Surface) aPlane = makePlane( anAx1 );
3614   if ( aPlane.IsNull() )
3615     return NULL;
3616
3617   // Find objects
3618   TCollection_AsciiString anAsciiList;
3619   Handle(TColStd_HSequenceOfTransient) aSeq;
3620   aSeq = getShapesOnSurface( aPlane, theShape, aShapeType, theState, anAsciiList );
3621   if ( aSeq.IsNull() || aSeq->Length() == 0 )
3622     return NULL;
3623
3624   // Make a Python command
3625
3626   Handle(GEOM_Object) anObj = Handle(GEOM_Object)::DownCast( aSeq->Value( 1 ));
3627   Handle(GEOM_Function) aFunction = anObj->GetLastFunction();
3628
3629   GEOM::TPythonDump(aFunction) << "[" << anAsciiList.ToCString()
3630     << "] = geompy.GetShapesOnPlane(" << theShape << ", "
3631       << aShapeType << ", " << theAx1 << ", " << theState << ")";
3632
3633   SetErrorCode(OK);
3634   return aSeq;
3635 }
3636
3637 //=============================================================================
3638 /*!
3639  *  GetShapesOnPlaneWithLocation
3640  */
3641 //=============================================================================
3642 Handle(TColStd_HSequenceOfTransient) GEOMImpl_IShapesOperations::GetShapesOnPlaneWithLocation
3643                                         (const Handle(GEOM_Object)& theShape,
3644                                          const Standard_Integer     theShapeType,
3645                                          const Handle(GEOM_Object)& theAx1,
3646                                          const Handle(GEOM_Object)& thePnt,
3647                                          const GEOMAlgo_State       theState)
3648 {
3649   SetErrorCode(KO);
3650
3651   if (theShape.IsNull() || theAx1.IsNull() || thePnt.IsNull()) return NULL;
3652
3653   TopoDS_Shape aShape = theShape->GetValue();
3654   TopoDS_Shape anAx1  = theAx1->GetValue();
3655   TopoDS_Shape anPnt = thePnt->GetValue();
3656
3657   if (aShape.IsNull() || anAx1.IsNull() || anPnt.IsNull()) return NULL;
3658
3659   TopAbs_ShapeEnum aShapeType = TopAbs_ShapeEnum(theShapeType);
3660   if ( !checkTypeShapesOn( theShapeType ))
3661     return NULL;
3662
3663   // Create plane
3664   if ( anAx1.ShapeType() != TopAbs_EDGE || anPnt.ShapeType() != TopAbs_VERTEX ) return NULL;
3665   TopoDS_Vertex V1, V2, V3;
3666   TopoDS_Edge anEdge = TopoDS::Edge(anAx1);
3667   TopExp::Vertices(anEdge, V1, V2, Standard_True);
3668
3669   if (V1.IsNull() || V2.IsNull()) {
3670     SetErrorCode("Bad edge given for the plane normal vector");
3671     return NULL;
3672   }
3673   V3 = TopoDS::Vertex(anPnt);
3674
3675   if(V3.IsNull()) {
3676     SetErrorCode("Bad vertex given for the plane location");
3677       return NULL;
3678   }
3679   gp_Pnt aLoc = BRep_Tool::Pnt(V3);
3680   gp_Vec aVec(BRep_Tool::Pnt(V1),BRep_Tool::Pnt(V2));
3681
3682   if (aVec.Magnitude() < Precision::Confusion()) {
3683     SetErrorCode("Vector with null magnitude given");
3684     return NULL;
3685   }
3686   Handle(Geom_Surface) aPlane = new Geom_Plane(aLoc, aVec);
3687
3688   if ( aPlane.IsNull() )
3689     return NULL;
3690
3691   // Find objects
3692   TCollection_AsciiString anAsciiList;
3693   Handle(TColStd_HSequenceOfTransient) aSeq;
3694   aSeq = getShapesOnSurface( aPlane, theShape, aShapeType, theState, anAsciiList );
3695   if ( aSeq.IsNull() || aSeq->Length() == 0 )
3696     return NULL;
3697
3698   // Make a Python command
3699
3700   Handle(GEOM_Object) anObj = Handle(GEOM_Object)::DownCast( aSeq->Value( 1 ));
3701   Handle(GEOM_Function) aFunction = anObj->GetLastFunction();
3702
3703   GEOM::TPythonDump(aFunction) << "[" << anAsciiList.ToCString()
3704     << "] = geompy.GetShapesOnPlaneWithLocation(" << theShape << ", "
3705     << aShapeType << ", " << theAx1 << ", "<< thePnt <<", " << theState << ")";
3706
3707   SetErrorCode(OK);
3708   return aSeq;
3709 }
3710
3711 //=============================================================================
3712 /*!
3713  *  GetShapesOnCylinder
3714  */
3715 //=============================================================================
3716 Handle(TColStd_HSequenceOfTransient) GEOMImpl_IShapesOperations::GetShapesOnCylinder
3717                                           (const Handle(GEOM_Object)& theShape,
3718                                            const Standard_Integer     theShapeType,
3719                                            const Handle(GEOM_Object)& theAxis,
3720                                            const Standard_Real        theRadius,
3721                                            const GEOMAlgo_State       theState)
3722 {
3723   SetErrorCode(KO);
3724
3725   if (theShape.IsNull() || theAxis.IsNull()) return NULL;
3726
3727   TopoDS_Shape aShape = theShape->GetValue();
3728   TopoDS_Shape anAxis = theAxis->GetValue();
3729
3730   if (aShape.IsNull() || anAxis.IsNull()) return NULL;
3731
3732   TopAbs_ShapeEnum aShapeType = TopAbs_ShapeEnum(theShapeType);
3733   if ( !checkTypeShapesOn( aShapeType ))
3734     return NULL;
3735
3736   // Create a cylinder surface
3737   Handle(Geom_Surface) aCylinder = makeCylinder( anAxis, theRadius );
3738   if ( aCylinder.IsNull() )
3739     return NULL;
3740
3741   // Find objects
3742   TCollection_AsciiString anAsciiList;
3743   Handle(TColStd_HSequenceOfTransient) aSeq;
3744   aSeq = getShapesOnSurface( aCylinder, theShape, aShapeType, theState, anAsciiList );
3745   if ( aSeq.IsNull() || aSeq->Length() == 0 )
3746     return NULL;
3747
3748   // Make a Python command
3749
3750   Handle(GEOM_Object) anObj = Handle(GEOM_Object)::DownCast( aSeq->Value( 1 ));
3751   Handle(GEOM_Function) aFunction = anObj->GetLastFunction();
3752
3753   GEOM::TPythonDump(aFunction) << "[" << anAsciiList.ToCString()
3754     << "] = geompy.GetShapesOnCylinder(" << theShape << ", " << aShapeType
3755       << ", " << theAxis << ", " << theRadius << ", " << theState << ")";
3756
3757   SetErrorCode(OK);
3758   return aSeq;
3759 }
3760
3761 //=============================================================================
3762 /*!
3763  *  GetShapesOnCylinderWithLocation
3764  */
3765 //=============================================================================
3766 Handle(TColStd_HSequenceOfTransient) GEOMImpl_IShapesOperations::GetShapesOnCylinderWithLocation
3767                                           (const Handle(GEOM_Object)& theShape,
3768                                            const Standard_Integer     theShapeType,
3769                                            const Handle(GEOM_Object)& theAxis,
3770                                            const Handle(GEOM_Object)& thePnt,
3771                                            const Standard_Real        theRadius,
3772                                            const GEOMAlgo_State       theState)
3773 {
3774   SetErrorCode(KO);
3775
3776   if (theShape.IsNull() || theAxis.IsNull() || thePnt.IsNull()) return NULL;
3777
3778   TopoDS_Shape aShape = theShape->GetValue();
3779   TopoDS_Shape anAxis = theAxis->GetValue();
3780   TopoDS_Shape aPnt   = thePnt->GetValue();
3781
3782   if (aShape.IsNull() || anAxis.IsNull() || aPnt.IsNull()) return NULL;
3783
3784   if (aPnt.ShapeType() != TopAbs_VERTEX )
3785   {
3786     SetErrorCode("Bottom location point must be vertex");
3787     return NULL;
3788   }
3789
3790   TopAbs_ShapeEnum aShapeType = TopAbs_ShapeEnum(theShapeType);
3791   if ( !checkTypeShapesOn( aShapeType ))
3792     return NULL;
3793
3794   // Create a cylinder surface
3795   Handle(Geom_Surface) aCylinder = makeCylinder( anAxis, theRadius );
3796   if ( aCylinder.IsNull() )
3797     return NULL;
3798
3799   // translate the surface
3800   Handle(Geom_CylindricalSurface) aCylSurface =
3801     Handle(Geom_CylindricalSurface)::DownCast( aCylinder );
3802   if ( aCylSurface.IsNull() )
3803   {
3804     SetErrorCode("Unexpected surface type instead of Geom_CylindricalSurface");
3805     return NULL;
3806   }
3807   gp_Pnt fromLoc = aCylSurface->Cylinder().Location();
3808   gp_Pnt toLoc   = BRep_Tool::Pnt( TopoDS::Vertex( aPnt ));
3809   aCylinder->Translate( fromLoc, toLoc );
3810
3811   // Find objects
3812   TCollection_AsciiString anAsciiList;
3813   Handle(TColStd_HSequenceOfTransient) aSeq;
3814   aSeq = getShapesOnSurface( aCylinder, theShape, aShapeType, theState, anAsciiList );
3815   if ( aSeq.IsNull() || aSeq->Length() == 0 )
3816     return NULL;
3817
3818   // Make a Python command
3819
3820   Handle(GEOM_Object) anObj = Handle(GEOM_Object)::DownCast( aSeq->Value( 1 ));
3821   Handle(GEOM_Function) aFunction = anObj->GetLastFunction();
3822
3823   GEOM::TPythonDump(aFunction)
3824     << "[" << anAsciiList.ToCString()
3825     << "] = geompy.GetShapesOnCylinderWithLocation(" << theShape << ", " << aShapeType << ", "
3826     << theAxis << ", " << thePnt << ", " << theRadius << ", " << theState << ")";
3827
3828   SetErrorCode(OK);
3829   return aSeq;
3830 }
3831
3832 //=============================================================================
3833 /*!
3834  *  GetShapesOnSphere
3835  */
3836 //=============================================================================
3837 Handle(TColStd_HSequenceOfTransient) GEOMImpl_IShapesOperations::GetShapesOnSphere
3838                                           (const Handle(GEOM_Object)& theShape,
3839                                            const Standard_Integer     theShapeType,
3840                                            const Handle(GEOM_Object)& theCenter,
3841                                            const Standard_Real        theRadius,
3842                                            const GEOMAlgo_State       theState)
3843 {
3844   SetErrorCode(KO);
3845
3846   if (theShape.IsNull() || theCenter.IsNull()) return NULL;
3847
3848   TopoDS_Shape aShape  = theShape->GetValue();
3849   TopoDS_Shape aCenter = theCenter->GetValue();
3850
3851   if (aShape.IsNull() || aCenter.IsNull()) return NULL;
3852
3853   TopAbs_ShapeEnum aShapeType = TopAbs_ShapeEnum(theShapeType);
3854   if ( !checkTypeShapesOn( aShapeType ))
3855     return NULL;
3856
3857   // Center of the sphere
3858   if (aCenter.ShapeType() != TopAbs_VERTEX) return NULL;
3859   gp_Pnt aLoc = BRep_Tool::Pnt(TopoDS::Vertex(aCenter));
3860
3861   gp_Ax3 anAx3 (aLoc, gp::DZ());
3862   Handle(Geom_SphericalSurface) aSphere =
3863     new Geom_SphericalSurface(anAx3, theRadius);
3864
3865   // Find objects
3866   TCollection_AsciiString anAsciiList;
3867   Handle(TColStd_HSequenceOfTransient) aSeq;
3868   aSeq = getShapesOnSurface( aSphere, theShape, aShapeType, theState, anAsciiList );
3869   if ( aSeq.IsNull() || aSeq->Length() == 0 )
3870     return NULL;
3871
3872   // Make a Python command
3873
3874   Handle(GEOM_Object) anObj = Handle(GEOM_Object)::DownCast( aSeq->Value( 1 ));
3875   Handle(GEOM_Function) aFunction = anObj->GetLastFunction();
3876
3877   GEOM::TPythonDump(aFunction) << "[" << anAsciiList.ToCString()
3878     << "] = geompy.GetShapesOnSphere(" << theShape << ", " << aShapeType
3879       << ", " << theCenter << ", " << theRadius << ", " << theState << ")";
3880
3881   SetErrorCode(OK);
3882   return aSeq;
3883 }
3884
3885 //=============================================================================
3886 /*!
3887  *  GetShapesOnPlaneIDs
3888  */
3889 //=============================================================================
3890 Handle(TColStd_HSequenceOfInteger) GEOMImpl_IShapesOperations::GetShapesOnPlaneIDs
3891                                         (const Handle(GEOM_Object)& theShape,
3892                                          const Standard_Integer     theShapeType,
3893                                          const Handle(GEOM_Object)& theAx1,
3894                                          const GEOMAlgo_State       theState)
3895 {
3896   SetErrorCode(KO);
3897
3898   if (theShape.IsNull() || theAx1.IsNull()) return NULL;
3899
3900   TopoDS_Shape aShape = theShape->GetValue();
3901   TopoDS_Shape anAx1  = theAx1->GetValue();
3902
3903   if (aShape.IsNull() || anAx1.IsNull()) return NULL;
3904
3905   TopAbs_ShapeEnum aShapeType = TopAbs_ShapeEnum(theShapeType);
3906   if ( !checkTypeShapesOn( aShapeType ))
3907     return NULL;
3908
3909   // Create plane
3910   Handle(Geom_Surface) aPlane = makePlane( anAx1 );
3911   if ( aPlane.IsNull() )
3912     return NULL;
3913
3914   // Find object IDs
3915   Handle(TColStd_HSequenceOfInteger) aSeq;
3916   aSeq = getShapesOnSurfaceIDs( aPlane, aShape, aShapeType, theState );
3917
3918   // The GetShapesOnPlaneIDs() doesn't change object so no new function is required.
3919   Handle(GEOM_Function) aFunction = GEOM::GetCreatedLast(theShape,theAx1)->GetLastFunction();
3920
3921   // VSR 29/08/2017: 0023327, 0023428: eliminate unnecessary lines in Python dump
3922 #ifdef DUMP_SUBSHAPE_IDS
3923   // Make a Python command
3924   GEOM::TPythonDump(aFunction, /*append=*/true)
3925     << "listShapesOnPlane = geompy.GetShapesOnPlaneIDs"
3926     << "(" << theShape << "," << aShapeType << "," << theAx1 << "," << theState << ")";
3927 #endif // DUMP_SUBSHAPE_IDS
3928
3929   SetErrorCode(OK);
3930   return aSeq;
3931 }
3932
3933 //=============================================================================
3934 /*!
3935  *  GetShapesOnPlaneWithLocationIDs
3936  */
3937 //=============================================================================
3938 Handle(TColStd_HSequenceOfInteger) GEOMImpl_IShapesOperations::GetShapesOnPlaneWithLocationIDs
3939                                         (const Handle(GEOM_Object)& theShape,
3940                                          const Standard_Integer     theShapeType,
3941                                          const Handle(GEOM_Object)& theAx1,
3942                                          const Handle(GEOM_Object)& thePnt,
3943                                          const GEOMAlgo_State       theState)
3944 {
3945   SetErrorCode(KO);
3946
3947   if (theShape.IsNull() || theAx1.IsNull() || thePnt.IsNull()) return NULL;
3948
3949   TopoDS_Shape aShape = theShape->GetValue();
3950   TopoDS_Shape anAx1  = theAx1->GetValue();
3951   TopoDS_Shape anPnt  = thePnt->GetValue();
3952
3953   if (aShape.IsNull() || anAx1.IsNull() || anPnt.IsNull()) return NULL;
3954
3955   TopAbs_ShapeEnum aShapeType = TopAbs_ShapeEnum(theShapeType);
3956   if ( !checkTypeShapesOn( aShapeType ))
3957     return NULL;
3958
3959   // Create plane
3960   if (anAx1.ShapeType() != TopAbs_EDGE || anPnt.ShapeType() != TopAbs_VERTEX) return NULL;
3961   TopoDS_Edge anEdge = TopoDS::Edge(anAx1);
3962   TopoDS_Vertex V1, V2, V3;
3963   TopExp::Vertices(anEdge, V1, V2, Standard_True);
3964   if (V1.IsNull() || V2.IsNull()) {
3965     SetErrorCode("Bad edge given for the plane normal vector");
3966     return NULL;
3967   }
3968   V3 = TopoDS::Vertex(anPnt);
3969   if(V3.IsNull()) {
3970     SetErrorCode("Bad vertex given for the plane location");
3971       return NULL;
3972   }
3973   gp_Pnt aLoc = BRep_Tool::Pnt(V3);
3974   gp_Vec aVec(BRep_Tool::Pnt(V1),BRep_Tool::Pnt(V2));
3975   if (aVec.Magnitude() < Precision::Confusion()) {
3976     SetErrorCode("Vector with null magnitude given");
3977     return NULL;
3978   }
3979
3980   Handle(Geom_Surface) aPlane = new Geom_Plane(aLoc, aVec);
3981   if ( aPlane.IsNull() )
3982     return NULL;
3983
3984   // Find object IDs
3985   Handle(TColStd_HSequenceOfInteger) aSeq;
3986   aSeq = getShapesOnSurfaceIDs( aPlane, aShape, aShapeType, theState );
3987
3988   // The GetShapesOnPlaneIDs() doesn't change object so no new function is required.
3989   Handle(GEOM_Function) aFunction = GEOM::GetCreatedLast(theShape,theAx1)->GetLastFunction();
3990
3991   // VSR 29/08/2017: 0023327, 0023428: eliminate unnecessary lines in Python dump
3992 #ifdef DUMP_SUBSHAPE_IDS
3993   // Make a Python command
3994   GEOM::TPythonDump(aFunction, /*append=*/true)
3995     << "listShapesOnPlane = geompy.GetShapesOnPlaneWithLocationIDs"
3996     << "(" << theShape << ", " << aShapeType << ", " << theAx1 << ", "<< thePnt << ", "  << theState << ")";
3997 #endif // DUMP_SUBSHAPE_IDS
3998
3999   SetErrorCode(OK);
4000   return aSeq;
4001 }
4002
4003 //=============================================================================
4004 /*!
4005  *  GetShapesOnCylinderIDs
4006  */
4007 //=============================================================================
4008 Handle(TColStd_HSequenceOfInteger) GEOMImpl_IShapesOperations::GetShapesOnCylinderIDs
4009                                           (const Handle(GEOM_Object)& theShape,
4010                                            const Standard_Integer     theShapeType,
4011                                            const Handle(GEOM_Object)& theAxis,
4012                                            const Standard_Real        theRadius,
4013                                            const GEOMAlgo_State       theState)
4014 {
4015   SetErrorCode(KO);
4016
4017   if (theShape.IsNull() || theAxis.IsNull()) return NULL;
4018
4019   TopoDS_Shape aShape = theShape->GetValue();
4020   TopoDS_Shape anAxis = theAxis->GetValue();
4021
4022   if (aShape.IsNull() || anAxis.IsNull()) return NULL;
4023
4024   TopAbs_ShapeEnum aShapeType = TopAbs_ShapeEnum(theShapeType);
4025   if ( !checkTypeShapesOn( aShapeType ))
4026     return NULL;
4027
4028   // Create a cylinder surface
4029   Handle(Geom_Surface) aCylinder = makeCylinder( anAxis, theRadius );
4030   if ( aCylinder.IsNull() )
4031     return NULL;
4032
4033   // Find object IDs
4034   Handle(TColStd_HSequenceOfInteger) aSeq;
4035   aSeq = getShapesOnSurfaceIDs( aCylinder, aShape, aShapeType, theState );
4036
4037   // The GetShapesOnCylinder() doesn't change object so no new function is required.
4038   Handle(GEOM_Function) aFunction = GEOM::GetCreatedLast(theShape,theAxis)->GetLastFunction();
4039
4040   // VSR 29/08/2017: 0023327, 0023428: eliminate unnecessary lines in Python dump
4041 #ifdef DUMP_SUBSHAPE_IDS
4042   // Make a Python command
4043   GEOM::TPythonDump(aFunction, /*append=*/true)
4044     << "listShapesOnCylinder = geompy.GetShapesOnCylinderIDs"
4045     << "(" << theShape << ", " << aShapeType << ", " << theAxis << ", "
4046     << theRadius << ", " << theState << ")";
4047 #endif // DUMP_SUBSHAPE_IDS
4048
4049   SetErrorCode(OK);
4050   return aSeq;
4051 }
4052
4053 //=============================================================================
4054 /*!
4055  *  GetShapesOnCylinderWithLocationIDs
4056  */
4057 //=============================================================================
4058 Handle(TColStd_HSequenceOfInteger) GEOMImpl_IShapesOperations::GetShapesOnCylinderWithLocationIDs
4059                                           (const Handle(GEOM_Object)& theShape,
4060                                            const Standard_Integer     theShapeType,
4061                                            const Handle(GEOM_Object)& theAxis,
4062                                            const Handle(GEOM_Object)& thePnt,
4063                                            const Standard_Real        theRadius,
4064                                            const GEOMAlgo_State       theState)
4065 {
4066   SetErrorCode(KO);
4067
4068   if (theShape.IsNull() || theAxis.IsNull() || thePnt.IsNull()) return NULL;
4069
4070   TopoDS_Shape aShape = theShape->GetValue();
4071   TopoDS_Shape anAxis = theAxis->GetValue();
4072   TopoDS_Shape aPnt   = thePnt->GetValue();
4073
4074   if (aShape.IsNull() || anAxis.IsNull() || aPnt.IsNull()) return NULL;
4075
4076   if (aPnt.ShapeType() != TopAbs_VERTEX )
4077   {
4078     SetErrorCode("Bottom location point must be vertex");
4079     return NULL;
4080   }
4081
4082   TopAbs_ShapeEnum aShapeType = TopAbs_ShapeEnum(theShapeType);
4083   if ( !checkTypeShapesOn( aShapeType ))
4084     return NULL;
4085
4086   // Create a cylinder surface
4087   Handle(Geom_Surface) aCylinder = makeCylinder( anAxis, theRadius );
4088   if ( aCylinder.IsNull() )
4089     return NULL;
4090
4091   // translate the surface
4092   Handle(Geom_CylindricalSurface) aCylSurface =
4093     Handle(Geom_CylindricalSurface)::DownCast( aCylinder );
4094   if ( aCylSurface.IsNull() )
4095   {
4096     SetErrorCode("Unexpected surface type instead of Geom_CylindricalSurface");
4097     return NULL;
4098   }
4099   gp_Pnt fromLoc = aCylSurface->Cylinder().Location();
4100   gp_Pnt toLoc   = BRep_Tool::Pnt( TopoDS::Vertex( aPnt ));
4101   aCylinder->Translate( fromLoc, toLoc );
4102
4103   // Find object IDs
4104   Handle(TColStd_HSequenceOfInteger) aSeq;
4105   aSeq = getShapesOnSurfaceIDs( aCylinder, aShape, aShapeType, theState );
4106
4107   // The GetShapesOnCylinder() doesn't change object so no new function is required.
4108   Handle(GEOM_Function) aFunction =
4109     GEOM::GetCreatedLast(theShape, GEOM::GetCreatedLast(thePnt,theAxis))->GetLastFunction();
4110
4111   // VSR 29/08/2017: 0023327, 0023428: eliminate unnecessary lines in Python dump
4112 #ifdef DUMP_SUBSHAPE_IDS
4113   // Make a Python command
4114   GEOM::TPythonDump(aFunction, /*append=*/true)
4115     << "listShapesOnCylinder = geompy.GetShapesOnCylinderWithLocationIDs"
4116     << "(" << theShape << ", " << aShapeType << ", " << theAxis << ", "
4117     << thePnt << ", " << theRadius << ", " << theState << ")";
4118 #endif // DUMP_SUBSHAPE_IDS
4119
4120   SetErrorCode(OK);
4121   return aSeq;
4122 }
4123
4124 //=============================================================================
4125 /*!
4126  *  GetShapesOnSphereIDs
4127  */
4128 //=============================================================================
4129 Handle(TColStd_HSequenceOfInteger) GEOMImpl_IShapesOperations::GetShapesOnSphereIDs
4130                                           (const Handle(GEOM_Object)& theShape,
4131                                            const Standard_Integer     theShapeType,
4132                                            const Handle(GEOM_Object)& theCenter,
4133                                            const Standard_Real        theRadius,
4134                                            const GEOMAlgo_State       theState)
4135 {
4136   SetErrorCode(KO);
4137
4138   if (theShape.IsNull() || theCenter.IsNull()) return NULL;
4139
4140   TopoDS_Shape aShape  = theShape->GetValue();
4141   TopoDS_Shape aCenter = theCenter->GetValue();
4142
4143   if (aShape.IsNull() || aCenter.IsNull()) return NULL;
4144
4145   TopAbs_ShapeEnum aShapeType = TopAbs_ShapeEnum(theShapeType);
4146   if ( !checkTypeShapesOn( aShapeType ))
4147     return NULL;
4148
4149   // Center of the sphere
4150   if (aCenter.ShapeType() != TopAbs_VERTEX) return NULL;
4151   gp_Pnt aLoc = BRep_Tool::Pnt(TopoDS::Vertex(aCenter));
4152
4153   gp_Ax3 anAx3 (aLoc, gp::DZ());
4154   Handle(Geom_SphericalSurface) aSphere =
4155     new Geom_SphericalSurface(anAx3, theRadius);
4156
4157   // Find object IDs
4158   Handle(TColStd_HSequenceOfInteger) aSeq;
4159   aSeq = getShapesOnSurfaceIDs( aSphere, aShape, aShapeType, theState );
4160
4161   // The GetShapesOnSphere() doesn't change object so no new function is required.
4162   Handle(GEOM_Function) aFunction = GEOM::GetCreatedLast(theShape,theCenter)->GetLastFunction();
4163
4164   // VSR 29/08/2017: 0023327, 0023428: eliminate unnecessary lines in Python dump
4165 #ifdef DUMP_SUBSHAPE_IDS
4166   // Make a Python command
4167   GEOM::TPythonDump(aFunction, /*append=*/true)
4168     << "listShapesOnSphere = geompy.GetShapesOnSphereIDs"
4169     << "(" << theShape << ", " << aShapeType << ", " << theCenter << ", "
4170     << theRadius << ", " << theState << ")";
4171 #endif // DUMP_SUBSHAPE_IDS
4172
4173   SetErrorCode(OK);
4174   return aSeq;
4175 }
4176
4177 //=======================================================================
4178 //function : getShapesOnQuadrangleIDs
4179   /*!
4180    * \brief Find IDs of sub-shapes complying with given status about quadrangle
4181     * \param theShape - the shape to explore
4182     * \param theShapeType - type of sub-shape of theShape
4183     * \param theTopLeftPoint - top left quadrangle corner
4184     * \param theTopRightPoint - top right quadrangle corner
4185     * \param theBottomLeftPoint - bottom left quadrangle corner
4186     * \param theBottomRightPoint - bottom right quadrangle corner
4187     * \param theState - required state
4188     * \retval Handle(TColStd_HSequenceOfInteger) - IDs of found sub-shapes
4189    */
4190 //=======================================================================
4191 Handle(TColStd_HSequenceOfInteger)
4192   GEOMImpl_IShapesOperations::getShapesOnQuadrangleIDs (const Handle(GEOM_Object)& theShape,
4193                                                         const Standard_Integer     theShapeType,
4194                                                         const Handle(GEOM_Object)& theTopLeftPoint,
4195                                                         const Handle(GEOM_Object)& theTopRightPoint,
4196                                                         const Handle(GEOM_Object)& theBottomLeftPoint,
4197                                                         const Handle(GEOM_Object)& theBottomRightPoint,
4198                                                         const GEOMAlgo_State       theState)
4199 {
4200   SetErrorCode(KO);
4201
4202   if ( theShape.IsNull() ||
4203        theTopLeftPoint.IsNull() ||
4204        theTopRightPoint.IsNull() ||
4205        theBottomLeftPoint.IsNull() ||
4206        theBottomRightPoint.IsNull() )
4207     return NULL;
4208
4209   TopoDS_Shape aShape = theShape->GetValue();
4210   TopoDS_Shape aTL = theTopLeftPoint->GetValue();
4211   TopoDS_Shape aTR = theTopRightPoint->GetValue();
4212   TopoDS_Shape aBL = theBottomLeftPoint->GetValue();
4213   TopoDS_Shape aBR = theBottomRightPoint->GetValue();
4214
4215   if (aShape.IsNull() ||
4216       aTL.IsNull() ||
4217       aTR.IsNull() ||
4218       aBL.IsNull() ||
4219       aBR.IsNull() ||
4220       aTL.ShapeType() != TopAbs_VERTEX ||
4221       aTR.ShapeType() != TopAbs_VERTEX ||
4222       aBL.ShapeType() != TopAbs_VERTEX ||
4223       aBR.ShapeType() != TopAbs_VERTEX )
4224     return NULL;
4225
4226   TopAbs_ShapeEnum aShapeType = TopAbs_ShapeEnum(theShapeType);
4227   if ( !checkTypeShapesOn( aShapeType ))
4228     return NULL;
4229
4230   Handle(TColStd_HSequenceOfInteger) aSeqOfIDs;
4231
4232   // Check presence of triangulation, build if need
4233   if (theShapeType != TopAbs_VERTEX && !GEOMUtils::CheckTriangulation(aShape)) {
4234     SetErrorCode("Cannot build triangulation on the shape");
4235     return aSeqOfIDs;
4236   }
4237
4238   // Call algo
4239   gp_Pnt aPntTL = BRep_Tool::Pnt(TopoDS::Vertex(aTL));
4240   gp_Pnt aPntTR = BRep_Tool::Pnt(TopoDS::Vertex(aTR));
4241   gp_Pnt aPntBL = BRep_Tool::Pnt(TopoDS::Vertex(aBL));
4242   gp_Pnt aPntBR = BRep_Tool::Pnt(TopoDS::Vertex(aBR));
4243
4244   GEOMAlgo_FinderShapeOn2  aFinder;
4245   Handle(GEOMAlgo_ClsfQuad) aClsfQuad = new GEOMAlgo_ClsfQuad;
4246
4247   Standard_Real aTol = 0.0001; // default value
4248
4249   aClsfQuad->SetCorners(aPntTL, aPntTR, aPntBL, aPntBR);
4250   aFinder.SetShape(aShape);
4251   aFinder.SetTolerance(aTol);
4252   aFinder.SetClsf(aClsfQuad);
4253   aFinder.SetShapeType(aShapeType);
4254   aFinder.SetState(theState);
4255
4256   // Sets the minimal number of inner points for the faces that do not have own
4257   // inner points at all (for e.g. rectangular planar faces have just 2 triangles).
4258   // Default value=3
4259   aFinder.SetNbPntsMin(3);
4260   // Sets the maximal number of inner points for edges or faces.
4261   // It is useful for the cases when this number is very big (e.g =2000) to improve
4262   // the performance. If this value =0, all inner points will be taken into account.
4263   // Default value=0
4264   aFinder.SetNbPntsMax(100);
4265
4266   aFinder.Perform();
4267
4268   // Interpret results
4269   Standard_Integer iErr = aFinder.ErrorStatus();
4270   // the detailed description of error codes is in GEOMAlgo_FinderShapeOn2.cxx
4271   if (iErr) {
4272     MESSAGE(" iErr : " << iErr);
4273     TCollection_AsciiString aMsg (" iErr : ");
4274     aMsg += TCollection_AsciiString(iErr);
4275     SetErrorCode(aMsg);
4276     return aSeqOfIDs;
4277   }
4278   Standard_Integer iWrn = aFinder.WarningStatus();
4279   // the detailed description of warning codes is in GEOMAlgo_FinderShapeOn2.cxx
4280   if (iWrn) {
4281     MESSAGE(" *** iWrn : " << iWrn);
4282   }
4283
4284   const TopTools_ListOfShape& listSS = aFinder.Shapes(); // the result
4285
4286   if (listSS.Extent() < 1) {
4287     //SetErrorCode("Not a single sub-shape of the requested type found on the given surface");
4288     SetErrorCode(NOT_FOUND_ANY); // NPAL18017
4289     return aSeqOfIDs;
4290   }
4291
4292   // Fill sequence of object IDs
4293   aSeqOfIDs = new TColStd_HSequenceOfInteger;
4294
4295   TopTools_IndexedMapOfShape anIndices;
4296   TopExp::MapShapes(aShape, anIndices);
4297
4298   TopTools_ListIteratorOfListOfShape itSub (listSS);
4299   for (int index = 1; itSub.More(); itSub.Next(), ++index) {
4300     int id = anIndices.FindIndex(itSub.Value());
4301     aSeqOfIDs->Append(id);
4302   }
4303   return aSeqOfIDs;
4304 }
4305
4306 //=======================================================================
4307 //function : GetShapesOnQuadrangle
4308   /*!
4309    * \brief Find sub-shapes complying with given status about quadrangle
4310     * \param theShape - the shape to explore
4311     * \param theShapeType - type of sub-shape of theShape
4312     * \param theTopLeftPoint - top left quadrangle corner
4313     * \param theTopRightPoint - top right quadrangle corner
4314     * \param theBottomLeftPoint - bottom left quadrangle corner
4315     * \param theBottomRightPoint - bottom right quadrangle corner
4316     * \param theState - required state
4317     * \retval Handle(TColStd_HSequenceOfInteger) - IDs of found sub-shapes
4318    */
4319 //=======================================================================
4320 Handle(TColStd_HSequenceOfTransient)
4321     GEOMImpl_IShapesOperations::GetShapesOnQuadrangle (const Handle(GEOM_Object)& theShape,
4322                                                        const Standard_Integer     theShapeType,
4323                                                        const Handle(GEOM_Object)& theTopLeftPoint,
4324                                                        const Handle(GEOM_Object)& theTopRightPoint,
4325                                                        const Handle(GEOM_Object)& theBottomLeftPoint,
4326                                                        const Handle(GEOM_Object)& theBottomRightPoint,
4327                                                        const GEOMAlgo_State       theState)
4328 {
4329   // Find indices
4330   Handle(TColStd_HSequenceOfInteger) aSeqOfIDs =
4331     getShapesOnQuadrangleIDs( theShape,
4332                               theShapeType,
4333                               theTopLeftPoint,
4334                               theTopRightPoint,
4335                               theBottomLeftPoint,
4336                               theBottomRightPoint,
4337                               theState);
4338   if ( aSeqOfIDs.IsNull() || aSeqOfIDs->IsEmpty() )
4339     return NULL;
4340
4341   // Find objects by indices
4342   TCollection_AsciiString anAsciiList;
4343   Handle(TColStd_HSequenceOfTransient) aSeq;
4344   aSeq = getObjectsShapesOn( theShape, aSeqOfIDs, anAsciiList );
4345   if ( aSeq.IsNull() || aSeq->IsEmpty() )
4346     return NULL;
4347
4348   // Make a Python command
4349
4350   Handle(GEOM_Object) anObj = Handle(GEOM_Object)::DownCast( aSeq->Value( 1 ));
4351   Handle(GEOM_Function) aFunction = anObj->GetLastFunction();
4352
4353   GEOM::TPythonDump(aFunction)
4354     << "[" << anAsciiList.ToCString() << "] = geompy.GetShapesOnQuadrangle("
4355     << theShape << ", "
4356     << TopAbs_ShapeEnum(theShapeType) << ", "
4357     << theTopLeftPoint << ", "
4358     << theTopRightPoint << ", "
4359     << theBottomLeftPoint << ", "
4360     << theBottomRightPoint << ", "
4361     << theState << ")";
4362
4363   SetErrorCode(OK);
4364   return aSeq;
4365 }
4366
4367 //=======================================================================
4368 //function : GetShapesOnQuadrangleIDs
4369   /*!
4370    * \brief Find IDs of sub-shapes complying with given status about quadrangle
4371     * \param theShape - the shape to explore
4372     * \param theShapeType - type of sub-shape of theShape
4373     * \param theTopLeftPoint - top left quadrangle corner
4374     * \param theTopRightPoint - top right quadrangle corner
4375     * \param theBottomLeftPoint - bottom left quadrangle corner
4376     * \param theBottomRightPoint - bottom right quadrangle corner
4377     * \param theState - required state
4378     * \retval Handle(TColStd_HSequenceOfInteger) - IDs of found sub-shapes
4379    */
4380 //=======================================================================
4381 Handle(TColStd_HSequenceOfInteger)
4382   GEOMImpl_IShapesOperations::GetShapesOnQuadrangleIDs (const Handle(GEOM_Object)& theShape,
4383                                                         const Standard_Integer     theShapeType,
4384                                                         const Handle(GEOM_Object)& theTopLeftPoint,
4385                                                         const Handle(GEOM_Object)& theTopRightPoint,
4386                                                         const Handle(GEOM_Object)& theBottomLeftPoint,
4387                                                         const Handle(GEOM_Object)& theBottomRightPoint,
4388                                                         const GEOMAlgo_State       theState)
4389 {
4390   // Find indices
4391   Handle(TColStd_HSequenceOfInteger) aSeqOfIDs =
4392     getShapesOnQuadrangleIDs( theShape,
4393                               theShapeType,
4394                               theTopLeftPoint,
4395                               theTopRightPoint,
4396                               theBottomLeftPoint,
4397                               theBottomRightPoint,
4398                               theState);
4399   if ( aSeqOfIDs.IsNull() || aSeqOfIDs->IsEmpty() )
4400     return NULL;
4401
4402   // Make a Python command
4403
4404   // The GetShapesOnCylinder() doesn't change object so no new function is required.
4405   Handle(GEOM_BaseObject) lastObj = GEOM::GetCreatedLast(theShape,theTopLeftPoint);
4406   lastObj = GEOM::GetCreatedLast(lastObj,theTopRightPoint);
4407   lastObj = GEOM::GetCreatedLast(lastObj,theBottomRightPoint);
4408   lastObj = GEOM::GetCreatedLast(lastObj,theBottomLeftPoint);
4409   Handle(GEOM_Function) aFunction = lastObj->GetLastFunction();
4410
4411   // VSR 29/08/2017: 0023327, 0023428: eliminate unnecessary lines in Python dump
4412 #ifdef DUMP_SUBSHAPE_IDS
4413   GEOM::TPythonDump(aFunction, /*append=*/true)
4414     << "listShapesOnQuadrangle = geompy.GetShapesOnQuadrangleIDs("
4415     << theShape << ", "
4416     << TopAbs_ShapeEnum(theShapeType) << ", "
4417     << theTopLeftPoint << ", "
4418     << theTopRightPoint << ", "
4419     << theBottomLeftPoint << ", "
4420     << theBottomRightPoint << ", "
4421     << theState << ")";
4422 #endif // DUMP_SUBSHAPE_IDS
4423
4424   SetErrorCode(OK);
4425   return aSeqOfIDs;
4426 }
4427
4428 //=============================================================================
4429 /*!
4430  *  case GetInPlace:
4431  *  default:
4432  */
4433 //=============================================================================
4434 Handle(GEOM_Object) GEOMImpl_IShapesOperations::GetInPlace (Handle(GEOM_Object) theShapeWhere,
4435                                                             Handle(GEOM_Object) theShapeWhat)
4436 {
4437   SetErrorCode(KO);
4438
4439   if (theShapeWhere.IsNull() || theShapeWhat.IsNull()) return NULL;
4440
4441   TopoDS_Shape aWhere = theShapeWhere->GetValue();
4442   TopoDS_Shape aWhat  = theShapeWhat->GetValue();
4443
4444   if (aWhere.IsNull() || aWhat.IsNull()) {
4445     SetErrorCode("Error: aWhere and aWhat TopoDS_Shape are Null.");
4446     return NULL;
4447   }
4448
4449   // Searching for the sub-shapes inside the ShapeWhere shape
4450   GEOMAlgo_GetInPlace aGIP;
4451
4452   if (!GEOMAlgo_GetInPlaceAPI::GetInPlace(aWhere, aWhat, aGIP)) {
4453     SetErrorCode("Error in GEOMAlgo_GetInPlace");
4454     return NULL;
4455   }
4456
4457   // Add direct result.
4458   TopTools_ListOfShape        aLSA;
4459   const TopoDS_Shape         &aShapeResult = aGIP.Result();
4460   TopTools_MapOfShape         aMFence;
4461   TopTools_IndexedMapOfShape  aWhereIndices;
4462   Standard_Integer            aShapeType = -1;
4463
4464   TopExp::MapShapes(aWhere, aWhereIndices);
4465
4466   if (aShapeResult.IsNull() == Standard_False) {
4467     TopoDS_Iterator  anIt(aShapeResult);
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 : GetInPlaceMap
4722 //purpose  :
4723 //=======================================================================
4724 void GEOMImpl_IShapesOperations::GetInPlaceMap (Handle(GEOM_Object) theShapeWhere,
4725                                                 Handle(GEOM_Object) theShapeWhat,
4726                                                 std::vector< std::vector< int > > & theResVec)
4727 {
4728   SetErrorCode(KO);
4729
4730   if (theShapeWhere.IsNull() || theShapeWhat.IsNull()) return;
4731
4732   TopoDS_Shape aWhere = theShapeWhere->GetValue();
4733   TopoDS_Shape aWhat  = theShapeWhat->GetValue();
4734
4735   if (aWhere.IsNull() || aWhat.IsNull()) return;
4736
4737   Handle(GEOM_Function) aWhereFunction = theShapeWhere->GetLastFunction();
4738   if (aWhereFunction.IsNull()) return;
4739
4740   bool isFound = GEOMAlgo_GetInPlaceAPI::GetInPlaceMap( aWhereFunction, aWhat, theResVec );
4741
4742   if ( isFound )
4743     SetErrorCode(OK);
4744
4745   Handle(GEOM_Function) aFunction =
4746     GEOM::GetCreatedLast(theShapeWhere,theShapeWhat)->GetLastFunction();
4747
4748   GEOM::TPythonDump(aFunction, /*append=*/true)
4749     << "resultList = geompy.GetInPlaceMap( "
4750     << theShapeWhere << ", "
4751     << theShapeWhat << ")";
4752
4753   return;
4754 }
4755
4756 //=======================================================================
4757 //function : isSameEdge
4758 //purpose  : Returns True if two edges coincide
4759 //=======================================================================
4760 static bool isSameEdge(const TopoDS_Edge& theEdge1, const TopoDS_Edge& theEdge2)
4761 {
4762   TopoDS_Vertex V11, V12, V21, V22;
4763   TopExp::Vertices(theEdge1, V11, V12);
4764   TopExp::Vertices(theEdge2, V21, V22);
4765   gp_Pnt P11 = BRep_Tool::Pnt(V11);
4766   gp_Pnt P12 = BRep_Tool::Pnt(V12);
4767   gp_Pnt P21 = BRep_Tool::Pnt(V21);
4768   gp_Pnt P22 = BRep_Tool::Pnt(V22);
4769   bool coincide = false;
4770
4771   //Check that ends of edges coincide
4772   if(P11.Distance(P21) <= MAX_TOLERANCE) {
4773     if(P12.Distance(P22) <= MAX_TOLERANCE) coincide =  true;
4774   }
4775   else if(P11.Distance(P22) <= MAX_TOLERANCE) {
4776     if(P12.Distance(P21) <= MAX_TOLERANCE) coincide = true;
4777   }
4778
4779   if(!coincide) return false;
4780
4781   if (BRep_Tool::Degenerated(theEdge1))
4782     if (BRep_Tool::Degenerated(theEdge2)) return true;
4783     else return false;
4784   else
4785     if (BRep_Tool::Degenerated(theEdge2)) return false;
4786
4787   double U11, U12, U21, U22;
4788   Handle(Geom_Curve) C1 = BRep_Tool::Curve(theEdge1, U11, U12);
4789   Handle(Geom_Curve) C2 = BRep_Tool::Curve(theEdge2, U21, U22);
4790
4791   //Check that both edges has the same geometry
4792   double range = U12-U11;
4793   double U = U11+ range/3.0;
4794   gp_Pnt P1 = C1->Value(U);     //Compute a point on one third of the edge's length
4795   U = U11+range*2.0/3.0;
4796   gp_Pnt P2 = C1->Value(U);     //Compute a point on two thirds of the edge's length
4797
4798   C2 = new Geom_TrimmedCurve(C2, U21, U22);
4799   // vsr 04/10/2018: 0023312 - As curve may be periodic, its parameters may be normalized
4800   // so, we re-take them from trimmed curve
4801   U21 = C2->FirstParameter();
4802   U22 = C2->LastParameter();
4803
4804   if(!GeomLib_Tool::Parameter(C2, P1, MAX_TOLERANCE, U) ||  U < U21 || U > U22)
4805     return false;
4806
4807   if(P1.Distance(C2->Value(U)) > MAX_TOLERANCE) return false;
4808
4809   if(!GeomLib_Tool::Parameter(C2, P2, MAX_TOLERANCE, U) || U < U21 || U > U22)
4810     return false;
4811
4812   if(P2.Distance(C2->Value(U)) > MAX_TOLERANCE) return false;
4813
4814   return true;
4815 }
4816
4817 //=======================================================================
4818 //function : isSameFace
4819 //purpose  : Returns True if two faces coincide
4820 //=======================================================================
4821 static bool isSameFace(const TopoDS_Face& theFace1, const TopoDS_Face& theFace2)
4822 {
4823   TopExp_Explorer E(theFace1, TopAbs_EDGE);
4824   TopTools_ListOfShape LS1, LS2;
4825   for(; E.More(); E.Next()) LS1.Append(E.Current());
4826
4827   E.Init(theFace2, TopAbs_EDGE);
4828   for(; E.More(); E.Next()) LS2.Append(E.Current());
4829
4830   //Compare the number of edges in the faces
4831   if(LS1.Extent() != LS2.Extent()) return false;
4832
4833   double aMin = RealFirst(), aMax = RealLast();
4834   double xminB1=aMax, yminB1=aMax, zminB1=aMax, xminB2=aMax, yminB2=aMax, zminB2=aMax;
4835   double xmaxB1=aMin, ymaxB1=aMin, zmaxB1=aMin, xmaxB2=aMin, ymaxB2=aMin, zmaxB2=aMin;
4836
4837   for(E.Init(theFace1, TopAbs_VERTEX); E.More(); E.Next()) {
4838     gp_Pnt P = BRep_Tool::Pnt(TopoDS::Vertex(E.Current()));
4839     if(P.X() < xminB1) xminB1 = P.X();
4840     if(P.Y() < yminB1) yminB1 = P.Y();
4841     if(P.Z() < zminB1) zminB1 = P.Z();
4842     if(P.X() > xmaxB1) xmaxB1 = P.X();
4843     if(P.Y() > ymaxB1) ymaxB1 = P.Y();
4844     if(P.Z() > zmaxB1) zmaxB1 = P.Z();
4845   }
4846
4847   for(E.Init(theFace2, TopAbs_VERTEX); E.More(); E.Next()) {
4848     gp_Pnt P = BRep_Tool::Pnt(TopoDS::Vertex(E.Current()));
4849     if(P.X() < xminB2) xminB2 = P.X();
4850     if(P.Y() < yminB2) yminB2 = P.Y();
4851     if(P.Z() < zminB2) zminB2 = P.Z();
4852     if(P.X() > xmaxB2) xmaxB2 = P.X();
4853     if(P.Y() > ymaxB2) ymaxB2 = P.Y();
4854     if(P.Z() > zmaxB2) zmaxB2 = P.Z();
4855   }
4856
4857   //Compare the bounding boxes of both faces
4858   if(gp_Pnt(xminB1, yminB1, zminB1).Distance(gp_Pnt(xminB2, yminB2, zminB2)) > MAX_TOLERANCE)
4859     return false;
4860
4861   if(gp_Pnt(xmaxB1, ymaxB1, zmaxB1).Distance(gp_Pnt(xmaxB2, ymaxB2, zmaxB2)) > MAX_TOLERANCE)
4862     return false;
4863
4864   Handle(Geom_Surface) S1 = BRep_Tool::Surface(theFace1);
4865   Handle(Geom_Surface) S2 = BRep_Tool::Surface(theFace2);
4866
4867   //Check if there a coincidence of two surfaces at least in two points
4868   double U11, U12, V11, V12, U21, U22, V21, V22;
4869   BRepTools::UVBounds(theFace1, U11, U12, V11, V12);
4870   BRepTools::UVBounds(theFace2, U21, U22, V21, V22);
4871
4872   double rangeU = U12-U11;
4873   double rangeV = V12-V11;
4874   double U = U11 + rangeU/3.0;
4875   double V = V11 + rangeV/3.0;
4876   gp_Pnt P1 = S1->Value(U, V);
4877   U = U11+rangeU*2.0/3.0;
4878   V = V11+rangeV*2.0/3.0;
4879   gp_Pnt P2 = S1->Value(U, V);
4880
4881   if (!GeomLib_Tool::Parameters(S2, P1, MAX_TOLERANCE, U, V) || U < U21 || U > U22 || V < V21 || V > V22)
4882     return false;
4883
4884   if (P1.Distance(S2->Value(U,V)) > MAX_TOLERANCE) return false;
4885
4886   if (!GeomLib_Tool::Parameters(S2, P2, MAX_TOLERANCE, U, V) || U < U21 || U > U22 || V < V21 || V > V22)
4887     return false;
4888
4889   if (P2.Distance(S2->Value(U, V)) > MAX_TOLERANCE) return false;
4890
4891   //Check that each edge of the Face1 has a counterpart in the Face2
4892   TopTools_MapOfOrientedShape aMap;
4893   TopTools_ListIteratorOfListOfShape LSI1(LS1);
4894   for(; LSI1.More(); LSI1.Next()) {
4895     TopoDS_Edge E = TopoDS::Edge(LSI1.Value());
4896     bool isFound = false;
4897     TopTools_ListIteratorOfListOfShape LSI2(LS2);
4898     for(; LSI2.More(); LSI2.Next()) {
4899       TopoDS_Shape aValue = LSI2.Value();
4900       if(aMap.Contains(aValue)) continue; //To avoid checking already found edge several times
4901       if(isSameEdge(E, TopoDS::Edge(aValue))) {
4902         aMap.Add(aValue);
4903         isFound = true;
4904         break;
4905       }
4906     }
4907     if(!isFound) return false;
4908   }
4909
4910   return true;
4911 }
4912
4913 //=======================================================================
4914 //function : isSameSolid
4915 //purpose  : Returns True if two solids coincide
4916 //=======================================================================
4917 bool isSameSolid(const TopoDS_Solid& theSolid1, const TopoDS_Solid& theSolid2)
4918 {
4919   TopExp_Explorer E(theSolid1, TopAbs_FACE);
4920   TopTools_ListOfShape LS1, LS2;
4921   for(; E.More(); E.Next()) LS1.Append(E.Current());
4922   E.Init(theSolid2, TopAbs_FACE);
4923   for(; E.More(); E.Next()) LS2.Append(E.Current());
4924
4925   if(LS1.Extent() != LS2.Extent()) return false;
4926
4927   double aMin = RealFirst(), aMax = RealLast();
4928   double xminB1=aMax, yminB1=aMax, zminB1=aMax, xminB2=aMax, yminB2=aMax, zminB2=aMax;
4929   double xmaxB1=aMin, ymaxB1=aMin, zmaxB1=aMin, xmaxB2=aMin, ymaxB2=aMin, zmaxB2=aMin;
4930
4931   for(E.Init(theSolid1, TopAbs_VERTEX); E.More(); E.Next()) {
4932     gp_Pnt P = BRep_Tool::Pnt(TopoDS::Vertex(E.Current()));
4933     if(P.X() < xminB1) xminB1 = P.X();
4934     if(P.Y() < yminB1) yminB1 = P.Y();
4935     if(P.Z() < zminB1) zminB1 = P.Z();
4936     if(P.X() > xmaxB1) xmaxB1 = P.X();
4937     if(P.Y() > ymaxB1) ymaxB1 = P.Y();
4938     if(P.Z() > zmaxB1) zmaxB1 = P.Z();
4939   }
4940
4941   for(E.Init(theSolid2, TopAbs_VERTEX); E.More(); E.Next()) {
4942     gp_Pnt P = BRep_Tool::Pnt(TopoDS::Vertex(E.Current()));
4943     if(P.X() < xminB2) xminB2 = P.X();
4944     if(P.Y() < yminB2) yminB2 = P.Y();
4945     if(P.Z() < zminB2) zminB2 = P.Z();
4946     if(P.X() > xmaxB2) xmaxB2 = P.X();
4947     if(P.Y() > ymaxB2) ymaxB2 = P.Y();
4948     if(P.Z() > zmaxB2) zmaxB2 = P.Z();
4949   }
4950
4951   //Compare the bounding boxes of both solids
4952   if(gp_Pnt(xminB1, yminB1, zminB1).Distance(gp_Pnt(xminB2, yminB2, zminB2)) > MAX_TOLERANCE)
4953     return false;
4954
4955   if(gp_Pnt(xmaxB1, ymaxB1, zmaxB1).Distance(gp_Pnt(xmaxB2, ymaxB2, zmaxB2)) > MAX_TOLERANCE)
4956     return false;
4957
4958   //Check that each face of the Solid1 has a counterpart in the Solid2
4959   TopTools_MapOfOrientedShape aMap;
4960   TopTools_ListIteratorOfListOfShape LSI1(LS1);
4961   for(; LSI1.More(); LSI1.Next()) {
4962     TopoDS_Face F = TopoDS::Face(LSI1.Value());
4963     bool isFound = false;
4964     TopTools_ListIteratorOfListOfShape LSI2(LS2);
4965     for(; LSI2.More(); LSI2.Next()) {
4966       if(aMap.Contains(LSI2.Value())) continue; //To avoid checking already found faces several times
4967       if(isSameFace(F, TopoDS::Face(LSI2.Value()))) {
4968         aMap.Add(LSI2.Value());
4969         isFound = true;
4970         break;
4971       }
4972     }
4973     if(!isFound) return false;
4974   }
4975
4976   return true;
4977 }
4978
4979 //=======================================================================
4980 //function : GetSame
4981 //purpose  :
4982 //=======================================================================
4983 Handle(GEOM_Object) GEOMImpl_IShapesOperations::GetSame(const Handle(GEOM_Object)& theShapeWhere,
4984                                                         const Handle(GEOM_Object)& theShapeWhat)
4985 {
4986   SetErrorCode(KO);
4987   if (theShapeWhere.IsNull() || theShapeWhat.IsNull()) return NULL;
4988
4989   TopoDS_Shape aWhere = theShapeWhere->GetValue();
4990   TopoDS_Shape aWhat  = theShapeWhat->GetValue();
4991
4992   if (aWhere.IsNull() || aWhat.IsNull()) return NULL;
4993
4994   int anIndex = -1;
4995   bool isFound = false;
4996   TopoDS_Shape aSubShape;
4997   TopTools_MapOfShape aMap;
4998
4999   if (aWhat.ShapeType() == TopAbs_COMPOUND || aWhat.ShapeType() == TopAbs_COMPSOLID) {
5000     TopoDS_Iterator It (aWhat, Standard_True, Standard_True);
5001     if (It.More()) aWhat = It.Value();
5002     It.Next();
5003     if (It.More()) {
5004       SetErrorCode("Compounds of two or more shapes are not allowed for aWhat argument");
5005       return NULL;
5006     }
5007   }
5008
5009   switch (aWhat.ShapeType()) {
5010     case TopAbs_VERTEX: {
5011       aSubShape = getSameVertex(aWhere, TopoDS::Vertex(aWhat));
5012       isFound   = !aSubShape.IsNull();
5013       break;
5014                         }
5015     case TopAbs_EDGE: {
5016       TopoDS_Edge anEdge = TopoDS::Edge(aWhat);
5017       TopExp_Explorer E(aWhere, TopAbs_EDGE);
5018       for(; E.More(); E.Next()) {
5019         if(!aMap.Add(E.Current())) continue;
5020         if(isSameEdge(anEdge, TopoDS::Edge(E.Current()))) {
5021           aSubShape = E.Current();
5022           isFound = true;
5023           break;
5024         }
5025       }
5026       break;
5027                       }
5028     case TopAbs_FACE: {
5029       TopoDS_Face aFace = TopoDS::Face(aWhat);
5030       TopExp_Explorer E(aWhere, TopAbs_FACE);
5031       for(; E.More(); E.Next()) {
5032         if(!aMap.Add(E.Current())) continue;
5033         if(isSameFace(aFace, TopoDS::Face(E.Current()))) {
5034           aSubShape = E.Current();
5035           isFound = true;
5036           break;
5037         }
5038       }
5039       break;
5040                       }
5041     case TopAbs_SOLID: {
5042       TopoDS_Solid aSolid = TopoDS::Solid(aWhat);
5043       TopExp_Explorer E(aWhere, TopAbs_SOLID);
5044       for(; E.More(); E.Next()) {
5045         if(!aMap.Add(E.Current())) continue;
5046         if(isSameSolid(aSolid, TopoDS::Solid(E.Current()))) {
5047           aSubShape = E.Current();
5048           isFound = true;
5049           break;
5050         }
5051       }
5052       break;
5053                        }
5054     default:
5055       return NULL;
5056   }
5057
5058   if (isFound) {
5059     TopTools_IndexedMapOfShape anIndices;
5060     TopExp::MapShapes(aWhere, anIndices);
5061     if (anIndices.Contains(aSubShape))
5062       anIndex = anIndices.FindIndex(aSubShape);
5063   }
5064
5065   if (anIndex < 0) return NULL;
5066
5067   Handle(TColStd_HArray1OfInteger) anArray = new TColStd_HArray1OfInteger(1,1);
5068
5069   anArray->SetValue(1, anIndex);
5070
5071   Handle(GEOM_Object) aResult = GetEngine()->AddSubShape(theShapeWhere, anArray);
5072   Handle(GEOM_Function) aFunction = aResult->GetLastFunction();
5073
5074   GEOM::TPythonDump(aFunction) << aResult << " = geompy.GetSame("
5075     << theShapeWhere << ", " << theShapeWhat << ")";
5076
5077   SetErrorCode(OK);
5078
5079   return aResult;
5080 }
5081
5082
5083 //=======================================================================
5084 //function : GetSameIDs
5085 //purpose  :
5086 //=======================================================================
5087 Handle(TColStd_HSequenceOfInteger) GEOMImpl_IShapesOperations::GetSameIDs
5088                                                        (const Handle(GEOM_Object)& theShapeWhere,
5089                                                         const Handle(GEOM_Object)& theShapeWhat)
5090 {
5091   SetErrorCode(KO);
5092   if (theShapeWhere.IsNull() || theShapeWhat.IsNull()) return NULL;
5093
5094   TopoDS_Shape aWhere = theShapeWhere->GetValue();
5095   TopoDS_Shape aWhat  = theShapeWhat->GetValue();
5096
5097   if (aWhere.IsNull() || aWhat.IsNull()) return NULL;
5098
5099   TopTools_ListOfShape listShape;
5100   TopTools_MapOfShape aMap;
5101
5102   if (aWhat.ShapeType() == TopAbs_COMPOUND || aWhat.ShapeType() == TopAbs_COMPSOLID) {
5103     TopoDS_Iterator It (aWhat, Standard_True, Standard_True);
5104     if (It.More()) aWhat = It.Value();
5105     It.Next();
5106     if (It.More()) {
5107       SetErrorCode("Compounds of two or more shapes are not allowed for aWhat argument");
5108       return NULL;
5109     }
5110   }
5111
5112   switch (aWhat.ShapeType()) {
5113     case TopAbs_VERTEX: {
5114       gp_Pnt P = BRep_Tool::Pnt(TopoDS::Vertex(aWhat));
5115       TopExp_Explorer E(aWhere, TopAbs_VERTEX);
5116       for(; E.More(); E.Next()) {
5117         if(!aMap.Add(E.Current())) continue;
5118         gp_Pnt P2 = BRep_Tool::Pnt(TopoDS::Vertex(E.Current()));
5119         if(P.Distance(P2) <= MAX_TOLERANCE) {
5120           listShape.Append(E.Current());
5121         }
5122       }
5123       break;
5124                         }
5125     case TopAbs_EDGE: {
5126       TopoDS_Edge anEdge = TopoDS::Edge(aWhat);
5127       TopExp_Explorer E(aWhere, TopAbs_EDGE);
5128       for(; E.More(); E.Next()) {
5129         if(!aMap.Add(E.Current())) continue;
5130         if(isSameEdge(anEdge, TopoDS::Edge(E.Current()))) {
5131           listShape.Append(E.Current());
5132         }
5133       }
5134       break;
5135                       }
5136     case TopAbs_FACE: {
5137       TopoDS_Face aFace = TopoDS::Face(aWhat);
5138       TopExp_Explorer E(aWhere, TopAbs_FACE);
5139       for(; E.More(); E.Next()) {
5140         if(!aMap.Add(E.Current())) continue;
5141         if(isSameFace(aFace, TopoDS::Face(E.Current()))) {
5142           listShape.Append(E.Current());
5143         }
5144       }
5145       break;
5146                       }
5147     case TopAbs_SOLID: {
5148       TopoDS_Solid aSolid = TopoDS::Solid(aWhat);
5149       TopExp_Explorer E(aWhere, TopAbs_SOLID);
5150       for(; E.More(); E.Next()) {
5151         if(!aMap.Add(E.Current())) continue;
5152         if(isSameSolid(aSolid, TopoDS::Solid(E.Current()))) {
5153           listShape.Append(E.Current());
5154         }
5155       }
5156       break;
5157                        }
5158     default:
5159       return NULL;
5160   }
5161
5162   if ( !listShape.IsEmpty() ) {
5163     TopTools_IndexedMapOfShape anIndices;
5164     TopExp::MapShapes(aWhere, anIndices);
5165     TopTools_ListIteratorOfListOfShape itSub (listShape);
5166     Handle(TColStd_HSequenceOfInteger) aSeq = new TColStd_HSequenceOfInteger;
5167     for (; itSub.More(); itSub.Next()) {
5168       if (anIndices.Contains(itSub.Value()))
5169         aSeq->Append(anIndices.FindIndex(itSub.Value()));
5170     }
5171     SetErrorCode(OK);
5172     // The GetSameIDs() doesn't change object so no new function is required.
5173     Handle(GEOM_Function) aFunction = GEOM::GetCreatedLast(theShapeWhere,theShapeWhat)->GetLastFunction();
5174
5175   // VSR 29/08/2017: 0023327, 0023428: eliminate unnecessary lines in Python dump
5176 #ifdef DUMP_SUBSHAPE_IDS
5177   // Make a Python command
5178   GEOM::TPythonDump(aFunction, /*append=*/true)
5179     << "listSameIDs = geompy.GetSameIDs("
5180     << theShapeWhere << ", "
5181     << theShapeWhat << ")";
5182 #endif // DUMP_SUBSHAPE_IDS
5183     return aSeq;
5184   } else {
5185     SetErrorCode(NOT_FOUND_ANY);
5186     return NULL;
5187   }
5188 }
5189
5190 //=======================================================================
5191 //function : ExtendEdge
5192 //purpose  :
5193 //=======================================================================
5194 Handle(GEOM_Object) GEOMImpl_IShapesOperations::ExtendEdge
5195                                       (const Handle(GEOM_Object) &theEdge,
5196                                        const Standard_Real        theMin,
5197                                        const Standard_Real        theMax)
5198 {
5199   SetErrorCode(KO);
5200
5201   if (theEdge.IsNull()) {
5202     return NULL;
5203   }
5204
5205   //Add a new Edge object
5206   Handle(GEOM_Object) aResEdge = GetEngine()->AddObject(GEOM_EDGE);
5207
5208   //Add a new Vector function
5209   Handle(GEOM_Function) aFunction =
5210     aResEdge->AddFunction(GEOMImpl_ShapeDriver::GetID(), EDGE_UV);
5211
5212   //Check if the function is set correctly
5213   if (aFunction->GetDriverGUID() != GEOMImpl_ShapeDriver::GetID()) {
5214     return NULL;
5215   }
5216
5217   GEOMImpl_IShapeExtend aCI (aFunction);
5218
5219   Handle(GEOM_Function) anEdge = theEdge->GetLastFunction();
5220
5221   if (anEdge.IsNull()) {
5222     return NULL;
5223   }
5224
5225   aCI.SetShape(anEdge);
5226   aCI.SetUMin(theMin);
5227   aCI.SetUMax(theMax);
5228
5229   //Compute the Edge value
5230   try {
5231     OCC_CATCH_SIGNALS;
5232     if (!GetSolver()->ComputeFunction(aFunction)) {
5233       SetErrorCode("Shape driver failed");
5234
5235       return NULL;
5236     }
5237   }
5238   catch (Standard_Failure& aFail) {
5239     SetErrorCode(aFail.GetMessageString());
5240
5241     return NULL;
5242   }
5243
5244   //Make a Python command
5245   GEOM::TPythonDump(aFunction)
5246              << aResEdge  << " = geompy.ExtendEdge("
5247              << theEdge << ", " << theMin << ", " << theMax << ")";
5248
5249   SetErrorCode(OK);
5250
5251   return aResEdge;
5252 }
5253
5254 //=======================================================================
5255 //function : ExtendFace
5256 //purpose  :
5257 //=======================================================================
5258 Handle(GEOM_Object) GEOMImpl_IShapesOperations::ExtendFace
5259                                       (const Handle(GEOM_Object) &theFace,
5260                                        const Standard_Real        theUMin,
5261                                        const Standard_Real        theUMax,
5262                                        const Standard_Real        theVMin,
5263                                        const Standard_Real        theVMax)
5264 {
5265   SetErrorCode(KO);
5266
5267   if (theFace.IsNull()) {
5268     return NULL;
5269   }
5270
5271   //Add a new Face object
5272   Handle(GEOM_Object) aResFace = GetEngine()->AddObject(GEOM_FACE);
5273
5274   //Add a new Vector function
5275   Handle(GEOM_Function) aFunction =
5276     aResFace->AddFunction(GEOMImpl_ShapeDriver::GetID(), FACE_UV);
5277
5278   //Check if the function is set correctly
5279   if (aFunction->GetDriverGUID() != GEOMImpl_ShapeDriver::GetID()) {
5280     return NULL;
5281   }
5282
5283   GEOMImpl_IShapeExtend aCI (aFunction);
5284
5285   Handle(GEOM_Function) aFace = theFace->GetLastFunction();
5286
5287   if (aFace.IsNull()) {
5288     return NULL;
5289   }
5290
5291   aCI.SetShape(aFace);
5292   aCI.SetUMin(theUMin);
5293   aCI.SetUMax(theUMax);
5294   aCI.SetVMin(theVMin);
5295   aCI.SetVMax(theVMax);
5296
5297   //Compute the Face value
5298   try {
5299     OCC_CATCH_SIGNALS;
5300     if (!GetSolver()->ComputeFunction(aFunction)) {
5301       SetErrorCode("Shape driver failed");
5302
5303       return NULL;
5304     }
5305   }
5306   catch (Standard_Failure& aFail) {
5307     SetErrorCode(aFail.GetMessageString());
5308
5309     return NULL;
5310   }
5311
5312   //Make a Python command
5313   GEOM::TPythonDump(aFunction)
5314              << aResFace  << " = geompy.ExtendFace("
5315              << theFace << ", " << theUMin << ", " << theUMax << ", "
5316              << theVMin << ", " << theVMax << ")";
5317
5318   SetErrorCode(OK);
5319
5320   return aResFace;
5321 }
5322
5323 //=======================================================================
5324 //function : MakeSurfaceFromFace
5325 //purpose  :
5326 //=======================================================================
5327 Handle(GEOM_Object) GEOMImpl_IShapesOperations::MakeSurfaceFromFace
5328                                       (const Handle(GEOM_Object) &theFace)
5329 {
5330   SetErrorCode(KO);
5331
5332   if (theFace.IsNull()) {
5333     return NULL;
5334   }
5335
5336   //Add a new Face object
5337   Handle(GEOM_Object) aResFace = GetEngine()->AddObject(GEOM_FACE);
5338
5339   //Add a new Vector function
5340   Handle(GEOM_Function) aFunction =
5341     aResFace->AddFunction(GEOMImpl_ShapeDriver::GetID(), SURFACE_FROM_FACE);
5342
5343   //Check if the function is set correctly
5344   if (aFunction->GetDriverGUID() != GEOMImpl_ShapeDriver::GetID()) {
5345     return NULL;
5346   }
5347
5348   GEOMImpl_IShapeExtend aCI (aFunction);
5349
5350   Handle(GEOM_Function) aFace = theFace->GetLastFunction();
5351
5352   if (aFace.IsNull()) {
5353     return NULL;
5354   }
5355
5356   aCI.SetShape(aFace);
5357
5358   //Compute the Face value
5359   try {
5360     OCC_CATCH_SIGNALS;
5361     if (!GetSolver()->ComputeFunction(aFunction)) {
5362       SetErrorCode("Shape driver failed");
5363
5364       return NULL;
5365     }
5366   }
5367   catch (Standard_Failure& aFail) {
5368     SetErrorCode(aFail.GetMessageString());
5369
5370     return NULL;
5371   }
5372
5373   //Make a Python command
5374   GEOM::TPythonDump(aFunction)
5375              << aResFace  << " = geompy.MakeSurfaceFromFace("
5376              << theFace << ")";
5377
5378   SetErrorCode(OK);
5379
5380   return aResFace;
5381 }