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