Salome HOME
Synchronize adm files
[modules/geom.git] / src / GEOMImpl / GEOMImpl_IShapesOperations.cxx
1 // Copyright (C) 2007-2014  CEA/DEN, EDF R&D, OPEN CASCADE
2 //
3 // Copyright (C) 2003-2007  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
4 // CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
5 //
6 // This library is free software; you can redistribute it and/or
7 // modify it under the terms of the GNU Lesser General Public
8 // License as published by the Free Software Foundation; either
9 // version 2.1 of the License, or (at your option) any later version.
10 //
11 // This library is distributed in the hope that it will be useful,
12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14 // Lesser General Public License for more details.
15 //
16 // You should have received a copy of the GNU Lesser General Public
17 // License along with this library; if not, write to the Free Software
18 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
19 //
20 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
21 //
22
23 //  File      : GEOMImpl_IShapesOperations.cxx
24 //  Created   :
25 //  Author    : modified by Lioka RAZAFINDRAZAKA (CEA) 22/06/2007
26 //  Project   : SALOME
27
28 #include <Standard_Stream.hxx>
29
30 #include "GEOMImpl_IShapesOperations.hxx"
31
32 #include "GEOMImpl_Types.hxx"
33
34 #include "GEOMImpl_VectorDriver.hxx"
35 #include "GEOMImpl_ShapeDriver.hxx"
36 #include "GEOMImpl_GlueDriver.hxx"
37
38 #include "GEOMImpl_IVector.hxx"
39 #include "GEOMImpl_IShapes.hxx"
40 #include "GEOMImpl_IGlue.hxx"
41
42 #include "GEOMImpl_Block6Explorer.hxx"
43 #include "GEOMImpl_IHealingOperations.hxx"
44
45 #include "GEOMImpl_Gen.hxx"
46
47 #include "GEOM_Function.hxx"
48 #include "GEOM_ISubShape.hxx"
49 #include "GEOM_PythonDump.hxx"
50
51 #include "GEOMUtils.hxx"
52
53 #include "GEOMAlgo_ClsfBox.hxx"
54 #include "GEOMAlgo_ClsfSolid.hxx"
55 #include "GEOMAlgo_CoupleOfShapes.hxx"
56 #include "GEOMAlgo_FinderShapeOn1.hxx"
57 #include "GEOMAlgo_FinderShapeOnQuad.hxx"
58 #include "GEOMAlgo_FinderShapeOn2.hxx"
59 #include "GEOMAlgo_GetInPlace.hxx"
60 #include "GEOMAlgo_GlueDetector.hxx"
61 #include "GEOMAlgo_ListIteratorOfListOfCoupleOfShapes.hxx"
62 #include "GEOMAlgo_ListOfCoupleOfShapes.hxx"
63
64 #include <Basics_OCCTVersion.hxx>
65
66 #include <utilities.h>
67 #include <OpUtil.hxx>
68 #include <Utils_ExceptHandlers.hxx>
69
70 #include <TFunction_DriverTable.hxx>
71 #include <TFunction_Driver.hxx>
72 #include <TFunction_Logbook.hxx>
73 #include <TDataStd_Integer.hxx>
74 #include <TDataStd_IntegerArray.hxx>
75 #include <TDataStd_ListIteratorOfListOfExtendedString.hxx>
76 #include <TDF_Tool.hxx>
77
78 #include <BRepExtrema_ExtCF.hxx>
79 #include <BRepExtrema_DistShapeShape.hxx>
80
81 #include <BRep_Tool.hxx>
82 #include <BRep_Builder.hxx>
83 #include <BRepTools.hxx>
84 #include <BRepGProp.hxx>
85 #include <BRepAdaptor_Curve.hxx>
86 #include <BRepAdaptor_Surface.hxx>
87 #include <BRepBndLib.hxx>
88 #include <BRepMesh_IncrementalMesh.hxx>
89
90 #include <TopAbs.hxx>
91 #include <TopExp.hxx>
92 #include <TopExp_Explorer.hxx>
93 #include <TopLoc_Location.hxx>
94 #include <TopoDS.hxx>
95 #include <TopoDS_Shape.hxx>
96 #include <TopoDS_Solid.hxx>
97 #include <TopoDS_Face.hxx>
98 #include <TopoDS_Edge.hxx>
99 #include <TopoDS_Vertex.hxx>
100 #include <TopoDS_Compound.hxx>
101 #include <TopoDS_Iterator.hxx>
102 #include <TopTools_Array1OfShape.hxx>
103 #include <TopTools_DataMapIteratorOfDataMapOfShapeListOfShape.hxx>
104 #include <TopTools_IndexedMapOfShape.hxx>
105 #include <TopTools_ListIteratorOfListOfShape.hxx>
106 #include <TopTools_MapOfShape.hxx>
107 #include <TopTools_MapOfOrientedShape.hxx>
108
109 #include <Geom_Surface.hxx>
110 #include <Geom_Plane.hxx>
111 #include <Geom_SphericalSurface.hxx>
112 #include <Geom_CylindricalSurface.hxx>
113 #include <GeomAdaptor_Surface.hxx>
114
115 #include <GeomLib_Tool.hxx>
116 #include <Geom2d_Curve.hxx>
117
118 #include <Bnd_Box.hxx>
119 #include <GProp_GProps.hxx>
120 #include <TColStd_Array1OfReal.hxx>
121 #include <TColStd_HArray1OfInteger.hxx>
122 #include <TColStd_ListIteratorOfListOfInteger.hxx>
123 #include <TColStd_ListOfInteger.hxx>
124 #include <gp_Cylinder.hxx>
125 #include <gp_Lin.hxx>
126 #include <gp_Pnt.hxx>
127
128 #include <vector>
129 #include <algorithm>
130 #include <functional>
131
132 #include <Standard_NullObject.hxx>
133 #include <Standard_Failure.hxx>
134 #include <Standard_ErrorHandler.hxx> // CAREFUL ! position of this file is critic : see Lucien PIGNOLONI / OCC
135
136 // Includes added for GetInPlace algorithm improvement
137
138 #include <GEOMImpl_MeasureDriver.hxx>
139 #include <GEOMImpl_IMeasure.hxx>
140 #include <BRepBuilderAPI_MakeVertex.hxx>
141
142 #include <BRepClass_FaceClassifier.hxx>
143 #include <BRepClass3d_SolidClassifier.hxx>
144 #include <Precision.hxx>
145
146 //=============================================================================
147 /*!
148  *   constructor:
149  */
150 //=============================================================================
151 GEOMImpl_IShapesOperations::GEOMImpl_IShapesOperations (GEOM_Engine* theEngine, int theDocID)
152 : GEOM_IOperations(theEngine, theDocID)
153 {
154   MESSAGE("GEOMImpl_IShapesOperations::GEOMImpl_IShapesOperations");
155 }
156
157 //=============================================================================
158 /*!
159  *  destructor
160  */
161 //=============================================================================
162 GEOMImpl_IShapesOperations::~GEOMImpl_IShapesOperations()
163 {
164   MESSAGE("GEOMImpl_IShapesOperations::~GEOMImpl_IShapesOperations");
165 }
166
167 //=============================================================================
168 /*!
169  *  MakeEdge
170  */
171 //=============================================================================
172 Handle(GEOM_Object) GEOMImpl_IShapesOperations::MakeEdge
173                      (Handle(GEOM_Object) thePnt1, Handle(GEOM_Object) thePnt2)
174 {
175   SetErrorCode(KO);
176
177   if (thePnt1.IsNull() || thePnt2.IsNull()) return NULL;
178
179   //Add a new Edge object
180   Handle(GEOM_Object) anEdge = GetEngine()->AddObject(GetDocID(), GEOM_EDGE);
181
182   //Add a new Vector function
183   Handle(GEOM_Function) aFunction =
184     anEdge->AddFunction(GEOMImpl_VectorDriver::GetID(), VECTOR_TWO_PNT);
185
186   //Check if the function is set correctly
187   if (aFunction->GetDriverGUID() != GEOMImpl_VectorDriver::GetID()) return NULL;
188
189   GEOMImpl_IVector aPI (aFunction);
190
191   Handle(GEOM_Function) aRef1 = thePnt1->GetLastFunction();
192   Handle(GEOM_Function) aRef2 = thePnt2->GetLastFunction();
193   if (aRef1.IsNull() || aRef2.IsNull()) return NULL;
194
195   aPI.SetPoint1(aRef1);
196   aPI.SetPoint2(aRef2);
197
198   //Compute the Edge value
199   try {
200 #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     // entity was not changed by the operation
3648     Standard_Integer aWhatIndex = theWhereIndices.FindIndex(theWhat);
3649     theModifiedList.Append(aWhatIndex);
3650     return true;
3651   }
3652
3653   // try to find in history
3654   TDF_Label aHistoryLabel = theWhereFunction->GetHistoryEntry(Standard_False);
3655
3656   // search in history for all argument shapes
3657   Standard_Boolean isFound = Standard_False;
3658   Standard_Boolean isGood = Standard_False;
3659
3660   TDF_LabelSequence aLabelSeq;
3661   theWhereFunction->GetDependency(aLabelSeq);
3662   Standard_Integer nbArg = aLabelSeq.Length();
3663
3664   for (Standard_Integer iarg = 1; iarg <= nbArg && !isFound; iarg++) {
3665
3666     TDF_Label anArgumentRefLabel = aLabelSeq.Value(iarg);
3667
3668     Handle(GEOM_Object) anArgumentObject = GEOM_Object::GetReferencedObject(anArgumentRefLabel);
3669     TopoDS_Shape anArgumentShape = anArgumentObject->GetValue();
3670
3671     TopTools_IndexedMapOfShape anArgumentIndices;
3672     TopExp::MapShapes(anArgumentShape, anArgumentIndices);
3673
3674     if (anArgumentIndices.Contains(theWhat)) {
3675       isFound = Standard_True;
3676       Standard_Integer aWhatIndex = anArgumentIndices.FindIndex(theWhat);
3677
3678       // Find corresponding label in history
3679       TDF_Label anArgumentHistoryLabel =
3680         theWhereFunction->GetArgumentHistoryEntry(anArgumentRefLabel, Standard_False);
3681       if (anArgumentHistoryLabel.IsNull()) {
3682         // Lost History of operation argument. Possibly, all its entities was removed.
3683         isGood = Standard_True;
3684       }
3685       else {
3686         TDF_Label aWhatHistoryLabel = anArgumentHistoryLabel.FindChild(aWhatIndex, Standard_False);
3687
3688         if (aWhatHistoryLabel.IsNull()) {
3689           // Removed entity ? Compound ? Compsolid ? Shell ? Wire
3690           isGood = Standard_False;
3691         } else {
3692           Handle(TDataStd_IntegerArray) anIntegerArray;
3693           if (!aWhatHistoryLabel.FindAttribute(TDataStd_IntegerArray::GetID(), anIntegerArray)) {
3694             //Error: Empty modifications history for the sought shape.
3695             isGood = Standard_False;
3696           }
3697           else {
3698             isGood = Standard_True;
3699             Standard_Integer imod, aModifLen = anIntegerArray->Array()->Length();
3700             for (imod = 1; imod <= aModifLen; imod++) {
3701               theModifiedList.Append(anIntegerArray->Array()->Value(imod));
3702             }
3703           }
3704         }
3705       }
3706     }
3707   }
3708
3709   isFound = isGood;
3710
3711   if (!isFound) {
3712     // try compound/compsolid/shell/wire element by element
3713     bool isFoundAny = false;
3714     TopTools_MapOfShape mapShape;
3715
3716     if (theWhat.ShapeType() == TopAbs_COMPOUND ||
3717         theWhat.ShapeType() == TopAbs_COMPSOLID) {
3718       // recursive processing of compound/compsolid
3719       TopoDS_Iterator anIt (theWhat, Standard_True, Standard_True);
3720       for (; anIt.More(); anIt.Next()) {
3721         if (mapShape.Add(anIt.Value())) {
3722           TopoDS_Shape curWhat = anIt.Value();
3723           isFoundAny = GetInPlaceOfShape(theWhereFunction, theWhereIndices, curWhat, theModifiedList);
3724           if (isFoundAny) isFound = Standard_True;
3725         }
3726       }
3727     }
3728     else if (theWhat.ShapeType() == TopAbs_SHELL) {
3729       // try to replace a shell by its faces images
3730       TopExp_Explorer anExp (theWhat, TopAbs_FACE);
3731       for (; anExp.More(); anExp.Next()) {
3732         if (mapShape.Add(anExp.Current())) {
3733           TopoDS_Shape curWhat = anExp.Current();
3734           isFoundAny = GetInPlaceOfShape(theWhereFunction, theWhereIndices, curWhat, theModifiedList);
3735           if (isFoundAny) isFound = Standard_True;
3736         }
3737       }
3738     }
3739     else if (theWhat.ShapeType() == TopAbs_WIRE) {
3740       // try to replace a wire by its edges images
3741       TopExp_Explorer anExp (theWhat, TopAbs_EDGE);
3742       for (; anExp.More(); anExp.Next()) {
3743         if (mapShape.Add(anExp.Current())) {
3744           TopoDS_Shape curWhat = anExp.Current();
3745           isFoundAny = GetInPlaceOfShape(theWhereFunction, theWhereIndices, curWhat, theModifiedList);
3746           if (isFoundAny) isFound = Standard_True;
3747         }
3748       }
3749     }
3750     else {
3751       // Removed entity
3752     }
3753   }
3754
3755   return isFound;
3756 }
3757
3758 //=============================================================================
3759 /*!
3760  *  GetShapeProperties
3761  */
3762 //=============================================================================
3763 void GEOMImpl_IShapesOperations::GetShapeProperties( const TopoDS_Shape aShape, Standard_Real tab[],
3764                                                      gp_Pnt & aVertex )
3765 {
3766   GProp_GProps theProps;
3767   gp_Pnt aCenterMass;
3768   //TopoDS_Shape aPntShape;
3769   Standard_Real aShapeSize;
3770
3771   if    (aShape.ShapeType() == TopAbs_VERTEX) aCenterMass = BRep_Tool::Pnt( TopoDS::Vertex( aShape ) );
3772   else if (aShape.ShapeType() == TopAbs_EDGE) BRepGProp::LinearProperties(aShape,  theProps);
3773   else if (aShape.ShapeType() == TopAbs_FACE) BRepGProp::SurfaceProperties(aShape, theProps);
3774   else                                        BRepGProp::VolumeProperties(aShape,  theProps);
3775
3776   if (aShape.ShapeType() == TopAbs_VERTEX)
3777     aShapeSize = 1;
3778   else {
3779     aCenterMass = theProps.CentreOfMass();
3780     aShapeSize  = theProps.Mass();
3781   }
3782
3783 //   aPntShape = BRepBuilderAPI_MakeVertex(aCenterMass).Shape();
3784 //   aVertex   = BRep_Tool::Pnt( TopoDS::Vertex( aPntShape ) );
3785   aVertex = aCenterMass;
3786   tab[0] = aVertex.X();
3787   tab[1] = aVertex.Y();
3788   tab[2] = aVertex.Z();
3789   tab[3] = aShapeSize;
3790   return;
3791 }
3792
3793 namespace {
3794
3795   //================================================================================
3796   /*!
3797    * \brief Return normal to face at extrema point
3798    */
3799   //================================================================================
3800
3801   gp_Vec GetNormal (const TopoDS_Face& face, const BRepExtrema_DistShapeShape& extrema)
3802   {
3803     gp_Vec defaultNorm(1,0,0); // to have same normals on different faces
3804     try {
3805       // get UV at extrema point
3806       Standard_Real u,v, f,l;
3807       switch ( extrema.SupportTypeShape2(1) ) {
3808       case BRepExtrema_IsInFace: {
3809         extrema.ParOnFaceS2(1, u, v );
3810         break;
3811       }
3812       case BRepExtrema_IsOnEdge: {
3813         TopoDS_Edge edge = TopoDS::Edge( extrema.SupportOnShape2(1));
3814         Handle(Geom2d_Curve) pcurve = BRep_Tool::CurveOnSurface( edge, face, f,l );
3815         extrema.ParOnEdgeS2( 1, u );
3816         gp_Pnt2d uv = pcurve->Value( u );
3817         u = uv.Coord(1);
3818         v = uv.Coord(2);
3819         break;
3820       }
3821       case BRepExtrema_IsVertex: return defaultNorm;
3822       }
3823       // get derivatives
3824       BRepAdaptor_Surface surface( face, false );
3825       gp_Vec du, dv; gp_Pnt p;
3826       surface.D1( u, v, p, du, dv );
3827
3828       return du ^ dv;
3829
3830     } catch (Standard_Failure ) {
3831     }
3832     return defaultNorm;
3833   }
3834 }
3835
3836 //=============================================================================
3837 /*!
3838  *  case GetInPlace:
3839  *  default:
3840  */
3841 //=============================================================================
3842 Handle(GEOM_Object) GEOMImpl_IShapesOperations::GetInPlace (Handle(GEOM_Object) theShapeWhere,
3843                                                             Handle(GEOM_Object) theShapeWhat)
3844 {
3845   SetErrorCode(KO);
3846
3847   if (theShapeWhere.IsNull() || theShapeWhat.IsNull()) return NULL;
3848
3849   TopoDS_Shape aWhere = theShapeWhere->GetValue();
3850   TopoDS_Shape aWhat  = theShapeWhat->GetValue();
3851   TopoDS_Shape aPntShape;
3852   TopoDS_Vertex aVertex;
3853
3854   if (aWhere.IsNull() || aWhat.IsNull()) {
3855     SetErrorCode("Error: aWhere and aWhat TopoDS_Shape are Null.");
3856     return NULL;
3857   }
3858
3859   Handle(GEOM_Function) aWhereFunction = theShapeWhere->GetLastFunction();
3860   if (aWhereFunction.IsNull()) {
3861     SetErrorCode("Error: aWhereFunction is Null.");
3862     return NULL;
3863   }
3864
3865   TopTools_IndexedMapOfShape aWhereIndices;
3866   TopExp::MapShapes(aWhere, aWhereIndices);
3867
3868   TopAbs_ShapeEnum iType = TopAbs_SOLID;
3869   Standard_Real    dl_l = 1e-3;
3870   Standard_Real    min_l, Tol_0D, Tol_1D, Tol_2D, Tol_3D, Tol_Mass;
3871   Standard_Real    aXmin, aYmin, aZmin, aXmax, aYmax, aZmax;
3872   Bnd_Box          BoundingBox;
3873   gp_Pnt           aPnt, aPnt_aWhat, tab_Pnt[2];
3874   GProp_GProps     aProps;
3875
3876   // Find the iType of the aWhat shape
3877   iType = GEOMUtils::GetTypeOfSimplePart(aWhat);
3878   if (iType == TopAbs_SHAPE) {
3879     SetErrorCode("Error: An attempt to extract a shape of not supported type.");
3880     return NULL;
3881   }
3882
3883   TopExp_Explorer Exp_aWhat  ( aWhat,  iType );
3884   TopExp_Explorer Exp_aWhere ( aWhere, iType );
3885   TopExp_Explorer Exp_Edge   ( aWhere, TopAbs_EDGE );
3886
3887   // Find the shortest edge in theShapeWhere shape
3888   BRepBndLib::Add(aWhere, BoundingBox);
3889   BoundingBox.Get(aXmin, aYmin, aZmin, aXmax, aYmax, aZmax);
3890   min_l = fabs(aXmax - aXmin);
3891   if( min_l < fabs(aYmax - aYmin) ) min_l = fabs(aYmax - aYmin);
3892   if( min_l < fabs(aZmax - aZmin) ) min_l = fabs(aZmax - aZmin);
3893
3894   // Mantis issue 0020908 BEGIN
3895   if (!Exp_Edge.More()) {
3896     min_l = Precision::Confusion();
3897   }
3898   // Mantis issue 0020908 END
3899   for ( Standard_Integer nbEdge = 0; Exp_Edge.More(); Exp_Edge.Next(), nbEdge++ ) {
3900     TopExp_Explorer Exp_Vertex( Exp_Edge.Current(), TopAbs_VERTEX);
3901     for ( Standard_Integer nbVertex = 0; Exp_Vertex.More(); Exp_Vertex.Next(), nbVertex++ ) {
3902       aPnt = BRep_Tool::Pnt( TopoDS::Vertex( Exp_Vertex.Current() ) );
3903       tab_Pnt[nbVertex] = aPnt;
3904     }
3905     if ( ! tab_Pnt[0].IsEqual(tab_Pnt[1], dl_l) ) {
3906       BRepGProp::LinearProperties(Exp_Edge.Current(), aProps);
3907       if ( aProps.Mass() < min_l ) min_l = aProps.Mass();
3908     }
3909   }
3910   min_l *= dl_l;
3911
3912   // Compute tolerances
3913   Tol_0D = dl_l;
3914   Tol_1D = dl_l * min_l;
3915   Tol_2D = dl_l * ( min_l * min_l) * ( 2. + dl_l);
3916   Tol_3D = dl_l * ( min_l * min_l * min_l ) * ( 3. + (3 * dl_l) + (dl_l * dl_l) );
3917
3918   if (Tol_0D < Precision::Confusion()) Tol_0D = Precision::Confusion();
3919   if (Tol_1D < Precision::Confusion()) Tol_1D = Precision::Confusion();
3920   if (Tol_2D < Precision::Confusion()) Tol_2D = Precision::Confusion();
3921   if (Tol_3D < Precision::Confusion()) Tol_3D = Precision::Confusion();
3922
3923   Tol_Mass = Tol_3D;
3924   if ( iType == TopAbs_VERTEX )    Tol_Mass = Tol_0D;
3925   else if ( iType == TopAbs_EDGE ) Tol_Mass = Tol_1D;
3926   else if ( iType == TopAbs_FACE ) Tol_Mass = Tol_2D;
3927
3928   // Searching for the sub-shapes inside the ShapeWhere shape
3929   GEOMAlgo_GetInPlace aGIP;
3930   aGIP.SetTolerance(Tol_1D);
3931   aGIP.SetTolMass(Tol_Mass);
3932   aGIP.SetTolCG(Tol_1D);
3933
3934   aGIP.SetArgument(aWhat);
3935   aGIP.SetShapeWhere(aWhere);
3936
3937   aGIP.Perform();
3938   int iErr = aGIP.ErrorStatus();
3939   if (iErr) {
3940     SetErrorCode("Error in GEOMAlgo_GetInPlace");
3941     return NULL;
3942   }
3943
3944   // aGIP.IsFound() returns true only when the whole theShapeWhat
3945   // is found (as one shape or several parts). But we are also interested
3946   // in the partial result, that is why this check is commented.
3947   //if (!aGIP.IsFound()) {
3948   //  SetErrorCode(NOT_FOUND_ANY);
3949   //  return NULL;
3950   //}
3951
3952   // Add direct result.
3953   TopTools_ListOfShape  aLSA;
3954   const TopoDS_Shape   &aShapeResult = aGIP.Result();
3955   TopTools_MapOfShape   aMFence;
3956
3957   if (aShapeResult.IsNull() == Standard_False) {
3958     TopoDS_Iterator anIt(aShapeResult);
3959
3960     for (; anIt.More(); anIt.Next()) {
3961       const TopoDS_Shape &aPart = anIt.Value();
3962
3963       if(aWhereIndices.Contains(aPart) && aMFence.Add(aPart)) {
3964         aLSA.Append(aPart);
3965       }
3966     }
3967   }
3968
3969   if (aLSA.Extent() == 0) {
3970     SetErrorCode(NOT_FOUND_ANY); // Not found any Results
3971     return NULL;
3972   }
3973
3974   Handle(TColStd_HArray1OfInteger) aModifiedArray = new TColStd_HArray1OfInteger (1, aLSA.Extent());
3975   TopTools_ListIteratorOfListOfShape anIterModif (aLSA);
3976   for (Standard_Integer imod = 1; anIterModif.More(); anIterModif.Next(), imod++) {
3977     if (aWhereIndices.Contains(anIterModif.Value())) {
3978       aModifiedArray->SetValue(imod, aWhereIndices.FindIndex(anIterModif.Value()));
3979     }
3980     else {
3981       SetErrorCode("Error: wrong sub-shape returned");
3982       return NULL;
3983     }
3984   }
3985
3986   //Add a new object
3987   Handle(GEOM_Object) aResult = GetEngine()->AddSubShape(theShapeWhere, aModifiedArray);
3988   if (aResult.IsNull()) {
3989     SetErrorCode("Error in algorithm: result found, but cannot be returned.");
3990     return NULL;
3991   }
3992
3993   if (aModifiedArray->Length() > 1 || theShapeWhat->GetType() == GEOM_GROUP) {
3994     //Set a GROUP type
3995     aResult->SetType(GEOM_GROUP);
3996
3997     //Set a sub-shape type
3998     TopoDS_Shape aFirstFound = aLSA.First();
3999     TopAbs_ShapeEnum aShapeType = aFirstFound.ShapeType();
4000
4001     TDF_Label aFreeLabel = aResult->GetFreeLabel();
4002     TDataStd_Integer::Set(aFreeLabel, (Standard_Integer)aShapeType);
4003   }
4004
4005   //Make a Python command
4006   Handle(GEOM_Function) aFunction = aResult->GetFunction(1);
4007
4008   GEOM::TPythonDump(aFunction) << aResult << " = geompy.GetInPlace("
4009     << theShapeWhere << ", " << theShapeWhat << ", True)";
4010
4011   SetErrorCode(OK);
4012   return aResult;
4013 }
4014
4015 //=============================================================================
4016 /*!
4017  *  case GetInPlaceOld:
4018  *  default:
4019  */
4020 //=============================================================================
4021 Handle(GEOM_Object) GEOMImpl_IShapesOperations::GetInPlaceOld (Handle(GEOM_Object) theShapeWhere,
4022                                                                Handle(GEOM_Object) theShapeWhat)
4023 {
4024   SetErrorCode(KO);
4025
4026   if (theShapeWhere.IsNull() || theShapeWhat.IsNull()) return NULL;
4027
4028   TopoDS_Shape aWhere = theShapeWhere->GetValue();
4029   TopoDS_Shape aWhat  = theShapeWhat->GetValue();
4030   TopoDS_Shape aPntShape;
4031   TopoDS_Vertex aVertex;
4032
4033   if (aWhere.IsNull() || aWhat.IsNull()) {
4034     SetErrorCode("Error: aWhere and aWhat TopoDS_Shape are Null.");
4035     return NULL;
4036   }
4037
4038   Handle(GEOM_Function) aWhereFunction = theShapeWhere->GetLastFunction();
4039   if (aWhereFunction.IsNull()) {
4040     SetErrorCode("Error: aWhereFunction is Null.");
4041     return NULL;
4042   }
4043
4044   TopTools_IndexedMapOfShape aWhereIndices;
4045   TopExp::MapShapes(aWhere, aWhereIndices);
4046
4047   TColStd_ListOfInteger aModifiedList;
4048   Standard_Integer aWhereIndex;
4049   Handle(TColStd_HArray1OfInteger) aModifiedArray;
4050   Handle(GEOM_Object) aResult;
4051
4052   bool isFound = false;
4053   TopAbs_ShapeEnum iType = TopAbs_SOLID;
4054   //Standard_Real    aWhat_Mass = 0., aWhere_Mass = 0.;
4055   Standard_Real    tab_aWhat[4],    tab_aWhere[4];
4056   Standard_Real    dl_l = 1e-3;
4057   Standard_Real    min_l, Tol_0D, Tol_1D, Tol_2D, Tol_3D, Tol_Mass;
4058   Standard_Real    aXmin, aYmin, aZmin, aXmax, aYmax, aZmax;
4059   Bnd_Box          BoundingBox;
4060   gp_Pnt           aPnt, aPnt_aWhat, tab_Pnt[2];
4061   GProp_GProps     aProps;
4062
4063   // Find the iType of the aWhat shape
4064   /*
4065   if      ( aWhat.ShapeType() == TopAbs_VERTEX )                                         iType = TopAbs_VERTEX;
4066   else if ( aWhat.ShapeType() == TopAbs_EDGE  || aWhat.ShapeType() == TopAbs_WIRE )      iType = TopAbs_EDGE;
4067   else if ( aWhat.ShapeType() == TopAbs_FACE  || aWhat.ShapeType() == TopAbs_SHELL )     iType = TopAbs_FACE;
4068   else if ( aWhat.ShapeType() == TopAbs_SOLID || aWhat.ShapeType() == TopAbs_COMPSOLID ) iType = TopAbs_SOLID;
4069   else if ( aWhat.ShapeType() == TopAbs_COMPOUND ) {
4070     // Only the iType of the first shape in the compound is taken into account
4071     TopoDS_Iterator It (aWhat, Standard_False, Standard_False);
4072     if ( !It.More() ) {
4073       SetErrorCode("Error: theShapeWhat is an empty COMPOUND.");
4074       return NULL;
4075     }
4076     TopAbs_ShapeEnum compType = It.Value().ShapeType();
4077     if      ( compType == TopAbs_VERTEX )                               iType = TopAbs_VERTEX;
4078     else if ( compType == TopAbs_EDGE  || compType == TopAbs_WIRE )     iType = TopAbs_EDGE;
4079     else if ( compType == TopAbs_FACE  || compType == TopAbs_SHELL)     iType = TopAbs_FACE;
4080     else if ( compType == TopAbs_SOLID || compType == TopAbs_COMPSOLID) iType = TopAbs_SOLID;
4081   }
4082   else {
4083     SetErrorCode("Error: An attempt to extract a shape of not supported type.");
4084     return NULL;
4085   }
4086   */
4087   iType = GEOMUtils::GetTypeOfSimplePart(aWhat);
4088   if (iType == TopAbs_SHAPE) {
4089     SetErrorCode("Error: An attempt to extract a shape of not supported type.");
4090     return NULL;
4091   }
4092
4093   TopExp_Explorer Exp_aWhat  ( aWhat,  iType );
4094   TopExp_Explorer Exp_aWhere ( aWhere, iType );
4095   TopExp_Explorer Exp_Edge   ( aWhere, TopAbs_EDGE );
4096
4097   // Find the shortest edge in theShapeWhere shape
4098   BRepBndLib::Add(aWhere, BoundingBox);
4099   BoundingBox.Get(aXmin, aYmin, aZmin, aXmax, aYmax, aZmax);
4100   min_l = fabs(aXmax - aXmin);
4101   if( min_l < fabs(aYmax - aYmin) ) min_l = fabs(aYmax - aYmin);
4102   if( min_l < fabs(aZmax - aZmin) ) min_l = fabs(aZmax - aZmin);
4103   min_l /= dl_l;
4104   // Mantis issue 0020908 BEGIN
4105   if (!Exp_Edge.More()) {
4106     min_l = Precision::Confusion();
4107   }
4108   // Mantis issue 0020908 END
4109   for ( Standard_Integer nbEdge = 0; Exp_Edge.More(); Exp_Edge.Next(), nbEdge++ ) {
4110     TopExp_Explorer Exp_Vertex( Exp_Edge.Current(), TopAbs_VERTEX);
4111     for ( Standard_Integer nbVertex = 0; Exp_Vertex.More(); Exp_Vertex.Next(), nbVertex++ ) {
4112       aPnt = BRep_Tool::Pnt( TopoDS::Vertex( Exp_Vertex.Current() ) );
4113       tab_Pnt[nbVertex] = aPnt;
4114     }
4115     if ( ! tab_Pnt[0].IsEqual(tab_Pnt[1], dl_l) ) {
4116       BRepGProp::LinearProperties(Exp_Edge.Current(), aProps);
4117       if ( aProps.Mass() < min_l ) min_l = aProps.Mass();
4118     }
4119   }
4120
4121   // Compute tolerances
4122   Tol_0D = dl_l;
4123   Tol_1D = dl_l * min_l;
4124   Tol_2D = dl_l * ( min_l * min_l) * ( 2. + dl_l);
4125   Tol_3D = dl_l * ( min_l * min_l * min_l ) * ( 3. + (3 * dl_l) + (dl_l * dl_l) );
4126
4127   if (Tol_0D < Precision::Confusion()) Tol_0D = Precision::Confusion();
4128   if (Tol_1D < Precision::Confusion()) Tol_1D = Precision::Confusion();
4129   if (Tol_2D < Precision::Confusion()) Tol_2D = Precision::Confusion();
4130   if (Tol_3D < Precision::Confusion()) Tol_3D = Precision::Confusion();
4131
4132   //if (Tol_1D > 1.0) Tol_1D = 1.0;
4133   //if (Tol_2D > 1.0) Tol_2D = 1.0;
4134   //if (Tol_3D > 1.0) Tol_3D = 1.0;
4135
4136   Tol_Mass = Tol_3D;
4137   if ( iType == TopAbs_VERTEX )    Tol_Mass = Tol_0D;
4138   else if ( iType == TopAbs_EDGE ) Tol_Mass = Tol_1D;
4139   else if ( iType == TopAbs_FACE ) Tol_Mass = Tol_2D;
4140
4141   // Compute the ShapeWhat Mass
4142   /*
4143   for ( ; Exp_aWhat.More(); Exp_aWhat.Next() ) {
4144     if ( iType == TopAbs_VERTEX ) {
4145       aWhat_Mass += 1;
4146       continue;
4147     }
4148     else if ( iType == TopAbs_EDGE ) BRepGProp::LinearProperties(Exp_aWhat.Current(),  aProps);
4149     else if ( iType == TopAbs_FACE ) BRepGProp::SurfaceProperties(Exp_aWhat.Current(), aProps);
4150     else                             BRepGProp::VolumeProperties(Exp_aWhat.Current(),  aProps);
4151     aWhat_Mass += aProps.Mass();
4152   }
4153   */
4154
4155   // Searching for the sub-shapes inside the ShapeWhere shape
4156   TopTools_MapOfShape map_aWhere;
4157   for ( Exp_aWhere.ReInit(); Exp_aWhere.More(); Exp_aWhere.Next() ) {
4158     if (!map_aWhere.Add(Exp_aWhere.Current()))
4159       continue; // skip repeated shape to avoid mass addition
4160     GetShapeProperties( Exp_aWhere.Current(), tab_aWhere, aPnt );
4161     for ( Exp_aWhat.ReInit(); Exp_aWhat.More(); Exp_aWhat.Next() ) {
4162       GetShapeProperties( Exp_aWhat.Current(), tab_aWhat, aPnt_aWhat );
4163       if ( fabs(tab_aWhat[3] - tab_aWhere[3]) <= Tol_Mass && aPnt_aWhat.Distance(aPnt) <= Tol_1D )
4164         isFound = true;
4165       else {
4166         if ( (tab_aWhat[3] - tab_aWhere[3]) > Tol_Mass ) {
4167           aPntShape = BRepBuilderAPI_MakeVertex( aPnt ).Shape();
4168           aVertex   = TopoDS::Vertex( aPntShape );
4169           BRepExtrema_DistShapeShape aWhereDistance ( aVertex, Exp_aWhere.Current() );
4170           BRepExtrema_DistShapeShape aWhatDistance  ( aVertex, Exp_aWhat.Current() );
4171           if ( aWhereDistance.IsDone() && aWhatDistance.IsDone() &&
4172                fabs(aWhereDistance.Value() - aWhatDistance.Value()) <= Tol_1D )
4173           {
4174             // 0020162: "EDF 961 GEOM : Getinplace is getting additionnal orthogonal faces"
4175             // aVertex must be projected to the same point on Where and on What
4176             gp_Pnt pOnWhat  = aWhatDistance.PointOnShape2(1);
4177             gp_Pnt pOnWhere = aWhereDistance.PointOnShape2(1);
4178             isFound = ( pOnWhat.Distance(pOnWhere) <= Tol_1D );
4179             if ( isFound && iType == TopAbs_FACE )
4180             {
4181               // check normals at pOnWhat and pOnWhere
4182               const double angleTol = M_PI/180.;
4183               gp_Vec normToWhat  = GetNormal( TopoDS::Face(Exp_aWhat.Current()), aWhatDistance);
4184               gp_Vec normToWhere = GetNormal( TopoDS::Face(Exp_aWhere.Current()), aWhereDistance);
4185               if ( normToWhat * normToWhere < 0 )
4186                 normToWhat.Reverse();
4187               isFound = ( normToWhat.Angle( normToWhere ) < angleTol );
4188             }
4189           }
4190         }
4191       }
4192       if ( isFound ) {
4193         aWhereIndex = aWhereIndices.FindIndex(Exp_aWhere.Current());
4194         aModifiedList.Append(aWhereIndex);
4195         //aWhere_Mass += tab_aWhere[3];
4196         isFound = false;
4197         break;
4198       }
4199     }
4200     //if ( fabs( aWhat_Mass - aWhere_Mass ) <= Tol_Mass )
4201       //break;
4202   }
4203
4204   if (aModifiedList.Extent() == 0) { // Not found any Results
4205     SetErrorCode(NOT_FOUND_ANY);
4206     return NULL;
4207   }
4208
4209   aModifiedArray = new TColStd_HArray1OfInteger (1, aModifiedList.Extent());
4210   TColStd_ListIteratorOfListOfInteger anIterModif (aModifiedList);
4211   for (Standard_Integer imod = 1; anIterModif.More(); anIterModif.Next(), imod++)
4212     aModifiedArray->SetValue(imod, anIterModif.Value());
4213
4214   //Add a new object
4215   aResult = GetEngine()->AddSubShape(theShapeWhere, aModifiedArray);
4216   if (aResult.IsNull()) {
4217     SetErrorCode("Error in algorithm: result found, but cannot be returned.");
4218     return NULL;
4219   }
4220
4221   if (aModifiedArray->Length() > 1 || theShapeWhat->GetType() == GEOM_GROUP) {
4222     //Set a GROUP type
4223     aResult->SetType(GEOM_GROUP);
4224
4225     //Set a sub-shape type
4226     TopoDS_Shape aFirstFound = aWhereIndices.FindKey(aModifiedArray->Value(1));
4227     TopAbs_ShapeEnum aShapeType = aFirstFound.ShapeType();
4228
4229     TDF_Label aFreeLabel = aResult->GetFreeLabel();
4230     TDataStd_Integer::Set(aFreeLabel, (Standard_Integer)aShapeType);
4231   }
4232
4233   //Make a Python command
4234   Handle(GEOM_Function) aFunction = aResult->GetFunction(1);
4235
4236   GEOM::TPythonDump(aFunction) << aResult << " = geompy.GetInPlace("
4237     << theShapeWhere << ", " << theShapeWhat << ", False)";
4238
4239   SetErrorCode(OK);
4240   return aResult;
4241 }
4242
4243 //=======================================================================
4244 //function : GetInPlaceByHistory
4245 //purpose  :
4246 //=======================================================================
4247 Handle(GEOM_Object) GEOMImpl_IShapesOperations::GetInPlaceByHistory
4248                                           (Handle(GEOM_Object) theShapeWhere,
4249                                            Handle(GEOM_Object) theShapeWhat)
4250 {
4251   SetErrorCode(KO);
4252
4253   if (theShapeWhere.IsNull() || theShapeWhat.IsNull()) return NULL;
4254
4255   TopoDS_Shape aWhere = theShapeWhere->GetValue();
4256   TopoDS_Shape aWhat  = theShapeWhat->GetValue();
4257
4258   if (aWhere.IsNull() || aWhat.IsNull()) return NULL;
4259
4260   Handle(GEOM_Function) aWhereFunction = theShapeWhere->GetLastFunction();
4261   if (aWhereFunction.IsNull()) return NULL;
4262
4263   //Fill array of indices
4264   TopTools_IndexedMapOfShape aWhereIndices;
4265   TopExp::MapShapes(aWhere, aWhereIndices);
4266
4267   // process shape
4268   TColStd_ListOfInteger aModifiedList;
4269   bool isFound = GetInPlaceOfShape(aWhereFunction, aWhereIndices, aWhat, aModifiedList);
4270
4271   if (!isFound || aModifiedList.Extent() < 1) {
4272     SetErrorCode("Error: No history found for the sought shape or its sub-shapes.");
4273     return NULL;
4274   }
4275
4276   Standard_Integer nbFound = aModifiedList.Extent();
4277   TColStd_ListIteratorOfListOfInteger anIterModif (aModifiedList);
4278   if ( nbFound > 1 )
4279   {
4280     // remove sub-shapes inappropriate for group creation
4281     TopAbs_ShapeEnum subType = TopAbs_SHAPE;
4282     while ( anIterModif.More() ) {
4283       TopAbs_ShapeEnum type = aWhereIndices( anIterModif.Value() ).ShapeType();
4284       bool okForGroup = ( type == TopAbs_VERTEX || type == TopAbs_EDGE ||
4285                           type == TopAbs_FACE   || type == TopAbs_SOLID );
4286       if ( okForGroup ) {
4287         if ( subType == TopAbs_SHAPE )
4288           subType = type;
4289         else
4290           okForGroup = ( subType == type );
4291       }
4292       if ( okForGroup )
4293         anIterModif.Next();
4294       else
4295         aModifiedList.Remove( anIterModif );
4296       nbFound -= ( !okForGroup );
4297     }
4298     if ( nbFound == 0 ) {
4299       SetErrorCode("Error: result found but it's type is inappropriate for group creation.");
4300       return NULL;
4301     }
4302   }
4303
4304   Handle(TColStd_HArray1OfInteger) aModifiedArray =
4305     new TColStd_HArray1OfInteger( 1, nbFound );
4306   anIterModif.Initialize(aModifiedList);
4307   for (Standard_Integer imod = 1; anIterModif.More(); anIterModif.Next(), imod++)
4308     aModifiedArray->SetValue(imod, anIterModif.Value());
4309
4310   //Add a new object
4311   Handle(GEOM_Object) aResult = GetEngine()->AddSubShape(theShapeWhere, aModifiedArray);
4312   if (aResult.IsNull()) {
4313     SetErrorCode("Error in algorithm: result found, but cannot be returned.");
4314     return NULL;
4315   }
4316
4317   if (aModifiedArray->Length() > 1) {
4318     //Set a GROUP type
4319     aResult->SetType(GEOM_GROUP);
4320
4321     //Set a sub-shape type
4322     TopoDS_Shape aFirstFound = aWhereIndices.FindKey(aModifiedArray->Value(1));
4323     TopAbs_ShapeEnum aShapeType = aFirstFound.ShapeType();
4324
4325     TDF_Label aFreeLabel = aResult->GetFreeLabel();
4326     TDataStd_Integer::Set(aFreeLabel, (Standard_Integer)aShapeType);
4327   }
4328
4329   //Make a Python command
4330   Handle(GEOM_Function) aFunction = aResult->GetFunction(1);
4331
4332   GEOM::TPythonDump(aFunction) << aResult << " = geompy.GetInPlaceByHistory("
4333                                << theShapeWhere << ", " << theShapeWhat << ")";
4334
4335   SetErrorCode(OK);
4336   return aResult;
4337 }
4338
4339 #define MAX_TOLERANCE 1.e-7
4340
4341 //=======================================================================
4342 //function : isSameEdge
4343 //purpose  : Returns True if two edges coincide
4344 //=======================================================================
4345 static bool isSameEdge(const TopoDS_Edge& theEdge1, const TopoDS_Edge& theEdge2)
4346 {
4347   TopoDS_Vertex V11, V12, V21, V22;
4348   TopExp::Vertices(theEdge1, V11, V12);
4349   TopExp::Vertices(theEdge2, V21, V22);
4350   gp_Pnt P11 = BRep_Tool::Pnt(V11);
4351   gp_Pnt P12 = BRep_Tool::Pnt(V12);
4352   gp_Pnt P21 = BRep_Tool::Pnt(V21);
4353   gp_Pnt P22 = BRep_Tool::Pnt(V22);
4354   bool coincide = false;
4355
4356   //Check that ends of edges coincide
4357   if(P11.Distance(P21) <= MAX_TOLERANCE) {
4358     if(P12.Distance(P22) <= MAX_TOLERANCE) coincide =  true;
4359   }
4360   else if(P11.Distance(P22) <= MAX_TOLERANCE) {
4361     if(P12.Distance(P21) <= MAX_TOLERANCE) coincide = true;
4362   }
4363
4364   if(!coincide) return false;
4365
4366   if (BRep_Tool::Degenerated(theEdge1))
4367     if (BRep_Tool::Degenerated(theEdge2)) return true;
4368     else return false;
4369   else
4370     if (BRep_Tool::Degenerated(theEdge2)) return false;
4371
4372   double U11, U12, U21, U22;
4373   Handle(Geom_Curve) C1 = BRep_Tool::Curve(theEdge1, U11, U12);
4374   Handle(Geom_Curve) C2 = BRep_Tool::Curve(theEdge2, U21, U22);
4375   if(C1->DynamicType() == C2->DynamicType()) return true;
4376
4377   //Check that both edges has the same geometry
4378   double range = U12-U11;
4379   double U = U11+ range/3.0;
4380   gp_Pnt P1 = C1->Value(U);     //Compute a point on one third of the edge's length
4381   U = U11+range*2.0/3.0;
4382   gp_Pnt P2 = C1->Value(U);     //Compute a point on two thirds of the edge's length
4383
4384   if(!GeomLib_Tool::Parameter(C2, P1, MAX_TOLERANCE, U) ||  U < U21 || U > U22)
4385     return false;
4386
4387   if(P1.Distance(C2->Value(U)) > MAX_TOLERANCE) return false;
4388
4389   if(!GeomLib_Tool::Parameter(C2, P2, MAX_TOLERANCE, U) || U < U21 || U > U22)
4390     return false;
4391
4392   if(P2.Distance(C2->Value(U)) > MAX_TOLERANCE) return false;
4393
4394   return true;
4395 }
4396
4397 #include <TopoDS_TShape.hxx>
4398 //=======================================================================
4399 //function : isSameFace
4400 //purpose  : Returns True if two faces coincide
4401 //=======================================================================
4402 static bool isSameFace(const TopoDS_Face& theFace1, const TopoDS_Face& theFace2)
4403 {
4404   TopExp_Explorer E(theFace1, TopAbs_EDGE);
4405   TopTools_ListOfShape LS1, LS2;
4406   for(; E.More(); E.Next()) LS1.Append(E.Current());
4407
4408   E.Init(theFace2, TopAbs_EDGE);
4409   for(; E.More(); E.Next()) LS2.Append(E.Current());
4410
4411   //Compare the number of edges in the faces
4412   if(LS1.Extent() != LS2.Extent()) return false;
4413
4414   double aMin = RealFirst(), aMax = RealLast();
4415   double xminB1=aMax, yminB1=aMax, zminB1=aMax, xminB2=aMax, yminB2=aMax, zminB2=aMax;
4416   double xmaxB1=aMin, ymaxB1=aMin, zmaxB1=aMin, xmaxB2=aMin, ymaxB2=aMin, zmaxB2=aMin;
4417
4418   for(E.Init(theFace1, TopAbs_VERTEX); E.More(); E.Next()) {
4419     gp_Pnt P = BRep_Tool::Pnt(TopoDS::Vertex(E.Current()));
4420     if(P.X() < xminB1) xminB1 = P.X();
4421     if(P.Y() < yminB1) yminB1 = P.Y();
4422     if(P.Z() < zminB1) zminB1 = P.Z();
4423     if(P.X() > xmaxB1) xmaxB1 = P.X();
4424     if(P.Y() > ymaxB1) ymaxB1 = P.Y();
4425     if(P.Z() > zmaxB1) zmaxB1 = P.Z();
4426   }
4427
4428   for(E.Init(theFace2, TopAbs_VERTEX); E.More(); E.Next()) {
4429     gp_Pnt P = BRep_Tool::Pnt(TopoDS::Vertex(E.Current()));
4430     if(P.X() < xminB2) xminB2 = P.X();
4431     if(P.Y() < yminB2) yminB2 = P.Y();
4432     if(P.Z() < zminB2) zminB2 = P.Z();
4433     if(P.X() > xmaxB2) xmaxB2 = P.X();
4434     if(P.Y() > ymaxB2) ymaxB2 = P.Y();
4435     if(P.Z() > zmaxB2) zmaxB2 = P.Z();
4436   }
4437
4438   //Compare the bounding boxes of both faces
4439   if(gp_Pnt(xminB1, yminB1, zminB1).Distance(gp_Pnt(xminB2, yminB2, zminB2)) > MAX_TOLERANCE)
4440     return false;
4441
4442   if(gp_Pnt(xmaxB1, ymaxB1, zmaxB1).Distance(gp_Pnt(xmaxB2, ymaxB2, zmaxB2)) > MAX_TOLERANCE)
4443     return false;
4444
4445   Handle(Geom_Surface) S1 = BRep_Tool::Surface(theFace1);
4446   Handle(Geom_Surface) S2 = BRep_Tool::Surface(theFace2);
4447
4448   //Check if there a coincidence of two surfaces at least in two points
4449   double U11, U12, V11, V12, U21, U22, V21, V22;
4450   BRepTools::UVBounds(theFace1, U11, U12, V11, V12);
4451   BRepTools::UVBounds(theFace2, U21, U22, V21, V22);
4452
4453   double rangeU = U12-U11;
4454   double rangeV = V12-V11;
4455   double U = U11 + rangeU/3.0;
4456   double V = V11 + rangeV/3.0;
4457   gp_Pnt P1 = S1->Value(U, V);
4458   U = U11+rangeU*2.0/3.0;
4459   V = V11+rangeV*2.0/3.0;
4460   gp_Pnt P2 = S1->Value(U, V);
4461
4462   if (!GeomLib_Tool::Parameters(S2, P1, MAX_TOLERANCE, U, V) || U < U21 || U > U22 || V < V21 || V > V22)
4463     return false;
4464
4465   if (P1.Distance(S2->Value(U,V)) > MAX_TOLERANCE) return false;
4466
4467   if (!GeomLib_Tool::Parameters(S2, P2, MAX_TOLERANCE, U, V) || U < U21 || U > U22 || V < V21 || V > V22)
4468     return false;
4469
4470   if (P2.Distance(S2->Value(U, V)) > MAX_TOLERANCE) return false;
4471
4472   //Check that each edge of the Face1 has a counterpart in the Face2
4473   TopTools_MapOfOrientedShape aMap;
4474   TopTools_ListIteratorOfListOfShape LSI1(LS1);
4475   for(; LSI1.More(); LSI1.Next()) {
4476     TopoDS_Edge E = TopoDS::Edge(LSI1.Value());
4477     bool isFound = false;
4478     TopTools_ListIteratorOfListOfShape LSI2(LS2);
4479     for(; LSI2.More(); LSI2.Next()) {
4480       TopoDS_Shape aValue = LSI2.Value();
4481       if(aMap.Contains(aValue)) continue; //To avoid checking already found edge several times
4482       if(isSameEdge(E, TopoDS::Edge(aValue))) {
4483         aMap.Add(aValue);
4484         isFound = true;
4485         break;
4486       }
4487     }
4488     if(!isFound) return false;
4489   }
4490
4491   return true;
4492 }
4493
4494 //=======================================================================
4495 //function : isSameSolid
4496 //purpose  : Returns True if two solids coincide
4497 //=======================================================================
4498 bool isSameSolid(const TopoDS_Solid& theSolid1, const TopoDS_Solid& theSolid2)
4499 {
4500   TopExp_Explorer E(theSolid1, TopAbs_FACE);
4501   TopTools_ListOfShape LS1, LS2;
4502   for(; E.More(); E.Next()) LS1.Append(E.Current());
4503   E.Init(theSolid2, TopAbs_FACE);
4504   for(; E.More(); E.Next()) LS2.Append(E.Current());
4505
4506   if(LS1.Extent() != LS2.Extent()) return false;
4507
4508   double aMin = RealFirst(), aMax = RealLast();
4509   double xminB1=aMax, yminB1=aMax, zminB1=aMax, xminB2=aMax, yminB2=aMax, zminB2=aMax;
4510   double xmaxB1=aMin, ymaxB1=aMin, zmaxB1=aMin, xmaxB2=aMin, ymaxB2=aMin, zmaxB2=aMin;
4511
4512   for(E.Init(theSolid1, TopAbs_VERTEX); E.More(); E.Next()) {
4513     gp_Pnt P = BRep_Tool::Pnt(TopoDS::Vertex(E.Current()));
4514     if(P.X() < xminB1) xminB1 = P.X();
4515     if(P.Y() < yminB1) yminB1 = P.Y();
4516     if(P.Z() < zminB1) zminB1 = P.Z();
4517     if(P.X() > xmaxB1) xmaxB1 = P.X();
4518     if(P.Y() > ymaxB1) ymaxB1 = P.Y();
4519     if(P.Z() > zmaxB1) zmaxB1 = P.Z();
4520   }
4521
4522   for(E.Init(theSolid2, TopAbs_VERTEX); E.More(); E.Next()) {
4523     gp_Pnt P = BRep_Tool::Pnt(TopoDS::Vertex(E.Current()));
4524     if(P.X() < xminB2) xminB2 = P.X();
4525     if(P.Y() < yminB2) yminB2 = P.Y();
4526     if(P.Z() < zminB2) zminB2 = P.Z();
4527     if(P.X() > xmaxB2) xmaxB2 = P.X();
4528     if(P.Y() > ymaxB2) ymaxB2 = P.Y();
4529     if(P.Z() > zmaxB2) zmaxB2 = P.Z();
4530   }
4531
4532   //Compare the bounding boxes of both solids
4533   if(gp_Pnt(xminB1, yminB1, zminB1).Distance(gp_Pnt(xminB2, yminB2, zminB2)) > MAX_TOLERANCE)
4534     return false;
4535
4536   if(gp_Pnt(xmaxB1, ymaxB1, zmaxB1).Distance(gp_Pnt(xmaxB2, ymaxB2, zmaxB2)) > MAX_TOLERANCE)
4537     return false;
4538
4539   //Check that each face of the Solid1 has a counterpart in the Solid2
4540   TopTools_MapOfOrientedShape aMap;
4541   TopTools_ListIteratorOfListOfShape LSI1(LS1);
4542   for(; LSI1.More(); LSI1.Next()) {
4543     TopoDS_Face F = TopoDS::Face(LSI1.Value());
4544     bool isFound = false;
4545     TopTools_ListIteratorOfListOfShape LSI2(LS2);
4546     for(; LSI2.More(); LSI2.Next()) {
4547       if(aMap.Contains(LSI2.Value())) continue; //To avoid checking already found faces several times
4548       if(isSameFace(F, TopoDS::Face(LSI2.Value()))) {
4549         aMap.Add(LSI2.Value());
4550         isFound = true;
4551         break;
4552       }
4553     }
4554     if(!isFound) return false;
4555   }
4556
4557   return true;
4558 }
4559
4560 //=======================================================================
4561 //function : GetSame
4562 //purpose  :
4563 //=======================================================================
4564 Handle(GEOM_Object) GEOMImpl_IShapesOperations::GetSame(const Handle(GEOM_Object)& theShapeWhere,
4565                                                         const Handle(GEOM_Object)& theShapeWhat)
4566 {
4567   SetErrorCode(KO);
4568   if (theShapeWhere.IsNull() || theShapeWhat.IsNull()) return NULL;
4569
4570   TopoDS_Shape aWhere = theShapeWhere->GetValue();
4571   TopoDS_Shape aWhat  = theShapeWhat->GetValue();
4572
4573   if (aWhere.IsNull() || aWhat.IsNull()) return NULL;
4574
4575   int anIndex = -1;
4576   bool isFound = false;
4577   TopoDS_Shape aSubShape;
4578   TopTools_MapOfShape aMap;
4579
4580   if (aWhat.ShapeType() == TopAbs_COMPOUND || aWhat.ShapeType() == TopAbs_COMPSOLID) {
4581     TopoDS_Iterator It (aWhat, Standard_True, Standard_True);
4582     if (It.More()) aWhat = It.Value();
4583     It.Next();
4584     if (It.More()) {
4585       SetErrorCode("Compounds of two or more shapes are not allowed for aWhat argument");
4586       return NULL;
4587     }
4588   }
4589
4590   switch (aWhat.ShapeType()) {
4591     case TopAbs_VERTEX: {
4592       gp_Pnt P = BRep_Tool::Pnt(TopoDS::Vertex(aWhat));
4593       TopExp_Explorer E(aWhere, TopAbs_VERTEX);
4594       for(; E.More(); E.Next()) {
4595         if(!aMap.Add(E.Current())) continue;
4596         gp_Pnt P2 = BRep_Tool::Pnt(TopoDS::Vertex(E.Current()));
4597         if(P.Distance(P2) <= MAX_TOLERANCE) {
4598           isFound = true;
4599           aSubShape = E.Current();
4600           break;
4601         }
4602       }
4603       break;
4604                         }
4605     case TopAbs_EDGE: {
4606       TopoDS_Edge anEdge = TopoDS::Edge(aWhat);
4607       TopExp_Explorer E(aWhere, TopAbs_EDGE);
4608       for(; E.More(); E.Next()) {
4609         if(!aMap.Add(E.Current())) continue;
4610         if(isSameEdge(anEdge, TopoDS::Edge(E.Current()))) {
4611           aSubShape = E.Current();
4612           isFound = true;
4613           break;
4614         }
4615       }
4616       break;
4617                       }
4618     case TopAbs_FACE: {
4619       TopoDS_Face aFace = TopoDS::Face(aWhat);
4620       TopExp_Explorer E(aWhere, TopAbs_FACE);
4621       for(; E.More(); E.Next()) {
4622         if(!aMap.Add(E.Current())) continue;
4623         if(isSameFace(aFace, TopoDS::Face(E.Current()))) {
4624           aSubShape = E.Current();
4625           isFound = true;
4626           break;
4627         }
4628       }
4629       break;
4630                       }
4631     case TopAbs_SOLID: {
4632       TopoDS_Solid aSolid = TopoDS::Solid(aWhat);
4633       TopExp_Explorer E(aWhere, TopAbs_SOLID);
4634       for(; E.More(); E.Next()) {
4635         if(!aMap.Add(E.Current())) continue;
4636         if(isSameSolid(aSolid, TopoDS::Solid(E.Current()))) {
4637           aSubShape = E.Current();
4638           isFound = true;
4639           break;
4640         }
4641       }
4642       break;
4643                        }
4644     default:
4645       return NULL;
4646   }
4647
4648   if (isFound) {
4649     TopTools_IndexedMapOfShape anIndices;
4650     TopExp::MapShapes(aWhere, anIndices);
4651     if (anIndices.Contains(aSubShape))
4652       anIndex = anIndices.FindIndex(aSubShape);
4653   }
4654
4655   if (anIndex < 0) return NULL;
4656
4657   Handle(TColStd_HArray1OfInteger) anArray = new TColStd_HArray1OfInteger(1,1);
4658
4659   anArray->SetValue(1, anIndex);
4660
4661   Handle(GEOM_Object) aResult = GetEngine()->AddSubShape(theShapeWhere, anArray);
4662   Handle(GEOM_Function) aFunction = aResult->GetLastFunction();
4663
4664   GEOM::TPythonDump(aFunction) << aResult << " = geompy.GetSame("
4665     << theShapeWhere << ", " << theShapeWhat << ")";
4666
4667   SetErrorCode(OK);
4668
4669   return aResult;
4670 }
4671
4672
4673 //=======================================================================
4674 //function : GetSameIDs
4675 //purpose  :
4676 //=======================================================================
4677 Handle(TColStd_HSequenceOfInteger) GEOMImpl_IShapesOperations::GetSameIDs
4678                                                        (const Handle(GEOM_Object)& theShapeWhere,
4679                                                         const Handle(GEOM_Object)& theShapeWhat)
4680 {
4681   SetErrorCode(KO);
4682   if (theShapeWhere.IsNull() || theShapeWhat.IsNull()) return NULL;
4683
4684   TopoDS_Shape aWhere = theShapeWhere->GetValue();
4685   TopoDS_Shape aWhat  = theShapeWhat->GetValue();
4686
4687   if (aWhere.IsNull() || aWhat.IsNull()) return NULL;
4688
4689   TopTools_ListOfShape listShape;
4690   TopTools_MapOfShape aMap;
4691
4692   if (aWhat.ShapeType() == TopAbs_COMPOUND || aWhat.ShapeType() == TopAbs_COMPSOLID) {
4693     TopoDS_Iterator It (aWhat, Standard_True, Standard_True);
4694     if (It.More()) aWhat = It.Value();
4695     It.Next();
4696     if (It.More()) {
4697       SetErrorCode("Compounds of two or more shapes are not allowed for aWhat argument");
4698       return NULL;
4699     }
4700   }
4701
4702   switch (aWhat.ShapeType()) {
4703     case TopAbs_VERTEX: {
4704       gp_Pnt P = BRep_Tool::Pnt(TopoDS::Vertex(aWhat));
4705       TopExp_Explorer E(aWhere, TopAbs_VERTEX);
4706       for(; E.More(); E.Next()) {
4707         if(!aMap.Add(E.Current())) continue;
4708         gp_Pnt P2 = BRep_Tool::Pnt(TopoDS::Vertex(E.Current()));
4709         if(P.Distance(P2) <= MAX_TOLERANCE) {
4710           listShape.Append(E.Current());
4711         }
4712       }
4713       break;
4714                         }
4715     case TopAbs_EDGE: {
4716       TopoDS_Edge anEdge = TopoDS::Edge(aWhat);
4717       TopExp_Explorer E(aWhere, TopAbs_EDGE);
4718       for(; E.More(); E.Next()) {
4719         if(!aMap.Add(E.Current())) continue;
4720         if(isSameEdge(anEdge, TopoDS::Edge(E.Current()))) {
4721           listShape.Append(E.Current());
4722         }
4723       }
4724       break;
4725                       }
4726     case TopAbs_FACE: {
4727       TopoDS_Face aFace = TopoDS::Face(aWhat);
4728       TopExp_Explorer E(aWhere, TopAbs_FACE);
4729       for(; E.More(); E.Next()) {
4730         if(!aMap.Add(E.Current())) continue;
4731         if(isSameFace(aFace, TopoDS::Face(E.Current()))) {
4732           listShape.Append(E.Current());
4733         }
4734       }
4735       break;
4736                       }
4737     case TopAbs_SOLID: {
4738       TopoDS_Solid aSolid = TopoDS::Solid(aWhat);
4739       TopExp_Explorer E(aWhere, TopAbs_SOLID);
4740       for(; E.More(); E.Next()) {
4741         if(!aMap.Add(E.Current())) continue;
4742         if(isSameSolid(aSolid, TopoDS::Solid(E.Current()))) {
4743           listShape.Append(E.Current());
4744         }
4745       }
4746       break;
4747                        }
4748     default:
4749       return NULL;
4750   }
4751
4752   if ( !listShape.IsEmpty() ) {
4753     TopTools_IndexedMapOfShape anIndices;
4754     TopExp::MapShapes(aWhere, anIndices);
4755     TopTools_ListIteratorOfListOfShape itSub (listShape);
4756     Handle(TColStd_HSequenceOfInteger) aSeq = new TColStd_HSequenceOfInteger;
4757     for (; itSub.More(); itSub.Next()) {
4758       if (anIndices.Contains(itSub.Value()))
4759         aSeq->Append(anIndices.FindIndex(itSub.Value()));
4760     }
4761     SetErrorCode(OK);
4762     // The GetSameIDs() doesn't change object so no new function is required.
4763     Handle(GEOM_Function) aFunction = GEOM::GetCreatedLast(theShapeWhere,theShapeWhat)->GetLastFunction();
4764
4765   // Make a Python command
4766   GEOM::TPythonDump(aFunction, /*append=*/true)
4767     << "listSameIDs = geompy.GetSameIDs("
4768     << theShapeWhere << ", "
4769     << theShapeWhat << ")";
4770     return aSeq;
4771   } else {
4772     SetErrorCode(NOT_FOUND_ANY);
4773     return NULL;
4774   }
4775 }