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