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