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