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