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