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