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