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