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