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