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