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