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