Salome HOME
Changes for bug NPAL14533 (improvement GetShapesOnShape())
[modules/geom.git] / src / GEOMImpl / GEOMImpl_IShapesOperations.cxx
1 // Copyright (C) 2005  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
2 // CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
3 //
4 // This library is free software; you can redistribute it and/or
5 // modify it under the terms of the GNU Lesser General Public
6 // License as published by the Free Software Foundation; either
7 // version 2.1 of the License.
8 //
9 // This library is distributed in the hope that it will be useful
10 // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12 // Lesser General Public License for more details.
13 //
14 // You should have received a copy of the GNU Lesser General Public
15 // License along with this library; if not, write to the Free Software
16 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
17 //
18 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
19 //
20 // File      : GEOMImpl_IShapesOperations.cxx
21 // Created   : 
22 // Author    : modified by Lioka RAZAFINDRAZAKA (CEA) 22/06/2007
23 // Project   : SALOME
24 // $Header$
25
26 using namespace std;
27
28 #include <Standard_Stream.hxx>
29
30 #include "GEOMImpl_IShapesOperations.hxx"
31
32 #include "GEOMImpl_Types.hxx"
33
34 #include "GEOMImpl_VectorDriver.hxx"
35 #include "GEOMImpl_ShapeDriver.hxx"
36 #include "GEOMImpl_CopyDriver.hxx"
37 #include "GEOMImpl_GlueDriver.hxx"
38
39 #include "GEOMImpl_IVector.hxx"
40 #include "GEOMImpl_IShapes.hxx"
41 #include "GEOMImpl_IGlue.hxx"
42
43 #include "GEOMImpl_Block6Explorer.hxx"
44
45 #include "GEOM_Function.hxx"
46 #include "GEOM_ISubShape.hxx"
47 #include "GEOM_PythonDump.hxx"
48
49 #include "GEOMAlgo_FinderShapeOn1.hxx"
50 #include "GEOMAlgo_FinderShapeOnQuad.hxx"
51 #include "GEOMAlgo_FinderShapeOn2.hxx"
52 #include "GEOMAlgo_ClsfBox.hxx"
53 #include "GEOMAlgo_ClsfSolid.hxx"
54 #include "GEOMAlgo_Gluer1.hxx"
55 #include "GEOMAlgo_ListIteratorOfListOfCoupleOfShapes.hxx"
56 #include "GEOMAlgo_CoupleOfShapes.hxx"
57 #include "GEOMAlgo_ListOfCoupleOfShapes.hxx"
58
59 #include "utilities.h"
60 #include "OpUtil.hxx"
61 #include "Utils_ExceptHandlers.hxx"
62
63 #include <TFunction_DriverTable.hxx>
64 #include <TFunction_Driver.hxx>
65 #include <TFunction_Logbook.hxx>
66 #include <TDataStd_Integer.hxx>
67 #include <TDataStd_IntegerArray.hxx>
68 #include <TDF_Tool.hxx>
69
70 #include <BRepExtrema_ExtCF.hxx>
71
72 #include <BRep_Tool.hxx>
73 #include <BRep_Builder.hxx>
74 #include <BRepTools.hxx>
75 #include <BRepGProp.hxx>
76 #include <BRepAdaptor_Curve.hxx>
77 #include <BRepAdaptor_Surface.hxx>
78 #include <BRepBndLib.hxx>
79 #include <BRepBuilderAPI_MakeFace.hxx>
80 #include <BRepMesh_IncrementalMesh.hxx>
81
82 #include <TopAbs.hxx>
83 #include <TopExp.hxx>
84 #include <TopoDS.hxx>
85 #include <TopoDS_Shape.hxx>
86 #include <TopoDS_Solid.hxx>
87 #include <TopoDS_Face.hxx>
88 #include <TopoDS_Edge.hxx>
89 #include <TopoDS_Vertex.hxx>
90 #include <TopoDS_Compound.hxx>
91 #include <TopoDS_Iterator.hxx>
92 #include <TopExp_Explorer.hxx>
93 #include <TopLoc_Location.hxx>
94 #include <TopTools_MapOfShape.hxx>
95 #include <TopTools_MapOfOrientedShape.hxx>
96 #include <TopTools_Array1OfShape.hxx>
97 #include <TopTools_ListIteratorOfListOfShape.hxx>
98 #include <TopTools_IndexedMapOfShape.hxx>
99
100 #include <Geom_Surface.hxx>
101 #include <Geom_Plane.hxx>
102 #include <Geom_SphericalSurface.hxx>
103 #include <Geom_CylindricalSurface.hxx>
104 #include <GeomAdaptor_Surface.hxx>
105
106 #include <GeomLib_Tool.hxx>
107 #include <Geom2d_Curve.hxx>
108
109 #include <Bnd_Box.hxx>
110 #include <GProp_GProps.hxx>
111 #include <gp_Pnt.hxx>
112 #include <gp_Lin.hxx>
113 #include <TColStd_ListOfInteger.hxx>
114 #include <TColStd_ListIteratorOfListOfInteger.hxx>
115 #include <TColStd_Array1OfReal.hxx>
116 #include <TColStd_HArray1OfInteger.hxx>
117
118 #include <vector>
119
120 #include <Standard_NullObject.hxx>
121 #include <Standard_Failure.hxx>
122 #include <Standard_ErrorHandler.hxx> // CAREFUL ! position of this file is critic : see Lucien PIGNOLONI / OCC
123
124 // Includes added for GetInPlace algorithm improvement
125
126 #include <GEOMImpl_MeasureDriver.hxx>
127 #include <GEOMImpl_IMeasure.hxx>
128 #include <BRepBuilderAPI_MakeVertex.hxx>
129
130 #include <BRepClass_FaceClassifier.hxx>
131 #include <BRepClass3d_SolidClassifier.hxx>
132 #include <Precision.hxx>
133
134 //=============================================================================
135 /*!
136  *   constructor:
137  */
138 //=============================================================================
139 GEOMImpl_IShapesOperations::GEOMImpl_IShapesOperations (GEOM_Engine* theEngine, int theDocID)
140 : GEOM_IOperations(theEngine, theDocID)
141 {
142   MESSAGE("GEOMImpl_IShapesOperations::GEOMImpl_IShapesOperations");
143 }
144
145 //=============================================================================
146 /*!
147  *  destructor
148  */
149 //=============================================================================
150 GEOMImpl_IShapesOperations::~GEOMImpl_IShapesOperations()
151 {
152   MESSAGE("GEOMImpl_IShapesOperations::~GEOMImpl_IShapesOperations");
153 }
154
155
156 //=============================================================================
157 /*!
158  *  MakeEdge
159  */
160 //=============================================================================
161 Handle(GEOM_Object) GEOMImpl_IShapesOperations::MakeEdge
162                      (Handle(GEOM_Object) thePnt1, Handle(GEOM_Object) thePnt2)
163 {
164   SetErrorCode(KO);
165
166   if (thePnt1.IsNull() || thePnt2.IsNull()) return NULL;
167
168   //Add a new Edge object
169   Handle(GEOM_Object) anEdge = GetEngine()->AddObject(GetDocID(), GEOM_EDGE);
170
171   //Add a new Vector function
172   Handle(GEOM_Function) aFunction =
173     anEdge->AddFunction(GEOMImpl_VectorDriver::GetID(), VECTOR_TWO_PNT);
174
175   //Check if the function is set correctly
176   if (aFunction->GetDriverGUID() != GEOMImpl_VectorDriver::GetID()) return NULL;
177
178   GEOMImpl_IVector aPI (aFunction);
179
180   Handle(GEOM_Function) aRef1 = thePnt1->GetLastFunction();
181   Handle(GEOM_Function) aRef2 = thePnt2->GetLastFunction();
182   if (aRef1.IsNull() || aRef2.IsNull()) return NULL;
183
184   aPI.SetPoint1(aRef1);
185   aPI.SetPoint2(aRef2);
186
187   //Compute the Edge value
188   try {
189 #if (OCC_VERSION_MAJOR << 16 | OCC_VERSION_MINOR << 8 | OCC_VERSION_MAINTENANCE) > 0x060100
190     OCC_CATCH_SIGNALS;
191 #endif
192     if (!GetSolver()->ComputeFunction(aFunction)) {
193       SetErrorCode("Vector driver failed");
194       return NULL;
195     }
196   }
197   catch (Standard_Failure) {
198     Handle(Standard_Failure) aFail = Standard_Failure::Caught();
199     SetErrorCode(aFail->GetMessageString());
200     return NULL;
201   }
202
203   //Make a Python command
204   GEOM::TPythonDump(aFunction) << anEdge << " = geompy.MakeEdge("
205                                << thePnt1 << ", " << thePnt2 << ")";
206
207   SetErrorCode(OK);
208   return anEdge;
209 }
210
211 //=============================================================================
212 /*!
213  *  MakeWire
214  */
215 //=============================================================================
216 Handle(GEOM_Object) GEOMImpl_IShapesOperations::MakeWire
217                              (list<Handle(GEOM_Object)> theShapes)
218 {
219   return MakeShape(theShapes, GEOM_WIRE, WIRE_EDGES, "MakeWire");
220 }
221
222 //=============================================================================
223 /*!
224  *  MakeFace
225  */
226 //=============================================================================
227 Handle(GEOM_Object) GEOMImpl_IShapesOperations::MakeFace (Handle(GEOM_Object) theWire,
228                                                           const bool isPlanarWanted)
229 {
230   SetErrorCode(KO);
231
232   if (theWire.IsNull()) return NULL;
233
234   //Add a new Face object
235   Handle(GEOM_Object) aFace = GetEngine()->AddObject(GetDocID(), GEOM_FACE);
236
237   //Add a new Shape function for creation of a face from a wire
238   Handle(GEOM_Function) aFunction =
239     aFace->AddFunction(GEOMImpl_ShapeDriver::GetID(), FACE_WIRE);
240   if (aFunction.IsNull()) return NULL;
241
242   //Check if the function is set correctly
243   if (aFunction->GetDriverGUID() != GEOMImpl_ShapeDriver::GetID()) return NULL;
244
245   GEOMImpl_IShapes aCI (aFunction);
246
247   Handle(GEOM_Function) aRefWire = theWire->GetLastFunction();
248
249   if (aRefWire.IsNull()) return NULL;
250
251   aCI.SetBase(aRefWire);
252   aCI.SetIsPlanar(isPlanarWanted);
253
254   //Compute the Face value
255   try {
256 #if (OCC_VERSION_MAJOR << 16 | OCC_VERSION_MINOR << 8 | OCC_VERSION_MAINTENANCE) > 0x060100
257     OCC_CATCH_SIGNALS;
258 #endif
259     if (!GetSolver()->ComputeFunction(aFunction)) {
260       SetErrorCode("Shape driver failed to compute a face");
261       return NULL;
262     }
263   }
264   catch (Standard_Failure) {
265     Handle(Standard_Failure) aFail = Standard_Failure::Caught();
266     SetErrorCode(aFail->GetMessageString());
267     return NULL;
268   }
269
270   //Make a Python command
271   GEOM::TPythonDump(aFunction) << aFace << " = geompy.MakeFace("
272     << theWire << ", " << (int)isPlanarWanted << ")";
273
274   SetErrorCode(OK);
275   return aFace;
276 }
277
278 //=============================================================================
279 /*!
280  *  MakeFaceWires
281  */
282 //=============================================================================
283 Handle(GEOM_Object) GEOMImpl_IShapesOperations::MakeFaceWires
284                              (list<Handle(GEOM_Object)> theShapes,
285                               const bool isPlanarWanted)
286 {
287   SetErrorCode(KO);
288
289   //Add a new object
290   Handle(GEOM_Object) aShape = GetEngine()->AddObject(GetDocID(), GEOM_FACE);
291
292   //Add a new function
293   Handle(GEOM_Function) aFunction =
294     aShape->AddFunction(GEOMImpl_ShapeDriver::GetID(), FACE_WIRES);
295   if (aFunction.IsNull()) return NULL;
296
297   //Check if the function is set correctly
298   if (aFunction->GetDriverGUID() != GEOMImpl_ShapeDriver::GetID()) return NULL;
299
300   GEOMImpl_IShapes aCI (aFunction);
301
302   Handle(TColStd_HSequenceOfTransient) aShapesSeq = new TColStd_HSequenceOfTransient;
303
304   // Shapes
305   list<Handle(GEOM_Object)>::iterator it = theShapes.begin();
306   for (; it != theShapes.end(); it++) {
307     Handle(GEOM_Function) aRefSh = (*it)->GetLastFunction();
308     if (aRefSh.IsNull()) {
309       SetErrorCode("NULL argument shape for the face construction");
310       return NULL;
311     }
312     aShapesSeq->Append(aRefSh);
313   }
314   aCI.SetShapes(aShapesSeq);
315
316   aCI.SetIsPlanar(isPlanarWanted);
317
318   //Compute the shape
319   try {
320 #if (OCC_VERSION_MAJOR << 16 | OCC_VERSION_MINOR << 8 | OCC_VERSION_MAINTENANCE) > 0x060100
321     OCC_CATCH_SIGNALS;
322 #endif
323     if (!GetSolver()->ComputeFunction(aFunction)) {
324       SetErrorCode("Shape driver failed");
325       return NULL;
326     }
327   }
328   catch (Standard_Failure) {
329     Handle(Standard_Failure) aFail = Standard_Failure::Caught();
330     SetErrorCode(aFail->GetMessageString());
331     return NULL;
332   }
333
334   //Make a Python command
335   GEOM::TPythonDump pd (aFunction);
336   pd << aShape << " = geompy.MakeFaceWires([";
337
338   // Shapes
339   it = theShapes.begin();
340   if (it != theShapes.end()) {
341     pd << (*it++);
342     while (it != theShapes.end()) {
343       pd << ", " << (*it++);
344     }
345   }
346   pd << "], " << (int)isPlanarWanted << ")";
347
348   SetErrorCode(OK);
349   return aShape;
350 }
351
352 //=============================================================================
353 /*!
354  *  MakeShell
355  */
356 //=============================================================================
357 Handle(GEOM_Object) GEOMImpl_IShapesOperations::MakeShell
358                              (list<Handle(GEOM_Object)> theShapes)
359 {
360   return MakeShape(theShapes, GEOM_SHELL, SHELL_FACES, "MakeShell");
361 }
362
363 //=============================================================================
364 /*!
365  *  MakeSolidShells
366  */
367 //=============================================================================
368 Handle(GEOM_Object) GEOMImpl_IShapesOperations::MakeSolidShells
369                              (list<Handle(GEOM_Object)> theShapes)
370 {
371   return MakeShape(theShapes, GEOM_SOLID, SOLID_SHELLS, "MakeSolid");
372 }
373
374 //=============================================================================
375 /*!
376  *  MakeSolidShell
377  */
378 //=============================================================================
379 Handle(GEOM_Object) GEOMImpl_IShapesOperations::MakeSolidShell (Handle(GEOM_Object) theShell)
380 {
381   SetErrorCode(KO);
382
383   if (theShell.IsNull()) return NULL;
384
385   //Add a new Solid object
386   Handle(GEOM_Object) aSolid = GetEngine()->AddObject(GetDocID(), GEOM_SOLID);
387
388   //Add a new Solid function for creation of a solid from a shell
389   Handle(GEOM_Function) aFunction =
390     aSolid->AddFunction(GEOMImpl_ShapeDriver::GetID(), SOLID_SHELL);
391   if (aFunction.IsNull()) return NULL;
392
393   //Check if the function is set correctly
394   if (aFunction->GetDriverGUID() != GEOMImpl_ShapeDriver::GetID()) return NULL;
395
396   GEOMImpl_IShapes aCI (aFunction);
397
398   Handle(GEOM_Function) aRefShell = theShell->GetLastFunction();
399
400   if (aRefShell.IsNull()) return NULL;
401
402   aCI.SetBase(aRefShell);
403
404   //Compute the Solid value
405   try {
406 #if (OCC_VERSION_MAJOR << 16 | OCC_VERSION_MINOR << 8 | OCC_VERSION_MAINTENANCE) > 0x060100
407     OCC_CATCH_SIGNALS;
408 #endif
409     if (!GetSolver()->ComputeFunction(aFunction)) {
410       SetErrorCode("Solid driver failed");
411       return NULL;
412     }
413   }
414   catch (Standard_Failure) {
415     Handle(Standard_Failure) aFail = Standard_Failure::Caught();
416     SetErrorCode(aFail->GetMessageString());
417     return NULL;
418   }
419
420   //Make a Python command
421   GEOM::TPythonDump(aFunction) << aSolid
422     << " = geompy.MakeSolid(" << theShell << ")";
423
424   SetErrorCode(OK);
425   return aSolid;
426 }
427
428 //=============================================================================
429 /*!
430  *  MakeCompound
431  */
432 //=============================================================================
433 Handle(GEOM_Object) GEOMImpl_IShapesOperations::MakeCompound
434                              (list<Handle(GEOM_Object)> theShapes)
435 {
436   return MakeShape(theShapes, GEOM_COMPOUND, COMPOUND_SHAPES, "MakeCompound");
437 }
438
439 //=============================================================================
440 /*!
441  *  MakeShape
442  */
443 //=============================================================================
444 Handle(GEOM_Object) GEOMImpl_IShapesOperations::MakeShape
445                              (list<Handle(GEOM_Object)>      theShapes,
446                               const Standard_Integer         theObjectType,
447                               const Standard_Integer         theFunctionType,
448                               const TCollection_AsciiString& theMethodName)
449 {
450   SetErrorCode(KO);
451
452   //Add a new object
453   Handle(GEOM_Object) aShape = GetEngine()->AddObject(GetDocID(), theObjectType);
454
455   //Add a new function
456   Handle(GEOM_Function) aFunction =
457     aShape->AddFunction(GEOMImpl_ShapeDriver::GetID(), theFunctionType);
458   if (aFunction.IsNull()) return NULL;
459
460   //Check if the function is set correctly
461   if (aFunction->GetDriverGUID() != GEOMImpl_ShapeDriver::GetID()) return NULL;
462
463   GEOMImpl_IShapes aCI (aFunction);
464
465   Handle(TColStd_HSequenceOfTransient) aShapesSeq = new TColStd_HSequenceOfTransient;
466
467   // Shapes
468   list<Handle(GEOM_Object)>::iterator it = theShapes.begin();
469   for (; it != theShapes.end(); it++) {
470     Handle(GEOM_Function) aRefSh = (*it)->GetLastFunction();
471     if (aRefSh.IsNull()) {
472       SetErrorCode("NULL argument shape for the shape construction");
473       return NULL;
474     }
475     aShapesSeq->Append(aRefSh);
476   }
477   aCI.SetShapes(aShapesSeq);
478
479   //Compute the shape
480   try {
481 #if (OCC_VERSION_MAJOR << 16 | OCC_VERSION_MINOR << 8 | OCC_VERSION_MAINTENANCE) > 0x060100
482     OCC_CATCH_SIGNALS;
483 #endif
484     if (!GetSolver()->ComputeFunction(aFunction)) {
485       SetErrorCode("Shape driver failed");
486       return NULL;
487     }
488   }
489   catch (Standard_Failure) {
490     Handle(Standard_Failure) aFail = Standard_Failure::Caught();
491     SetErrorCode(aFail->GetMessageString());
492     return NULL;
493   }
494
495   //Make a Python command
496   GEOM::TPythonDump pd (aFunction);
497   pd << aShape << " = geompy." << theMethodName.ToCString() << "([";
498
499   // Shapes
500   it = theShapes.begin();
501   if (it != theShapes.end()) {
502     pd << (*it++);
503     while (it != theShapes.end()) {
504       pd << ", " << (*it++);
505     }
506   }
507   pd << "])";
508
509   SetErrorCode(OK);
510   return aShape;
511 }
512
513 //=============================================================================
514 /*!
515  *  MakeGlueFaces
516  */
517 //=============================================================================
518 Handle(GEOM_Object) GEOMImpl_IShapesOperations::MakeGlueFaces
519                                                 (Handle(GEOM_Object) theShape,
520                                                  const Standard_Real theTolerance,
521                                                  const Standard_Boolean doKeepNonSolids)
522 {
523   SetErrorCode(KO);
524
525   if (theShape.IsNull()) return NULL;
526
527   //Add a new Glued object
528   Handle(GEOM_Object) aGlued = GetEngine()->AddObject(GetDocID(), GEOM_GLUED);
529
530   //Add a new Glue function
531   Handle(GEOM_Function) aFunction;
532   aFunction = aGlued->AddFunction(GEOMImpl_GlueDriver::GetID(), GLUE_FACES);
533   if (aFunction.IsNull()) return NULL;
534
535   //Check if the function is set correctly
536   if (aFunction->GetDriverGUID() != GEOMImpl_GlueDriver::GetID()) return NULL;
537
538   GEOMImpl_IGlue aCI (aFunction);
539
540   Handle(GEOM_Function) aRefShape = theShape->GetLastFunction();
541   if (aRefShape.IsNull()) return NULL;
542
543   aCI.SetBase(aRefShape);
544   aCI.SetTolerance(theTolerance);
545   aCI.SetKeepNonSolids(doKeepNonSolids);
546
547   //Compute the sub-shape value
548   Standard_Boolean isWarning = Standard_False;
549   try {
550 #if (OCC_VERSION_MAJOR << 16 | OCC_VERSION_MINOR << 8 | OCC_VERSION_MAINTENANCE) > 0x060100
551     OCC_CATCH_SIGNALS;
552 #endif
553     if (!GetSolver()->ComputeFunction(aFunction)) {
554       SetErrorCode("Shape driver failed to glue faces");
555       return NULL;
556     }
557   }
558   catch (Standard_Failure) {
559     Handle(Standard_Failure) aFail = Standard_Failure::Caught();
560     SetErrorCode(aFail->GetMessageString());
561     // to provide warning
562     if (!aFunction->GetValue().IsNull()) {
563       isWarning = Standard_True;
564     } else {
565       return NULL;
566     }
567   }
568
569   //Make a Python command
570   GEOM::TPythonDump(aFunction) << aGlued << " = geompy.MakeGlueFaces("
571     << theShape << ", " << theTolerance << ")";
572
573   // to provide warning
574   if (!isWarning) SetErrorCode(OK);
575   return aGlued;
576 }
577
578 //=============================================================================
579 /*!
580  *  GetGlueFaces
581  */
582 //=============================================================================
583 Handle(TColStd_HSequenceOfTransient) GEOMImpl_IShapesOperations::GetGlueFaces
584                                                 (Handle(GEOM_Object) theShape,
585                                                  const Standard_Real theTolerance)
586 {
587   SetErrorCode(KO);
588
589   if (theShape.IsNull()) return NULL;
590   TopoDS_Shape aShape = theShape->GetValue();
591   if (aShape.IsNull()) return NULL;
592
593   Handle(TColStd_HSequenceOfTransient) aSeq = new TColStd_HSequenceOfTransient;
594
595   Standard_Integer iErr;
596   TopoDS_Shape aS;
597   GEOMAlgo_Gluer1 aGluer;
598   GEOMAlgo_ListIteratorOfListOfCoupleOfShapes aItCS;
599   GEOMAlgo_CoupleOfShapes aCS;
600   GEOMAlgo_ListOfCoupleOfShapes aLCS;
601
602   //aGluer = new GEOMAlgo_Gluer1;
603   aGluer.SetShape(aShape);
604   aGluer.SetTolerance(theTolerance);
605   aGluer.Perform();
606   iErr = aGluer.ErrorStatus();
607   if (iErr) return NULL;
608
609   TopTools_ListOfShape listShape;
610   const GEOMAlgo_ListOfCoupleOfShapes& aLCSG = aGluer.GluedFaces();
611   // Access to faces
612   aItCS.Initialize(aLCSG);
613   for (; aItCS.More(); aItCS.Next()) {
614     const GEOMAlgo_CoupleOfShapes& aCSG = aItCS.Value();
615     listShape.Append(aCSG.Shape1());
616   }
617
618   TopTools_ListIteratorOfListOfShape itSub (listShape);
619   TCollection_AsciiString anAsciiList, anEntry;
620   TopTools_IndexedMapOfShape anIndices;
621   TopExp::MapShapes(aShape, anIndices);
622   Handle(TColStd_HArray1OfInteger) anArray;
623   Handle(GEOM_Object) anObj;
624   for (int index = 1; itSub.More(); itSub.Next(), ++index) {
625     TopoDS_Shape aValue = itSub.Value();
626     anArray = new TColStd_HArray1OfInteger(1,1);
627     anArray->SetValue(1, anIndices.FindIndex(aValue));
628     anObj = GetEngine()->AddSubShape(theShape, anArray);
629     if (!anObj.IsNull()) {
630       aSeq->Append(anObj);
631
632       // for python command
633       TDF_Tool::Entry(anObj->GetEntry(), anEntry);
634       anAsciiList += anEntry;
635       anAsciiList += ",";
636     }
637   }
638
639   //Make a Python command
640   if(anAsciiList.Length()>0)
641     anAsciiList.Trunc(anAsciiList.Length() - 1);
642   Handle(GEOM_Function) aFunction = theShape->GetLastFunction();
643   GEOM::TPythonDump pd (aFunction, /*append=*/true);
644   pd << "[" << anAsciiList.ToCString();
645   pd << "] = geompy.GetGlueFaces(" << theShape << ", " << theTolerance << ")";
646
647   SetErrorCode(OK);
648
649   return aSeq;
650 }
651
652
653 //=============================================================================
654 /*!
655  *  MakeGlueFacesByList
656  */
657 //=============================================================================
658 Handle(GEOM_Object) GEOMImpl_IShapesOperations::MakeGlueFacesByList
659                                                 (Handle(GEOM_Object) theShape,
660                                                  const Standard_Real theTolerance,
661                                                  list<Handle(GEOM_Object)> theFaces,
662                                                  const Standard_Boolean doKeepNonSolids)
663 {
664   SetErrorCode(KO);
665
666   if (theShape.IsNull()) return NULL;
667
668   //Add a new Glued object
669   Handle(GEOM_Object) aGlued = GetEngine()->AddObject(GetDocID(), GEOM_GLUED);
670
671   //Add a new Glue function
672   Handle(GEOM_Function) aFunction;
673   aFunction = aGlued->AddFunction(GEOMImpl_GlueDriver::GetID(), GLUE_FACES_BY_LIST);
674   if (aFunction.IsNull()) return NULL;
675
676   //Check if the function is set correctly
677   if (aFunction->GetDriverGUID() != GEOMImpl_GlueDriver::GetID()) return NULL;
678
679   GEOMImpl_IGlue aCI (aFunction);
680
681   Handle(GEOM_Function) aRefShape = theShape->GetLastFunction();
682   if (aRefShape.IsNull()) return NULL;
683
684   aCI.SetBase(aRefShape);
685   aCI.SetTolerance(theTolerance);
686   aCI.SetKeepNonSolids(doKeepNonSolids);
687
688   Handle(TColStd_HSequenceOfTransient) aFaces = new TColStd_HSequenceOfTransient;
689   list<Handle(GEOM_Object)>::iterator it = theFaces.begin();
690   for (; it != theFaces.end(); it++) {
691     Handle(GEOM_Function) aRefSh = (*it)->GetLastFunction();
692     if (aRefSh.IsNull()) {
693       SetErrorCode("NULL argument shape for the shape construction");
694       return NULL;
695     }
696     aFaces->Append(aRefSh);
697   }
698   aCI.SetFaces(aFaces);
699
700   //Compute the sub-shape value
701   Standard_Boolean isWarning = Standard_False;
702   try {
703 #if (OCC_VERSION_MAJOR << 16 | OCC_VERSION_MINOR << 8 | OCC_VERSION_MAINTENANCE) > 0x060100
704     OCC_CATCH_SIGNALS;
705 #endif
706     if (!GetSolver()->ComputeFunction(aFunction)) {
707       SetErrorCode("Shape driver failed to glue faces");
708       return NULL;
709     }
710   }
711   catch (Standard_Failure) {
712     Handle(Standard_Failure) aFail = Standard_Failure::Caught();
713     SetErrorCode(aFail->GetMessageString());
714     // to provide warning
715     if (!aFunction->GetValue().IsNull()) {
716       isWarning = Standard_True;
717     } else {
718       return NULL;
719     }
720   }
721
722   //Make a Python command
723   
724   GEOM::TPythonDump pd(aFunction);
725   pd << aGlued << " = geompy.MakeGlueFacesByList("
726      << theShape << ", " << theTolerance << ", [";
727   // Faces
728   it = theFaces.begin();
729   if (it != theFaces.end()) {
730     pd << (*it++);
731     while (it != theFaces.end()) {
732       pd << ", " << (*it++);
733     }
734   }
735   pd << "])";
736
737
738   // to provide warning
739   if (!isWarning) SetErrorCode(OK);
740   return aGlued;
741 }
742
743
744
745 //=============================================================================
746 /*!
747  *  MakeExplode
748  */
749 //=============================================================================
750 Handle(TColStd_HSequenceOfTransient) GEOMImpl_IShapesOperations::MakeExplode
751                                           (Handle(GEOM_Object)    theShape,
752                                            const Standard_Integer theShapeType,
753                                            const Standard_Boolean isSorted)
754 {
755   SetErrorCode(KO);
756
757   if (theShape.IsNull()) return NULL;
758   TopoDS_Shape aShape = theShape->GetValue();
759   if (aShape.IsNull()) return NULL;
760
761   Handle(GEOM_Function) aMainShape = theShape->GetLastFunction();
762
763   Handle(TColStd_HSequenceOfTransient) aSeq = new TColStd_HSequenceOfTransient;
764   Handle(GEOM_Object) anObj;
765   TopTools_MapOfShape mapShape;
766   TopTools_ListOfShape listShape;
767
768   if (aShape.ShapeType() == TopAbs_COMPOUND &&
769       (TopAbs_ShapeEnum(theShapeType) == TopAbs_SHAPE ||
770        TopAbs_ShapeEnum(theShapeType) == TopAbs_COMPSOLID ||
771        TopAbs_ShapeEnum(theShapeType) == TopAbs_COMPOUND)) {
772     TopoDS_Iterator It (aShape, Standard_True, Standard_True);
773     for (; It.More(); It.Next()) {
774       if (mapShape.Add(It.Value())) {
775         if (TopAbs_ShapeEnum(theShapeType) == TopAbs_SHAPE ||
776             TopAbs_ShapeEnum(theShapeType) == It.Value().ShapeType()) {
777           listShape.Append(It.Value());
778         }
779       }
780     }
781   } else {
782     TopExp_Explorer exp (aShape, TopAbs_ShapeEnum(theShapeType));
783     for (; exp.More(); exp.Next())
784       if (mapShape.Add(exp.Current()))
785         listShape.Append(exp.Current());
786   }
787
788   if (listShape.IsEmpty()) {
789     //SetErrorCode("The given shape has no sub-shapes of the requested type");
790     SetErrorCode(NOT_FOUND_ANY); // NPAL18017
791     return aSeq;
792   }
793
794   if (isSorted)
795     SortShapes(listShape);
796
797   TopTools_IndexedMapOfShape anIndices;
798   TopExp::MapShapes(aShape, anIndices);
799   Handle(TColStd_HArray1OfInteger) anArray;
800
801   Standard_Integer nbAllSubShape = anIndices.Extent();
802
803   TopTools_ListIteratorOfListOfShape itSub (listShape);
804   TCollection_AsciiString anAsciiList, anEntry;
805   for (int index = 1; itSub.More(); itSub.Next(), ++index)
806   {
807     TopoDS_Shape aValue = itSub.Value();
808     anArray = new TColStd_HArray1OfInteger(1,1);
809     anArray->SetValue(1, anIndices.FindIndex(aValue));
810
811     //anObj = GetEngine()->AddSubShape(theShape, anArray);
812     {
813       anObj = GetEngine()->AddObject(GetDocID(), GEOM_SUBSHAPE);
814       Handle(GEOM_Function) aFunction = anObj->AddFunction(GEOM_Object::GetSubShapeID(), 1);
815       if (aFunction.IsNull()) return aSeq;
816
817       GEOM_ISubShape aSSI (aFunction);
818       aSSI.SetMainShape(aMainShape);
819       aSSI.SetIndices(anArray);
820
821       // Set function value directly, as we know it.
822       // Usage of Solver here would lead to significant loss of time,
823       // because GEOM_SubShapeDriver will build TopTools_IndexedMapOfShape
824       // on the main shape for each being calculated sub-shape separately.
825       aFunction->SetValue(aValue);
826     }
827
828     if (!anObj.IsNull()) {
829       aSeq->Append(anObj);
830
831       // for python command
832       TDF_Tool::Entry(anObj->GetEntry(), anEntry);
833       anAsciiList += anEntry;
834       anAsciiList += ",";
835     }
836   }
837
838   //Make a Python command
839   anAsciiList.Trunc(anAsciiList.Length() - 1);
840
841   GEOM::TPythonDump pd (aMainShape, /*append=*/true);
842   pd << "[" << anAsciiList.ToCString();
843   pd << "] = geompy.SubShapeAll" << (isSorted ? "Sorted(" : "(");
844   pd << theShape << ", " << TopAbs_ShapeEnum(theShapeType) << ")";
845
846   SetErrorCode(OK);
847
848   return aSeq;
849 }
850
851 //=============================================================================
852 /*!
853  *  SubShapeAllIDs
854  */
855 //=============================================================================
856 Handle(TColStd_HSequenceOfInteger) GEOMImpl_IShapesOperations::SubShapeAllIDs
857                                           (Handle(GEOM_Object)    theShape,
858                                            const Standard_Integer theShapeType,
859                                            const Standard_Boolean isSorted)
860 {
861   SetErrorCode(KO);
862
863   if (theShape.IsNull()) return NULL;
864   TopoDS_Shape aShape = theShape->GetValue();
865   if (aShape.IsNull()) return NULL;
866
867   Handle(TColStd_HSequenceOfInteger) aSeq = new TColStd_HSequenceOfInteger;
868   TopTools_MapOfShape mapShape;
869   TopTools_ListOfShape listShape;
870
871   if (aShape.ShapeType() == TopAbs_COMPOUND &&
872       (TopAbs_ShapeEnum(theShapeType) == TopAbs_SHAPE ||
873        TopAbs_ShapeEnum(theShapeType) == TopAbs_COMPSOLID ||
874        TopAbs_ShapeEnum(theShapeType) == TopAbs_COMPOUND)) {
875     TopoDS_Iterator It (aShape, Standard_True, Standard_True);
876     for (; It.More(); It.Next()) {
877       if (mapShape.Add(It.Value())) {
878         if (TopAbs_ShapeEnum(theShapeType) == TopAbs_SHAPE ||
879             TopAbs_ShapeEnum(theShapeType) == It.Value().ShapeType()) {
880           listShape.Append(It.Value());
881         }
882       }
883     }
884   } else {
885     TopExp_Explorer exp (aShape, TopAbs_ShapeEnum(theShapeType));
886     for (; exp.More(); exp.Next())
887       if (mapShape.Add(exp.Current()))
888         listShape.Append(exp.Current());
889   }
890
891   if (listShape.IsEmpty()) {
892     //SetErrorCode("The given shape has no sub-shapes of the requested type");
893     SetErrorCode(NOT_FOUND_ANY); // NPAL18017
894     return aSeq;
895   }
896
897   if (isSorted)
898     SortShapes(listShape);
899
900   TopTools_IndexedMapOfShape anIndices;
901   TopExp::MapShapes(aShape, anIndices);
902   Handle(TColStd_HArray1OfInteger) anArray;
903
904   TopTools_ListIteratorOfListOfShape itSub (listShape);
905   for (int index = 1; itSub.More(); itSub.Next(), ++index) {
906     TopoDS_Shape aValue = itSub.Value();
907     aSeq->Append(anIndices.FindIndex(aValue));
908   }
909
910   Handle(GEOM_Function) aFunction = theShape->GetLastFunction();
911
912   //Make a Python command
913   GEOM::TPythonDump pd (aFunction, /*append=*/true);
914   pd << "listSubShapeIDs = geompy.SubShapeAll";
915   pd << (isSorted ? "SortedIDs(" : "IDs(");
916   pd << theShape << ", " << TopAbs_ShapeEnum(theShapeType) << ")";
917
918   SetErrorCode(OK);
919   return aSeq;
920 }
921
922 //=============================================================================
923 /*!
924  *  GetSubShape
925  */
926 //=============================================================================
927 Handle(GEOM_Object) GEOMImpl_IShapesOperations::GetSubShape
928                                           (Handle(GEOM_Object)    theMainShape,
929                                            const Standard_Integer theID)
930 {
931   SetErrorCode(KO);
932
933   if (theMainShape.IsNull()) return NULL;
934
935   Handle(TColStd_HArray1OfInteger) anArray = new TColStd_HArray1OfInteger(1,1);
936   anArray->SetValue(1, theID);
937   Handle(GEOM_Object) anObj = GetEngine()->AddSubShape(theMainShape, anArray,true);
938   if (anObj.IsNull()) {
939     SetErrorCode("Can not get a sub-shape with the given ID");
940     return NULL;
941   }
942
943   Handle(GEOM_Function) aFunction = anObj->GetLastFunction();
944
945   //Make a Python command
946   GEOM::TPythonDump(aFunction) << anObj << " = geompy.GetSubShape("
947                                << theMainShape << ", [" << theID << "])";
948
949   SetErrorCode(OK);
950   return anObj;
951 }
952
953 //=============================================================================
954 /*!
955  *  GetSubShapeIndex
956  */
957 //=============================================================================
958 Standard_Integer GEOMImpl_IShapesOperations::GetSubShapeIndex (Handle(GEOM_Object) theMainShape,
959                                                                Handle(GEOM_Object) theSubShape)
960 {
961   SetErrorCode(KO);
962
963   TopoDS_Shape aMainShape = theMainShape->GetValue();
964   TopoDS_Shape aSubShape = theSubShape->GetValue();
965
966   if (aMainShape.IsNull() || aSubShape.IsNull()) return -1;
967
968   TopTools_IndexedMapOfShape anIndices;
969   TopExp::MapShapes(aMainShape, anIndices);
970   if (anIndices.Contains(aSubShape)) {
971     SetErrorCode(OK);
972     return anIndices.FindIndex(aSubShape);
973   }
974
975   return -1;
976 }
977
978 //=============================================================================
979 /*!
980  *  GetTopologyIndex
981  */
982 //=============================================================================
983 Standard_Integer GEOMImpl_IShapesOperations::GetTopologyIndex (Handle(GEOM_Object) theMainShape,
984                                                                Handle(GEOM_Object) theSubShape)
985 {
986   SetErrorCode(OK);
987
988   TopoDS_Shape aMainShape = theMainShape->GetValue();
989   TopoDS_Shape aSubShape = theSubShape->GetValue();
990
991   if (aMainShape.IsNull() || aSubShape.IsNull()) {
992     SetErrorCode("Null argument shape given");
993     return -1;
994   }
995
996   int index = 1;
997   if (aSubShape.ShapeType() == TopAbs_COMPOUND) {
998     TopoDS_Iterator it;
999     TopTools_ListOfShape CL;
1000     CL.Append(aMainShape);
1001     TopTools_ListIteratorOfListOfShape itC;
1002     for (itC.Initialize(CL); itC.More(); itC.Next()) {
1003       for (it.Initialize(itC.Value()); it.More(); it.Next()) {
1004         if (it.Value().ShapeType() == TopAbs_COMPOUND) {
1005           if (it.Value().IsSame(aSubShape))
1006             return index;
1007           else
1008             index++;
1009           CL.Append(it.Value());
1010         }
1011       }
1012     }
1013   } else {
1014     TopExp_Explorer anExp (aMainShape, aSubShape.ShapeType());
1015     TopTools_MapOfShape M;
1016     for (; anExp.More(); anExp.Next()) {
1017       if (M.Add(anExp.Current())) {
1018         if (anExp.Current().IsSame(aSubShape))
1019           return index;
1020         index++;
1021       }
1022     }
1023   }
1024
1025   SetErrorCode("The sub-shape does not belong to the main shape");
1026   return -1;
1027 }
1028
1029 //=============================================================================
1030 /*!
1031  *  GetShapeTypeString
1032  */
1033 //=============================================================================
1034 TCollection_AsciiString GEOMImpl_IShapesOperations::GetShapeTypeString (Handle(GEOM_Object) theShape)
1035 {
1036   SetErrorCode(KO);
1037
1038   TCollection_AsciiString aTypeName ("Null Shape");
1039
1040   TopoDS_Shape aShape = theShape->GetValue();
1041   if (aShape.IsNull())
1042     return aTypeName;
1043
1044   switch (aShape.ShapeType() )
1045   {
1046   case TopAbs_COMPOUND:
1047     aTypeName = "Compound";
1048     break;
1049   case  TopAbs_COMPSOLID:
1050     aTypeName = "Compound Solid";
1051     break;
1052   case TopAbs_SOLID:
1053     aTypeName = "Solid";
1054     break;
1055   case TopAbs_SHELL:
1056     aTypeName = "Shell";
1057     break;
1058   case TopAbs_FACE:
1059     {
1060       BRepAdaptor_Surface surf (TopoDS::Face(aShape));
1061       if (surf.GetType() == GeomAbs_Plane)
1062         aTypeName = "Plane";
1063       else if (surf.GetType() == GeomAbs_Cylinder)
1064         aTypeName = "Cylindrical Face";
1065       else if (surf.GetType() == GeomAbs_Sphere)
1066         aTypeName = "Spherical Face";
1067       else if (surf.GetType() == GeomAbs_Torus)
1068         aTypeName = "Toroidal Face";
1069       else if (surf.GetType() == GeomAbs_Cone)
1070         aTypeName = "Conical Face";
1071       else
1072         aTypeName = "GEOM::FACE";
1073     }
1074     break;
1075   case TopAbs_WIRE:
1076     aTypeName = "Wire";
1077     break;
1078   case TopAbs_EDGE:
1079     {
1080       BRepAdaptor_Curve curv (TopoDS::Edge(aShape));
1081       if (curv.GetType() == GeomAbs_Line) {
1082         if ((Abs(curv.FirstParameter()) >= 1E6) ||
1083             (Abs(curv.LastParameter()) >= 1E6))
1084           aTypeName = "Line";
1085         else
1086           aTypeName = "Edge" ;
1087       } else if (curv.GetType() == GeomAbs_Circle) {
1088         if (curv.IsClosed())
1089           aTypeName = "Circle";
1090         else
1091           aTypeName = "Arc";
1092       } else {
1093         aTypeName = "Edge";
1094       }
1095     }
1096     break;
1097   case TopAbs_VERTEX:
1098     aTypeName = "Vertex";
1099     break;
1100   case TopAbs_SHAPE:
1101     aTypeName = "Shape";
1102     break;
1103   default:
1104     aTypeName = "Shape of unknown type";
1105   }
1106
1107   return aTypeName;
1108 }
1109
1110
1111 //=============================================================================
1112 /*!
1113  *  NumberOfFaces
1114  */
1115 //=============================================================================
1116 Standard_Integer GEOMImpl_IShapesOperations::NumberOfFaces (Handle(GEOM_Object) theShape)
1117 {
1118   SetErrorCode(KO);
1119
1120   Standard_Integer nb = 0;
1121
1122   if (theShape.IsNull()) return -1;
1123   TopoDS_Shape aShape = theShape->GetValue();
1124   if (aShape.IsNull()) return -1;
1125
1126   TopTools_MapOfShape mapShape;
1127
1128   TopExp_Explorer exp (aShape, TopAbs_FACE);
1129   for (; exp.More(); exp.Next())
1130     if (mapShape.Add(exp.Current()))
1131       nb++;
1132
1133   SetErrorCode(OK);
1134   return nb;
1135 }
1136
1137 //=============================================================================
1138 /*!
1139  *  NumberOfEdges
1140  */
1141 //=============================================================================
1142 Standard_Integer GEOMImpl_IShapesOperations::NumberOfEdges (Handle(GEOM_Object) theShape)
1143 {
1144   SetErrorCode(KO);
1145
1146   Standard_Integer nb = 0;
1147
1148   if (theShape.IsNull()) return -1;
1149   TopoDS_Shape aShape = theShape->GetValue();
1150   if (aShape.IsNull()) return -1;
1151
1152   TopTools_MapOfShape mapShape;
1153
1154   TopExp_Explorer exp (aShape, TopAbs_EDGE);
1155   for (; exp.More(); exp.Next())
1156     if (mapShape.Add(exp.Current()))
1157       nb++;
1158
1159   SetErrorCode(OK);
1160   return nb;
1161 }
1162
1163 //=============================================================================
1164 /*!
1165  *  ReverseShape
1166  */
1167 //=============================================================================
1168 Handle(GEOM_Object) GEOMImpl_IShapesOperations::ReverseShape(Handle(GEOM_Object) theShape)
1169 {
1170   SetErrorCode(KO);
1171
1172   if (theShape.IsNull()) return NULL;
1173
1174   //Add a new reversed object
1175   Handle(GEOM_Object) aReversed = GetEngine()->AddObject(GetDocID(), theShape->GetType());
1176
1177   //Add a new Revese function
1178   Handle(GEOM_Function) aFunction;
1179   aFunction = aReversed->AddFunction(GEOMImpl_ShapeDriver::GetID(), REVERSE_ORIENTATION);
1180   if (aFunction.IsNull()) return NULL;
1181
1182   //Check if the function is set correctly
1183   if (aFunction->GetDriverGUID() != GEOMImpl_ShapeDriver::GetID()) return NULL;
1184
1185   GEOMImpl_IShapes aSI (aFunction);
1186
1187   Handle(GEOM_Function) aRefShape = theShape->GetLastFunction();
1188   if (aRefShape.IsNull()) return NULL;
1189
1190   aSI.SetBase(aRefShape);
1191
1192   //Compute the sub-shape value
1193   try {
1194 #if (OCC_VERSION_MAJOR << 16 | OCC_VERSION_MINOR << 8 | OCC_VERSION_MAINTENANCE) > 0x060100
1195     OCC_CATCH_SIGNALS;
1196 #endif
1197     if (!GetSolver()->ComputeFunction(aFunction)) {
1198       SetErrorCode("Shape driver failed to reverse shape");
1199       return NULL;
1200     }
1201   }
1202   catch (Standard_Failure) {
1203     Handle(Standard_Failure) aFail = Standard_Failure::Caught();
1204     SetErrorCode(aFail->GetMessageString());
1205     return NULL;
1206   }
1207
1208   //Make a Python command
1209   GEOM::TPythonDump(aFunction) << aReversed
1210     << " = geompy.ChangeOrientation(" << theShape << ")";
1211
1212   SetErrorCode(OK);
1213   return aReversed;
1214 }
1215
1216 //=============================================================================
1217 /*!
1218  *  GetFreeFacesIDs
1219  */
1220 //=============================================================================
1221 Handle(TColStd_HSequenceOfInteger) GEOMImpl_IShapesOperations::GetFreeFacesIDs
1222                                                  (Handle(GEOM_Object) theShape)
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(TColStd_HSequenceOfInteger) aSeq = new TColStd_HSequenceOfInteger;
1231
1232   TopTools_IndexedDataMapOfShapeListOfShape mapFaceBlocks;
1233   GEOMImpl_Block6Explorer::MapShapesAndAncestors
1234     (aShape, TopAbs_FACE, TopAbs_SOLID, mapFaceBlocks);
1235
1236   Standard_Integer ind = 1, nbFaces = mapFaceBlocks.Extent();
1237
1238   if (nbFaces == 0) {
1239     SetErrorCode("The given shape has no faces");
1240     return aSeq;
1241   }
1242
1243   TopTools_IndexedMapOfShape anIndices;
1244   TopExp::MapShapes(aShape, anIndices);
1245
1246   Standard_Integer id;
1247   for (; ind <= nbFaces; ind++) {
1248     if (mapFaceBlocks.FindFromIndex(ind).Extent() != 2) {
1249       id = anIndices.FindIndex(mapFaceBlocks.FindKey(ind));
1250       aSeq->Append(id);
1251     }
1252   }
1253
1254   //The explode doesn't change object so no new function is required.
1255   Handle(GEOM_Function) aFunction = theShape->GetLastFunction();
1256
1257   //Make a Python command
1258   GEOM::TPythonDump(aFunction, /*append=*/true)
1259     << "listFreeFacesIDs = geompy.GetFreeFacesIDs(" << theShape << ")";
1260
1261   SetErrorCode(OK);
1262   return aSeq;
1263 }
1264
1265 //=======================================================================
1266 //function : GetSharedShapes
1267 //purpose  :
1268 //=======================================================================
1269
1270 Handle(TColStd_HSequenceOfTransient) GEOMImpl_IShapesOperations::GetSharedShapes
1271                                                 (Handle(GEOM_Object)    theShape1,
1272                                                  Handle(GEOM_Object)    theShape2,
1273                                                  const Standard_Integer theShapeType)
1274 {
1275   SetErrorCode(KO);
1276
1277   if (theShape1.IsNull() || theShape2.IsNull()) return NULL;
1278
1279   TopoDS_Shape aShape1 = theShape1->GetValue();
1280   TopoDS_Shape aShape2 = theShape2->GetValue();
1281
1282   if (aShape1.IsNull() || aShape2.IsNull()) return NULL;
1283
1284   TopTools_IndexedMapOfShape anIndices;
1285   TopExp::MapShapes(aShape1, anIndices);
1286   Handle(TColStd_HArray1OfInteger) anArray;
1287
1288   TopTools_IndexedMapOfShape mapShape1;
1289   TopExp::MapShapes(aShape1, TopAbs_ShapeEnum(theShapeType), mapShape1);
1290
1291   Handle(GEOM_Object) anObj;
1292   Handle(TColStd_HSequenceOfTransient) aSeq = new TColStd_HSequenceOfTransient;
1293   TCollection_AsciiString anAsciiList, anEntry;
1294
1295   TopTools_MapOfShape mapShape2;
1296   TopExp_Explorer exp (aShape2, TopAbs_ShapeEnum(theShapeType));
1297   for (; exp.More(); exp.Next()) {
1298     TopoDS_Shape aSS = exp.Current();
1299     if (mapShape2.Add(aSS) && mapShape1.Contains(aSS)) {
1300       anArray = new TColStd_HArray1OfInteger(1,1);
1301       anArray->SetValue(1, anIndices.FindIndex(aSS));
1302       anObj = GetEngine()->AddSubShape(theShape1, anArray);
1303       aSeq->Append(anObj);
1304
1305       // for python command
1306       TDF_Tool::Entry(anObj->GetEntry(), anEntry);
1307       anAsciiList += anEntry;
1308       anAsciiList += ",";
1309     }
1310   }
1311
1312   if (aSeq->IsEmpty()) {
1313     SetErrorCode("The given shapes have no shared sub-shapes of the requested type");
1314     return aSeq;
1315   }
1316
1317   //Make a Python command
1318   anAsciiList.Trunc(anAsciiList.Length() - 1);
1319
1320   Handle(GEOM_Function) aFunction = anObj->GetLastFunction();
1321
1322   GEOM::TPythonDump(aFunction) << "[" << anAsciiList.ToCString()
1323     << "] = geompy.GetSharedShapes(" << theShape1 << ", "
1324       << theShape2 << ", " << TopAbs_ShapeEnum(theShapeType) << ")";
1325
1326   SetErrorCode(OK);
1327   return aSeq;
1328 }
1329
1330 //=============================================================================
1331 /*!
1332  *
1333  */
1334 //=============================================================================
1335 static GEOM::TPythonDump& operator<< (GEOM::TPythonDump&   theDump,
1336                                       const GEOMAlgo_State theState)
1337 {
1338   switch (theState) {
1339   case GEOMAlgo_ST_IN:
1340     theDump << "geompy.GEOM.ST_IN";
1341     break;
1342   case GEOMAlgo_ST_OUT:
1343     theDump << "geompy.GEOM.ST_OUT";
1344     break;
1345   case GEOMAlgo_ST_ON:
1346     theDump << "geompy.GEOM.ST_ON";
1347     break;
1348   case GEOMAlgo_ST_ONIN:
1349     theDump << "geompy.GEOM.ST_ONIN";
1350     break;
1351   case GEOMAlgo_ST_ONOUT:
1352     theDump << "geompy.GEOM.ST_ONOUT";
1353     break;
1354   default:
1355     theDump << "geompy.GEOM.ST_UNKNOWN";
1356     break;
1357   }
1358   return theDump;
1359 }
1360
1361 //=======================================================================
1362 //function : checkTypeShapesOn
1363 /*!
1364  * \brief Checks if theShapeType parameter of GetShapesOnXXX() is OK
1365  * \param theShapeType - the shape type to check
1366  * \retval bool  - result of the check
1367  */
1368 //=======================================================================
1369
1370 bool GEOMImpl_IShapesOperations::checkTypeShapesOn(const Standard_Integer theShapeType)
1371 {
1372   if (theShapeType != TopAbs_VERTEX &&
1373       theShapeType != TopAbs_EDGE &&
1374       theShapeType != TopAbs_FACE &&
1375       theShapeType != TopAbs_SOLID) {
1376     SetErrorCode("Only solids, vertices, edges or faces can be found by this method");
1377     return false;
1378   }
1379   return true;
1380 }
1381
1382 //=======================================================================
1383 //function : makePlane
1384   /*!
1385    * \brief Creates Geom_Plane
1386     * \param theAx1 - shape object defining plane parameters
1387     * \retval Handle(Geom_Surface) - resulting surface
1388    */
1389 //=======================================================================
1390
1391 Handle(Geom_Surface) GEOMImpl_IShapesOperations::makePlane(const TopoDS_Shape& anAx1)
1392 {
1393   if (anAx1.ShapeType() != TopAbs_EDGE) return NULL;
1394   TopoDS_Edge anEdge = TopoDS::Edge(anAx1);
1395   TopoDS_Vertex V1, V2;
1396   TopExp::Vertices(anEdge, V1, V2, Standard_True);
1397   if (V1.IsNull() || V2.IsNull()) {
1398     SetErrorCode("Bad edge given for the plane normal vector");
1399     return NULL;
1400   }
1401   gp_Pnt aLoc = BRep_Tool::Pnt(V1);
1402   gp_Vec aVec (aLoc, BRep_Tool::Pnt(V2));
1403   if (aVec.Magnitude() < Precision::Confusion()) {
1404     SetErrorCode("Vector with null magnitude given");
1405     return NULL;
1406   }
1407   return new Geom_Plane(aLoc, aVec);
1408 }
1409
1410 //=======================================================================
1411 //function : makeCylinder
1412   /*!
1413    * \brief Creates Geom_CylindricalSurface
1414     * \param theAx1 - edge defining cylinder axis
1415     * \param theRadius - cylinder radius
1416     * \retval Handle(Geom_Surface) - resulting surface
1417    */
1418 //=======================================================================
1419
1420 Handle(Geom_Surface) GEOMImpl_IShapesOperations::makeCylinder(const TopoDS_Shape& anAxis,
1421                                                               const Standard_Real theRadius)
1422 {
1423   //Axis of the cylinder
1424   if (anAxis.ShapeType() != TopAbs_EDGE) {
1425     SetErrorCode("Not an edge given for the axis");
1426     return NULL;
1427   }
1428   TopoDS_Edge anEdge = TopoDS::Edge(anAxis);
1429   TopoDS_Vertex V1, V2;
1430   TopExp::Vertices(anEdge, V1, V2, Standard_True);
1431   if (V1.IsNull() || V2.IsNull()) {
1432     SetErrorCode("Bad edge given for the axis");
1433     return NULL;
1434   }
1435   gp_Pnt aLoc = BRep_Tool::Pnt(V1);
1436   gp_Vec aVec (aLoc, BRep_Tool::Pnt(V2));
1437   if (aVec.Magnitude() < Precision::Confusion()) {
1438     SetErrorCode("Vector with null magnitude given");
1439     return NULL;
1440   }
1441
1442   gp_Ax3 anAx3 (aLoc, aVec);
1443   return new Geom_CylindricalSurface(anAx3, theRadius);
1444 }
1445
1446
1447 //=======================================================================
1448 //function : getShapesOnBoxIDs
1449   /*!
1450    * \brief Find IDs of subshapes complying with given status about surface
1451     * \param theBox - the box to check state of subshapes against
1452     * \param theShape - the shape to explore
1453     * \param theShapeType - type of subshape of theShape
1454     * \param theState - required state
1455     * \retval Handle(TColStd_HSequenceOfInteger) - IDs of found subshapes
1456    */
1457 //=======================================================================
1458
1459 Handle(TColStd_HSequenceOfInteger)
1460   GEOMImpl_IShapesOperations::getShapesOnBoxIDs(const Handle(GEOM_Object)& theBox,
1461                                                 const Handle(GEOM_Object)& theShape,
1462                                                 const Standard_Integer theShapeType,
1463                                                 GEOMAlgo_State theState)
1464 {
1465   Handle(TColStd_HSequenceOfInteger) aSeqOfIDs;
1466
1467   TopoDS_Shape aBox = theBox->GetValue();
1468   TopoDS_Shape aShape = theShape->GetValue();
1469
1470   // Check presence of triangulation, build if need
1471   if (!CheckTriangulation(aShape)) {
1472     SetErrorCode("Cannot build triangulation on the shape");
1473     return aSeqOfIDs;
1474   }
1475
1476   // Call algo
1477   GEOMAlgo_FinderShapeOn2 aFinder;
1478   Standard_Real aTol = 0.0001; // default value
1479
1480   Handle(GEOMAlgo_ClsfBox) aClsfBox = new GEOMAlgo_ClsfBox;
1481   aClsfBox->SetBox(aBox);
1482
1483   aFinder.SetShape(aShape);
1484   aFinder.SetTolerance(aTol);
1485   aFinder.SetClsf(aClsfBox);
1486   aFinder.SetShapeType( (TopAbs_ShapeEnum)theShapeType );
1487   aFinder.SetState(theState);
1488   aFinder.Perform();
1489
1490   // Interprete results
1491   Standard_Integer iErr = aFinder.ErrorStatus();
1492   // the detailed description of error codes is in GEOMAlgo_FinderShapeOn1.cxx
1493   if (iErr) {
1494     MESSAGE(" iErr : " << iErr);
1495     TCollection_AsciiString aMsg (" iErr : ");
1496     aMsg += TCollection_AsciiString(iErr);
1497     SetErrorCode(aMsg);
1498     return aSeqOfIDs;
1499   }
1500   Standard_Integer iWrn = aFinder.WarningStatus();
1501   // the detailed description of warning codes is in GEOMAlgo_FinderShapeOn1.cxx
1502   if (iWrn) {
1503     MESSAGE(" *** iWrn : " << iWrn);
1504   }
1505
1506   const TopTools_ListOfShape& listSS = aFinder.Shapes(); // the result
1507
1508   if (listSS.Extent() < 1) {
1509     //SetErrorCode("Not a single sub-shape of the requested type found on the given surface");
1510     SetErrorCode(NOT_FOUND_ANY); // NPAL18017
1511     return aSeqOfIDs;
1512   }
1513
1514   // Fill sequence of object IDs
1515   aSeqOfIDs = new TColStd_HSequenceOfInteger;
1516
1517   TopTools_IndexedMapOfShape anIndices;
1518   TopExp::MapShapes(aShape, anIndices);
1519
1520   TopTools_ListIteratorOfListOfShape itSub (listSS);
1521   for (int index = 1; itSub.More(); itSub.Next(), ++index) {
1522     int id = anIndices.FindIndex(itSub.Value());
1523     aSeqOfIDs->Append(id);
1524   }
1525
1526   return aSeqOfIDs;
1527 }
1528
1529
1530 //=======================================================================
1531 //function : GetShapesOnBoxIDs
1532 /*!
1533    * \brief Find subshapes complying with given status about surface
1534     * \param theBox - the box to check state of subshapes against
1535     * \param theShape - the shape to explore
1536     * \param theShapeType - type of subshape of theShape
1537     * \param theState - required state
1538     * \retval Handle(TColStd_HSequenceOfInteger) - IDs of found subshapes
1539  */
1540 //=======================================================================
1541
1542 Handle(TColStd_HSequenceOfInteger)
1543     GEOMImpl_IShapesOperations::GetShapesOnBoxIDs(const Handle(GEOM_Object)& theBox,
1544                                                   const Handle(GEOM_Object)& theShape,
1545                                                   const Standard_Integer theShapeType,
1546                                                   GEOMAlgo_State theState)
1547 {
1548   // Find subshapes ids
1549   Handle(TColStd_HSequenceOfInteger) aSeqOfIDs =
1550     getShapesOnBoxIDs (theBox, theShape, theShapeType, theState);
1551   if ( aSeqOfIDs.IsNull()  || aSeqOfIDs->Length() == 0 )
1552     return NULL;
1553
1554   // The GetShapesOnBox() doesn't change object so no new function is required.
1555   Handle(GEOM_Function) aFunction = GEOM::GetCreatedLast(theShape,theBox)->GetLastFunction();
1556
1557   // Make a Python command
1558   GEOM::TPythonDump(aFunction)
1559     << "listShapesOnBoxIDs = geompy.GetShapesOnBoxIDs("
1560     << theBox << ", "
1561     << theShape << ", "
1562     << TopAbs_ShapeEnum(theShapeType) << ", "
1563     << theState << ")";
1564
1565   SetErrorCode(OK);
1566   return aSeqOfIDs;
1567 }
1568
1569 //=======================================================================
1570 //function : GetShapesOnBox
1571 /*!
1572    * \brief Find subshapes complying with given status about surface
1573     * \param theBox - the box to check state of subshapes against
1574     * \param theShape - the shape to explore
1575     * \param theShapeType - type of subshape of theShape
1576     * \param theState - required state
1577     * \retval Handle(TColStd_HSequenceOfTransient) - found subshapes
1578  */
1579 //=======================================================================
1580
1581 Handle(TColStd_HSequenceOfTransient)
1582     GEOMImpl_IShapesOperations::GetShapesOnBox(const Handle(GEOM_Object)& theBox,
1583                                                const Handle(GEOM_Object)&  theShape,
1584                                                const Standard_Integer theShapeType,
1585                                                GEOMAlgo_State theState)
1586 {
1587   // Find subshapes ids
1588   Handle(TColStd_HSequenceOfInteger) aSeqOfIDs =
1589     getShapesOnBoxIDs (theBox, theShape, theShapeType, theState);
1590   if ( aSeqOfIDs.IsNull()  || aSeqOfIDs->Length() == 0 )
1591     return NULL;
1592
1593   // Find objects by indices
1594   TCollection_AsciiString anAsciiList;
1595   Handle(TColStd_HSequenceOfTransient) aSeq;
1596   aSeq = getObjectsShapesOn( theShape, aSeqOfIDs, anAsciiList );
1597   if ( aSeq.IsNull() || aSeq->IsEmpty() )
1598     return NULL;
1599
1600   // Make a Python command
1601
1602   Handle(GEOM_Object) anObj = Handle(GEOM_Object)::DownCast( aSeq->Value( 1 ));
1603   Handle(GEOM_Function) aFunction = anObj->GetLastFunction();
1604
1605   GEOM::TPythonDump(aFunction)
1606     << "[" << anAsciiList.ToCString() << "] = geompy.GetShapesOnBox("
1607     << theBox << ", "
1608     << theShape << ", "
1609     << TopAbs_ShapeEnum(theShapeType) << ", "
1610     << theState << ")";
1611
1612   SetErrorCode(OK);
1613   return aSeq;
1614 }
1615
1616
1617 //=======================================================================
1618 //function : getShapesOnShapeIDs
1619 /*!
1620  * \brief Find IDs of subshapes complying with given status about surface
1621  * \param theCheckShape - the shape to check state of subshapes against
1622  * \param theShape - the shape to explore
1623  * \param theShapeType - type of subshape of theShape
1624  * \param theState - required state
1625  * \retval Handle(TColStd_HSequenceOfInteger) - IDs of found subshapes
1626  */
1627 //=======================================================================
1628
1629 Handle(TColStd_HSequenceOfInteger) 
1630   GEOMImpl_IShapesOperations::getShapesOnShapeIDs
1631                                  (const Handle(GEOM_Object)& theCheckShape,
1632                                   const Handle(GEOM_Object)& theShape,
1633                                   const Standard_Integer theShapeType,
1634                                   GEOMAlgo_State theState)
1635 {
1636   Handle(TColStd_HSequenceOfInteger) aSeqOfIDs;
1637
1638   TopoDS_Shape aCheckShape = theCheckShape->GetValue();
1639   TopoDS_Shape aShape = theShape->GetValue();
1640   TopTools_ListOfShape res;
1641
1642   // Check presence of triangulation, build if need
1643   if (!CheckTriangulation(aShape)) {
1644     SetErrorCode("Cannot build triangulation on the shape");
1645     return aSeqOfIDs;
1646   }
1647
1648   // Call algo
1649   GEOMAlgo_FinderShapeOn2 aFinder;
1650   Standard_Real aTol = 0.0001; // default value
1651
1652   Handle(GEOMAlgo_ClsfSolid) aClsfSolid = new GEOMAlgo_ClsfSolid;
1653   aClsfSolid->SetShape(aCheckShape);
1654
1655   aFinder.SetShape(aShape);
1656   aFinder.SetTolerance(aTol);
1657   aFinder.SetClsf(aClsfSolid);
1658   aFinder.SetShapeType( (TopAbs_ShapeEnum)theShapeType );
1659   aFinder.SetState(theState);
1660   aFinder.Perform();
1661
1662   // Interprete results
1663   Standard_Integer iErr = aFinder.ErrorStatus();
1664   // the detailed description of error codes is in GEOMAlgo_FinderShapeOn1.cxx
1665   if (iErr) {
1666     MESSAGE(" iErr : " << iErr);
1667     TCollection_AsciiString aMsg (" iErr : ");
1668     aMsg += TCollection_AsciiString(iErr);
1669     SetErrorCode(aMsg);
1670     return aSeqOfIDs;
1671   }
1672   Standard_Integer iWrn = aFinder.WarningStatus();
1673   // the detailed description of warning codes is in GEOMAlgo_FinderShapeOn1.cxx
1674   if (iWrn) {
1675     MESSAGE(" *** iWrn : " << iWrn);
1676   }
1677
1678   const TopTools_ListOfShape& listSS = aFinder.Shapes(); // the result
1679
1680   if (listSS.Extent() < 1) {
1681     //SetErrorCode("Not a single sub-shape of the requested type found on the given surface");
1682     SetErrorCode(NOT_FOUND_ANY); // NPAL18017
1683   }
1684
1685   // Fill sequence of object IDs
1686   aSeqOfIDs = new TColStd_HSequenceOfInteger;
1687
1688   TopTools_IndexedMapOfShape anIndices;
1689   TopExp::MapShapes(aShape, anIndices);
1690
1691   TopTools_ListIteratorOfListOfShape itSub (listSS);
1692   for (int index = 1; itSub.More(); itSub.Next(), ++index) {
1693     int id = anIndices.FindIndex(itSub.Value());
1694     aSeqOfIDs->Append(id);
1695   }
1696
1697   return aSeqOfIDs;
1698 }
1699
1700
1701 //=======================================================================
1702 //function : GetShapesOnShapeIDs
1703 /*!
1704  * \brief Find subshapes complying with given status about surface
1705  * \param theCheckShape - the shape to check state of subshapes against
1706  * \param theShape - the shape to explore
1707  * \param theShapeType - type of subshape of theShape
1708  * \param theState - required state
1709  * \retval Handle(TColStd_HSequenceOfInteger) - IDs of found subshapes
1710  */
1711 //=======================================================================
1712
1713 Handle(TColStd_HSequenceOfInteger)
1714     GEOMImpl_IShapesOperations::GetShapesOnShapeIDs
1715                             (const Handle(GEOM_Object)& theCheckShape,
1716                              const Handle(GEOM_Object)& theShape,
1717                              const Standard_Integer theShapeType,
1718                              GEOMAlgo_State theState)
1719 {
1720   Handle(TColStd_HSequenceOfInteger) aSeqOfIDs =
1721     getShapesOnShapeIDs (theCheckShape, theShape, theShapeType, theState);
1722
1723   if ( aSeqOfIDs.IsNull()  || aSeqOfIDs->Length() == 0 )
1724     return NULL;
1725
1726   // The GetShapesOnShape() doesn't change object so no new function is required.
1727   Handle(GEOM_Function) aFunction =
1728     GEOM::GetCreatedLast(theShape,theCheckShape)->GetLastFunction();
1729
1730   // Make a Python command
1731   GEOM::TPythonDump(aFunction)
1732     << "listShapesOnBoxIDs = geompy.GetShapesOnShapeIDs("
1733     << theCheckShape << ", "
1734     << theShape << ", "
1735     << TopAbs_ShapeEnum(theShapeType) << ", "
1736     << theState << ")";
1737
1738   SetErrorCode(OK);
1739   return aSeqOfIDs;
1740 }
1741
1742
1743 //=======================================================================
1744 //function : GetShapesOnShape
1745 /*!
1746  * \brief Find subshapes complying with given status about surface
1747  * \param theCheckShape - the shape to check state of subshapes against
1748  * \param theShape - the shape to explore
1749  * \param theShapeType - type of subshape of theShape
1750  * \param theState - required state
1751  * \retval Handle(TColStd_HSequenceOfTransient) - found subshapes
1752  */
1753 //=======================================================================
1754
1755 Handle(TColStd_HSequenceOfTransient)
1756   GEOMImpl_IShapesOperations::GetShapesOnShape
1757                              (const Handle(GEOM_Object)& theCheckShape,
1758                               const Handle(GEOM_Object)&  theShape,
1759                               const Standard_Integer theShapeType,
1760                               GEOMAlgo_State theState)
1761 {
1762   Handle(TColStd_HSequenceOfInteger) aSeqOfIDs =
1763     getShapesOnShapeIDs (theCheckShape, theShape, theShapeType, theState);
1764   if ( aSeqOfIDs.IsNull()  || aSeqOfIDs->Length() == 0 )
1765     return NULL;
1766
1767   // Find objects by indices
1768   TCollection_AsciiString anAsciiList;
1769   Handle(TColStd_HSequenceOfTransient) aSeq;
1770   aSeq = getObjectsShapesOn( theShape, aSeqOfIDs, anAsciiList );
1771
1772   if ( aSeq.IsNull() || aSeq->IsEmpty() )
1773     return NULL;
1774
1775   // Make a Python command
1776
1777   Handle(GEOM_Object) anObj = Handle(GEOM_Object)::DownCast( aSeq->Value( 1 ));
1778   Handle(GEOM_Function) aFunction = anObj->GetLastFunction();
1779
1780   GEOM::TPythonDump(aFunction)
1781     << "[" << anAsciiList.ToCString() << "] = geompy.GetShapesOnShape("
1782     << theCheckShape << ", "
1783     << theShape << ", "
1784     << TopAbs_ShapeEnum(theShapeType) << ", "
1785     << theState << ")";
1786
1787
1788   SetErrorCode(OK);
1789   return aSeq;
1790 }
1791
1792
1793 //=======================================================================
1794 //function : GetShapesOnShapeAsCompound
1795 //=======================================================================
1796
1797 Handle(GEOM_Object) GEOMImpl_IShapesOperations::GetShapesOnShapeAsCompound
1798                              (const Handle(GEOM_Object)& theCheckShape,
1799                               const Handle(GEOM_Object)&  theShape,
1800                               const Standard_Integer theShapeType,
1801                               GEOMAlgo_State theState)
1802 {
1803   Handle(TColStd_HSequenceOfInteger) aSeqOfIDs =
1804     getShapesOnShapeIDs (theCheckShape, theShape, theShapeType, theState);
1805
1806   if ( aSeqOfIDs.IsNull()  || aSeqOfIDs->Length() == 0 )
1807     return NULL;
1808
1809   // Find objects by indices
1810   TCollection_AsciiString anAsciiList;
1811   Handle(TColStd_HSequenceOfTransient) aSeq;
1812   aSeq = getObjectsShapesOn( theShape, aSeqOfIDs, anAsciiList );
1813
1814   if ( aSeq.IsNull() || aSeq->IsEmpty() )
1815     return NULL;
1816
1817   TopoDS_Compound aCompound;
1818   BRep_Builder B;
1819   B.MakeCompound(aCompound);
1820   int i = 1;
1821   for(; i<=aSeq->Length(); i++) {
1822     Handle(GEOM_Object) anObj = Handle(GEOM_Object)::DownCast(aSeq->Value(i));
1823     TopoDS_Shape aShape_i = anObj->GetValue();
1824     B.Add(aCompound,aShape_i);
1825   }
1826
1827   //Add a new result object
1828   Handle(GEOM_Object) aRes = GetEngine()->AddObject(GetDocID(), GEOM_SHAPES_ON_SHAPE);
1829   Handle(GEOM_Function) aFunction =
1830     aRes->AddFunction(GEOMImpl_ShapeDriver::GetID(), SHAPES_ON_SHAPE);
1831   aFunction->SetValue(aCompound);
1832
1833   GEOM::TPythonDump(aFunction)
1834     << aRes << " = geompy.GetShapesOnShapeAsCompound("
1835     << theCheckShape << ", "
1836     << theShape << ", "
1837     << TopAbs_ShapeEnum(theShapeType) << ", "
1838     << theState << ")";
1839
1840   SetErrorCode(OK);
1841
1842   return aRes;
1843 }
1844
1845
1846 //=======================================================================
1847 //function : getShapesOnSurfaceIDs
1848   /*!
1849    * \brief Find IDs of subshapes complying with given status about surface
1850     * \param theSurface - the surface to check state of subshapes against
1851     * \param theShape - the shape to explore
1852     * \param theShapeType - type of subshape of theShape
1853     * \param theState - required state
1854     * \retval Handle(TColStd_HSequenceOfInteger) - IDs of found subshapes
1855    */
1856 //=======================================================================
1857
1858 Handle(TColStd_HSequenceOfInteger)
1859   GEOMImpl_IShapesOperations::getShapesOnSurfaceIDs(const Handle(Geom_Surface)& theSurface,
1860                                                     const TopoDS_Shape&         theShape,
1861                                                     TopAbs_ShapeEnum            theShapeType,
1862                                                     GEOMAlgo_State              theState)
1863 {
1864   Handle(TColStd_HSequenceOfInteger) aSeqOfIDs;
1865
1866   // Check presence of triangulation, build if need
1867   if (!CheckTriangulation(theShape)) {
1868     SetErrorCode("Cannot build triangulation on the shape");
1869     return aSeqOfIDs;
1870   }
1871
1872   // Call algo
1873   GEOMAlgo_FinderShapeOn1 aFinder;
1874   Standard_Real aTol = 0.0001; // default value
1875
1876   aFinder.SetShape(theShape);
1877   aFinder.SetTolerance(aTol);
1878   aFinder.SetSurface(theSurface);
1879   aFinder.SetShapeType(theShapeType);
1880   aFinder.SetState(theState);
1881
1882   // Sets the minimal number of inner points for the faces that do not have own
1883   // inner points at all (for e.g. rectangular planar faces have just 2 triangles).
1884   // Default value=3
1885   aFinder.SetNbPntsMin(3);
1886   // Sets the maximal number of inner points for edges or faces.
1887   // It is usefull for the cases when this number is very big (e.g =2000) to improve
1888   // the performance. If this value =0, all inner points will be taken into account.
1889   // Default value=0
1890   aFinder.SetNbPntsMax(100);
1891
1892   aFinder.Perform();
1893
1894   // Interprete results
1895   Standard_Integer iErr = aFinder.ErrorStatus();
1896   // the detailed description of error codes is in GEOMAlgo_FinderShapeOn1.cxx
1897   if (iErr) {
1898     MESSAGE(" iErr : " << iErr);
1899     TCollection_AsciiString aMsg (" iErr : ");
1900     aMsg += TCollection_AsciiString(iErr);
1901     SetErrorCode(aMsg);
1902     return aSeqOfIDs;
1903   }
1904   Standard_Integer iWrn = aFinder.WarningStatus();
1905   // the detailed description of warning codes is in GEOMAlgo_FinderShapeOn1.cxx
1906   if (iWrn) {
1907     MESSAGE(" *** iWrn : " << iWrn);
1908   }
1909
1910   const TopTools_ListOfShape& listSS = aFinder.Shapes(); // the result
1911
1912   if (listSS.Extent() < 1) {
1913     //SetErrorCode("Not a single sub-shape of the requested type found on the given surface");
1914     SetErrorCode(NOT_FOUND_ANY); // NPAL18017
1915     return aSeqOfIDs;
1916   }
1917
1918   // Fill sequence of object IDs
1919   aSeqOfIDs = new TColStd_HSequenceOfInteger;
1920
1921   TopTools_IndexedMapOfShape anIndices;
1922   TopExp::MapShapes(theShape, anIndices);
1923
1924   TopTools_ListIteratorOfListOfShape itSub (listSS);
1925   for (int index = 1; itSub.More(); itSub.Next(), ++index) {
1926     int id = anIndices.FindIndex(itSub.Value());
1927     aSeqOfIDs->Append(id);
1928   }
1929
1930   return aSeqOfIDs;
1931 }
1932
1933 //=======================================================================
1934 //function : getObjectsShapesOn
1935 /*!
1936  * \brief Find shape objects and their entries by their ids
1937  * \param theShapeIDs - incoming shape ids
1938  * \param theShapeEntries - outgoing entries like "entry1, entry2, ..."
1939  * \retval Handle(TColStd_HSequenceOfTransient) - found shape objects
1940  */
1941 //=======================================================================
1942
1943 Handle(TColStd_HSequenceOfTransient) GEOMImpl_IShapesOperations::
1944  getObjectsShapesOn(const Handle(GEOM_Object)&                theShape,
1945                     const Handle(TColStd_HSequenceOfInteger)& theShapeIDs,
1946                     TCollection_AsciiString &                 theShapeEntries)
1947 {
1948   Handle(TColStd_HSequenceOfTransient) aSeq;
1949
1950   if ( !theShapeIDs.IsNull() && theShapeIDs->Length() > 0 )
1951   {
1952     aSeq = new TColStd_HSequenceOfTransient;
1953     Handle(TColStd_HArray1OfInteger) anArray = new TColStd_HArray1OfInteger(1,1);
1954     TCollection_AsciiString anEntry;
1955     for ( int i = 1; i <= theShapeIDs->Length(); ++i )
1956     {
1957       anArray->SetValue(1, theShapeIDs->Value( i ));
1958       Handle(GEOM_Object) anObj = GetEngine()->AddSubShape(theShape, anArray);
1959       aSeq->Append( anObj );
1960
1961       TDF_Tool::Entry(anObj->GetEntry(), anEntry);
1962       if ( i != 1 ) theShapeEntries += ",";
1963       theShapeEntries += anEntry;
1964     }
1965   }
1966   return aSeq;
1967 }
1968
1969 //=======================================================================
1970 //function : getShapesOnSurface
1971 /*!
1972    * \brief Find subshapes complying with given status about surface
1973     * \param theSurface - the surface to check state of subshapes against
1974     * \param theShape - the shape to explore
1975     * \param theShapeType - type of subshape of theShape
1976     * \param theState - required state
1977     * \param theShapeEntries - outgoing entries like "entry1, entry2, ..."
1978     * \retval Handle(TColStd_HSequenceOfInteger) - IDs of found subshapes
1979  */
1980 //=======================================================================
1981
1982 Handle(TColStd_HSequenceOfTransient)
1983     GEOMImpl_IShapesOperations::getShapesOnSurface(const Handle(Geom_Surface)& theSurface,
1984                                                    const Handle(GEOM_Object)&  theShape,
1985                                                    TopAbs_ShapeEnum            theShapeType,
1986                                                    GEOMAlgo_State              theState,
1987                                                    TCollection_AsciiString &   theShapeEntries)
1988 {
1989   // Find subshapes ids
1990   Handle(TColStd_HSequenceOfInteger) aSeqOfIDs =
1991     getShapesOnSurfaceIDs (theSurface, theShape->GetValue(), theShapeType, theState);
1992   if ( aSeqOfIDs.IsNull()  || aSeqOfIDs->Length() == 0 )
1993     return NULL;
1994
1995   return getObjectsShapesOn( theShape, aSeqOfIDs, theShapeEntries );
1996 }
1997
1998 //=============================================================================
1999 /*!
2000  *  GetShapesOnPlane
2001  */
2002 //=============================================================================
2003 Handle(TColStd_HSequenceOfTransient) GEOMImpl_IShapesOperations::GetShapesOnPlane
2004                                         (const Handle(GEOM_Object)& theShape,
2005                                          const Standard_Integer     theShapeType,
2006                                          const Handle(GEOM_Object)& theAx1,
2007                                          const GEOMAlgo_State       theState)
2008 {
2009   SetErrorCode(KO);
2010
2011   if (theShape.IsNull() || theAx1.IsNull()) return NULL;
2012
2013   TopoDS_Shape aShape = theShape->GetValue();
2014   TopoDS_Shape anAx1  = theAx1->GetValue();
2015
2016   if (aShape.IsNull() || anAx1.IsNull()) return NULL;
2017
2018   TopAbs_ShapeEnum aShapeType = TopAbs_ShapeEnum(theShapeType);
2019   if ( !checkTypeShapesOn( theShapeType ))
2020     return NULL;
2021
2022   // Create plane
2023   Handle(Geom_Surface) aPlane = makePlane( anAx1 );
2024   if ( aPlane.IsNull() )
2025     return NULL;
2026
2027   // Find objects
2028   TCollection_AsciiString anAsciiList;
2029   Handle(TColStd_HSequenceOfTransient) aSeq;
2030   aSeq = getShapesOnSurface( aPlane, theShape, aShapeType, theState, anAsciiList );
2031   if ( aSeq.IsNull() || aSeq->Length() == 0 )
2032     return NULL;
2033
2034   // Make a Python command
2035
2036   Handle(GEOM_Object) anObj = Handle(GEOM_Object)::DownCast( aSeq->Value( 1 ));
2037   Handle(GEOM_Function) aFunction = anObj->GetLastFunction();
2038
2039   GEOM::TPythonDump(aFunction) << "[" << anAsciiList.ToCString()
2040     << "] = geompy.GetShapesOnPlane(" << theShape << ", "
2041       << aShapeType << ", " << theAx1 << ", " << theState << ")";
2042
2043   SetErrorCode(OK);
2044   return aSeq;
2045 }
2046
2047 //=============================================================================
2048 /*!
2049  *  GetShapesOnPlaneWithLocation
2050  */
2051 //=============================================================================
2052 Handle(TColStd_HSequenceOfTransient) GEOMImpl_IShapesOperations::GetShapesOnPlaneWithLocation
2053                                         (const Handle(GEOM_Object)& theShape,
2054                                          const Standard_Integer     theShapeType,
2055                                          const Handle(GEOM_Object)& theAx1,
2056                                          const Handle(GEOM_Object)& thePnt,
2057                                          const GEOMAlgo_State       theState)
2058 {
2059   SetErrorCode(KO);
2060
2061   if (theShape.IsNull() || theAx1.IsNull() || thePnt.IsNull()) return NULL;
2062
2063   TopoDS_Shape aShape = theShape->GetValue();
2064   TopoDS_Shape anAx1  = theAx1->GetValue();
2065   TopoDS_Shape anPnt = thePnt->GetValue();
2066
2067   if (aShape.IsNull() || anAx1.IsNull() || anPnt.IsNull()) return NULL;
2068
2069   TopAbs_ShapeEnum aShapeType = TopAbs_ShapeEnum(theShapeType);
2070   if ( !checkTypeShapesOn( theShapeType ))
2071     return NULL;
2072
2073   // Create plane
2074   if ( anAx1.ShapeType() != TopAbs_EDGE || anPnt.ShapeType() != TopAbs_VERTEX ) return NULL;
2075   TopoDS_Vertex V1, V2, V3;
2076   TopoDS_Edge anEdge = TopoDS::Edge(anAx1);
2077   TopExp::Vertices(anEdge, V1, V2, Standard_True);
2078
2079   if (V1.IsNull() || V2.IsNull()) {
2080     SetErrorCode("Bad edge given for the plane normal vector");
2081     return NULL;
2082   }
2083   V3 = TopoDS::Vertex(anPnt);
2084
2085   if(V3.IsNull()) {
2086     SetErrorCode("Bad vertex given for the plane location");
2087       return NULL;
2088   }
2089   gp_Pnt aLoc = BRep_Tool::Pnt(V3);
2090   gp_Vec aVec(BRep_Tool::Pnt(V1),BRep_Tool::Pnt(V2));
2091
2092   if (aVec.Magnitude() < Precision::Confusion()) {
2093      SetErrorCode("Vector with null magnitude given");
2094     return NULL;
2095   }
2096   Handle(Geom_Surface) aPlane = new Geom_Plane(aLoc, aVec);
2097
2098   if ( aPlane.IsNull() )
2099     return NULL;
2100
2101   // Find objects
2102   TCollection_AsciiString anAsciiList;
2103   Handle(TColStd_HSequenceOfTransient) aSeq;
2104   aSeq = getShapesOnSurface( aPlane, theShape, aShapeType, theState, anAsciiList );
2105   if ( aSeq.IsNull() || aSeq->Length() == 0 )
2106     return NULL;
2107
2108   // Make a Python command
2109
2110   Handle(GEOM_Object) anObj = Handle(GEOM_Object)::DownCast( aSeq->Value( 1 ));
2111   Handle(GEOM_Function) aFunction = anObj->GetLastFunction();
2112
2113   GEOM::TPythonDump(aFunction) << "[" << anAsciiList.ToCString()
2114     << "] = geompy.GetShapesOnPlaneWithLocation(" << theShape << ", "
2115     << aShapeType << ", " << theAx1 << ", "<< thePnt <<", " << theState << ")";
2116
2117   SetErrorCode(OK);
2118   return aSeq;
2119 }
2120
2121 //=============================================================================
2122 /*!
2123  *  GetShapesOnCylinder
2124  */
2125 //=============================================================================
2126 Handle(TColStd_HSequenceOfTransient) GEOMImpl_IShapesOperations::GetShapesOnCylinder
2127                                           (const Handle(GEOM_Object)& theShape,
2128                                            const Standard_Integer     theShapeType,
2129                                            const Handle(GEOM_Object)& theAxis,
2130                                            const Standard_Real        theRadius,
2131                                            const GEOMAlgo_State       theState)
2132 {
2133   SetErrorCode(KO);
2134
2135   if (theShape.IsNull() || theAxis.IsNull()) return NULL;
2136
2137   TopoDS_Shape aShape = theShape->GetValue();
2138   TopoDS_Shape anAxis = theAxis->GetValue();
2139
2140   if (aShape.IsNull() || anAxis.IsNull()) return NULL;
2141
2142   TopAbs_ShapeEnum aShapeType = TopAbs_ShapeEnum(theShapeType);
2143   if ( !checkTypeShapesOn( aShapeType ))
2144     return NULL;
2145
2146   // Create a cylinder surface
2147   Handle(Geom_Surface) aCylinder = makeCylinder( anAxis, theRadius );
2148   if ( aCylinder.IsNull() )
2149     return NULL;
2150
2151   // Find objects
2152   TCollection_AsciiString anAsciiList;
2153   Handle(TColStd_HSequenceOfTransient) aSeq;
2154   aSeq = getShapesOnSurface( aCylinder, theShape, aShapeType, theState, anAsciiList );
2155   if ( aSeq.IsNull() || aSeq->Length() == 0 )
2156     return NULL;
2157
2158   // Make a Python command
2159
2160   Handle(GEOM_Object) anObj = Handle(GEOM_Object)::DownCast( aSeq->Value( 1 ));
2161   Handle(GEOM_Function) aFunction = anObj->GetLastFunction();
2162
2163   GEOM::TPythonDump(aFunction) << "[" << anAsciiList.ToCString()
2164     << "] = geompy.GetShapesOnCylinder(" << theShape << ", " << aShapeType
2165       << ", " << theAxis << ", " << theRadius << ", " << theState << ")";
2166
2167   SetErrorCode(OK);
2168   return aSeq;
2169 }
2170
2171 //=============================================================================
2172 /*!
2173  *  GetShapesOnSphere
2174  */
2175 //=============================================================================
2176 Handle(TColStd_HSequenceOfTransient) GEOMImpl_IShapesOperations::GetShapesOnSphere
2177                                           (const Handle(GEOM_Object)& theShape,
2178                                            const Standard_Integer     theShapeType,
2179                                            const Handle(GEOM_Object)& theCenter,
2180                                            const Standard_Real        theRadius,
2181                                            const GEOMAlgo_State       theState)
2182 {
2183   SetErrorCode(KO);
2184
2185   if (theShape.IsNull() || theCenter.IsNull()) return NULL;
2186
2187   TopoDS_Shape aShape  = theShape->GetValue();
2188   TopoDS_Shape aCenter = theCenter->GetValue();
2189
2190   if (aShape.IsNull() || aCenter.IsNull()) return NULL;
2191
2192   TopAbs_ShapeEnum aShapeType = TopAbs_ShapeEnum(theShapeType);
2193   if ( !checkTypeShapesOn( aShapeType ))
2194     return NULL;
2195
2196   // Center of the sphere
2197   if (aCenter.ShapeType() != TopAbs_VERTEX) return NULL;
2198   gp_Pnt aLoc = BRep_Tool::Pnt(TopoDS::Vertex(aCenter));
2199
2200   gp_Ax3 anAx3 (aLoc, gp::DZ());
2201   Handle(Geom_SphericalSurface) aSphere =
2202     new Geom_SphericalSurface(anAx3, theRadius);
2203
2204   // Find objects
2205   TCollection_AsciiString anAsciiList;
2206   Handle(TColStd_HSequenceOfTransient) aSeq;
2207   aSeq = getShapesOnSurface( aSphere, theShape, aShapeType, theState, anAsciiList );
2208   if ( aSeq.IsNull() || aSeq->Length() == 0 )
2209     return NULL;
2210
2211   // Make a Python command
2212
2213   Handle(GEOM_Object) anObj = Handle(GEOM_Object)::DownCast( aSeq->Value( 1 ));
2214   Handle(GEOM_Function) aFunction = anObj->GetLastFunction();
2215
2216   GEOM::TPythonDump(aFunction) << "[" << anAsciiList.ToCString()
2217     << "] = geompy.GetShapesOnSphere(" << theShape << ", " << aShapeType
2218       << ", " << theCenter << ", " << theRadius << ", " << theState << ")";
2219
2220   SetErrorCode(OK);
2221   return aSeq;
2222 }
2223
2224 //=============================================================================
2225 /*!
2226  *  GetShapesOnPlaneIDs
2227  */
2228 //=============================================================================
2229 Handle(TColStd_HSequenceOfInteger) GEOMImpl_IShapesOperations::GetShapesOnPlaneIDs
2230                                         (const Handle(GEOM_Object)& theShape,
2231                                          const Standard_Integer     theShapeType,
2232                                          const Handle(GEOM_Object)& theAx1,
2233                                          const GEOMAlgo_State       theState)
2234 {
2235   SetErrorCode(KO);
2236
2237   if (theShape.IsNull() || theAx1.IsNull()) return NULL;
2238
2239   TopoDS_Shape aShape = theShape->GetValue();
2240   TopoDS_Shape anAx1  = theAx1->GetValue();
2241
2242   if (aShape.IsNull() || anAx1.IsNull()) return NULL;
2243
2244   TopAbs_ShapeEnum aShapeType = TopAbs_ShapeEnum(theShapeType);
2245   if ( !checkTypeShapesOn( aShapeType ))
2246     return NULL;
2247
2248   // Create plane
2249   Handle(Geom_Surface) aPlane = makePlane( anAx1 );
2250   if ( aPlane.IsNull() )
2251     return NULL;
2252
2253   // Find object IDs
2254   Handle(TColStd_HSequenceOfInteger) aSeq;
2255   aSeq = getShapesOnSurfaceIDs( aPlane, aShape, aShapeType, theState );
2256
2257   // The GetShapesOnPlaneIDs() doesn't change object so no new function is required.
2258   Handle(GEOM_Function) aFunction = GEOM::GetCreatedLast(theShape,theAx1)->GetLastFunction();
2259
2260   // Make a Python command
2261   GEOM::TPythonDump(aFunction, /*append=*/true)
2262     << "listShapesOnPlane = geompy.GetShapesOnPlaneIDs"
2263     << "(" << theShape << "," << aShapeType << "," << theAx1 << "," << theState << ")";
2264
2265   SetErrorCode(OK);
2266   return aSeq;
2267 }
2268
2269 //=============================================================================
2270 /*!
2271  *  GetShapesOnPlaneWithLocationIDs
2272  */
2273 //=============================================================================
2274 Handle(TColStd_HSequenceOfInteger) GEOMImpl_IShapesOperations::GetShapesOnPlaneWithLocationIDs
2275                                         (const Handle(GEOM_Object)& theShape,
2276                                          const Standard_Integer     theShapeType,
2277                                          const Handle(GEOM_Object)& theAx1,
2278                                          const Handle(GEOM_Object)& thePnt,
2279                                          const GEOMAlgo_State       theState)
2280 {
2281   SetErrorCode(KO);
2282
2283   if (theShape.IsNull() || theAx1.IsNull() || thePnt.IsNull()) return NULL;
2284
2285   TopoDS_Shape aShape = theShape->GetValue();
2286   TopoDS_Shape anAx1  = theAx1->GetValue();
2287   TopoDS_Shape anPnt  = thePnt->GetValue();
2288
2289   if (aShape.IsNull() || anAx1.IsNull() || anPnt.IsNull()) return NULL;
2290
2291   TopAbs_ShapeEnum aShapeType = TopAbs_ShapeEnum(theShapeType);
2292   if ( !checkTypeShapesOn( aShapeType ))
2293     return NULL;
2294
2295   // Create plane
2296   if (anAx1.ShapeType() != TopAbs_EDGE || anPnt.ShapeType() != TopAbs_VERTEX) return NULL;
2297   TopoDS_Edge anEdge = TopoDS::Edge(anAx1);
2298   TopoDS_Vertex V1, V2, V3;
2299   TopExp::Vertices(anEdge, V1, V2, Standard_True);
2300   if (V1.IsNull() || V2.IsNull()) {
2301     SetErrorCode("Bad edge given for the plane normal vector");
2302     return NULL;
2303   }
2304   V3 = TopoDS::Vertex(anPnt);
2305   if(V3.IsNull()) {
2306     SetErrorCode("Bad vertex given for the plane location");
2307       return NULL;
2308   }
2309   gp_Pnt aLoc = BRep_Tool::Pnt(V3);
2310   gp_Vec aVec(BRep_Tool::Pnt(V1),BRep_Tool::Pnt(V2));
2311   if (aVec.Magnitude() < Precision::Confusion()) {
2312     SetErrorCode("Vector with null magnitude given");
2313     return NULL;
2314   }
2315
2316   Handle(Geom_Surface) aPlane = new Geom_Plane(aLoc, aVec);
2317   if ( aPlane.IsNull() )
2318     return NULL;
2319
2320   // Find object IDs
2321   Handle(TColStd_HSequenceOfInteger) aSeq;
2322   aSeq = getShapesOnSurfaceIDs( aPlane, aShape, aShapeType, theState );
2323
2324   // The GetShapesOnPlaneIDs() doesn't change object so no new function is required.
2325   Handle(GEOM_Function) aFunction = GEOM::GetCreatedLast(theShape,theAx1)->GetLastFunction();
2326
2327   // Make a Python command
2328   GEOM::TPythonDump(aFunction, /*append=*/true)
2329     << "listShapesOnPlane = geompy.GetShapesOnPlaneWithLocationIDs"
2330     << "(" << theShape << ", " << aShapeType << ", " << theAx1 << ", "<< thePnt << ", "  << theState << ")";
2331
2332   SetErrorCode(OK);
2333   return aSeq;
2334 }
2335
2336 //=============================================================================
2337 /*!
2338  *  GetShapesOnCylinderIDs
2339  */
2340 //=============================================================================
2341 Handle(TColStd_HSequenceOfInteger) GEOMImpl_IShapesOperations::GetShapesOnCylinderIDs
2342                                           (const Handle(GEOM_Object)& theShape,
2343                                            const Standard_Integer     theShapeType,
2344                                            const Handle(GEOM_Object)& theAxis,
2345                                            const Standard_Real        theRadius,
2346                                            const GEOMAlgo_State       theState)
2347 {
2348   SetErrorCode(KO);
2349
2350   if (theShape.IsNull() || theAxis.IsNull()) return NULL;
2351
2352   TopoDS_Shape aShape = theShape->GetValue();
2353   TopoDS_Shape anAxis = theAxis->GetValue();
2354
2355   if (aShape.IsNull() || anAxis.IsNull()) return NULL;
2356
2357   TopAbs_ShapeEnum aShapeType = TopAbs_ShapeEnum(theShapeType);
2358   if ( !checkTypeShapesOn( aShapeType ))
2359     return NULL;
2360
2361   // Create a cylinder surface
2362   Handle(Geom_Surface) aCylinder = makeCylinder( anAxis, theRadius );
2363   if ( aCylinder.IsNull() )
2364     return NULL;
2365
2366   // Find object IDs
2367   Handle(TColStd_HSequenceOfInteger) aSeq;
2368   aSeq = getShapesOnSurfaceIDs( aCylinder, aShape, aShapeType, theState );
2369
2370   // The GetShapesOnCylinder() doesn't change object so no new function is required.
2371   Handle(GEOM_Function) aFunction = GEOM::GetCreatedLast(theShape,theAxis)->GetLastFunction();
2372
2373   // Make a Python command
2374   GEOM::TPythonDump(aFunction, /*append=*/true)
2375     << "listShapesOnCylinder = geompy.GetShapesOnCylinderIDs"
2376     << "(" << theShape << ", " << aShapeType << ", " << theAxis << ", "
2377     << theRadius << ", " << theState << ")";
2378
2379   SetErrorCode(OK);
2380   return aSeq;
2381 }
2382
2383 //=============================================================================
2384 /*!
2385  *  GetShapesOnSphereIDs
2386  */
2387 //=============================================================================
2388 Handle(TColStd_HSequenceOfInteger) GEOMImpl_IShapesOperations::GetShapesOnSphereIDs
2389                                           (const Handle(GEOM_Object)& theShape,
2390                                            const Standard_Integer     theShapeType,
2391                                            const Handle(GEOM_Object)& theCenter,
2392                                            const Standard_Real        theRadius,
2393                                            const GEOMAlgo_State       theState)
2394 {
2395   SetErrorCode(KO);
2396
2397   if (theShape.IsNull() || theCenter.IsNull()) return NULL;
2398
2399   TopoDS_Shape aShape  = theShape->GetValue();
2400   TopoDS_Shape aCenter = theCenter->GetValue();
2401
2402   if (aShape.IsNull() || aCenter.IsNull()) return NULL;
2403
2404   TopAbs_ShapeEnum aShapeType = TopAbs_ShapeEnum(theShapeType);
2405   if ( !checkTypeShapesOn( aShapeType ))
2406     return NULL;
2407
2408   // Center of the sphere
2409   if (aCenter.ShapeType() != TopAbs_VERTEX) return NULL;
2410   gp_Pnt aLoc = BRep_Tool::Pnt(TopoDS::Vertex(aCenter));
2411
2412   gp_Ax3 anAx3 (aLoc, gp::DZ());
2413   Handle(Geom_SphericalSurface) aSphere =
2414     new Geom_SphericalSurface(anAx3, theRadius);
2415
2416   // Find object IDs
2417   Handle(TColStd_HSequenceOfInteger) aSeq;
2418   aSeq = getShapesOnSurfaceIDs( aSphere, aShape, aShapeType, theState );
2419
2420   // The GetShapesOnSphere() doesn't change object so no new function is required.
2421   Handle(GEOM_Function) aFunction = GEOM::GetCreatedLast(theShape,theCenter)->GetLastFunction();
2422
2423   // Make a Python command
2424   GEOM::TPythonDump(aFunction, /*append=*/true)
2425     << "listShapesOnCylinder = geompy.GetShapesOnCylinderIDs"
2426     << "(" << theShape << ", " << aShapeType << ", " << theCenter << ", "
2427     << theRadius << ", " << theState << ")";
2428
2429   SetErrorCode(OK);
2430   return aSeq;
2431 }
2432
2433 //=======================================================================
2434 //function : getShapesOnQuadrangleIDs
2435   /*!
2436    * \brief Find IDs of subshapes complying with given status about quadrangle
2437     * \param theShape - the shape to explore
2438     * \param theShapeType - type of subshape of theShape
2439     * \param theTopLeftPoint - top left quadrangle corner
2440     * \param theTopRigthPoint - top right quadrangle corner
2441     * \param theBottomLeftPoint - bottom left quadrangle corner
2442     * \param theBottomRigthPoint - bottom right quadrangle corner
2443     * \param theState - required state
2444     * \retval Handle(TColStd_HSequenceOfInteger) - IDs of found subshapes
2445    */
2446 //=======================================================================
2447
2448 Handle(TColStd_HSequenceOfInteger)
2449   GEOMImpl_IShapesOperations::getShapesOnQuadrangleIDs (const Handle(GEOM_Object)& theShape,
2450                                                         const Standard_Integer     theShapeType,
2451                                                         const Handle(GEOM_Object)& theTopLeftPoint,
2452                                                         const Handle(GEOM_Object)& theTopRigthPoint,
2453                                                         const Handle(GEOM_Object)& theBottomLeftPoint,
2454                                                         const Handle(GEOM_Object)& theBottomRigthPoint,
2455                                                         const GEOMAlgo_State       theState)
2456 {
2457   SetErrorCode(KO);
2458
2459   if ( theShape.IsNull() ||
2460        theTopLeftPoint.IsNull() ||
2461        theTopRigthPoint.IsNull() ||
2462        theBottomLeftPoint.IsNull() ||
2463        theBottomRigthPoint.IsNull() )
2464     return NULL;
2465
2466   TopoDS_Shape aShape = theShape->GetValue();
2467   TopoDS_Shape aTL = theTopLeftPoint->GetValue();
2468   TopoDS_Shape aTR = theTopRigthPoint->GetValue();
2469   TopoDS_Shape aBL = theBottomLeftPoint->GetValue();
2470   TopoDS_Shape aBR = theBottomRigthPoint->GetValue();
2471
2472   if (aShape.IsNull() ||
2473       aTL.IsNull() ||
2474       aTR.IsNull() ||
2475       aBL.IsNull() ||
2476       aBR.IsNull() ||
2477       aTL.ShapeType() != TopAbs_VERTEX ||
2478       aTR.ShapeType() != TopAbs_VERTEX ||
2479       aBL.ShapeType() != TopAbs_VERTEX ||
2480       aBR.ShapeType() != TopAbs_VERTEX )
2481     return NULL;
2482
2483   TopAbs_ShapeEnum aShapeType = TopAbs_ShapeEnum(theShapeType);
2484   if ( !checkTypeShapesOn( aShapeType ))
2485     return NULL;
2486
2487   Handle(TColStd_HSequenceOfInteger) aSeqOfIDs;
2488
2489   // Check presence of triangulation, build if need
2490   if (!CheckTriangulation(aShape)) {
2491     SetErrorCode("Cannot build triangulation on the shape");
2492     return aSeqOfIDs;
2493   }
2494
2495   // Call algo
2496   gp_Pnt aPntTL = BRep_Tool::Pnt(TopoDS::Vertex(aTL));
2497   gp_Pnt aPntTR = BRep_Tool::Pnt(TopoDS::Vertex(aTR));
2498   gp_Pnt aPntBL = BRep_Tool::Pnt(TopoDS::Vertex(aBL));
2499   gp_Pnt aPntBR = BRep_Tool::Pnt(TopoDS::Vertex(aBR));
2500
2501   GEOMAlgo_FinderShapeOnQuad aFinder( aPntTL, aPntTR, aPntBL, aPntBR );
2502   Standard_Real aTol = 0.0001; // default value
2503
2504   aFinder.SetShape(aShape);
2505   aFinder.SetTolerance(aTol);
2506   //aFinder.SetSurface(theSurface);
2507   aFinder.SetShapeType(aShapeType);
2508   aFinder.SetState(theState);
2509
2510   // Sets the minimal number of inner points for the faces that do not have own
2511   // inner points at all (for e.g. rectangular planar faces have just 2 triangles).
2512   // Default value=3
2513   aFinder.SetNbPntsMin(3);
2514   // Sets the maximal number of inner points for edges or faces.
2515   // It is usefull for the cases when this number is very big (e.g =2000) to improve
2516   // the performance. If this value =0, all inner points will be taken into account.
2517   // Default value=0
2518   aFinder.SetNbPntsMax(100);
2519
2520   aFinder.Perform();
2521
2522   // Interprete results
2523   Standard_Integer iErr = aFinder.ErrorStatus();
2524   // the detailed description of error codes is in GEOMAlgo_FinderShapeOn1.cxx
2525   if (iErr) {
2526     MESSAGE(" iErr : " << iErr);
2527     TCollection_AsciiString aMsg (" iErr : ");
2528     aMsg += TCollection_AsciiString(iErr);
2529     SetErrorCode(aMsg);
2530     return aSeqOfIDs;
2531   }
2532   Standard_Integer iWrn = aFinder.WarningStatus();
2533   // the detailed description of warning codes is in GEOMAlgo_FinderShapeOn1.cxx
2534   if (iWrn) {
2535     MESSAGE(" *** iWrn : " << iWrn);
2536   }
2537
2538   const TopTools_ListOfShape& listSS = aFinder.Shapes(); // the result
2539
2540   if (listSS.Extent() < 1) {
2541     //SetErrorCode("Not a single sub-shape of the requested type found on the given surface");
2542     SetErrorCode(NOT_FOUND_ANY); // NPAL18017
2543     return aSeqOfIDs;
2544   }
2545
2546   // Fill sequence of object IDs
2547   aSeqOfIDs = new TColStd_HSequenceOfInteger;
2548
2549   TopTools_IndexedMapOfShape anIndices;
2550   TopExp::MapShapes(aShape, anIndices);
2551
2552   TopTools_ListIteratorOfListOfShape itSub (listSS);
2553   for (int index = 1; itSub.More(); itSub.Next(), ++index) {
2554     int id = anIndices.FindIndex(itSub.Value());
2555     aSeqOfIDs->Append(id);
2556   }
2557   return aSeqOfIDs;
2558 }
2559
2560 //=======================================================================
2561 //function : GetShapesOnQuadrangle
2562   /*!
2563    * \brief Find subshapes complying with given status about quadrangle
2564     * \param theShape - the shape to explore
2565     * \param theShapeType - type of subshape of theShape
2566     * \param theTopLeftPoint - top left quadrangle corner
2567     * \param theTopRigthPoint - top right quadrangle corner
2568     * \param theBottomLeftPoint - bottom left quadrangle corner
2569     * \param theBottomRigthPoint - bottom right quadrangle corner
2570     * \param theState - required state
2571     * \retval Handle(TColStd_HSequenceOfInteger) - IDs of found subshapes
2572    */
2573 //=======================================================================
2574
2575 Handle(TColStd_HSequenceOfTransient)
2576     GEOMImpl_IShapesOperations::GetShapesOnQuadrangle (const Handle(GEOM_Object)& theShape,
2577                                                        const Standard_Integer     theShapeType,
2578                                                        const Handle(GEOM_Object)& theTopLeftPoint,
2579                                                        const Handle(GEOM_Object)& theTopRigthPoint,
2580                                                        const Handle(GEOM_Object)& theBottomLeftPoint,
2581                                                        const Handle(GEOM_Object)& theBottomRigthPoint,
2582                                                        const GEOMAlgo_State       theState)
2583 {
2584   // Find indices
2585   Handle(TColStd_HSequenceOfInteger) aSeqOfIDs =
2586     getShapesOnQuadrangleIDs( theShape,
2587                               theShapeType,
2588                               theTopLeftPoint,
2589                               theTopRigthPoint,
2590                               theBottomLeftPoint,
2591                               theBottomRigthPoint,
2592                               theState);
2593   if ( aSeqOfIDs.IsNull() || aSeqOfIDs->IsEmpty() )
2594     return NULL;
2595
2596   // Find objects by indices
2597   TCollection_AsciiString anAsciiList;
2598   Handle(TColStd_HSequenceOfTransient) aSeq;
2599   aSeq = getObjectsShapesOn( theShape, aSeqOfIDs, anAsciiList );
2600   if ( aSeq.IsNull() || aSeq->IsEmpty() )
2601     return NULL;
2602
2603   // Make a Python command
2604
2605   Handle(GEOM_Object) anObj = Handle(GEOM_Object)::DownCast( aSeq->Value( 1 ));
2606   Handle(GEOM_Function) aFunction = anObj->GetLastFunction();
2607
2608   GEOM::TPythonDump(aFunction)
2609     << "[" << anAsciiList.ToCString() << "] = geompy.GetShapesOnQuadrangle("
2610     << theShape << ", "
2611     << TopAbs_ShapeEnum(theShapeType) << ", "
2612     << theTopLeftPoint << ", "
2613     << theTopRigthPoint << ", "
2614     << theBottomLeftPoint << ", "
2615     << theBottomRigthPoint << ", "
2616     << theState << ")";
2617
2618   SetErrorCode(OK);
2619   return aSeq;
2620 }
2621
2622 //=======================================================================
2623 //function : GetShapesOnQuadrangleIDs
2624   /*!
2625    * \brief Find IDs of subshapes complying with given status about quadrangle
2626     * \param theShape - the shape to explore
2627     * \param theShapeType - type of subshape of theShape
2628     * \param theTopLeftPoint - top left quadrangle corner
2629     * \param theTopRigthPoint - top right quadrangle corner
2630     * \param theBottomLeftPoint - bottom left quadrangle corner
2631     * \param theBottomRigthPoint - bottom right quadrangle corner
2632     * \param theState - required state
2633     * \retval Handle(TColStd_HSequenceOfInteger) - IDs of found subshapes
2634    */
2635 //=======================================================================
2636
2637 Handle(TColStd_HSequenceOfInteger)
2638   GEOMImpl_IShapesOperations::GetShapesOnQuadrangleIDs (const Handle(GEOM_Object)& theShape,
2639                                                         const Standard_Integer     theShapeType,
2640                                                         const Handle(GEOM_Object)& theTopLeftPoint,
2641                                                         const Handle(GEOM_Object)& theTopRigthPoint,
2642                                                         const Handle(GEOM_Object)& theBottomLeftPoint,
2643                                                         const Handle(GEOM_Object)& theBottomRigthPoint,
2644                                                         const GEOMAlgo_State       theState)
2645 {
2646   // Find indices
2647   Handle(TColStd_HSequenceOfInteger) aSeqOfIDs =
2648     getShapesOnQuadrangleIDs( theShape,
2649                               theShapeType,
2650                               theTopLeftPoint,
2651                               theTopRigthPoint,
2652                               theBottomLeftPoint,
2653                               theBottomRigthPoint,
2654                               theState);
2655   if ( aSeqOfIDs.IsNull() || aSeqOfIDs->IsEmpty() )
2656     return NULL;
2657
2658   // Make a Python command
2659
2660   // The GetShapesOnCylinder() doesn't change object so no new function is required.
2661   Handle(GEOM_Object) lastObj = GEOM::GetCreatedLast(theShape,theTopLeftPoint);
2662   lastObj = GEOM::GetCreatedLast(lastObj,theTopRigthPoint);
2663   lastObj = GEOM::GetCreatedLast(lastObj,theBottomRigthPoint);
2664   lastObj = GEOM::GetCreatedLast(lastObj,theBottomLeftPoint);
2665   Handle(GEOM_Function) aFunction = lastObj->GetLastFunction();
2666
2667   GEOM::TPythonDump(aFunction, /*append=*/true)
2668     << "listShapesOnQuadrangle = geompy.GetShapesOnQuadrangleIDs("
2669     << theShape << ", "
2670     << TopAbs_ShapeEnum(theShapeType) << ", "
2671     << theTopLeftPoint << ", "
2672     << theTopRigthPoint << ", "
2673     << theBottomLeftPoint << ", "
2674     << theBottomRigthPoint << ", "
2675     << theState << ")";
2676
2677   SetErrorCode(OK);
2678   return aSeqOfIDs;
2679 }
2680
2681
2682 //=============================================================================
2683 /*!
2684  *  GetInPlaceOfShape
2685  */
2686 //=============================================================================
2687 static bool GetInPlaceOfShape (const Handle(GEOM_Function)& theWhereFunction,
2688                                const TopTools_IndexedMapOfShape& theWhereIndices,
2689                                const TopoDS_Shape& theWhat,
2690                                TColStd_ListOfInteger& theModifiedList)
2691 {
2692   if (theWhereFunction.IsNull() || theWhat.IsNull()) return false;
2693
2694   if (theWhereIndices.Contains(theWhat)) {
2695     // entity was not changed by the operation
2696     Standard_Integer aWhatIndex = theWhereIndices.FindIndex(theWhat);
2697     theModifiedList.Append(aWhatIndex);
2698     return true;
2699   }
2700
2701   // try to find in history
2702   TDF_Label aHistoryLabel = theWhereFunction->GetHistoryEntry(Standard_False);
2703
2704   // search in history for all argument shapes
2705   Standard_Boolean isFound = Standard_False;
2706   Standard_Boolean isGood = Standard_False;
2707
2708   TDF_LabelSequence aLabelSeq;
2709   theWhereFunction->GetDependency(aLabelSeq);
2710   Standard_Integer nbArg = aLabelSeq.Length();
2711
2712   for (Standard_Integer iarg = 1; iarg <= nbArg && !isFound; iarg++) {
2713
2714     TDF_Label anArgumentRefLabel = aLabelSeq.Value(iarg);
2715
2716     Handle(GEOM_Object) anArgumentObject = GEOM_Object::GetReferencedObject(anArgumentRefLabel);
2717     TopoDS_Shape anArgumentShape = anArgumentObject->GetValue();
2718
2719     TopTools_IndexedMapOfShape anArgumentIndices;
2720     TopExp::MapShapes(anArgumentShape, anArgumentIndices);
2721
2722     if (anArgumentIndices.Contains(theWhat)) {
2723       isFound = Standard_True;
2724       Standard_Integer aWhatIndex = anArgumentIndices.FindIndex(theWhat);
2725
2726       // Find corresponding label in history
2727       TDF_Label anArgumentHistoryLabel =
2728         theWhereFunction->GetArgumentHistoryEntry(anArgumentRefLabel, Standard_False);
2729       if (anArgumentHistoryLabel.IsNull()) {
2730         // Lost History of operation argument. Possibly, all its entities was removed.
2731         isGood = Standard_True;
2732       }
2733       else {
2734         TDF_Label aWhatHistoryLabel = anArgumentHistoryLabel.FindChild(aWhatIndex, Standard_False);
2735
2736         if (aWhatHistoryLabel.IsNull()) {
2737           // Removed entity ? Compound ? Compsolid ? Shell ? Wire
2738           isGood = Standard_False;
2739         } else {
2740           Handle(TDataStd_IntegerArray) anIntegerArray;
2741           if (!aWhatHistoryLabel.FindAttribute(TDataStd_IntegerArray::GetID(), anIntegerArray)) {
2742             //Error: Empty modifications history for the sought shape.
2743             isGood = Standard_False;
2744           }
2745           else {
2746             isGood = Standard_True;
2747             Standard_Integer imod, aModifLen = anIntegerArray->Array()->Length();
2748             for (imod = 1; imod <= aModifLen; imod++) {
2749               theModifiedList.Append(anIntegerArray->Array()->Value(imod));
2750             }
2751           }
2752         }
2753       }
2754     }
2755   }
2756
2757   isFound = isGood;
2758
2759   if (!isFound) {
2760     // try compound/compsolid/shell/wire element by element
2761     bool isFoundAny = false;
2762     TopTools_MapOfShape mapShape;
2763
2764     if (theWhat.ShapeType() == TopAbs_COMPOUND ||
2765         theWhat.ShapeType() == TopAbs_COMPSOLID) {
2766       // recursive processing of compound/compsolid
2767       TopoDS_Iterator anIt (theWhat, Standard_True, Standard_True);
2768       for (; anIt.More(); anIt.Next()) {
2769         if (mapShape.Add(anIt.Value())) {
2770           TopoDS_Shape curWhat = anIt.Value();
2771           isFoundAny = GetInPlaceOfShape(theWhereFunction, theWhereIndices, curWhat, theModifiedList);
2772           if (isFoundAny) isFound = Standard_True;
2773         }
2774       }
2775     }
2776     else if (theWhat.ShapeType() == TopAbs_SHELL) {
2777       // try to replace a shell by its faces images
2778       TopExp_Explorer anExp (theWhat, TopAbs_FACE);
2779       for (; anExp.More(); anExp.Next()) {
2780         if (mapShape.Add(anExp.Current())) {
2781           TopoDS_Shape curWhat = anExp.Current();
2782           isFoundAny = GetInPlaceOfShape(theWhereFunction, theWhereIndices, curWhat, theModifiedList);
2783           if (isFoundAny) isFound = Standard_True;
2784         }
2785       }
2786     }
2787     else if (theWhat.ShapeType() == TopAbs_WIRE) {
2788       // try to replace a wire by its edges images
2789       TopExp_Explorer anExp (theWhat, TopAbs_EDGE);
2790       for (; anExp.More(); anExp.Next()) {
2791         if (mapShape.Add(anExp.Current())) {
2792           TopoDS_Shape curWhat = anExp.Current();
2793           isFoundAny = GetInPlaceOfShape(theWhereFunction, theWhereIndices, curWhat, theModifiedList);
2794           if (isFoundAny) isFound = Standard_True;
2795         }
2796       }
2797     }
2798     else {
2799       // Removed entity
2800     }
2801   }
2802
2803   return isFound;
2804 }
2805
2806 //=============================================================================
2807 /*!
2808  *  GetShapeProperties
2809  */
2810 //=============================================================================
2811
2812 void GEOMImpl_IShapesOperations::GetShapeProperties( const TopoDS_Shape aShape, Standard_Real tab[],
2813                                                      gp_Pnt & aVertex )
2814 {
2815   GProp_GProps SProps, VProps;
2816   gp_Pnt aCenterMass;
2817   TopoDS_Shape aPntShape;
2818   Standard_Real aShapeSize;
2819
2820   BRepGProp::VolumeProperties(aShape, VProps);
2821   aCenterMass = VProps.CentreOfMass();
2822   aShapeSize  = VProps.Mass();
2823   if (aShape.ShapeType() == TopAbs_FACE) {
2824     BRepGProp::SurfaceProperties(aShape, SProps);
2825     aCenterMass = SProps.CentreOfMass();
2826     aShapeSize  = SProps.Mass();
2827   }
2828
2829   aPntShape = BRepBuilderAPI_MakeVertex(aCenterMass).Shape();
2830   aVertex   = BRep_Tool::Pnt( TopoDS::Vertex( aPntShape ) );
2831   tab[0] = aVertex.X();
2832   tab[1] = aVertex.Y();
2833   tab[2] = aVertex.Z();
2834   tab[3] = aShapeSize;
2835   return;
2836 }
2837
2838 //=============================================================================
2839 /*!
2840  *  GetInPlace
2841  */
2842 //=============================================================================
2843 Handle(GEOM_Object) GEOMImpl_IShapesOperations::GetInPlace (Handle(GEOM_Object) theShapeWhere,
2844                                                             Handle(GEOM_Object) theShapeWhat)
2845 {
2846   SetErrorCode(KO);
2847
2848   if (theShapeWhere.IsNull() || theShapeWhat.IsNull()) return NULL;
2849
2850   TopoDS_Shape aWhere = theShapeWhere->GetValue();
2851   TopoDS_Shape aWhat  = theShapeWhat->GetValue();
2852
2853   if (aWhere.IsNull() || aWhat.IsNull()) {
2854     SetErrorCode("Error: aWhere and aWhat TopoDS_Shape are Null.");
2855     return NULL;
2856   }
2857
2858   Handle(GEOM_Function) aWhereFunction = theShapeWhere->GetLastFunction();
2859   if (aWhereFunction.IsNull()) {
2860     SetErrorCode("Error: aWhereFunction is Null.");
2861     return NULL;
2862   }
2863
2864   TopTools_IndexedMapOfShape aWhereIndices;
2865   TopExp::MapShapes(aWhere, aWhereIndices);
2866
2867   TColStd_ListOfInteger aModifiedList;
2868   Standard_Integer aWhereIndex;
2869   Handle(TColStd_HArray1OfInteger) aModifiedArray;
2870   Handle(GEOM_Object) aResult;
2871
2872   bool isFound = false;
2873   Standard_Integer iType = TopAbs_SOLID;
2874   Standard_Real    aWhat_Mass = 0., aWhere_Mass = 0.;
2875   Standard_Real    tab_aWhat[4],    tab_aWhere[4];
2876   Standard_Real    dl_l = 1e-3;
2877   Standard_Real    min_l, Tol_1D, Tol_2D, Tol_3D, Tol_Mass;
2878   gp_Pnt           aPnt, aPnt_aWhat;
2879   GProp_GProps     aProps;
2880
2881   // 2D or 3D shapes
2882   if ( aWhat.ShapeType() == TopAbs_COMPOUND  ||
2883        aWhat.ShapeType() == TopAbs_SHELL     ||
2884        aWhat.ShapeType() == TopAbs_COMPSOLID ) {
2885     TopExp_Explorer Exp( aWhat, TopAbs_ShapeEnum( iType ) );
2886     if ( ! Exp.More() ) iType = TopAbs_FACE;
2887   }
2888   else if ( aWhat.ShapeType() == TopAbs_FACE )
2889     iType = TopAbs_FACE;
2890
2891   TopExp_Explorer Exp_aWhat( aWhat,   TopAbs_ShapeEnum( iType ) );
2892   TopExp_Explorer Exp_aWhere( aWhere, TopAbs_ShapeEnum( iType ) );
2893   TopExp_Explorer Exp_Edge( aWhere,   TopAbs_EDGE );
2894
2895   // Find the shortest edge in theShapeWhere shape
2896   for ( Standard_Integer nbEdge = 0; Exp_Edge.More(); Exp_Edge.Next(), nbEdge++ ) {
2897     BRepGProp::LinearProperties(Exp_Edge.Current(), aProps);
2898     if ( ! nbEdge ) min_l = aProps.Mass();
2899     if ( aProps.Mass() < min_l ) min_l = aProps.Mass();
2900   }
2901
2902   // Compute tolerances
2903   Tol_1D = dl_l * min_l;
2904   Tol_2D = dl_l * ( min_l * min_l) * ( 2. + dl_l);
2905   Tol_3D = dl_l * ( min_l * min_l * min_l ) * ( 3. + (3 * dl_l) + (dl_l * dl_l) );
2906
2907   Tol_Mass = Tol_3D;
2908   if ( iType == TopAbs_FACE ) Tol_Mass = Tol_2D;
2909
2910   // Compute the ShapeWhat Mass
2911   for ( ; Exp_aWhat.More(); Exp_aWhat.Next() ) {
2912     if      ( iType == TopAbs_SOLID ) BRepGProp::VolumeProperties(Exp_aWhat.Current(), aProps);
2913     else if ( iType == TopAbs_FACE )  BRepGProp::SurfaceProperties(Exp_aWhat.Current(), aProps);
2914     aWhat_Mass += aProps.Mass();
2915   }
2916
2917   // Finding the Sub-ShapeWhere
2918   for ( Exp_aWhere.ReInit(); Exp_aWhere.More(); Exp_aWhere.Next() ) {
2919     GetShapeProperties( Exp_aWhere.Current(), tab_aWhere, aPnt );
2920     for ( Exp_aWhat.ReInit(); Exp_aWhat.More(); Exp_aWhat.Next() ) {
2921       GetShapeProperties( Exp_aWhat.Current(), tab_aWhat, aPnt_aWhat );
2922       if ( fabs(tab_aWhat[3] - tab_aWhere[3]) <= Tol_Mass && aPnt_aWhat.Distance(aPnt) <= Tol_1D )
2923         isFound = true;
2924       else if ( tab_aWhat[3] - ( tab_aWhere[3] > Tol_Mass) ) {
2925         BRepClass3d_SolidClassifier SC_aWhere (Exp_aWhere.Current(), aPnt, Precision::Confusion());
2926         BRepClass3d_SolidClassifier SC_aWhat  (Exp_aWhat.Current(),  aPnt, Precision::Confusion());
2927         // Block construction 3D
2928         if      ( SC_aWhere.State() == TopAbs_IN && SC_aWhat.State() == TopAbs_IN ) isFound = true;
2929         // Block construction 2D
2930         else if ( SC_aWhere.State() == TopAbs_ON && SC_aWhat.State() == TopAbs_ON ) isFound = true;
2931       }
2932       if ( isFound ) {
2933         aWhereIndex = aWhereIndices.FindIndex(Exp_aWhere.Current());
2934         aModifiedList.Append(aWhereIndex);
2935         aWhere_Mass += tab_aWhere[3];
2936         isFound = false;
2937         break;
2938       }
2939     }
2940     if ( fabs( aWhat_Mass - aWhere_Mass ) <= Tol_Mass ) break;
2941   }
2942
2943   aModifiedArray = new TColStd_HArray1OfInteger (1, aModifiedList.Extent());
2944   TColStd_ListIteratorOfListOfInteger anIterModif (aModifiedList);
2945   for (Standard_Integer imod = 1; anIterModif.More(); anIterModif.Next(), imod++)
2946     aModifiedArray->SetValue(imod, anIterModif.Value());
2947
2948   //Add a new object
2949   aResult = GetEngine()->AddSubShape(theShapeWhere, aModifiedArray);
2950   if (aResult.IsNull()) {
2951     SetErrorCode("Error in algorithm: result found, but cannot be returned.");
2952     return NULL;
2953   }
2954
2955   if (aModifiedArray->Length() > 1) {
2956     //Set a GROUP type
2957     aResult->SetType(GEOM_GROUP);
2958
2959     //Set a sub shape type
2960     TopoDS_Shape aFirstFound = aWhereIndices.FindKey(aModifiedArray->Value(1));
2961     TopAbs_ShapeEnum aShapeType = aFirstFound.ShapeType();
2962
2963     TDF_Label aFreeLabel = aResult->GetFreeLabel();
2964     TDataStd_Integer::Set(aFreeLabel, (Standard_Integer)aShapeType);
2965   }
2966
2967   //Make a Python command
2968   Handle(GEOM_Function) aFunction = aResult->GetFunction(1);
2969
2970   GEOM::TPythonDump(aFunction) << aResult << " = geompy.GetInPlace("
2971     << theShapeWhere << ", " << theShapeWhat << ")";
2972
2973   SetErrorCode(OK);
2974   return aResult;
2975 }
2976
2977 //=======================================================================
2978 //function : GetInPlaceByHistory
2979 //purpose  :
2980 //=======================================================================
2981 Handle(GEOM_Object) GEOMImpl_IShapesOperations::GetInPlaceByHistory
2982                                           (Handle(GEOM_Object) theShapeWhere,
2983                                            Handle(GEOM_Object) theShapeWhat)
2984 {
2985   SetErrorCode(KO);
2986
2987   if (theShapeWhere.IsNull() || theShapeWhat.IsNull()) return NULL;
2988
2989   TopoDS_Shape aWhere = theShapeWhere->GetValue();
2990   TopoDS_Shape aWhat  = theShapeWhat->GetValue();
2991
2992   if (aWhere.IsNull() || aWhat.IsNull()) return NULL;
2993
2994   Handle(GEOM_Function) aWhereFunction = theShapeWhere->GetLastFunction();
2995   if (aWhereFunction.IsNull()) return NULL;
2996
2997   //Fill array of indices
2998   TopTools_IndexedMapOfShape aWhereIndices;
2999   TopExp::MapShapes(aWhere, aWhereIndices);
3000
3001   // process shape
3002   TColStd_ListOfInteger aModifiedList;
3003   bool isFound = GetInPlaceOfShape(aWhereFunction, aWhereIndices, aWhat, aModifiedList);
3004
3005   if (!isFound || aModifiedList.Extent() < 1) {
3006     SetErrorCode("Error: No history found for the sought shape or its sub-shapes.");
3007     return NULL;
3008   }
3009
3010   Handle(TColStd_HArray1OfInteger) aModifiedArray =
3011     new TColStd_HArray1OfInteger (1, aModifiedList.Extent());
3012   TColStd_ListIteratorOfListOfInteger anIterModif (aModifiedList);
3013   for (Standard_Integer imod = 1; anIterModif.More(); anIterModif.Next(), imod++) {
3014     aModifiedArray->SetValue(imod, anIterModif.Value());
3015   }
3016
3017   //Add a new object
3018   Handle(GEOM_Object) aResult = GetEngine()->AddSubShape(theShapeWhere, aModifiedArray);
3019   if (aResult.IsNull()) {
3020     SetErrorCode("Error in algorithm: result found, but cannot be returned.");
3021     return NULL;
3022   }
3023
3024   if (aModifiedArray->Length() > 1) {
3025     //Set a GROUP type
3026     aResult->SetType(GEOM_GROUP);
3027
3028     //Set a sub shape type
3029     TopoDS_Shape aFirstFound = aWhereIndices.FindKey(aModifiedArray->Value(1));
3030     TopAbs_ShapeEnum aShapeType = aFirstFound.ShapeType();
3031
3032     TDF_Label aFreeLabel = aResult->GetFreeLabel();
3033     TDataStd_Integer::Set(aFreeLabel, (Standard_Integer)aShapeType);
3034   }
3035
3036   //Make a Python command
3037   Handle(GEOM_Function) aFunction = aResult->GetFunction(1);
3038
3039   GEOM::TPythonDump(aFunction) << aResult << " = geompy.GetInPlace("
3040     << theShapeWhere << ", " << theShapeWhat << ")";
3041
3042   SetErrorCode(OK);
3043   return aResult;
3044 }
3045
3046 //=======================================================================
3047 //function : SortShapes
3048 //purpose  :
3049 //=======================================================================
3050 void GEOMImpl_IShapesOperations::SortShapes(TopTools_ListOfShape& SL)
3051 {
3052   Standard_Integer MaxShapes = SL.Extent();
3053   TopTools_Array1OfShape  aShapes (1,MaxShapes);
3054   TColStd_Array1OfInteger OrderInd(1,MaxShapes);
3055   TColStd_Array1OfReal    MidXYZ  (1,MaxShapes); //X,Y,Z;
3056   TColStd_Array1OfReal    Length  (1,MaxShapes); //X,Y,Z;
3057
3058   // Computing of CentreOfMass
3059   Standard_Integer Index;
3060   GProp_GProps GPr;
3061   gp_Pnt GPoint;
3062   TopTools_ListIteratorOfListOfShape it(SL);
3063   for (Index=1;  it.More();  Index++)
3064   {
3065     TopoDS_Shape S = it.Value();
3066     SL.Remove( it ); // == it.Next()
3067     aShapes(Index) = S;
3068     OrderInd.SetValue (Index, Index);
3069     if (S.ShapeType() == TopAbs_VERTEX)
3070     {
3071       GPoint = BRep_Tool::Pnt( TopoDS::Vertex( S ));
3072       Length.SetValue( Index, (Standard_Real) S.Orientation());
3073     }
3074     else
3075     {
3076       BRepGProp::LinearProperties (S, GPr);
3077       GPoint = GPr.CentreOfMass();
3078       Length.SetValue( Index, GPr.Mass() );
3079     }
3080     MidXYZ.SetValue(Index,
3081                     GPoint.X()*999 + GPoint.Y()*99 + GPoint.Z()*0.9);
3082     //cout << Index << " L: " << Length(Index) << "CG: " << MidXYZ(Index) << endl;
3083   }
3084
3085   // Sorting
3086   Standard_Integer aTemp;
3087   Standard_Boolean exchange, Sort = Standard_True;
3088   Standard_Real    tol = Precision::Confusion();
3089   while (Sort)
3090   {
3091     Sort = Standard_False;
3092     for (Index=1; Index < MaxShapes; Index++)
3093     {
3094       Standard_Real dMidXYZ = MidXYZ(OrderInd(Index)) - MidXYZ(OrderInd(Index+1));
3095       Standard_Real dLength = Length(OrderInd(Index)) - Length(OrderInd(Index+1));
3096       if ( dMidXYZ >= tol ) {
3097 //         cout << "MidXYZ: " << MidXYZ(OrderInd(Index))<< " > " <<MidXYZ(OrderInd(Index+1))
3098 //              << " d: " << dMidXYZ << endl;
3099         exchange = Standard_True;
3100       }
3101       else if ( Abs(dMidXYZ) < tol && dLength >= tol ) {
3102 //         cout << "Length: " << Length(OrderInd(Index))<< " > " <<Length(OrderInd(Index+1))
3103 //              << " d: " << dLength << endl;
3104         exchange = Standard_True;
3105       }
3106       else if ( Abs(dMidXYZ) < tol && Abs(dLength) < tol &&
3107                 aShapes(OrderInd(Index)).ShapeType() <= TopAbs_FACE) {
3108         // PAL17233
3109         // equal values possible on shapes such as two halves of a sphere and
3110         // a membrane inside the sphere
3111         Bnd_Box box1,box2;
3112         BRepBndLib::Add( aShapes( OrderInd(Index) ), box1 );
3113         if ( box1.IsVoid() ) continue;
3114         BRepBndLib::Add( aShapes( OrderInd(Index+1) ), box2 );
3115         Standard_Real dSquareExtent = box1.SquareExtent() - box2.SquareExtent();
3116         if ( dSquareExtent >= tol ) {
3117 //           cout << "SquareExtent: " << box1.SquareExtent()<<" > "<<box2.SquareExtent() << endl;
3118           exchange = Standard_True;
3119         }
3120         else if ( Abs(dSquareExtent) < tol ) {
3121           Standard_Real aXmin, aYmin, aZmin, aXmax, aYmax, aZmax, val1, val2;
3122           box1.Get(aXmin, aYmin, aZmin, aXmax, aYmax, aZmax);
3123           val1 = (aXmin+aXmax)*999 + (aYmin+aYmax)*99 + (aZmin+aZmax)*0.9;
3124           box2.Get(aXmin, aYmin, aZmin, aXmax, aYmax, aZmax);
3125           val2 = (aXmin+aXmax)*999 + (aYmin+aYmax)*99 + (aZmin+aZmax)*0.9;
3126           exchange = val1 > val2;
3127 //           cout << "box: " << val1<<" > "<<val2 << endl;
3128         }
3129       }
3130       else {
3131         exchange = Standard_False;
3132       }
3133       if (exchange)
3134       {
3135 //         cout << "exchange " << Index << " & " << Index+1 << endl;
3136         aTemp = OrderInd(Index);
3137         OrderInd(Index) = OrderInd(Index+1);
3138         OrderInd(Index+1) = aTemp;
3139         Sort = Standard_True;
3140       }
3141     }
3142   }
3143     
3144   for (Index=1; Index <= MaxShapes; Index++)
3145     SL.Append( aShapes( OrderInd(Index) ));
3146 }
3147
3148 //=======================================================================
3149 //function : CompsolidToCompound
3150 //purpose  :
3151 //=======================================================================
3152 TopoDS_Shape GEOMImpl_IShapesOperations::CompsolidToCompound (const TopoDS_Shape& theCompsolid)
3153 {
3154   if (theCompsolid.ShapeType() != TopAbs_COMPSOLID) {
3155     return theCompsolid;
3156   }
3157
3158   TopoDS_Compound aCompound;
3159   BRep_Builder B;
3160   B.MakeCompound(aCompound);
3161
3162   TopTools_MapOfShape mapShape;
3163   TopoDS_Iterator It (theCompsolid, Standard_True, Standard_True);
3164
3165   for (; It.More(); It.Next()) {
3166     TopoDS_Shape aShape_i = It.Value();
3167     if (mapShape.Add(aShape_i)) {
3168       B.Add(aCompound, aShape_i);
3169     }
3170   }
3171
3172   return aCompound;
3173 }
3174
3175 //=======================================================================
3176 //function : CheckTriangulation
3177 //purpose  :
3178 //=======================================================================
3179 bool GEOMImpl_IShapesOperations::CheckTriangulation (const TopoDS_Shape& aShape)
3180 {
3181   bool isTriangulation = true;
3182
3183   TopExp_Explorer exp (aShape, TopAbs_FACE);
3184   if (exp.More())
3185   {
3186     TopLoc_Location aTopLoc;
3187     Handle(Poly_Triangulation) aTRF;
3188     aTRF = BRep_Tool::Triangulation(TopoDS::Face(exp.Current()), aTopLoc);
3189     if (aTRF.IsNull()) {
3190       isTriangulation = false;
3191     }
3192   }
3193   else // no faces, try edges
3194   {
3195     TopExp_Explorer expe (aShape, TopAbs_EDGE);
3196     if (!expe.More()) {
3197       return false;
3198     }
3199     TopLoc_Location aLoc;
3200     Handle(Poly_Polygon3D) aPE = BRep_Tool::Polygon3D(TopoDS::Edge(expe.Current()), aLoc);
3201     if (aPE.IsNull()) {
3202       isTriangulation = false;
3203     }
3204   }
3205
3206   if (!isTriangulation) {
3207     // calculate deflection
3208     Standard_Real aDeviationCoefficient = 0.001;
3209
3210     Bnd_Box B;
3211     BRepBndLib::Add(aShape, B);
3212     Standard_Real aXmin, aYmin, aZmin, aXmax, aYmax, aZmax;
3213     B.Get(aXmin, aYmin, aZmin, aXmax, aYmax, aZmax);
3214
3215     Standard_Real dx = aXmax - aXmin, dy = aYmax - aYmin, dz = aZmax - aZmin;
3216     Standard_Real aDeflection = Max(Max(dx, dy), dz) * aDeviationCoefficient * 4;
3217     Standard_Real aHLRAngle = 0.349066;
3218
3219     BRepMesh_IncrementalMesh Inc (aShape, aDeflection, Standard_False, aHLRAngle);
3220   }
3221
3222   return true;
3223 }
3224
3225 #define MAX_TOLERANCE 1.e-7
3226
3227
3228 //=======================================================================
3229 //function : isSameEdge
3230 //purpose  : Returns True if two edges coincide
3231 //=======================================================================
3232 static bool isSameEdge(const TopoDS_Edge& theEdge1, const TopoDS_Edge& theEdge2)
3233 {
3234   TopoDS_Vertex V11, V12, V21, V22;
3235   TopExp::Vertices(theEdge1, V11, V12);
3236   TopExp::Vertices(theEdge2, V21, V22);
3237   gp_Pnt P11 = BRep_Tool::Pnt(V11);
3238   gp_Pnt P12 = BRep_Tool::Pnt(V12);
3239   gp_Pnt P21 = BRep_Tool::Pnt(V21);
3240   gp_Pnt P22 = BRep_Tool::Pnt(V22);
3241   bool coincide = false;
3242
3243   //Check that ends of edges coincide
3244   if(P11.Distance(P21) <= MAX_TOLERANCE) {
3245     if(P12.Distance(P22) <= MAX_TOLERANCE) coincide =  true;
3246   }
3247   else if(P11.Distance(P22) <= MAX_TOLERANCE) {
3248     if(P12.Distance(P21) <= MAX_TOLERANCE) coincide = true;
3249   }
3250
3251   if(!coincide) return false;
3252
3253   double U11, U12, U21, U22;
3254   Handle(Geom_Curve) C1 = BRep_Tool::Curve(theEdge1, U11, U12);
3255   Handle(Geom_Curve) C2 = BRep_Tool::Curve(theEdge2, U21, U22);
3256   if(C1->DynamicType() == C2->DynamicType()) return true;
3257
3258   //Check that both edges has the same geometry
3259   double range = U12-U11;
3260   double U = U11+ range/3.0;
3261   gp_Pnt P1 = C1->Value(U);     //Compute a point on one third of the edge's length
3262   U = U11+range*2.0/3.0;
3263   gp_Pnt P2 = C1->Value(U);     //Compute a point on two thirds of the edge's length
3264
3265   if(!GeomLib_Tool::Parameter(C2, P1, MAX_TOLERANCE, U) ||  U < U21 || U > U22)
3266     return false;
3267
3268   if(P1.Distance(C2->Value(U)) > MAX_TOLERANCE) return false;
3269
3270   if(!GeomLib_Tool::Parameter(C2, P2, MAX_TOLERANCE, U) || U < U21 || U > U22)
3271     return false;
3272
3273   if(P2.Distance(C2->Value(U)) > MAX_TOLERANCE) return false;
3274
3275   return true;
3276 }
3277
3278 #include <TopoDS_TShape.hxx>
3279 //=======================================================================
3280 //function : isSameFace
3281 //purpose  : Returns True if two faces coincide
3282 //=======================================================================
3283 static bool isSameFace(const TopoDS_Face& theFace1, const TopoDS_Face& theFace2)
3284 {
3285   TopExp_Explorer E(theFace1, TopAbs_EDGE);
3286   TopTools_ListOfShape LS1, LS2;
3287   for(; E.More(); E.Next()) LS1.Append(E.Current());
3288
3289   E.Init(theFace2, TopAbs_EDGE);
3290   for(; E.More(); E.Next()) LS2.Append(E.Current());
3291
3292   //Compare the number of edges in the faces
3293   if(LS1.Extent() != LS2.Extent()) return false;
3294
3295   double aMin = RealFirst(), aMax = RealLast();
3296   double xminB1=aMax, yminB1=aMax, zminB1=aMax, xminB2=aMax, yminB2=aMax, zminB2=aMax;
3297   double xmaxB1=aMin, ymaxB1=aMin, zmaxB1=aMin, xmaxB2=aMin, ymaxB2=aMin, zmaxB2=aMin;
3298
3299   for(E.Init(theFace1, TopAbs_VERTEX); E.More(); E.Next()) {
3300     gp_Pnt P = BRep_Tool::Pnt(TopoDS::Vertex(E.Current()));
3301     if(P.X() < xminB1) xminB1 = P.X();
3302     if(P.Y() < yminB1) yminB1 = P.Y();
3303     if(P.Z() < zminB1) zminB1 = P.Z();
3304     if(P.X() > xmaxB1) xmaxB1 = P.X();
3305     if(P.Y() > ymaxB1) ymaxB1 = P.Y();
3306     if(P.Z() > zmaxB1) zmaxB1 = P.Z();
3307   }
3308
3309   for(E.Init(theFace2, TopAbs_VERTEX); E.More(); E.Next()) {
3310     gp_Pnt P = BRep_Tool::Pnt(TopoDS::Vertex(E.Current()));
3311     if(P.X() < xminB2) xminB2 = P.X();
3312     if(P.Y() < yminB2) yminB2 = P.Y();
3313     if(P.Z() < zminB2) zminB2 = P.Z();
3314     if(P.X() > xmaxB2) xmaxB2 = P.X();
3315     if(P.Y() > ymaxB2) ymaxB2 = P.Y();
3316     if(P.Z() > zmaxB2) zmaxB2 = P.Z();
3317   }
3318
3319
3320   //Compare the bounding boxes of both faces
3321   if(gp_Pnt(xminB1, yminB1, zminB1).Distance(gp_Pnt(xminB2, yminB2, zminB2)) > MAX_TOLERANCE)
3322     return false;
3323
3324   if(gp_Pnt(xmaxB1, ymaxB1, zmaxB1).Distance(gp_Pnt(xmaxB2, ymaxB2, zmaxB2)) > MAX_TOLERANCE)
3325     return false;
3326
3327   Handle(Geom_Surface) S1 = BRep_Tool::Surface(theFace1);
3328   Handle(Geom_Surface) S2 = BRep_Tool::Surface(theFace2);
3329
3330   //Check if there a coincidence of two surfaces at least in two points
3331   double U11, U12, V11, V12, U21, U22, V21, V22;
3332   BRepTools::UVBounds(theFace1, U11, U12, V11, V12);
3333   BRepTools::UVBounds(theFace2, U21, U22, V21, V22);
3334
3335   double rangeU = U12-U11;
3336   double rangeV = V12-V11;
3337   double U = U11 + rangeU/3.0;
3338   double V = V11 + rangeV/3.0;
3339   gp_Pnt P1 = S1->Value(U, V);
3340   U = U11+rangeU*2.0/3.0;
3341   V = V11+rangeV*2.0/3.0;
3342   gp_Pnt P2 = S1->Value(U, V);
3343   
3344   if(!GeomLib_Tool::Parameters(S2, P1, MAX_TOLERANCE, U, V) || U < U21 || U > U22 || V < V21 || V > V22)
3345     return false;
3346   
3347   if(P1.Distance(S2->Value(U,V)) > MAX_TOLERANCE) return false;
3348   
3349   if(!GeomLib_Tool::Parameters(S2, P2, MAX_TOLERANCE, U, V) || U < U21 || U > U22 || V < V21 || V > V22)
3350     return false;
3351   
3352   if(P2.Distance(S2->Value(U, V)) > MAX_TOLERANCE) return false;
3353
3354   //Check that each edge of the Face1 has a counterpart in the Face2
3355   TopTools_MapOfOrientedShape aMap;
3356   TopTools_ListIteratorOfListOfShape LSI1(LS1);
3357   for(; LSI1.More(); LSI1.Next()) {
3358     TopoDS_Edge E = TopoDS::Edge(LSI1.Value());
3359     bool isFound = false;
3360     TopTools_ListIteratorOfListOfShape LSI2(LS2);
3361     for(; LSI2.More(); LSI2.Next()) {
3362       TopoDS_Shape aValue = LSI2.Value();
3363       if(aMap.Contains(aValue)) continue; //To avoid checking already found edge several times
3364       if(isSameEdge(E, TopoDS::Edge(aValue))) {
3365         aMap.Add(aValue);
3366         isFound = true;
3367         break;
3368       }
3369     }
3370     if(!isFound) return false;
3371   }
3372
3373   return true;
3374 }
3375
3376 //=======================================================================
3377 //function : isSameSolid
3378 //purpose  : Returns True if two solids coincide
3379 //=======================================================================
3380 bool isSameSolid(const TopoDS_Solid& theSolid1, const TopoDS_Solid& theSolid2)
3381 {
3382   TopExp_Explorer E(theSolid1, TopAbs_FACE);
3383   TopTools_ListOfShape LS1, LS2;
3384   for(; E.More(); E.Next()) LS1.Append(E.Current());
3385   E.Init(theSolid2, TopAbs_FACE);
3386   for(; E.More(); E.Next()) LS2.Append(E.Current());
3387
3388   if(LS1.Extent() != LS2.Extent()) return false;
3389
3390   double aMin = RealFirst(), aMax = RealLast();
3391   double xminB1=aMax, yminB1=aMax, zminB1=aMax, xminB2=aMax, yminB2=aMax, zminB2=aMax;
3392   double xmaxB1=aMin, ymaxB1=aMin, zmaxB1=aMin, xmaxB2=aMin, ymaxB2=aMin, zmaxB2=aMin;
3393
3394   for(E.Init(theSolid1, TopAbs_VERTEX); E.More(); E.Next()) {
3395     gp_Pnt P = BRep_Tool::Pnt(TopoDS::Vertex(E.Current()));
3396     if(P.X() < xminB1) xminB1 = P.X();
3397     if(P.Y() < yminB1) yminB1 = P.Y();
3398     if(P.Z() < zminB1) zminB1 = P.Z();
3399     if(P.X() > xmaxB1) xmaxB1 = P.X();
3400     if(P.Y() > ymaxB1) ymaxB1 = P.Y();
3401     if(P.Z() > zmaxB1) zmaxB1 = P.Z();
3402   }
3403
3404   for(E.Init(theSolid2, TopAbs_VERTEX); E.More(); E.Next()) {
3405     gp_Pnt P = BRep_Tool::Pnt(TopoDS::Vertex(E.Current()));
3406     if(P.X() < xminB2) xminB2 = P.X();
3407     if(P.Y() < yminB2) yminB2 = P.Y();
3408     if(P.Z() < zminB2) zminB2 = P.Z();
3409     if(P.X() > xmaxB2) xmaxB2 = P.X();
3410     if(P.Y() > ymaxB2) ymaxB2 = P.Y();
3411     if(P.Z() > zmaxB2) zmaxB2 = P.Z();
3412   }
3413
3414   //Compare the bounding boxes of both solids
3415   if(gp_Pnt(xminB1, yminB1, zminB1).Distance(gp_Pnt(xminB2, yminB2, zminB2)) > MAX_TOLERANCE)
3416     return false;
3417
3418   if(gp_Pnt(xmaxB1, ymaxB1, zmaxB1).Distance(gp_Pnt(xmaxB2, ymaxB2, zmaxB2)) > MAX_TOLERANCE)
3419     return false;
3420
3421   //Check that each face of the Solid1 has a counterpart in the Solid2
3422   TopTools_MapOfOrientedShape aMap;
3423   TopTools_ListIteratorOfListOfShape LSI1(LS1);
3424   for(; LSI1.More(); LSI1.Next()) {
3425     TopoDS_Face F = TopoDS::Face(LSI1.Value());
3426     bool isFound = false;
3427     TopTools_ListIteratorOfListOfShape LSI2(LS2);
3428     for(; LSI2.More(); LSI2.Next()) {
3429       if(aMap.Contains(LSI2.Value())) continue; //To avoid checking already found faces several times
3430       if(isSameFace(F, TopoDS::Face(LSI2.Value()))) {
3431         aMap.Add(LSI2.Value());
3432         isFound = true;
3433         break;
3434       }
3435     }
3436     if(!isFound) return false;
3437   }
3438
3439   return true;
3440 }
3441
3442 //=======================================================================
3443 //function : GetSame
3444 //purpose  :
3445 //=======================================================================
3446 Handle(GEOM_Object) GEOMImpl_IShapesOperations::GetSame(const Handle(GEOM_Object)& theShapeWhere,
3447                                                         const Handle(GEOM_Object)& theShapeWhat)
3448 {
3449   SetErrorCode(KO);
3450   if (theShapeWhere.IsNull() || theShapeWhat.IsNull()) return NULL;
3451
3452   TopoDS_Shape aWhere = theShapeWhere->GetValue();
3453   TopoDS_Shape aWhat  = theShapeWhat->GetValue();
3454
3455   if (aWhere.IsNull() || aWhat.IsNull()) return NULL;
3456
3457   int anIndex = -1;
3458   bool isFound = false;
3459   TopoDS_Shape aSubShape;
3460   TopTools_MapOfShape aMap;
3461
3462   switch(aWhat.ShapeType()) {
3463     case TopAbs_VERTEX: {
3464       gp_Pnt P = BRep_Tool::Pnt(TopoDS::Vertex(aWhat));
3465       TopExp_Explorer E(aWhere, TopAbs_VERTEX);
3466       for(; E.More(); E.Next()) {
3467         if(!aMap.Add(E.Current())) continue;
3468         gp_Pnt P2 = BRep_Tool::Pnt(TopoDS::Vertex(E.Current()));
3469         if(P.Distance(P2) <= MAX_TOLERANCE) {
3470           isFound = true;
3471           aSubShape = E.Current();
3472           break;
3473         }
3474       }
3475       break;
3476                         }
3477     case TopAbs_FACE: {
3478       TopoDS_Face aFace = TopoDS::Face(aWhat);
3479       TopExp_Explorer E(aWhere, TopAbs_FACE);
3480       for(; E.More(); E.Next()) {
3481         if(!aMap.Add(E.Current())) continue;
3482         if(isSameFace(aFace, TopoDS::Face(E.Current()))) {
3483           aSubShape = E.Current();
3484           isFound = true;
3485           break;
3486         }
3487       }
3488       break;
3489                       }
3490     case TopAbs_EDGE: {
3491       TopoDS_Edge anEdge = TopoDS::Edge(aWhat);
3492       TopExp_Explorer E(aWhere, TopAbs_EDGE);
3493       for(; E.More(); E.Next()) {
3494         if(!aMap.Add(E.Current())) continue;
3495         if(isSameEdge(anEdge, TopoDS::Edge(E.Current()))) {
3496           aSubShape = E.Current();
3497           isFound = true;
3498           break;
3499         }
3500       }
3501       break;
3502                       }
3503     case TopAbs_SOLID: {
3504       TopoDS_Solid aSolid = TopoDS::Solid(aWhat);
3505       TopExp_Explorer E(aWhere, TopAbs_SOLID);
3506       for(; E.More(); E.Next()) {
3507         if(!aMap.Add(E.Current())) continue;
3508         if(isSameSolid(aSolid, TopoDS::Solid(E.Current()))) {
3509           aSubShape = E.Current();
3510           isFound = true;
3511           break;
3512         }
3513       }
3514       break;
3515                        }
3516     default:
3517       return NULL;
3518   }
3519
3520   if(isFound) {
3521     TopTools_IndexedMapOfShape anIndices;
3522     TopExp::MapShapes(aWhere, anIndices);
3523     if (anIndices.Contains(aSubShape))
3524       anIndex = anIndices.FindIndex(aSubShape);
3525   }
3526
3527   if(anIndex < 0) return NULL;
3528
3529   Handle(TColStd_HArray1OfInteger) anArray = new TColStd_HArray1OfInteger(1,1);
3530
3531   anArray->SetValue(1, anIndex);
3532
3533   Handle(GEOM_Object) aResult = GetEngine()->AddSubShape(theShapeWhere, anArray);
3534   Handle(GEOM_Function) aFunction = aResult->GetLastFunction();
3535
3536   GEOM::TPythonDump(aFunction) << aResult << " = geompy.GetSame("
3537     << theShapeWhere << ", " << theShapeWhat << ")";
3538
3539   SetErrorCode(OK);
3540
3541   return aResult;
3542 }