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