Salome HOME
Mantis issue 0021532: EDF 2202 GEOM: Problem when restoring groups containing a singl...
[modules/geom.git] / src / GEOMImpl / GEOMImpl_IShapesOperations.cxx
1 // Copyright (C) 2007-2011  CEA/DEN, EDF R&D, OPEN CASCADE
2 //
3 // Copyright (C) 2003-2007  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
4 // CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
5 //
6 // This library is free software; you can redistribute it and/or
7 // modify it under the terms of the GNU Lesser General Public
8 // License as published by the Free Software Foundation; either
9 // version 2.1 of the License.
10 //
11 // This library is distributed in the hope that it will be useful,
12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14 // Lesser General Public License for more details.
15 //
16 // You should have received a copy of the GNU Lesser General Public
17 // License along with this library; if not, write to the Free Software
18 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
19 //
20 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
21
22 //  File      : GEOMImpl_IShapesOperations.cxx
23 //  Created   :
24 //  Author    : modified by Lioka RAZAFINDRAZAKA (CEA) 22/06/2007
25 //  Project   : SALOME
26
27 #include <Standard_Stream.hxx>
28
29 #include "GEOMImpl_IShapesOperations.hxx"
30
31 #include "GEOMImpl_Types.hxx"
32
33 #include "GEOMImpl_VectorDriver.hxx"
34 #include "GEOMImpl_ShapeDriver.hxx"
35 #include "GEOMImpl_CopyDriver.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 "GEOMAlgo_ClsfBox.hxx"
52 #include "GEOMAlgo_ClsfSolid.hxx"
53 #include "GEOMAlgo_CoupleOfShapes.hxx"
54 #include "GEOMAlgo_FinderShapeOn1.hxx"
55 #include "GEOMAlgo_FinderShapeOnQuad.hxx"
56 #include "GEOMAlgo_FinderShapeOn2.hxx"
57 #include "GEOMAlgo_GetInPlace.hxx"
58 #include "GEOMAlgo_GlueDetector.hxx"
59 #include "GEOMAlgo_ListIteratorOfListOfCoupleOfShapes.hxx"
60 #include "GEOMAlgo_ListOfCoupleOfShapes.hxx"
61
62 #include <Basics_OCCTVersion.hxx>
63
64 #include "utilities.h"
65 #include "OpUtil.hxx"
66 #include "Utils_ExceptHandlers.hxx"
67
68 #include <TFunction_DriverTable.hxx>
69 #include <TFunction_Driver.hxx>
70 #include <TFunction_Logbook.hxx>
71 #include <TDataStd_Integer.hxx>
72 #include <TDataStd_IntegerArray.hxx>
73 #include <TDataStd_ListIteratorOfListOfExtendedString.hxx>
74 #include <TDF_Tool.hxx>
75
76 #include <BRepExtrema_ExtCF.hxx>
77 #include <BRepExtrema_DistShapeShape.hxx>
78
79 #include <BRep_Tool.hxx>
80 #include <BRep_Builder.hxx>
81 #include <BRepTools.hxx>
82 #include <BRepGProp.hxx>
83 #include <BRepAdaptor_Curve.hxx>
84 #include <BRepAdaptor_Surface.hxx>
85 #include <BRepBndLib.hxx>
86 #include <BRepMesh_IncrementalMesh.hxx>
87
88 #include <TopAbs.hxx>
89 #include <TopExp.hxx>
90 #include <TopExp_Explorer.hxx>
91 #include <TopLoc_Location.hxx>
92 #include <TopoDS.hxx>
93 #include <TopoDS_Shape.hxx>
94 #include <TopoDS_Solid.hxx>
95 #include <TopoDS_Face.hxx>
96 #include <TopoDS_Edge.hxx>
97 #include <TopoDS_Vertex.hxx>
98 #include <TopoDS_Compound.hxx>
99 #include <TopoDS_Iterator.hxx>
100 #include <TopTools_Array1OfShape.hxx>
101 #include <TopTools_DataMapIteratorOfDataMapOfShapeListOfShape.hxx>
102 #include <TopTools_IndexedMapOfShape.hxx>
103 #include <TopTools_ListIteratorOfListOfShape.hxx>
104 #include <TopTools_MapOfShape.hxx>
105 #include <TopTools_MapOfOrientedShape.hxx>
106
107 #include <Geom_Surface.hxx>
108 #include <Geom_Plane.hxx>
109 #include <Geom_SphericalSurface.hxx>
110 #include <Geom_CylindricalSurface.hxx>
111 #include <GeomAdaptor_Surface.hxx>
112
113 #include <GeomLib_Tool.hxx>
114 #include <Geom2d_Curve.hxx>
115
116 #include <Bnd_Box.hxx>
117 #include <GProp_GProps.hxx>
118 #include <TColStd_Array1OfReal.hxx>
119 #include <TColStd_HArray1OfInteger.hxx>
120 #include <TColStd_ListIteratorOfListOfInteger.hxx>
121 #include <TColStd_ListOfInteger.hxx>
122 #include <gp_Cylinder.hxx>
123 #include <gp_Lin.hxx>
124 #include <gp_Pnt.hxx>
125
126 #include <vector>
127 #include <algorithm>
128 #include <functional>
129
130 #include <Standard_NullObject.hxx>
131 #include <Standard_Failure.hxx>
132 #include <Standard_ErrorHandler.hxx> // CAREFUL ! position of this file is critic : see Lucien PIGNOLONI / OCC
133
134 // Includes added for GetInPlace algorithm improvement
135
136 #include <GEOMImpl_MeasureDriver.hxx>
137 #include <GEOMImpl_IMeasure.hxx>
138 #include <BRepBuilderAPI_MakeVertex.hxx>
139
140 #include <BRepClass_FaceClassifier.hxx>
141 #include <BRepClass3d_SolidClassifier.hxx>
142 #include <Precision.hxx>
143
144 #define STD_SORT_ALGO 1
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   GEOMImpl_IShapesOperations::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];
1181     anEntry.ToUTF8CString(anEntryStr);
1182     Handle(GEOM_Object) anObj = GetEngine()->GetObject(GetDocID(), anEntryStr, false);
1183     if (!anObj.IsNull()) {
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     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     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
1566   return -1;
1567 }
1568
1569 //=============================================================================
1570 /*!
1571  *  GetTopologyIndex
1572  */
1573 //=============================================================================
1574 Standard_Integer GEOMImpl_IShapesOperations::GetTopologyIndex (Handle(GEOM_Object) theMainShape,
1575                                                                Handle(GEOM_Object) theSubShape)
1576 {
1577   SetErrorCode(OK);
1578
1579   TopoDS_Shape aMainShape = theMainShape->GetValue();
1580   TopoDS_Shape aSubShape = theSubShape->GetValue();
1581
1582   if (aMainShape.IsNull() || aSubShape.IsNull()) {
1583     SetErrorCode("Null argument shape given");
1584     return -1;
1585   }
1586
1587   int index = 1;
1588   if (aSubShape.ShapeType() == TopAbs_COMPOUND) {
1589     TopoDS_Iterator it;
1590     TopTools_ListOfShape CL;
1591     CL.Append(aMainShape);
1592     TopTools_ListIteratorOfListOfShape itC;
1593     for (itC.Initialize(CL); itC.More(); itC.Next()) {
1594       for (it.Initialize(itC.Value()); it.More(); it.Next()) {
1595         if (it.Value().ShapeType() == TopAbs_COMPOUND) {
1596           if (it.Value().IsSame(aSubShape))
1597             return index;
1598           else
1599             index++;
1600           CL.Append(it.Value());
1601         }
1602       }
1603     }
1604   } else {
1605     TopExp_Explorer anExp (aMainShape, aSubShape.ShapeType());
1606     TopTools_MapOfShape M;
1607     for (; anExp.More(); anExp.Next()) {
1608       if (M.Add(anExp.Current())) {
1609         if (anExp.Current().IsSame(aSubShape))
1610           return index;
1611         index++;
1612       }
1613     }
1614   }
1615
1616   SetErrorCode("The sub-shape does not belong to the main shape");
1617   return -1;
1618 }
1619
1620 //=============================================================================
1621 /*!
1622  *  GetShapeTypeString
1623  */
1624 //=============================================================================
1625 TCollection_AsciiString GEOMImpl_IShapesOperations::GetShapeTypeString (Handle(GEOM_Object) theShape)
1626 {
1627   SetErrorCode(KO);
1628
1629   TCollection_AsciiString aTypeName ("Null Shape");
1630
1631   TopoDS_Shape aShape = theShape->GetValue();
1632   if (aShape.IsNull())
1633     return aTypeName;
1634
1635   switch (aShape.ShapeType() )
1636   {
1637   case TopAbs_COMPOUND:
1638     aTypeName = "Compound";
1639     break;
1640   case  TopAbs_COMPSOLID:
1641     aTypeName = "Compound Solid";
1642     break;
1643   case TopAbs_SOLID:
1644     aTypeName = "Solid";
1645     break;
1646   case TopAbs_SHELL:
1647     aTypeName = "Shell";
1648     break;
1649   case TopAbs_FACE:
1650     {
1651       BRepAdaptor_Surface surf (TopoDS::Face(aShape));
1652       if (surf.GetType() == GeomAbs_Plane)
1653         aTypeName = "Plane";
1654       else if (surf.GetType() == GeomAbs_Cylinder)
1655         aTypeName = "Cylindrical Face";
1656       else if (surf.GetType() == GeomAbs_Sphere)
1657         aTypeName = "Spherical Face";
1658       else if (surf.GetType() == GeomAbs_Torus)
1659         aTypeName = "Toroidal Face";
1660       else if (surf.GetType() == GeomAbs_Cone)
1661         aTypeName = "Conical Face";
1662       else
1663         aTypeName = "GEOM::FACE";
1664     }
1665     break;
1666   case TopAbs_WIRE:
1667     aTypeName = "Wire";
1668     break;
1669   case TopAbs_EDGE:
1670     {
1671       BRepAdaptor_Curve curv (TopoDS::Edge(aShape));
1672       if (curv.GetType() == GeomAbs_Line) {
1673         if ((Abs(curv.FirstParameter()) >= 1E6) ||
1674             (Abs(curv.LastParameter()) >= 1E6))
1675           aTypeName = "Line";
1676         else
1677           aTypeName = "Edge";
1678       } else if (curv.GetType() == GeomAbs_Circle) {
1679         if (curv.IsClosed())
1680           aTypeName = "Circle";
1681         else
1682           aTypeName = "Arc";
1683       } else {
1684         aTypeName = "Edge";
1685       }
1686     }
1687     break;
1688   case TopAbs_VERTEX:
1689     aTypeName = "Vertex";
1690     break;
1691   case TopAbs_SHAPE:
1692     aTypeName = "Shape";
1693     break;
1694   default:
1695     aTypeName = "Shape of unknown type";
1696   }
1697
1698   return aTypeName;
1699 }
1700
1701 //=============================================================================
1702 /*!
1703  *  NumberOfSubShapes
1704  */
1705 //=============================================================================
1706 Standard_Integer GEOMImpl_IShapesOperations::NumberOfSubShapes
1707                                           (Handle(GEOM_Object)    theShape,
1708                                            const Standard_Integer theShapeType)
1709 {
1710   SetErrorCode(KO);
1711   Standard_Integer nbShapes = 0;
1712
1713   if (theShape.IsNull()) return -1;
1714   TopoDS_Shape aShape = theShape->GetValue();
1715   if (aShape.IsNull()) return -1;
1716
1717   /*
1718   TopTools_MapOfShape mapShape;
1719
1720   if (aShape.ShapeType() == TopAbs_COMPOUND &&
1721       (TopAbs_ShapeEnum(theShapeType) == TopAbs_SHAPE ||
1722        TopAbs_ShapeEnum(theShapeType) == TopAbs_COMPSOLID ||
1723        TopAbs_ShapeEnum(theShapeType) == TopAbs_COMPOUND)) {
1724     TopoDS_Iterator It (aShape, Standard_True, Standard_True);
1725     for (; It.More(); It.Next()) {
1726       if (mapShape.Add(It.Value())) {
1727         if (TopAbs_ShapeEnum(theShapeType) == TopAbs_SHAPE ||
1728             TopAbs_ShapeEnum(theShapeType) == It.Value().ShapeType()) {
1729           nbShapes++;
1730         }
1731       }
1732     }
1733   } else {
1734     TopExp_Explorer exp (aShape, TopAbs_ShapeEnum(theShapeType));
1735     for (; exp.More(); exp.Next())
1736       if (mapShape.Add(exp.Current()))
1737         nbShapes++;
1738   }
1739   */
1740
1741   try {
1742 #if OCC_VERSION_LARGE > 0x06010000
1743     OCC_CATCH_SIGNALS;
1744 #endif
1745     int iType, nbTypes [TopAbs_SHAPE];
1746     for (iType = 0; iType < TopAbs_SHAPE; ++iType)
1747       nbTypes[iType] = 0;
1748     nbTypes[aShape.ShapeType()]++;
1749
1750     TopTools_MapOfShape aMapOfShape;
1751     aMapOfShape.Add(aShape);
1752     TopTools_ListOfShape aListOfShape;
1753     aListOfShape.Append(aShape);
1754
1755     TopTools_ListIteratorOfListOfShape itL (aListOfShape);
1756     for (; itL.More(); itL.Next()) {
1757       TopoDS_Iterator it (itL.Value());
1758       for (; it.More(); it.Next()) {
1759         TopoDS_Shape s = it.Value();
1760         if (aMapOfShape.Add(s)) {
1761           aListOfShape.Append(s);
1762           nbTypes[s.ShapeType()]++;
1763         }
1764       }
1765     }
1766
1767     if (TopAbs_ShapeEnum(theShapeType) == TopAbs_SHAPE)
1768       nbShapes = aMapOfShape.Extent();
1769     else
1770       nbShapes = nbTypes[theShapeType];
1771   }
1772   catch (Standard_Failure) {
1773     Handle(Standard_Failure) aFail = Standard_Failure::Caught();
1774     SetErrorCode(aFail->GetMessageString());
1775     return -1;
1776   }
1777
1778   SetErrorCode(OK);
1779   return nbShapes;
1780 }
1781
1782 //=============================================================================
1783 /*!
1784  *  ReverseShape
1785  */
1786 //=============================================================================
1787 Handle(GEOM_Object) GEOMImpl_IShapesOperations::ReverseShape(Handle(GEOM_Object) theShape)
1788 {
1789   SetErrorCode(KO);
1790
1791   if (theShape.IsNull()) return NULL;
1792
1793   /*
1794   //Add a new reversed object
1795   Handle(GEOM_Object) aReversed = GetEngine()->AddObject(GetDocID(), theShape->GetType());
1796
1797   //Add a new Revese function
1798   Handle(GEOM_Function) aFunction;
1799   aFunction = aReversed->AddFunction(GEOMImpl_ShapeDriver::GetID(), REVERSE_ORIENTATION);
1800   if (aFunction.IsNull()) return NULL;
1801
1802   //Check if the function is set correctly
1803   if (aFunction->GetDriverGUID() != GEOMImpl_ShapeDriver::GetID()) return NULL;
1804
1805   GEOMImpl_IShapes aSI (aFunction);
1806
1807   Handle(GEOM_Function) aRefShape = theShape->GetLastFunction();
1808   if (aRefShape.IsNull()) return NULL;
1809
1810   aSI.SetBase(aRefShape);
1811
1812   //Compute the sub-shape value
1813   try {
1814 #if OCC_VERSION_LARGE > 0x06010000
1815     OCC_CATCH_SIGNALS;
1816 #endif
1817     if (!GetSolver()->ComputeFunction(aFunction)) {
1818       SetErrorCode("Shape driver failed to reverse shape");
1819       return NULL;
1820     }
1821   }
1822   catch (Standard_Failure) {
1823     Handle(Standard_Failure) aFail = Standard_Failure::Caught();
1824     SetErrorCode(aFail->GetMessageString());
1825     return NULL;
1826   }
1827
1828   //Make a Python command
1829   GEOM::TPythonDump(aFunction) << aReversed
1830     << " = geompy.ChangeOrientation(" << theShape << ")";
1831
1832   SetErrorCode(OK);
1833   */
1834
1835   Handle(GEOM_Object) aReversed;
1836
1837   GEOM_Engine* anEngine = GetEngine();
1838   //GEOMImpl_Gen* aGen = dynamic_cast<GEOMImpl_Gen*>(anEngine);
1839   GEOMImpl_Gen* aGen = (GEOMImpl_Gen*)anEngine;
1840
1841   if (aGen) {
1842     GEOMImpl_IHealingOperations* anIHealingOperations =
1843       aGen->GetIHealingOperations(GetDocID());
1844     aReversed = anIHealingOperations->ChangeOrientationCopy(theShape);
1845     SetErrorCode(anIHealingOperations->GetErrorCode());
1846   }
1847
1848   return aReversed;
1849 }
1850
1851 //=============================================================================
1852 /*!
1853  *  GetFreeFacesIDs
1854  */
1855 //=============================================================================
1856 Handle(TColStd_HSequenceOfInteger) GEOMImpl_IShapesOperations::GetFreeFacesIDs
1857                                                  (Handle(GEOM_Object) theShape)
1858 {
1859   SetErrorCode(KO);
1860
1861   if (theShape.IsNull()) return NULL;
1862   TopoDS_Shape aShape = theShape->GetValue();
1863   if (aShape.IsNull()) return NULL;
1864
1865   Handle(TColStd_HSequenceOfInteger) aSeq = new TColStd_HSequenceOfInteger;
1866
1867   TopTools_IndexedDataMapOfShapeListOfShape mapFaceBlocks;
1868   GEOMImpl_Block6Explorer::MapShapesAndAncestors
1869     (aShape, TopAbs_FACE, TopAbs_SOLID, mapFaceBlocks);
1870
1871   Standard_Integer ind = 1, nbFaces = mapFaceBlocks.Extent();
1872
1873   if (nbFaces == 0) {
1874     SetErrorCode("The given shape has no faces");
1875     return aSeq;
1876   }
1877
1878   TopTools_IndexedMapOfShape anIndices;
1879   TopExp::MapShapes(aShape, anIndices);
1880
1881   Standard_Integer id;
1882   for (; ind <= nbFaces; ind++) {
1883     if (mapFaceBlocks.FindFromIndex(ind).Extent() != 2) {
1884       id = anIndices.FindIndex(mapFaceBlocks.FindKey(ind));
1885       aSeq->Append(id);
1886     }
1887   }
1888
1889   //The explode doesn't change object so no new function is required.
1890   Handle(GEOM_Function) aFunction = theShape->GetLastFunction();
1891
1892   //Make a Python command
1893   GEOM::TPythonDump(aFunction, /*append=*/true)
1894     << "listFreeFacesIDs = geompy.GetFreeFacesIDs(" << theShape << ")";
1895
1896   SetErrorCode(OK);
1897   return aSeq;
1898 }
1899
1900 //=======================================================================
1901 //function : GetSharedShapes
1902 //purpose  :
1903 //=======================================================================
1904 Handle(TColStd_HSequenceOfTransient) GEOMImpl_IShapesOperations::GetSharedShapes
1905                                                 (Handle(GEOM_Object)    theShape1,
1906                                                  Handle(GEOM_Object)    theShape2,
1907                                                  const Standard_Integer theShapeType)
1908 {
1909   SetErrorCode(KO);
1910
1911   if (theShape1.IsNull() || theShape2.IsNull()) return NULL;
1912
1913   TopoDS_Shape aShape1 = theShape1->GetValue();
1914   TopoDS_Shape aShape2 = theShape2->GetValue();
1915
1916   if (aShape1.IsNull() || aShape2.IsNull()) return NULL;
1917
1918   TopTools_IndexedMapOfShape anIndices;
1919   TopExp::MapShapes(aShape1, anIndices);
1920   Handle(TColStd_HArray1OfInteger) anArray;
1921
1922   TopTools_IndexedMapOfShape mapShape1;
1923   TopExp::MapShapes(aShape1, TopAbs_ShapeEnum(theShapeType), mapShape1);
1924
1925   Handle(GEOM_Object) anObj;
1926   Handle(TColStd_HSequenceOfTransient) aSeq = new TColStd_HSequenceOfTransient;
1927   TCollection_AsciiString anAsciiList, anEntry;
1928
1929   TopTools_MapOfShape mapShape2;
1930   TopExp_Explorer exp (aShape2, TopAbs_ShapeEnum(theShapeType));
1931   for (; exp.More(); exp.Next()) {
1932     TopoDS_Shape aSS = exp.Current();
1933     if (mapShape2.Add(aSS) && mapShape1.Contains(aSS)) {
1934       anArray = new TColStd_HArray1OfInteger(1,1);
1935       anArray->SetValue(1, anIndices.FindIndex(aSS));
1936       anObj = GetEngine()->AddSubShape(theShape1, anArray);
1937       aSeq->Append(anObj);
1938
1939       // for python command
1940       TDF_Tool::Entry(anObj->GetEntry(), anEntry);
1941       anAsciiList += anEntry;
1942       anAsciiList += ",";
1943     }
1944   }
1945
1946   if (aSeq->IsEmpty()) {
1947     SetErrorCode("The given shapes have no shared sub-shapes of the requested type");
1948     return aSeq;
1949   }
1950
1951   //Make a Python command
1952   anAsciiList.Trunc(anAsciiList.Length() - 1);
1953
1954   Handle(GEOM_Function) aFunction = anObj->GetLastFunction();
1955
1956   GEOM::TPythonDump(aFunction) << "[" << anAsciiList.ToCString()
1957     << "] = geompy.GetSharedShapes(" << theShape1 << ", "
1958       << theShape2 << ", " << TopAbs_ShapeEnum(theShapeType) << ")";
1959
1960   SetErrorCode(OK);
1961   return aSeq;
1962 }
1963
1964 //=======================================================================
1965 //function : GetSharedShapes
1966 //purpose  :
1967 //=======================================================================
1968 Handle(TColStd_HSequenceOfTransient) GEOMImpl_IShapesOperations::GetSharedShapes
1969                                      (std::list<Handle(GEOM_Object)> theShapes,
1970                                       const Standard_Integer         theShapeType)
1971 {
1972   SetErrorCode(KO);
1973
1974   int aLen = theShapes.size();
1975   if (aLen < 1) return NULL;
1976
1977   int ind = 1;
1978   std::list<Handle(GEOM_Object)>::iterator it = theShapes.begin();
1979
1980   Handle(GEOM_Object) aMainObj = (*it++);
1981   Handle(GEOM_Function) aMainShape = aMainObj->GetLastFunction();
1982   if (aMainShape.IsNull()) {
1983     SetErrorCode("NULL shape for GetSharedShapes");
1984     return NULL;
1985   }
1986
1987   TopoDS_Shape aShape1 = aMainShape->GetValue();
1988   if (aShape1.IsNull()) return NULL;
1989
1990   TopTools_IndexedMapOfShape anIndices;
1991   TopExp::MapShapes(aShape1, anIndices);
1992
1993   TopTools_IndexedMapOfShape mapSelected;
1994   TopExp::MapShapes(aShape1, TopAbs_ShapeEnum(theShapeType), mapSelected);
1995
1996   // Find shared shapes
1997   BRep_Builder B;
1998   TopoDS_Compound aCurrSelection;
1999
2000   for (; it != theShapes.end(); it++, ind++) {
2001     Handle(GEOM_Function) aRefShape = (*it)->GetLastFunction();
2002     if (aRefShape.IsNull()) {
2003       SetErrorCode("NULL shape for GetSharedShapes");
2004       return NULL;
2005     }
2006
2007     TopoDS_Compound aCompound;
2008     B.MakeCompound(aCompound);
2009
2010     TopoDS_Shape aShape2 = aRefShape->GetValue();
2011     if (aShape2.IsNull()) return NULL;
2012
2013     TopTools_MapOfShape mapShape2;
2014     TopExp_Explorer exp (aShape2, TopAbs_ShapeEnum(theShapeType));
2015     for (; exp.More(); exp.Next()) {
2016       TopoDS_Shape aSS = exp.Current();
2017       if (mapShape2.Add(aSS) && mapSelected.Contains(aSS)) {
2018         B.Add(aCompound, aSS);
2019       }
2020     }
2021
2022     mapSelected.Clear();
2023     TopExp::MapShapes(aCompound, TopAbs_ShapeEnum(theShapeType), mapSelected);
2024     aCurrSelection = aCompound;
2025   }
2026
2027   // Create GEOM_Object for each found shared shape (collected in aCurrSelection)
2028   Handle(GEOM_Object) anObj;
2029   Handle(TColStd_HArray1OfInteger) anArray;
2030   Handle(TColStd_HSequenceOfTransient) aSeq = new TColStd_HSequenceOfTransient;
2031   TCollection_AsciiString anAsciiList, anEntry;
2032
2033   TopoDS_Iterator itSel (aCurrSelection, Standard_True, Standard_True);
2034   for (; itSel.More(); itSel.Next()) {
2035     anArray = new TColStd_HArray1OfInteger(1,1);
2036     anArray->SetValue(1, anIndices.FindIndex(itSel.Value()));
2037     anObj = GetEngine()->AddSubShape(aMainObj, anArray);
2038     aSeq->Append(anObj);
2039
2040     // for python command
2041     TDF_Tool::Entry(anObj->GetEntry(), anEntry);
2042     anAsciiList += anEntry;
2043     anAsciiList += ",";
2044   }
2045
2046   if (aSeq->IsEmpty()) {
2047     SetErrorCode("The given shapes have no shared sub-shapes of the requested type");
2048     return aSeq;
2049   }
2050
2051   // Make a Python command
2052   anAsciiList.Trunc(anAsciiList.Length() - 1);
2053
2054   GEOM::TPythonDump pd (aMainShape, /*append=*/true);
2055   pd << "[" << anAsciiList.ToCString()
2056      << "] = geompy.GetSharedShapesMulti([";
2057
2058   it = theShapes.begin();
2059   pd << (*it++);
2060   while (it != theShapes.end()) {
2061     pd << ", " << (*it++);
2062   }
2063
2064   pd << "], " << TopAbs_ShapeEnum(theShapeType) << ")";
2065
2066   SetErrorCode(OK);
2067   return aSeq;
2068 }
2069
2070 //=============================================================================
2071 /*!
2072  *
2073  */
2074 //=============================================================================
2075 static GEOM::TPythonDump& operator<< (GEOM::TPythonDump&   theDump,
2076                                       const GEOMAlgo_State theState)
2077 {
2078   switch (theState) {
2079   case GEOMAlgo_ST_IN:
2080     theDump << "geompy.GEOM.ST_IN";
2081     break;
2082   case GEOMAlgo_ST_OUT:
2083     theDump << "geompy.GEOM.ST_OUT";
2084     break;
2085   case GEOMAlgo_ST_ON:
2086     theDump << "geompy.GEOM.ST_ON";
2087     break;
2088   case GEOMAlgo_ST_ONIN:
2089     theDump << "geompy.GEOM.ST_ONIN";
2090     break;
2091   case GEOMAlgo_ST_ONOUT:
2092     theDump << "geompy.GEOM.ST_ONOUT";
2093     break;
2094   default:
2095     theDump << "geompy.GEOM.ST_UNKNOWN";
2096     break;
2097   }
2098   return theDump;
2099 }
2100
2101 //=======================================================================
2102 //function : checkTypeShapesOn
2103 /*!
2104  * \brief Checks if theShapeType parameter of GetShapesOnXXX() is OK
2105  * \param theShapeType - the shape type to check
2106  * \retval bool  - result of the check
2107  */
2108 //=======================================================================
2109 bool GEOMImpl_IShapesOperations::checkTypeShapesOn(const Standard_Integer theShapeType)
2110 {
2111   if (theShapeType != TopAbs_VERTEX &&
2112       theShapeType != TopAbs_EDGE &&
2113       theShapeType != TopAbs_FACE &&
2114       theShapeType != TopAbs_SOLID) {
2115     SetErrorCode("Only solids, vertices, edges or faces can be found by this method");
2116     return false;
2117   }
2118   return true;
2119 }
2120
2121 //=======================================================================
2122 //function : makePlane
2123   /*!
2124    * \brief Creates Geom_Plane
2125     * \param theAx1 - shape object defining plane parameters
2126     * \retval Handle(Geom_Surface) - resulting surface
2127    */
2128 //=======================================================================
2129 Handle(Geom_Surface) GEOMImpl_IShapesOperations::makePlane(const TopoDS_Shape& anAx1)
2130 {
2131   if (anAx1.ShapeType() != TopAbs_EDGE) return NULL;
2132   TopoDS_Edge anEdge = TopoDS::Edge(anAx1);
2133   TopoDS_Vertex V1, V2;
2134   TopExp::Vertices(anEdge, V1, V2, Standard_True);
2135   if (V1.IsNull() || V2.IsNull()) {
2136     SetErrorCode("Bad edge given for the plane normal vector");
2137     return NULL;
2138   }
2139   gp_Pnt aLoc = BRep_Tool::Pnt(V1);
2140   gp_Vec aVec (aLoc, BRep_Tool::Pnt(V2));
2141   if (aVec.Magnitude() < Precision::Confusion()) {
2142     SetErrorCode("Vector with null magnitude given");
2143     return NULL;
2144   }
2145   return new Geom_Plane(aLoc, aVec);
2146 }
2147
2148 //=======================================================================
2149 //function : makeCylinder
2150   /*!
2151    * \brief Creates Geom_CylindricalSurface
2152     * \param theAx1 - edge defining cylinder axis
2153     * \param theRadius - cylinder radius
2154     * \retval Handle(Geom_Surface) - resulting surface
2155    */
2156 //=======================================================================
2157 Handle(Geom_Surface) GEOMImpl_IShapesOperations::makeCylinder(const TopoDS_Shape& anAxis,
2158                                                               const Standard_Real theRadius)
2159 {
2160   //Axis of the cylinder
2161   if (anAxis.ShapeType() != TopAbs_EDGE) {
2162     SetErrorCode("Not an edge given for the axis");
2163     return NULL;
2164   }
2165   TopoDS_Edge anEdge = TopoDS::Edge(anAxis);
2166   TopoDS_Vertex V1, V2;
2167   TopExp::Vertices(anEdge, V1, V2, Standard_True);
2168   if (V1.IsNull() || V2.IsNull()) {
2169     SetErrorCode("Bad edge given for the axis");
2170     return NULL;
2171   }
2172   gp_Pnt aLoc = BRep_Tool::Pnt(V1);
2173   gp_Vec aVec (aLoc, BRep_Tool::Pnt(V2));
2174   if (aVec.Magnitude() < Precision::Confusion()) {
2175     SetErrorCode("Vector with null magnitude given");
2176     return NULL;
2177   }
2178
2179   gp_Ax3 anAx3 (aLoc, aVec);
2180   return new Geom_CylindricalSurface(anAx3, theRadius);
2181 }
2182
2183 //=======================================================================
2184 //function : getShapesOnBoxIDs
2185   /*!
2186    * \brief Find IDs of sub-shapes complying with given status about surface
2187     * \param theBox - the box to check state of sub-shapes against
2188     * \param theShape - the shape to explore
2189     * \param theShapeType - type of sub-shape of theShape
2190     * \param theState - required state
2191     * \retval Handle(TColStd_HSequenceOfInteger) - IDs of found sub-shapes
2192    */
2193 //=======================================================================
2194 Handle(TColStd_HSequenceOfInteger)
2195   GEOMImpl_IShapesOperations::getShapesOnBoxIDs(const Handle(GEOM_Object)& theBox,
2196                                                 const Handle(GEOM_Object)& theShape,
2197                                                 const Standard_Integer theShapeType,
2198                                                 GEOMAlgo_State theState)
2199 {
2200   Handle(TColStd_HSequenceOfInteger) aSeqOfIDs;
2201
2202   TopoDS_Shape aBox = theBox->GetValue();
2203   TopoDS_Shape aShape = theShape->GetValue();
2204
2205   // Check presence of triangulation, build if need
2206   if (!CheckTriangulation(aShape)) {
2207     SetErrorCode("Cannot build triangulation on the shape");
2208     return aSeqOfIDs;
2209   }
2210
2211   // Call algo
2212   GEOMAlgo_FinderShapeOn2 aFinder;
2213   Standard_Real aTol = 0.0001; // default value
2214
2215   Handle(GEOMAlgo_ClsfBox) aClsfBox = new GEOMAlgo_ClsfBox;
2216   aClsfBox->SetBox(aBox);
2217
2218   aFinder.SetShape(aShape);
2219   aFinder.SetTolerance(aTol);
2220   aFinder.SetClsf(aClsfBox);
2221   aFinder.SetShapeType( (TopAbs_ShapeEnum)theShapeType );
2222   aFinder.SetState(theState);
2223   aFinder.Perform();
2224
2225   // Interprete results
2226   Standard_Integer iErr = aFinder.ErrorStatus();
2227   // the detailed description of error codes is in GEOMAlgo_FinderShapeOn1.cxx
2228   if (iErr) {
2229     MESSAGE(" iErr : " << iErr);
2230     TCollection_AsciiString aMsg (" iErr : ");
2231     aMsg += TCollection_AsciiString(iErr);
2232     SetErrorCode(aMsg);
2233     return aSeqOfIDs;
2234   }
2235   Standard_Integer iWrn = aFinder.WarningStatus();
2236   // the detailed description of warning codes is in GEOMAlgo_FinderShapeOn1.cxx
2237   if (iWrn) {
2238     MESSAGE(" *** iWrn : " << iWrn);
2239   }
2240
2241   const TopTools_ListOfShape& listSS = aFinder.Shapes(); // the result
2242
2243   if (listSS.Extent() < 1) {
2244     //SetErrorCode("Not a single sub-shape of the requested type found on the given surface");
2245     SetErrorCode(NOT_FOUND_ANY); // NPAL18017
2246     return aSeqOfIDs;
2247   }
2248
2249   // Fill sequence of object IDs
2250   aSeqOfIDs = new TColStd_HSequenceOfInteger;
2251
2252   TopTools_IndexedMapOfShape anIndices;
2253   TopExp::MapShapes(aShape, anIndices);
2254
2255   TopTools_ListIteratorOfListOfShape itSub (listSS);
2256   for (int index = 1; itSub.More(); itSub.Next(), ++index) {
2257     int id = anIndices.FindIndex(itSub.Value());
2258     aSeqOfIDs->Append(id);
2259   }
2260
2261   return aSeqOfIDs;
2262 }
2263
2264 //=======================================================================
2265 //function : GetShapesOnBoxIDs
2266 /*!
2267    * \brief Find sub-shapes complying with given status about surface
2268     * \param theBox - the box to check state of sub-shapes against
2269     * \param theShape - the shape to explore
2270     * \param theShapeType - type of sub-shape of theShape
2271     * \param theState - required state
2272     * \retval Handle(TColStd_HSequenceOfInteger) - IDs of found sub-shapes
2273  */
2274 //=======================================================================
2275 Handle(TColStd_HSequenceOfInteger)
2276     GEOMImpl_IShapesOperations::GetShapesOnBoxIDs(const Handle(GEOM_Object)& theBox,
2277                                                   const Handle(GEOM_Object)& theShape,
2278                                                   const Standard_Integer theShapeType,
2279                                                   GEOMAlgo_State theState)
2280 {
2281   // Find sub-shapes ids
2282   Handle(TColStd_HSequenceOfInteger) aSeqOfIDs =
2283     getShapesOnBoxIDs (theBox, theShape, theShapeType, theState);
2284   if ( aSeqOfIDs.IsNull()  || aSeqOfIDs->Length() == 0 )
2285     return NULL;
2286
2287   // The GetShapesOnBox() doesn't change object so no new function is required.
2288   Handle(GEOM_Function) aFunction = GEOM::GetCreatedLast(theShape,theBox)->GetLastFunction();
2289
2290   // Make a Python command
2291   GEOM::TPythonDump(aFunction)
2292     << "listShapesOnBoxIDs = geompy.GetShapesOnBoxIDs("
2293     << theBox << ", "
2294     << theShape << ", "
2295     << TopAbs_ShapeEnum(theShapeType) << ", "
2296     << theState << ")";
2297
2298   SetErrorCode(OK);
2299   return aSeqOfIDs;
2300 }
2301
2302 //=======================================================================
2303 //function : GetShapesOnBox
2304 /*!
2305    * \brief Find sub-shapes complying with given status about surface
2306     * \param theBox - the box to check state of sub-shapes against
2307     * \param theShape - the shape to explore
2308     * \param theShapeType - type of sub-shape of theShape
2309     * \param theState - required state
2310     * \retval Handle(TColStd_HSequenceOfTransient) - found sub-shapes
2311  */
2312 //=======================================================================
2313 Handle(TColStd_HSequenceOfTransient)
2314     GEOMImpl_IShapesOperations::GetShapesOnBox(const Handle(GEOM_Object)& theBox,
2315                                                const Handle(GEOM_Object)&  theShape,
2316                                                const Standard_Integer theShapeType,
2317                                                GEOMAlgo_State theState)
2318 {
2319   // Find sub-shapes ids
2320   Handle(TColStd_HSequenceOfInteger) aSeqOfIDs =
2321     getShapesOnBoxIDs (theBox, theShape, theShapeType, theState);
2322   if ( aSeqOfIDs.IsNull()  || aSeqOfIDs->Length() == 0 )
2323     return NULL;
2324
2325   // Find objects by indices
2326   TCollection_AsciiString anAsciiList;
2327   Handle(TColStd_HSequenceOfTransient) aSeq;
2328   aSeq = getObjectsShapesOn( theShape, aSeqOfIDs, anAsciiList );
2329   if ( aSeq.IsNull() || aSeq->IsEmpty() )
2330     return NULL;
2331
2332   // Make a Python command
2333
2334   Handle(GEOM_Object) anObj = Handle(GEOM_Object)::DownCast( aSeq->Value( 1 ));
2335   Handle(GEOM_Function) aFunction = anObj->GetLastFunction();
2336
2337   GEOM::TPythonDump(aFunction)
2338     << "[" << anAsciiList.ToCString() << "] = geompy.GetShapesOnBox("
2339     << theBox << ", "
2340     << theShape << ", "
2341     << TopAbs_ShapeEnum(theShapeType) << ", "
2342     << theState << ")";
2343
2344   SetErrorCode(OK);
2345   return aSeq;
2346 }
2347
2348 //=======================================================================
2349 //function : getShapesOnShapeIDs
2350 /*!
2351  * \brief Find IDs of sub-shapes complying with given status about surface
2352  * \param theCheckShape - the shape to check state of sub-shapes against
2353  * \param theShape - the shape to explore
2354  * \param theShapeType - type of sub-shape of theShape
2355  * \param theState - required state
2356  * \retval Handle(TColStd_HSequenceOfInteger) - IDs of found sub-shapes
2357  */
2358 //=======================================================================
2359 Handle(TColStd_HSequenceOfInteger)
2360   GEOMImpl_IShapesOperations::getShapesOnShapeIDs
2361                                  (const Handle(GEOM_Object)& theCheckShape,
2362                                   const Handle(GEOM_Object)& theShape,
2363                                   const Standard_Integer theShapeType,
2364                                   GEOMAlgo_State theState)
2365 {
2366   Handle(TColStd_HSequenceOfInteger) aSeqOfIDs;
2367
2368   TopoDS_Shape aCheckShape = theCheckShape->GetValue();
2369   TopoDS_Shape aShape = theShape->GetValue();
2370   TopTools_ListOfShape res;
2371
2372   // Check presence of triangulation, build if need
2373   if (!CheckTriangulation(aShape)) {
2374     SetErrorCode("Cannot build triangulation on the shape");
2375     return aSeqOfIDs;
2376   }
2377
2378   // Call algo
2379   GEOMAlgo_FinderShapeOn2 aFinder;
2380   Standard_Real aTol = 0.0001; // default value
2381
2382   Handle(GEOMAlgo_ClsfSolid) aClsfSolid = new GEOMAlgo_ClsfSolid;
2383   aClsfSolid->SetShape(aCheckShape);
2384
2385   aFinder.SetShape(aShape);
2386   aFinder.SetTolerance(aTol);
2387   aFinder.SetClsf(aClsfSolid);
2388   aFinder.SetShapeType( (TopAbs_ShapeEnum)theShapeType );
2389   aFinder.SetState(theState);
2390   aFinder.Perform();
2391
2392   // Interprete results
2393   Standard_Integer iErr = aFinder.ErrorStatus();
2394   // the detailed description of error codes is in GEOMAlgo_FinderShapeOn1.cxx
2395   if (iErr) {
2396     if (iErr == 41) {
2397       SetErrorCode("theCheckShape must be a solid");
2398     }
2399     else {
2400       MESSAGE(" iErr : " << iErr);
2401       TCollection_AsciiString aMsg (" iErr : ");
2402       aMsg += TCollection_AsciiString(iErr);
2403       SetErrorCode(aMsg);
2404     }
2405     return aSeqOfIDs;
2406   }
2407   Standard_Integer iWrn = aFinder.WarningStatus();
2408   // the detailed description of warning codes is in GEOMAlgo_FinderShapeOn1.cxx
2409   if (iWrn) {
2410     MESSAGE(" *** iWrn : " << iWrn);
2411   }
2412
2413   const TopTools_ListOfShape& listSS = aFinder.Shapes(); // the result
2414
2415   if (listSS.Extent() < 1) {
2416     //SetErrorCode("Not a single sub-shape of the requested type found on the given surface");
2417     SetErrorCode(NOT_FOUND_ANY); // NPAL18017
2418   }
2419
2420   // Fill sequence of object IDs
2421   aSeqOfIDs = new TColStd_HSequenceOfInteger;
2422
2423   TopTools_IndexedMapOfShape anIndices;
2424   TopExp::MapShapes(aShape, anIndices);
2425
2426   TopTools_ListIteratorOfListOfShape itSub (listSS);
2427   for (int index = 1; itSub.More(); itSub.Next(), ++index) {
2428     int id = anIndices.FindIndex(itSub.Value());
2429     aSeqOfIDs->Append(id);
2430   }
2431
2432   return aSeqOfIDs;
2433 }
2434
2435 //=======================================================================
2436 //function : GetShapesOnShapeIDs
2437 /*!
2438  * \brief Find sub-shapes complying with given status about surface
2439  * \param theCheckShape - the shape to check state of sub-shapes against
2440  * \param theShape - the shape to explore
2441  * \param theShapeType - type of sub-shape of theShape
2442  * \param theState - required state
2443  * \retval Handle(TColStd_HSequenceOfInteger) - IDs of found sub-shapes
2444  */
2445 //=======================================================================
2446 Handle(TColStd_HSequenceOfInteger)
2447     GEOMImpl_IShapesOperations::GetShapesOnShapeIDs
2448                             (const Handle(GEOM_Object)& theCheckShape,
2449                              const Handle(GEOM_Object)& theShape,
2450                              const Standard_Integer theShapeType,
2451                              GEOMAlgo_State theState)
2452 {
2453   Handle(TColStd_HSequenceOfInteger) aSeqOfIDs =
2454     getShapesOnShapeIDs (theCheckShape, theShape, theShapeType, theState);
2455
2456   if ( aSeqOfIDs.IsNull()  || aSeqOfIDs->Length() == 0 )
2457     return NULL;
2458
2459   // The GetShapesOnShape() doesn't change object so no new function is required.
2460   Handle(GEOM_Function) aFunction =
2461     GEOM::GetCreatedLast(theShape,theCheckShape)->GetLastFunction();
2462
2463   // Make a Python command
2464   GEOM::TPythonDump(aFunction)
2465     << "listShapesOnBoxIDs = geompy.GetShapesOnShapeIDs("
2466     << theCheckShape << ", "
2467     << theShape << ", "
2468     << TopAbs_ShapeEnum(theShapeType) << ", "
2469     << theState << ")";
2470
2471   SetErrorCode(OK);
2472   return aSeqOfIDs;
2473 }
2474
2475 //=======================================================================
2476 //function : GetShapesOnShape
2477 /*!
2478  * \brief Find sub-shapes complying with given status about surface
2479  * \param theCheckShape - the shape to check state of sub-shapes against
2480  * \param theShape - the shape to explore
2481  * \param theShapeType - type of sub-shape of theShape
2482  * \param theState - required state
2483  * \retval Handle(TColStd_HSequenceOfTransient) - found sub-shapes
2484  */
2485 //=======================================================================
2486 Handle(TColStd_HSequenceOfTransient)
2487   GEOMImpl_IShapesOperations::GetShapesOnShape
2488                              (const Handle(GEOM_Object)& theCheckShape,
2489                               const Handle(GEOM_Object)&  theShape,
2490                               const Standard_Integer theShapeType,
2491                               GEOMAlgo_State theState)
2492 {
2493   Handle(TColStd_HSequenceOfInteger) aSeqOfIDs =
2494     getShapesOnShapeIDs (theCheckShape, theShape, theShapeType, theState);
2495   if ( aSeqOfIDs.IsNull()  || aSeqOfIDs->Length() == 0 )
2496     return NULL;
2497
2498   // Find objects by indices
2499   TCollection_AsciiString anAsciiList;
2500   Handle(TColStd_HSequenceOfTransient) aSeq;
2501   aSeq = getObjectsShapesOn( theShape, aSeqOfIDs, anAsciiList );
2502
2503   if ( aSeq.IsNull() || aSeq->IsEmpty() )
2504     return NULL;
2505
2506   // Make a Python command
2507
2508   Handle(GEOM_Object) anObj = Handle(GEOM_Object)::DownCast( aSeq->Value( 1 ));
2509   Handle(GEOM_Function) aFunction = anObj->GetLastFunction();
2510
2511   GEOM::TPythonDump(aFunction)
2512     << "[" << anAsciiList.ToCString() << "] = geompy.GetShapesOnShape("
2513     << theCheckShape << ", "
2514     << theShape << ", "
2515     << TopAbs_ShapeEnum(theShapeType) << ", "
2516     << theState << ")";
2517
2518   SetErrorCode(OK);
2519   return aSeq;
2520 }
2521
2522 //=======================================================================
2523 //function : GetShapesOnShapeAsCompound
2524 //=======================================================================
2525 Handle(GEOM_Object) GEOMImpl_IShapesOperations::GetShapesOnShapeAsCompound
2526                              (const Handle(GEOM_Object)& theCheckShape,
2527                               const Handle(GEOM_Object)&  theShape,
2528                               const Standard_Integer theShapeType,
2529                               GEOMAlgo_State theState)
2530 {
2531   Handle(TColStd_HSequenceOfInteger) aSeqOfIDs =
2532     getShapesOnShapeIDs (theCheckShape, theShape, theShapeType, theState);
2533
2534   if ( aSeqOfIDs.IsNull()  || aSeqOfIDs->Length() == 0 )
2535     return NULL;
2536
2537   // Find objects by indices
2538   TCollection_AsciiString anAsciiList;
2539   Handle(TColStd_HSequenceOfTransient) aSeq;
2540   aSeq = getObjectsShapesOn( theShape, aSeqOfIDs, anAsciiList );
2541
2542   if ( aSeq.IsNull() || aSeq->IsEmpty() )
2543     return NULL;
2544
2545   TopoDS_Compound aCompound;
2546   BRep_Builder B;
2547   B.MakeCompound(aCompound);
2548   int i = 1;
2549   for(; i<=aSeq->Length(); i++) {
2550     Handle(GEOM_Object) anObj = Handle(GEOM_Object)::DownCast(aSeq->Value(i));
2551     TopoDS_Shape aShape_i = anObj->GetValue();
2552     B.Add(aCompound,aShape_i);
2553   }
2554
2555   //Add a new result object
2556   Handle(GEOM_Object) aRes = GetEngine()->AddObject(GetDocID(), GEOM_SHAPES_ON_SHAPE);
2557   Handle(GEOM_Function) aFunction =
2558     aRes->AddFunction(GEOMImpl_ShapeDriver::GetID(), SHAPES_ON_SHAPE);
2559   aFunction->SetValue(aCompound);
2560
2561   GEOM::TPythonDump(aFunction)
2562     << aRes << " = geompy.GetShapesOnShapeAsCompound("
2563     << theCheckShape << ", "
2564     << theShape << ", "
2565     << TopAbs_ShapeEnum(theShapeType) << ", "
2566     << theState << ")";
2567
2568   SetErrorCode(OK);
2569
2570   return aRes;
2571 }
2572
2573 //=======================================================================
2574 //function : getShapesOnSurfaceIDs
2575   /*!
2576    * \brief Find IDs of sub-shapes complying with given status about surface
2577     * \param theSurface - the surface to check state of sub-shapes against
2578     * \param theShape - the shape to explore
2579     * \param theShapeType - type of sub-shape of theShape
2580     * \param theState - required state
2581     * \retval Handle(TColStd_HSequenceOfInteger) - IDs of found sub-shapes
2582    */
2583 //=======================================================================
2584 Handle(TColStd_HSequenceOfInteger)
2585   GEOMImpl_IShapesOperations::getShapesOnSurfaceIDs(const Handle(Geom_Surface)& theSurface,
2586                                                     const TopoDS_Shape&         theShape,
2587                                                     TopAbs_ShapeEnum            theShapeType,
2588                                                     GEOMAlgo_State              theState)
2589 {
2590   Handle(TColStd_HSequenceOfInteger) aSeqOfIDs;
2591
2592   // Check presence of triangulation, build if need
2593   if (!CheckTriangulation(theShape)) {
2594     SetErrorCode("Cannot build triangulation on the shape");
2595     return aSeqOfIDs;
2596   }
2597
2598   // BEGIN: Mantis issue 0020961: Error on a pipe T-Shape
2599   // Compute tolerance
2600   Standard_Real T, VertMax = -RealLast();
2601   try {
2602 #if OCC_VERSION_LARGE > 0x06010000
2603     OCC_CATCH_SIGNALS;
2604 #endif
2605     for (TopExp_Explorer ExV (theShape, TopAbs_VERTEX); ExV.More(); ExV.Next()) {
2606       TopoDS_Vertex Vertex = TopoDS::Vertex(ExV.Current());
2607       T = BRep_Tool::Tolerance(Vertex);
2608       if (T > VertMax)
2609         VertMax = T;
2610     }
2611   }
2612   catch (Standard_Failure) {
2613     Handle(Standard_Failure) aFail = Standard_Failure::Caught();
2614     SetErrorCode(aFail->GetMessageString());
2615     return aSeqOfIDs;
2616   }
2617   // END: Mantis issue 0020961
2618
2619   // Call algo
2620   GEOMAlgo_FinderShapeOn1 aFinder;
2621   //Standard_Real aTol = 0.0001; // default value
2622   Standard_Real aTol = VertMax; // Mantis issue 0020961
2623
2624   aFinder.SetShape(theShape);
2625   aFinder.SetTolerance(aTol);
2626   aFinder.SetSurface(theSurface);
2627   aFinder.SetShapeType(theShapeType);
2628   aFinder.SetState(theState);
2629
2630   // Sets the minimal number of inner points for the faces that do not have own
2631   // inner points at all (for e.g. rectangular planar faces have just 2 triangles).
2632   // Default value=3
2633   aFinder.SetNbPntsMin(3);
2634   // Sets the maximal number of inner points for edges or faces.
2635   // It is usefull for the cases when this number is very big (e.g =2000) to improve
2636   // the performance. If this value =0, all inner points will be taken into account.
2637   // Default value=0
2638   aFinder.SetNbPntsMax(100);
2639
2640   aFinder.Perform();
2641
2642   // Interprete results
2643   Standard_Integer iErr = aFinder.ErrorStatus();
2644   // the detailed description of error codes is in GEOMAlgo_FinderShapeOn1.cxx
2645   if (iErr) {
2646     MESSAGE(" iErr : " << iErr);
2647     TCollection_AsciiString aMsg (" iErr : ");
2648     aMsg += TCollection_AsciiString(iErr);
2649     SetErrorCode(aMsg);
2650     return aSeqOfIDs;
2651   }
2652   Standard_Integer iWrn = aFinder.WarningStatus();
2653   // the detailed description of warning codes is in GEOMAlgo_FinderShapeOn1.cxx
2654   if (iWrn) {
2655     MESSAGE(" *** iWrn : " << iWrn);
2656   }
2657
2658   const TopTools_ListOfShape& listSS = aFinder.Shapes(); // the result
2659
2660   if (listSS.Extent() < 1) {
2661     //SetErrorCode("Not a single sub-shape of the requested type found on the given surface");
2662     SetErrorCode(NOT_FOUND_ANY); // NPAL18017
2663     return aSeqOfIDs;
2664   }
2665
2666   // Fill sequence of object IDs
2667   aSeqOfIDs = new TColStd_HSequenceOfInteger;
2668
2669   TopTools_IndexedMapOfShape anIndices;
2670   TopExp::MapShapes(theShape, anIndices);
2671
2672   TopTools_ListIteratorOfListOfShape itSub (listSS);
2673   for (int index = 1; itSub.More(); itSub.Next(), ++index) {
2674     int id = anIndices.FindIndex(itSub.Value());
2675     aSeqOfIDs->Append(id);
2676   }
2677
2678   return aSeqOfIDs;
2679 }
2680
2681 //=======================================================================
2682 //function : getObjectsShapesOn
2683 /*!
2684  * \brief Find shape objects and their entries by their ids
2685  * \param theShapeIDs - incoming shape ids
2686  * \param theShapeEntries - outgoing entries like "entry1, entry2, ..."
2687  * \retval Handle(TColStd_HSequenceOfTransient) - found shape objects
2688  */
2689 //=======================================================================
2690 Handle(TColStd_HSequenceOfTransient) GEOMImpl_IShapesOperations::
2691  getObjectsShapesOn(const Handle(GEOM_Object)&                theShape,
2692                     const Handle(TColStd_HSequenceOfInteger)& theShapeIDs,
2693                     TCollection_AsciiString &                 theShapeEntries)
2694 {
2695   Handle(TColStd_HSequenceOfTransient) aSeq;
2696
2697   if ( !theShapeIDs.IsNull() && theShapeIDs->Length() > 0 )
2698   {
2699     aSeq = new TColStd_HSequenceOfTransient;
2700     Handle(TColStd_HArray1OfInteger) anArray = new TColStd_HArray1OfInteger(1,1);
2701     TCollection_AsciiString anEntry;
2702     for ( int i = 1; i <= theShapeIDs->Length(); ++i )
2703     {
2704       anArray->SetValue(1, theShapeIDs->Value( i ));
2705       Handle(GEOM_Object) anObj = GetEngine()->AddSubShape(theShape, anArray);
2706       aSeq->Append( anObj );
2707
2708       TDF_Tool::Entry(anObj->GetEntry(), anEntry);
2709       if ( i != 1 ) theShapeEntries += ",";
2710       theShapeEntries += anEntry;
2711     }
2712   }
2713   return aSeq;
2714 }
2715
2716 //=======================================================================
2717 //function : getShapesOnSurface
2718 /*!
2719    * \brief Find sub-shapes complying with given status about surface
2720     * \param theSurface - the surface to check state of sub-shapes against
2721     * \param theShape - the shape to explore
2722     * \param theShapeType - type of sub-shape of theShape
2723     * \param theState - required state
2724     * \param theShapeEntries - outgoing entries like "entry1, entry2, ..."
2725     * \retval Handle(TColStd_HSequenceOfInteger) - IDs of found sub-shapes
2726  */
2727 //=======================================================================
2728 Handle(TColStd_HSequenceOfTransient)
2729     GEOMImpl_IShapesOperations::getShapesOnSurface(const Handle(Geom_Surface)& theSurface,
2730                                                    const Handle(GEOM_Object)&  theShape,
2731                                                    TopAbs_ShapeEnum            theShapeType,
2732                                                    GEOMAlgo_State              theState,
2733                                                    TCollection_AsciiString &   theShapeEntries)
2734 {
2735   // Find sub-shapes ids
2736   Handle(TColStd_HSequenceOfInteger) aSeqOfIDs =
2737     getShapesOnSurfaceIDs (theSurface, theShape->GetValue(), theShapeType, theState);
2738   if ( aSeqOfIDs.IsNull()  || aSeqOfIDs->Length() == 0 )
2739     return NULL;
2740
2741   return getObjectsShapesOn( theShape, aSeqOfIDs, theShapeEntries );
2742 }
2743
2744 //=============================================================================
2745 /*!
2746  *  GetShapesOnPlane
2747  */
2748 //=============================================================================
2749 Handle(TColStd_HSequenceOfTransient) GEOMImpl_IShapesOperations::GetShapesOnPlane
2750                                         (const Handle(GEOM_Object)& theShape,
2751                                          const Standard_Integer     theShapeType,
2752                                          const Handle(GEOM_Object)& theAx1,
2753                                          const GEOMAlgo_State       theState)
2754 {
2755   SetErrorCode(KO);
2756
2757   if (theShape.IsNull() || theAx1.IsNull()) return NULL;
2758
2759   TopoDS_Shape aShape = theShape->GetValue();
2760   TopoDS_Shape anAx1  = theAx1->GetValue();
2761
2762   if (aShape.IsNull() || anAx1.IsNull()) return NULL;
2763
2764   TopAbs_ShapeEnum aShapeType = TopAbs_ShapeEnum(theShapeType);
2765   if ( !checkTypeShapesOn( theShapeType ))
2766     return NULL;
2767
2768   // Create plane
2769   Handle(Geom_Surface) aPlane = makePlane( anAx1 );
2770   if ( aPlane.IsNull() )
2771     return NULL;
2772
2773   // Find objects
2774   TCollection_AsciiString anAsciiList;
2775   Handle(TColStd_HSequenceOfTransient) aSeq;
2776   aSeq = getShapesOnSurface( aPlane, theShape, aShapeType, theState, anAsciiList );
2777   if ( aSeq.IsNull() || aSeq->Length() == 0 )
2778     return NULL;
2779
2780   // Make a Python command
2781
2782   Handle(GEOM_Object) anObj = Handle(GEOM_Object)::DownCast( aSeq->Value( 1 ));
2783   Handle(GEOM_Function) aFunction = anObj->GetLastFunction();
2784
2785   GEOM::TPythonDump(aFunction) << "[" << anAsciiList.ToCString()
2786     << "] = geompy.GetShapesOnPlane(" << theShape << ", "
2787       << aShapeType << ", " << theAx1 << ", " << theState << ")";
2788
2789   SetErrorCode(OK);
2790   return aSeq;
2791 }
2792
2793 //=============================================================================
2794 /*!
2795  *  GetShapesOnPlaneWithLocation
2796  */
2797 //=============================================================================
2798 Handle(TColStd_HSequenceOfTransient) GEOMImpl_IShapesOperations::GetShapesOnPlaneWithLocation
2799                                         (const Handle(GEOM_Object)& theShape,
2800                                          const Standard_Integer     theShapeType,
2801                                          const Handle(GEOM_Object)& theAx1,
2802                                          const Handle(GEOM_Object)& thePnt,
2803                                          const GEOMAlgo_State       theState)
2804 {
2805   SetErrorCode(KO);
2806
2807   if (theShape.IsNull() || theAx1.IsNull() || thePnt.IsNull()) return NULL;
2808
2809   TopoDS_Shape aShape = theShape->GetValue();
2810   TopoDS_Shape anAx1  = theAx1->GetValue();
2811   TopoDS_Shape anPnt = thePnt->GetValue();
2812
2813   if (aShape.IsNull() || anAx1.IsNull() || anPnt.IsNull()) return NULL;
2814
2815   TopAbs_ShapeEnum aShapeType = TopAbs_ShapeEnum(theShapeType);
2816   if ( !checkTypeShapesOn( theShapeType ))
2817     return NULL;
2818
2819   // Create plane
2820   if ( anAx1.ShapeType() != TopAbs_EDGE || anPnt.ShapeType() != TopAbs_VERTEX ) return NULL;
2821   TopoDS_Vertex V1, V2, V3;
2822   TopoDS_Edge anEdge = TopoDS::Edge(anAx1);
2823   TopExp::Vertices(anEdge, V1, V2, Standard_True);
2824
2825   if (V1.IsNull() || V2.IsNull()) {
2826     SetErrorCode("Bad edge given for the plane normal vector");
2827     return NULL;
2828   }
2829   V3 = TopoDS::Vertex(anPnt);
2830
2831   if(V3.IsNull()) {
2832     SetErrorCode("Bad vertex given for the plane location");
2833       return NULL;
2834   }
2835   gp_Pnt aLoc = BRep_Tool::Pnt(V3);
2836   gp_Vec aVec(BRep_Tool::Pnt(V1),BRep_Tool::Pnt(V2));
2837
2838   if (aVec.Magnitude() < Precision::Confusion()) {
2839     SetErrorCode("Vector with null magnitude given");
2840     return NULL;
2841   }
2842   Handle(Geom_Surface) aPlane = new Geom_Plane(aLoc, aVec);
2843
2844   if ( aPlane.IsNull() )
2845     return NULL;
2846
2847   // Find objects
2848   TCollection_AsciiString anAsciiList;
2849   Handle(TColStd_HSequenceOfTransient) aSeq;
2850   aSeq = getShapesOnSurface( aPlane, theShape, aShapeType, theState, anAsciiList );
2851   if ( aSeq.IsNull() || aSeq->Length() == 0 )
2852     return NULL;
2853
2854   // Make a Python command
2855
2856   Handle(GEOM_Object) anObj = Handle(GEOM_Object)::DownCast( aSeq->Value( 1 ));
2857   Handle(GEOM_Function) aFunction = anObj->GetLastFunction();
2858
2859   GEOM::TPythonDump(aFunction) << "[" << anAsciiList.ToCString()
2860     << "] = geompy.GetShapesOnPlaneWithLocation(" << theShape << ", "
2861     << aShapeType << ", " << theAx1 << ", "<< thePnt <<", " << theState << ")";
2862
2863   SetErrorCode(OK);
2864   return aSeq;
2865 }
2866
2867 //=============================================================================
2868 /*!
2869  *  GetShapesOnCylinder
2870  */
2871 //=============================================================================
2872 Handle(TColStd_HSequenceOfTransient) GEOMImpl_IShapesOperations::GetShapesOnCylinder
2873                                           (const Handle(GEOM_Object)& theShape,
2874                                            const Standard_Integer     theShapeType,
2875                                            const Handle(GEOM_Object)& theAxis,
2876                                            const Standard_Real        theRadius,
2877                                            const GEOMAlgo_State       theState)
2878 {
2879   SetErrorCode(KO);
2880
2881   if (theShape.IsNull() || theAxis.IsNull()) return NULL;
2882
2883   TopoDS_Shape aShape = theShape->GetValue();
2884   TopoDS_Shape anAxis = theAxis->GetValue();
2885
2886   if (aShape.IsNull() || anAxis.IsNull()) return NULL;
2887
2888   TopAbs_ShapeEnum aShapeType = TopAbs_ShapeEnum(theShapeType);
2889   if ( !checkTypeShapesOn( aShapeType ))
2890     return NULL;
2891
2892   // Create a cylinder surface
2893   Handle(Geom_Surface) aCylinder = makeCylinder( anAxis, theRadius );
2894   if ( aCylinder.IsNull() )
2895     return NULL;
2896
2897   // Find objects
2898   TCollection_AsciiString anAsciiList;
2899   Handle(TColStd_HSequenceOfTransient) aSeq;
2900   aSeq = getShapesOnSurface( aCylinder, theShape, aShapeType, theState, anAsciiList );
2901   if ( aSeq.IsNull() || aSeq->Length() == 0 )
2902     return NULL;
2903
2904   // Make a Python command
2905
2906   Handle(GEOM_Object) anObj = Handle(GEOM_Object)::DownCast( aSeq->Value( 1 ));
2907   Handle(GEOM_Function) aFunction = anObj->GetLastFunction();
2908
2909   GEOM::TPythonDump(aFunction) << "[" << anAsciiList.ToCString()
2910     << "] = geompy.GetShapesOnCylinder(" << theShape << ", " << aShapeType
2911       << ", " << theAxis << ", " << theRadius << ", " << theState << ")";
2912
2913   SetErrorCode(OK);
2914   return aSeq;
2915 }
2916
2917 //=============================================================================
2918 /*!
2919  *  GetShapesOnCylinderWithLocation
2920  */
2921 //=============================================================================
2922 Handle(TColStd_HSequenceOfTransient) GEOMImpl_IShapesOperations::GetShapesOnCylinderWithLocation
2923                                           (const Handle(GEOM_Object)& theShape,
2924                                            const Standard_Integer     theShapeType,
2925                                            const Handle(GEOM_Object)& theAxis,
2926                                            const Handle(GEOM_Object)& thePnt,
2927                                            const Standard_Real        theRadius,
2928                                            const GEOMAlgo_State       theState)
2929 {
2930   SetErrorCode(KO);
2931
2932   if (theShape.IsNull() || theAxis.IsNull() || thePnt.IsNull()) return NULL;
2933
2934   TopoDS_Shape aShape = theShape->GetValue();
2935   TopoDS_Shape anAxis = theAxis->GetValue();
2936   TopoDS_Shape aPnt   = thePnt->GetValue();
2937
2938   if (aShape.IsNull() || anAxis.IsNull() || aPnt.IsNull()) return NULL;
2939
2940   if (aPnt.ShapeType() != TopAbs_VERTEX )
2941   {
2942     SetErrorCode("Bottom location point must be vertex");
2943     return NULL;
2944   }
2945
2946   TopAbs_ShapeEnum aShapeType = TopAbs_ShapeEnum(theShapeType);
2947   if ( !checkTypeShapesOn( aShapeType ))
2948     return NULL;
2949
2950   // Create a cylinder surface
2951   Handle(Geom_Surface) aCylinder = makeCylinder( anAxis, theRadius );
2952   if ( aCylinder.IsNull() )
2953     return NULL;
2954
2955   // translate the surface
2956   Handle(Geom_CylindricalSurface) aCylSurface =
2957     Handle(Geom_CylindricalSurface)::DownCast( aCylinder );
2958   if ( aCylSurface.IsNull() )
2959   {
2960     SetErrorCode("Unexpected surface type instead of Geom_CylindricalSurface");
2961     return NULL;
2962   }
2963   gp_Pnt fromLoc = aCylSurface->Cylinder().Location();
2964   gp_Pnt toLoc   = BRep_Tool::Pnt( TopoDS::Vertex( aPnt ));
2965   aCylinder->Translate( fromLoc, toLoc );
2966
2967   // Find objects
2968   TCollection_AsciiString anAsciiList;
2969   Handle(TColStd_HSequenceOfTransient) aSeq;
2970   aSeq = getShapesOnSurface( aCylinder, theShape, aShapeType, theState, anAsciiList );
2971   if ( aSeq.IsNull() || aSeq->Length() == 0 )
2972     return NULL;
2973
2974   // Make a Python command
2975
2976   Handle(GEOM_Object) anObj = Handle(GEOM_Object)::DownCast( aSeq->Value( 1 ));
2977   Handle(GEOM_Function) aFunction = anObj->GetLastFunction();
2978
2979   GEOM::TPythonDump(aFunction)
2980     << "[" << anAsciiList.ToCString()
2981     << "] = geompy.GetShapesOnCylinderWithLocation(" << theShape << ", " << aShapeType << ", "
2982     << theAxis << ", " << thePnt << ", " << theRadius << ", " << theState << ")";
2983
2984   SetErrorCode(OK);
2985   return aSeq;
2986 }
2987
2988 //=============================================================================
2989 /*!
2990  *  GetShapesOnSphere
2991  */
2992 //=============================================================================
2993 Handle(TColStd_HSequenceOfTransient) GEOMImpl_IShapesOperations::GetShapesOnSphere
2994                                           (const Handle(GEOM_Object)& theShape,
2995                                            const Standard_Integer     theShapeType,
2996                                            const Handle(GEOM_Object)& theCenter,
2997                                            const Standard_Real        theRadius,
2998                                            const GEOMAlgo_State       theState)
2999 {
3000   SetErrorCode(KO);
3001
3002   if (theShape.IsNull() || theCenter.IsNull()) return NULL;
3003
3004   TopoDS_Shape aShape  = theShape->GetValue();
3005   TopoDS_Shape aCenter = theCenter->GetValue();
3006
3007   if (aShape.IsNull() || aCenter.IsNull()) return NULL;
3008
3009   TopAbs_ShapeEnum aShapeType = TopAbs_ShapeEnum(theShapeType);
3010   if ( !checkTypeShapesOn( aShapeType ))
3011     return NULL;
3012
3013   // Center of the sphere
3014   if (aCenter.ShapeType() != TopAbs_VERTEX) return NULL;
3015   gp_Pnt aLoc = BRep_Tool::Pnt(TopoDS::Vertex(aCenter));
3016
3017   gp_Ax3 anAx3 (aLoc, gp::DZ());
3018   Handle(Geom_SphericalSurface) aSphere =
3019     new Geom_SphericalSurface(anAx3, theRadius);
3020
3021   // Find objects
3022   TCollection_AsciiString anAsciiList;
3023   Handle(TColStd_HSequenceOfTransient) aSeq;
3024   aSeq = getShapesOnSurface( aSphere, theShape, aShapeType, theState, anAsciiList );
3025   if ( aSeq.IsNull() || aSeq->Length() == 0 )
3026     return NULL;
3027
3028   // Make a Python command
3029
3030   Handle(GEOM_Object) anObj = Handle(GEOM_Object)::DownCast( aSeq->Value( 1 ));
3031   Handle(GEOM_Function) aFunction = anObj->GetLastFunction();
3032
3033   GEOM::TPythonDump(aFunction) << "[" << anAsciiList.ToCString()
3034     << "] = geompy.GetShapesOnSphere(" << theShape << ", " << aShapeType
3035       << ", " << theCenter << ", " << theRadius << ", " << theState << ")";
3036
3037   SetErrorCode(OK);
3038   return aSeq;
3039 }
3040
3041 //=============================================================================
3042 /*!
3043  *  GetShapesOnPlaneIDs
3044  */
3045 //=============================================================================
3046 Handle(TColStd_HSequenceOfInteger) GEOMImpl_IShapesOperations::GetShapesOnPlaneIDs
3047                                         (const Handle(GEOM_Object)& theShape,
3048                                          const Standard_Integer     theShapeType,
3049                                          const Handle(GEOM_Object)& theAx1,
3050                                          const GEOMAlgo_State       theState)
3051 {
3052   SetErrorCode(KO);
3053
3054   if (theShape.IsNull() || theAx1.IsNull()) return NULL;
3055
3056   TopoDS_Shape aShape = theShape->GetValue();
3057   TopoDS_Shape anAx1  = theAx1->GetValue();
3058
3059   if (aShape.IsNull() || anAx1.IsNull()) return NULL;
3060
3061   TopAbs_ShapeEnum aShapeType = TopAbs_ShapeEnum(theShapeType);
3062   if ( !checkTypeShapesOn( aShapeType ))
3063     return NULL;
3064
3065   // Create plane
3066   Handle(Geom_Surface) aPlane = makePlane( anAx1 );
3067   if ( aPlane.IsNull() )
3068     return NULL;
3069
3070   // Find object IDs
3071   Handle(TColStd_HSequenceOfInteger) aSeq;
3072   aSeq = getShapesOnSurfaceIDs( aPlane, aShape, aShapeType, theState );
3073
3074   // The GetShapesOnPlaneIDs() doesn't change object so no new function is required.
3075   Handle(GEOM_Function) aFunction = GEOM::GetCreatedLast(theShape,theAx1)->GetLastFunction();
3076
3077   // Make a Python command
3078   GEOM::TPythonDump(aFunction, /*append=*/true)
3079     << "listShapesOnPlane = geompy.GetShapesOnPlaneIDs"
3080     << "(" << theShape << "," << aShapeType << "," << theAx1 << "," << theState << ")";
3081
3082   SetErrorCode(OK);
3083   return aSeq;
3084 }
3085
3086 //=============================================================================
3087 /*!
3088  *  GetShapesOnPlaneWithLocationIDs
3089  */
3090 //=============================================================================
3091 Handle(TColStd_HSequenceOfInteger) GEOMImpl_IShapesOperations::GetShapesOnPlaneWithLocationIDs
3092                                         (const Handle(GEOM_Object)& theShape,
3093                                          const Standard_Integer     theShapeType,
3094                                          const Handle(GEOM_Object)& theAx1,
3095                                          const Handle(GEOM_Object)& thePnt,
3096                                          const GEOMAlgo_State       theState)
3097 {
3098   SetErrorCode(KO);
3099
3100   if (theShape.IsNull() || theAx1.IsNull() || thePnt.IsNull()) return NULL;
3101
3102   TopoDS_Shape aShape = theShape->GetValue();
3103   TopoDS_Shape anAx1  = theAx1->GetValue();
3104   TopoDS_Shape anPnt  = thePnt->GetValue();
3105
3106   if (aShape.IsNull() || anAx1.IsNull() || anPnt.IsNull()) return NULL;
3107
3108   TopAbs_ShapeEnum aShapeType = TopAbs_ShapeEnum(theShapeType);
3109   if ( !checkTypeShapesOn( aShapeType ))
3110     return NULL;
3111
3112   // Create plane
3113   if (anAx1.ShapeType() != TopAbs_EDGE || anPnt.ShapeType() != TopAbs_VERTEX) return NULL;
3114   TopoDS_Edge anEdge = TopoDS::Edge(anAx1);
3115   TopoDS_Vertex V1, V2, V3;
3116   TopExp::Vertices(anEdge, V1, V2, Standard_True);
3117   if (V1.IsNull() || V2.IsNull()) {
3118     SetErrorCode("Bad edge given for the plane normal vector");
3119     return NULL;
3120   }
3121   V3 = TopoDS::Vertex(anPnt);
3122   if(V3.IsNull()) {
3123     SetErrorCode("Bad vertex given for the plane location");
3124       return NULL;
3125   }
3126   gp_Pnt aLoc = BRep_Tool::Pnt(V3);
3127   gp_Vec aVec(BRep_Tool::Pnt(V1),BRep_Tool::Pnt(V2));
3128   if (aVec.Magnitude() < Precision::Confusion()) {
3129     SetErrorCode("Vector with null magnitude given");
3130     return NULL;
3131   }
3132
3133   Handle(Geom_Surface) aPlane = new Geom_Plane(aLoc, aVec);
3134   if ( aPlane.IsNull() )
3135     return NULL;
3136
3137   // Find object IDs
3138   Handle(TColStd_HSequenceOfInteger) aSeq;
3139   aSeq = getShapesOnSurfaceIDs( aPlane, aShape, aShapeType, theState );
3140
3141   // The GetShapesOnPlaneIDs() doesn't change object so no new function is required.
3142   Handle(GEOM_Function) aFunction = GEOM::GetCreatedLast(theShape,theAx1)->GetLastFunction();
3143
3144   // Make a Python command
3145   GEOM::TPythonDump(aFunction, /*append=*/true)
3146     << "listShapesOnPlane = geompy.GetShapesOnPlaneWithLocationIDs"
3147     << "(" << theShape << ", " << aShapeType << ", " << theAx1 << ", "<< thePnt << ", "  << theState << ")";
3148
3149   SetErrorCode(OK);
3150   return aSeq;
3151 }
3152
3153 //=============================================================================
3154 /*!
3155  *  GetShapesOnCylinderIDs
3156  */
3157 //=============================================================================
3158 Handle(TColStd_HSequenceOfInteger) GEOMImpl_IShapesOperations::GetShapesOnCylinderIDs
3159                                           (const Handle(GEOM_Object)& theShape,
3160                                            const Standard_Integer     theShapeType,
3161                                            const Handle(GEOM_Object)& theAxis,
3162                                            const Standard_Real        theRadius,
3163                                            const GEOMAlgo_State       theState)
3164 {
3165   SetErrorCode(KO);
3166
3167   if (theShape.IsNull() || theAxis.IsNull()) return NULL;
3168
3169   TopoDS_Shape aShape = theShape->GetValue();
3170   TopoDS_Shape anAxis = theAxis->GetValue();
3171
3172   if (aShape.IsNull() || anAxis.IsNull()) return NULL;
3173
3174   TopAbs_ShapeEnum aShapeType = TopAbs_ShapeEnum(theShapeType);
3175   if ( !checkTypeShapesOn( aShapeType ))
3176     return NULL;
3177
3178   // Create a cylinder surface
3179   Handle(Geom_Surface) aCylinder = makeCylinder( anAxis, theRadius );
3180   if ( aCylinder.IsNull() )
3181     return NULL;
3182
3183   // Find object IDs
3184   Handle(TColStd_HSequenceOfInteger) aSeq;
3185   aSeq = getShapesOnSurfaceIDs( aCylinder, aShape, aShapeType, theState );
3186
3187   // The GetShapesOnCylinder() doesn't change object so no new function is required.
3188   Handle(GEOM_Function) aFunction = GEOM::GetCreatedLast(theShape,theAxis)->GetLastFunction();
3189
3190   // Make a Python command
3191   GEOM::TPythonDump(aFunction, /*append=*/true)
3192     << "listShapesOnCylinder = geompy.GetShapesOnCylinderIDs"
3193     << "(" << theShape << ", " << aShapeType << ", " << theAxis << ", "
3194     << theRadius << ", " << theState << ")";
3195
3196   SetErrorCode(OK);
3197   return aSeq;
3198 }
3199
3200 //=============================================================================
3201 /*!
3202  *  GetShapesOnCylinderWithLocationIDs
3203  */
3204 //=============================================================================
3205 Handle(TColStd_HSequenceOfInteger) GEOMImpl_IShapesOperations::GetShapesOnCylinderWithLocationIDs
3206                                           (const Handle(GEOM_Object)& theShape,
3207                                            const Standard_Integer     theShapeType,
3208                                            const Handle(GEOM_Object)& theAxis,
3209                                            const Handle(GEOM_Object)& thePnt,
3210                                            const Standard_Real        theRadius,
3211                                            const GEOMAlgo_State       theState)
3212 {
3213   SetErrorCode(KO);
3214
3215   if (theShape.IsNull() || theAxis.IsNull() || thePnt.IsNull()) return NULL;
3216
3217   TopoDS_Shape aShape = theShape->GetValue();
3218   TopoDS_Shape anAxis = theAxis->GetValue();
3219   TopoDS_Shape aPnt   = thePnt->GetValue();
3220
3221   if (aShape.IsNull() || anAxis.IsNull() || aPnt.IsNull()) return NULL;
3222
3223   if (aPnt.ShapeType() != TopAbs_VERTEX )
3224   {
3225     SetErrorCode("Bottom location point must be vertex");
3226     return NULL;
3227   }
3228
3229   TopAbs_ShapeEnum aShapeType = TopAbs_ShapeEnum(theShapeType);
3230   if ( !checkTypeShapesOn( aShapeType ))
3231     return NULL;
3232
3233   // Create a cylinder surface
3234   Handle(Geom_Surface) aCylinder = makeCylinder( anAxis, theRadius );
3235   if ( aCylinder.IsNull() )
3236     return NULL;
3237
3238   // translate the surface
3239   Handle(Geom_CylindricalSurface) aCylSurface =
3240     Handle(Geom_CylindricalSurface)::DownCast( aCylinder );
3241   if ( aCylSurface.IsNull() )
3242   {
3243     SetErrorCode("Unexpected surface type instead of Geom_CylindricalSurface");
3244     return NULL;
3245   }
3246   gp_Pnt fromLoc = aCylSurface->Cylinder().Location();
3247   gp_Pnt toLoc   = BRep_Tool::Pnt( TopoDS::Vertex( aPnt ));
3248   aCylinder->Translate( fromLoc, toLoc );
3249
3250   // Find object IDs
3251   Handle(TColStd_HSequenceOfInteger) aSeq;
3252   aSeq = getShapesOnSurfaceIDs( aCylinder, aShape, aShapeType, theState );
3253
3254   // The GetShapesOnCylinder() doesn't change object so no new function is required.
3255   Handle(GEOM_Function) aFunction =
3256     GEOM::GetCreatedLast(theShape, GEOM::GetCreatedLast(thePnt,theAxis))->GetLastFunction();
3257
3258   // Make a Python command
3259   GEOM::TPythonDump(aFunction, /*append=*/true)
3260     << "listShapesOnCylinder = geompy.GetShapesOnCylinderWithLocationIDs"
3261     << "(" << theShape << ", " << aShapeType << ", " << theAxis << ", "
3262     << thePnt << ", " << theRadius << ", " << theState << ")";
3263
3264   SetErrorCode(OK);
3265   return aSeq;
3266 }
3267
3268 //=============================================================================
3269 /*!
3270  *  GetShapesOnSphereIDs
3271  */
3272 //=============================================================================
3273 Handle(TColStd_HSequenceOfInteger) GEOMImpl_IShapesOperations::GetShapesOnSphereIDs
3274                                           (const Handle(GEOM_Object)& theShape,
3275                                            const Standard_Integer     theShapeType,
3276                                            const Handle(GEOM_Object)& theCenter,
3277                                            const Standard_Real        theRadius,
3278                                            const GEOMAlgo_State       theState)
3279 {
3280   SetErrorCode(KO);
3281
3282   if (theShape.IsNull() || theCenter.IsNull()) return NULL;
3283
3284   TopoDS_Shape aShape  = theShape->GetValue();
3285   TopoDS_Shape aCenter = theCenter->GetValue();
3286
3287   if (aShape.IsNull() || aCenter.IsNull()) return NULL;
3288
3289   TopAbs_ShapeEnum aShapeType = TopAbs_ShapeEnum(theShapeType);
3290   if ( !checkTypeShapesOn( aShapeType ))
3291     return NULL;
3292
3293   // Center of the sphere
3294   if (aCenter.ShapeType() != TopAbs_VERTEX) return NULL;
3295   gp_Pnt aLoc = BRep_Tool::Pnt(TopoDS::Vertex(aCenter));
3296
3297   gp_Ax3 anAx3 (aLoc, gp::DZ());
3298   Handle(Geom_SphericalSurface) aSphere =
3299     new Geom_SphericalSurface(anAx3, theRadius);
3300
3301   // Find object IDs
3302   Handle(TColStd_HSequenceOfInteger) aSeq;
3303   aSeq = getShapesOnSurfaceIDs( aSphere, aShape, aShapeType, theState );
3304
3305   // The GetShapesOnSphere() doesn't change object so no new function is required.
3306   Handle(GEOM_Function) aFunction = GEOM::GetCreatedLast(theShape,theCenter)->GetLastFunction();
3307
3308   // Make a Python command
3309   GEOM::TPythonDump(aFunction, /*append=*/true)
3310     << "listShapesOnCylinder = geompy.GetShapesOnCylinderIDs"
3311     << "(" << theShape << ", " << aShapeType << ", " << theCenter << ", "
3312     << theRadius << ", " << theState << ")";
3313
3314   SetErrorCode(OK);
3315   return aSeq;
3316 }
3317
3318 //=======================================================================
3319 //function : getShapesOnQuadrangleIDs
3320   /*!
3321    * \brief Find IDs of sub-shapes complying with given status about quadrangle
3322     * \param theShape - the shape to explore
3323     * \param theShapeType - type of sub-shape of theShape
3324     * \param theTopLeftPoint - top left quadrangle corner
3325     * \param theTopRigthPoint - top right quadrangle corner
3326     * \param theBottomLeftPoint - bottom left quadrangle corner
3327     * \param theBottomRigthPoint - bottom right quadrangle corner
3328     * \param theState - required state
3329     * \retval Handle(TColStd_HSequenceOfInteger) - IDs of found sub-shapes
3330    */
3331 //=======================================================================
3332 Handle(TColStd_HSequenceOfInteger)
3333   GEOMImpl_IShapesOperations::getShapesOnQuadrangleIDs (const Handle(GEOM_Object)& theShape,
3334                                                         const Standard_Integer     theShapeType,
3335                                                         const Handle(GEOM_Object)& theTopLeftPoint,
3336                                                         const Handle(GEOM_Object)& theTopRigthPoint,
3337                                                         const Handle(GEOM_Object)& theBottomLeftPoint,
3338                                                         const Handle(GEOM_Object)& theBottomRigthPoint,
3339                                                         const GEOMAlgo_State       theState)
3340 {
3341   SetErrorCode(KO);
3342
3343   if ( theShape.IsNull() ||
3344        theTopLeftPoint.IsNull() ||
3345        theTopRigthPoint.IsNull() ||
3346        theBottomLeftPoint.IsNull() ||
3347        theBottomRigthPoint.IsNull() )
3348     return NULL;
3349
3350   TopoDS_Shape aShape = theShape->GetValue();
3351   TopoDS_Shape aTL = theTopLeftPoint->GetValue();
3352   TopoDS_Shape aTR = theTopRigthPoint->GetValue();
3353   TopoDS_Shape aBL = theBottomLeftPoint->GetValue();
3354   TopoDS_Shape aBR = theBottomRigthPoint->GetValue();
3355
3356   if (aShape.IsNull() ||
3357       aTL.IsNull() ||
3358       aTR.IsNull() ||
3359       aBL.IsNull() ||
3360       aBR.IsNull() ||
3361       aTL.ShapeType() != TopAbs_VERTEX ||
3362       aTR.ShapeType() != TopAbs_VERTEX ||
3363       aBL.ShapeType() != TopAbs_VERTEX ||
3364       aBR.ShapeType() != TopAbs_VERTEX )
3365     return NULL;
3366
3367   TopAbs_ShapeEnum aShapeType = TopAbs_ShapeEnum(theShapeType);
3368   if ( !checkTypeShapesOn( aShapeType ))
3369     return NULL;
3370
3371   Handle(TColStd_HSequenceOfInteger) aSeqOfIDs;
3372
3373   // Check presence of triangulation, build if need
3374   if (!CheckTriangulation(aShape)) {
3375     SetErrorCode("Cannot build triangulation on the shape");
3376     return aSeqOfIDs;
3377   }
3378
3379   // Call algo
3380   gp_Pnt aPntTL = BRep_Tool::Pnt(TopoDS::Vertex(aTL));
3381   gp_Pnt aPntTR = BRep_Tool::Pnt(TopoDS::Vertex(aTR));
3382   gp_Pnt aPntBL = BRep_Tool::Pnt(TopoDS::Vertex(aBL));
3383   gp_Pnt aPntBR = BRep_Tool::Pnt(TopoDS::Vertex(aBR));
3384
3385   GEOMAlgo_FinderShapeOnQuad aFinder( aPntTL, aPntTR, aPntBL, aPntBR );
3386   Standard_Real aTol = 0.0001; // default value
3387
3388   aFinder.SetShape(aShape);
3389   aFinder.SetTolerance(aTol);
3390   //aFinder.SetSurface(theSurface);
3391   aFinder.SetShapeType(aShapeType);
3392   aFinder.SetState(theState);
3393
3394   // Sets the minimal number of inner points for the faces that do not have own
3395   // inner points at all (for e.g. rectangular planar faces have just 2 triangles).
3396   // Default value=3
3397   aFinder.SetNbPntsMin(3);
3398   // Sets the maximal number of inner points for edges or faces.
3399   // It is usefull for the cases when this number is very big (e.g =2000) to improve
3400   // the performance. If this value =0, all inner points will be taken into account.
3401   // Default value=0
3402   aFinder.SetNbPntsMax(100);
3403
3404   aFinder.Perform();
3405
3406   // Interprete results
3407   Standard_Integer iErr = aFinder.ErrorStatus();
3408   // the detailed description of error codes is in GEOMAlgo_FinderShapeOn1.cxx
3409   if (iErr) {
3410     MESSAGE(" iErr : " << iErr);
3411     TCollection_AsciiString aMsg (" iErr : ");
3412     aMsg += TCollection_AsciiString(iErr);
3413     SetErrorCode(aMsg);
3414     return aSeqOfIDs;
3415   }
3416   Standard_Integer iWrn = aFinder.WarningStatus();
3417   // the detailed description of warning codes is in GEOMAlgo_FinderShapeOn1.cxx
3418   if (iWrn) {
3419     MESSAGE(" *** iWrn : " << iWrn);
3420   }
3421
3422   const TopTools_ListOfShape& listSS = aFinder.Shapes(); // the result
3423
3424   if (listSS.Extent() < 1) {
3425     //SetErrorCode("Not a single sub-shape of the requested type found on the given surface");
3426     SetErrorCode(NOT_FOUND_ANY); // NPAL18017
3427     return aSeqOfIDs;
3428   }
3429
3430   // Fill sequence of object IDs
3431   aSeqOfIDs = new TColStd_HSequenceOfInteger;
3432
3433   TopTools_IndexedMapOfShape anIndices;
3434   TopExp::MapShapes(aShape, anIndices);
3435
3436   TopTools_ListIteratorOfListOfShape itSub (listSS);
3437   for (int index = 1; itSub.More(); itSub.Next(), ++index) {
3438     int id = anIndices.FindIndex(itSub.Value());
3439     aSeqOfIDs->Append(id);
3440   }
3441   return aSeqOfIDs;
3442 }
3443
3444 //=======================================================================
3445 //function : GetShapesOnQuadrangle
3446   /*!
3447    * \brief Find sub-shapes complying with given status about quadrangle
3448     * \param theShape - the shape to explore
3449     * \param theShapeType - type of sub-shape of theShape
3450     * \param theTopLeftPoint - top left quadrangle corner
3451     * \param theTopRigthPoint - top right quadrangle corner
3452     * \param theBottomLeftPoint - bottom left quadrangle corner
3453     * \param theBottomRigthPoint - bottom right quadrangle corner
3454     * \param theState - required state
3455     * \retval Handle(TColStd_HSequenceOfInteger) - IDs of found sub-shapes
3456    */
3457 //=======================================================================
3458 Handle(TColStd_HSequenceOfTransient)
3459     GEOMImpl_IShapesOperations::GetShapesOnQuadrangle (const Handle(GEOM_Object)& theShape,
3460                                                        const Standard_Integer     theShapeType,
3461                                                        const Handle(GEOM_Object)& theTopLeftPoint,
3462                                                        const Handle(GEOM_Object)& theTopRigthPoint,
3463                                                        const Handle(GEOM_Object)& theBottomLeftPoint,
3464                                                        const Handle(GEOM_Object)& theBottomRigthPoint,
3465                                                        const GEOMAlgo_State       theState)
3466 {
3467   // Find indices
3468   Handle(TColStd_HSequenceOfInteger) aSeqOfIDs =
3469     getShapesOnQuadrangleIDs( theShape,
3470                               theShapeType,
3471                               theTopLeftPoint,
3472                               theTopRigthPoint,
3473                               theBottomLeftPoint,
3474                               theBottomRigthPoint,
3475                               theState);
3476   if ( aSeqOfIDs.IsNull() || aSeqOfIDs->IsEmpty() )
3477     return NULL;
3478
3479   // Find objects by indices
3480   TCollection_AsciiString anAsciiList;
3481   Handle(TColStd_HSequenceOfTransient) aSeq;
3482   aSeq = getObjectsShapesOn( theShape, aSeqOfIDs, anAsciiList );
3483   if ( aSeq.IsNull() || aSeq->IsEmpty() )
3484     return NULL;
3485
3486   // Make a Python command
3487
3488   Handle(GEOM_Object) anObj = Handle(GEOM_Object)::DownCast( aSeq->Value( 1 ));
3489   Handle(GEOM_Function) aFunction = anObj->GetLastFunction();
3490
3491   GEOM::TPythonDump(aFunction)
3492     << "[" << anAsciiList.ToCString() << "] = geompy.GetShapesOnQuadrangle("
3493     << theShape << ", "
3494     << TopAbs_ShapeEnum(theShapeType) << ", "
3495     << theTopLeftPoint << ", "
3496     << theTopRigthPoint << ", "
3497     << theBottomLeftPoint << ", "
3498     << theBottomRigthPoint << ", "
3499     << theState << ")";
3500
3501   SetErrorCode(OK);
3502   return aSeq;
3503 }
3504
3505 //=======================================================================
3506 //function : GetShapesOnQuadrangleIDs
3507   /*!
3508    * \brief Find IDs of sub-shapes complying with given status about quadrangle
3509     * \param theShape - the shape to explore
3510     * \param theShapeType - type of sub-shape of theShape
3511     * \param theTopLeftPoint - top left quadrangle corner
3512     * \param theTopRigthPoint - top right quadrangle corner
3513     * \param theBottomLeftPoint - bottom left quadrangle corner
3514     * \param theBottomRigthPoint - bottom right quadrangle corner
3515     * \param theState - required state
3516     * \retval Handle(TColStd_HSequenceOfInteger) - IDs of found sub-shapes
3517    */
3518 //=======================================================================
3519 Handle(TColStd_HSequenceOfInteger)
3520   GEOMImpl_IShapesOperations::GetShapesOnQuadrangleIDs (const Handle(GEOM_Object)& theShape,
3521                                                         const Standard_Integer     theShapeType,
3522                                                         const Handle(GEOM_Object)& theTopLeftPoint,
3523                                                         const Handle(GEOM_Object)& theTopRigthPoint,
3524                                                         const Handle(GEOM_Object)& theBottomLeftPoint,
3525                                                         const Handle(GEOM_Object)& theBottomRigthPoint,
3526                                                         const GEOMAlgo_State       theState)
3527 {
3528   // Find indices
3529   Handle(TColStd_HSequenceOfInteger) aSeqOfIDs =
3530     getShapesOnQuadrangleIDs( theShape,
3531                               theShapeType,
3532                               theTopLeftPoint,
3533                               theTopRigthPoint,
3534                               theBottomLeftPoint,
3535                               theBottomRigthPoint,
3536                               theState);
3537   if ( aSeqOfIDs.IsNull() || aSeqOfIDs->IsEmpty() )
3538     return NULL;
3539
3540   // Make a Python command
3541
3542   // The GetShapesOnCylinder() doesn't change object so no new function is required.
3543   Handle(GEOM_Object) lastObj = GEOM::GetCreatedLast(theShape,theTopLeftPoint);
3544   lastObj = GEOM::GetCreatedLast(lastObj,theTopRigthPoint);
3545   lastObj = GEOM::GetCreatedLast(lastObj,theBottomRigthPoint);
3546   lastObj = GEOM::GetCreatedLast(lastObj,theBottomLeftPoint);
3547   Handle(GEOM_Function) aFunction = lastObj->GetLastFunction();
3548
3549   GEOM::TPythonDump(aFunction, /*append=*/true)
3550     << "listShapesOnQuadrangle = geompy.GetShapesOnQuadrangleIDs("
3551     << theShape << ", "
3552     << TopAbs_ShapeEnum(theShapeType) << ", "
3553     << theTopLeftPoint << ", "
3554     << theTopRigthPoint << ", "
3555     << theBottomLeftPoint << ", "
3556     << theBottomRigthPoint << ", "
3557     << theState << ")";
3558
3559   SetErrorCode(OK);
3560   return aSeqOfIDs;
3561 }
3562
3563 //=============================================================================
3564 /*!
3565  *  GetInPlaceOfShape
3566  */
3567 //=============================================================================
3568 static bool GetInPlaceOfShape (const Handle(GEOM_Function)& theWhereFunction,
3569                                const TopTools_IndexedMapOfShape& theWhereIndices,
3570                                const TopoDS_Shape& theWhat,
3571                                TColStd_ListOfInteger& theModifiedList)
3572 {
3573   if (theWhereFunction.IsNull() || theWhat.IsNull()) return false;
3574
3575   if (theWhereIndices.Contains(theWhat)) {
3576     // entity was not changed by the operation
3577     Standard_Integer aWhatIndex = theWhereIndices.FindIndex(theWhat);
3578     theModifiedList.Append(aWhatIndex);
3579     return true;
3580   }
3581
3582   // try to find in history
3583   TDF_Label aHistoryLabel = theWhereFunction->GetHistoryEntry(Standard_False);
3584
3585   // search in history for all argument shapes
3586   Standard_Boolean isFound = Standard_False;
3587   Standard_Boolean isGood = Standard_False;
3588
3589   TDF_LabelSequence aLabelSeq;
3590   theWhereFunction->GetDependency(aLabelSeq);
3591   Standard_Integer nbArg = aLabelSeq.Length();
3592
3593   for (Standard_Integer iarg = 1; iarg <= nbArg && !isFound; iarg++) {
3594
3595     TDF_Label anArgumentRefLabel = aLabelSeq.Value(iarg);
3596
3597     Handle(GEOM_Object) anArgumentObject = GEOM_Object::GetReferencedObject(anArgumentRefLabel);
3598     TopoDS_Shape anArgumentShape = anArgumentObject->GetValue();
3599
3600     TopTools_IndexedMapOfShape anArgumentIndices;
3601     TopExp::MapShapes(anArgumentShape, anArgumentIndices);
3602
3603     if (anArgumentIndices.Contains(theWhat)) {
3604       isFound = Standard_True;
3605       Standard_Integer aWhatIndex = anArgumentIndices.FindIndex(theWhat);
3606
3607       // Find corresponding label in history
3608       TDF_Label anArgumentHistoryLabel =
3609         theWhereFunction->GetArgumentHistoryEntry(anArgumentRefLabel, Standard_False);
3610       if (anArgumentHistoryLabel.IsNull()) {
3611         // Lost History of operation argument. Possibly, all its entities was removed.
3612         isGood = Standard_True;
3613       }
3614       else {
3615         TDF_Label aWhatHistoryLabel = anArgumentHistoryLabel.FindChild(aWhatIndex, Standard_False);
3616
3617         if (aWhatHistoryLabel.IsNull()) {
3618           // Removed entity ? Compound ? Compsolid ? Shell ? Wire
3619           isGood = Standard_False;
3620         } else {
3621           Handle(TDataStd_IntegerArray) anIntegerArray;
3622           if (!aWhatHistoryLabel.FindAttribute(TDataStd_IntegerArray::GetID(), anIntegerArray)) {
3623             //Error: Empty modifications history for the sought shape.
3624             isGood = Standard_False;
3625           }
3626           else {
3627             isGood = Standard_True;
3628             Standard_Integer imod, aModifLen = anIntegerArray->Array()->Length();
3629             for (imod = 1; imod <= aModifLen; imod++) {
3630               theModifiedList.Append(anIntegerArray->Array()->Value(imod));
3631             }
3632           }
3633         }
3634       }
3635     }
3636   }
3637
3638   isFound = isGood;
3639
3640   if (!isFound) {
3641     // try compound/compsolid/shell/wire element by element
3642     bool isFoundAny = false;
3643     TopTools_MapOfShape mapShape;
3644
3645     if (theWhat.ShapeType() == TopAbs_COMPOUND ||
3646         theWhat.ShapeType() == TopAbs_COMPSOLID) {
3647       // recursive processing of compound/compsolid
3648       TopoDS_Iterator anIt (theWhat, Standard_True, Standard_True);
3649       for (; anIt.More(); anIt.Next()) {
3650         if (mapShape.Add(anIt.Value())) {
3651           TopoDS_Shape curWhat = anIt.Value();
3652           isFoundAny = GetInPlaceOfShape(theWhereFunction, theWhereIndices, curWhat, theModifiedList);
3653           if (isFoundAny) isFound = Standard_True;
3654         }
3655       }
3656     }
3657     else if (theWhat.ShapeType() == TopAbs_SHELL) {
3658       // try to replace a shell by its faces images
3659       TopExp_Explorer anExp (theWhat, TopAbs_FACE);
3660       for (; anExp.More(); anExp.Next()) {
3661         if (mapShape.Add(anExp.Current())) {
3662           TopoDS_Shape curWhat = anExp.Current();
3663           isFoundAny = GetInPlaceOfShape(theWhereFunction, theWhereIndices, curWhat, theModifiedList);
3664           if (isFoundAny) isFound = Standard_True;
3665         }
3666       }
3667     }
3668     else if (theWhat.ShapeType() == TopAbs_WIRE) {
3669       // try to replace a wire by its edges images
3670       TopExp_Explorer anExp (theWhat, TopAbs_EDGE);
3671       for (; anExp.More(); anExp.Next()) {
3672         if (mapShape.Add(anExp.Current())) {
3673           TopoDS_Shape curWhat = anExp.Current();
3674           isFoundAny = GetInPlaceOfShape(theWhereFunction, theWhereIndices, curWhat, theModifiedList);
3675           if (isFoundAny) isFound = Standard_True;
3676         }
3677       }
3678     }
3679     else {
3680       // Removed entity
3681     }
3682   }
3683
3684   return isFound;
3685 }
3686
3687 //=============================================================================
3688 /*!
3689  *  GetShapeProperties
3690  */
3691 //=============================================================================
3692 void GEOMImpl_IShapesOperations::GetShapeProperties( const TopoDS_Shape aShape, Standard_Real tab[],
3693                                                      gp_Pnt & aVertex )
3694 {
3695   GProp_GProps theProps;
3696   gp_Pnt aCenterMass;
3697   //TopoDS_Shape aPntShape;
3698   Standard_Real aShapeSize;
3699
3700   if    (aShape.ShapeType() == TopAbs_VERTEX) aCenterMass = BRep_Tool::Pnt( TopoDS::Vertex( aShape ) );
3701   else if (aShape.ShapeType() == TopAbs_EDGE) BRepGProp::LinearProperties(aShape,  theProps);
3702   else if (aShape.ShapeType() == TopAbs_FACE) BRepGProp::SurfaceProperties(aShape, theProps);
3703   else                                        BRepGProp::VolumeProperties(aShape,  theProps);
3704
3705   if (aShape.ShapeType() == TopAbs_VERTEX)
3706     aShapeSize = 1;
3707   else {
3708     aCenterMass = theProps.CentreOfMass();
3709     aShapeSize  = theProps.Mass();
3710   }
3711
3712 //   aPntShape = BRepBuilderAPI_MakeVertex(aCenterMass).Shape();
3713 //   aVertex   = BRep_Tool::Pnt( TopoDS::Vertex( aPntShape ) );
3714   aVertex = aCenterMass;
3715   tab[0] = aVertex.X();
3716   tab[1] = aVertex.Y();
3717   tab[2] = aVertex.Z();
3718   tab[3] = aShapeSize;
3719   return;
3720 }
3721
3722 namespace {
3723
3724   //================================================================================
3725   /*!
3726    * \brief Return normal to face at extrema point
3727    */
3728   //================================================================================
3729
3730   gp_Vec GetNormal (const TopoDS_Face& face, const BRepExtrema_DistShapeShape& extrema)
3731   {
3732     gp_Vec defaultNorm(1,0,0); // to have same normals on different faces
3733     try {
3734       // get UV at extrema point
3735       Standard_Real u,v, f,l;
3736       switch ( extrema.SupportTypeShape2(1) ) {
3737       case BRepExtrema_IsInFace: {
3738         extrema.ParOnFaceS2(1, u, v );
3739         break;
3740       }
3741       case BRepExtrema_IsOnEdge: {
3742         TopoDS_Edge edge = TopoDS::Edge( extrema.SupportOnShape2(1));
3743         Handle(Geom2d_Curve) pcurve = BRep_Tool::CurveOnSurface( edge, face, f,l );
3744         extrema.ParOnEdgeS2( 1, u );
3745         gp_Pnt2d uv = pcurve->Value( u );
3746         u = uv.Coord(1);
3747         v = uv.Coord(2);
3748         break;
3749       }
3750       case BRepExtrema_IsVertex: return defaultNorm;
3751       }
3752       // get derivatives
3753       BRepAdaptor_Surface surface( face, false );
3754       gp_Vec du, dv; gp_Pnt p;
3755       surface.D1( u, v, p, du, dv );
3756
3757       return du ^ dv;
3758
3759     } catch (Standard_Failure ) {
3760     }
3761     return defaultNorm;
3762   }
3763 }
3764
3765 //================================================================================
3766 /*!
3767  * \brief Return type of shape for explode. In case of compound it will be a type of sub-shape.
3768  */
3769 //================================================================================
3770 TopAbs_ShapeEnum GEOMImpl_IShapesOperations::GetTypeOfSimplePart (const TopoDS_Shape& theShape)
3771 {
3772   TopAbs_ShapeEnum aType = theShape.ShapeType();
3773   if      (aType == TopAbs_VERTEX)                             return TopAbs_VERTEX;
3774   else if (aType == TopAbs_EDGE  || aType == TopAbs_WIRE)      return TopAbs_EDGE;
3775   else if (aType == TopAbs_FACE  || aType == TopAbs_SHELL)     return TopAbs_FACE;
3776   else if (aType == TopAbs_SOLID || aType == TopAbs_COMPSOLID) return TopAbs_SOLID;
3777   else if (aType == TopAbs_COMPOUND) {
3778     // Only the iType of the first shape in the compound is taken into account
3779     TopoDS_Iterator It (theShape, Standard_False, Standard_False);
3780     if (It.More()) {
3781       return GetTypeOfSimplePart(It.Value());
3782     }
3783   }
3784   return TopAbs_SHAPE;
3785 }
3786
3787 //=============================================================================
3788 /*!
3789  *  case GetInPlace:
3790  *  default:
3791  */
3792 //=============================================================================
3793 Handle(GEOM_Object) GEOMImpl_IShapesOperations::GetInPlace (Handle(GEOM_Object) theShapeWhere,
3794                                                             Handle(GEOM_Object) theShapeWhat)
3795 {
3796   SetErrorCode(KO);
3797
3798   if (theShapeWhere.IsNull() || theShapeWhat.IsNull()) return NULL;
3799
3800   TopoDS_Shape aWhere = theShapeWhere->GetValue();
3801   TopoDS_Shape aWhat  = theShapeWhat->GetValue();
3802   TopoDS_Shape aPntShape;
3803   TopoDS_Vertex aVertex;
3804
3805   if (aWhere.IsNull() || aWhat.IsNull()) {
3806     SetErrorCode("Error: aWhere and aWhat TopoDS_Shape are Null.");
3807     return NULL;
3808   }
3809
3810   Handle(GEOM_Function) aWhereFunction = theShapeWhere->GetLastFunction();
3811   if (aWhereFunction.IsNull()) {
3812     SetErrorCode("Error: aWhereFunction is Null.");
3813     return NULL;
3814   }
3815
3816   TopTools_IndexedMapOfShape aWhereIndices;
3817   TopExp::MapShapes(aWhere, aWhereIndices);
3818
3819   TopAbs_ShapeEnum iType = TopAbs_SOLID;
3820   Standard_Real    dl_l = 1e-3;
3821   Standard_Real    min_l, Tol_0D, Tol_1D, Tol_2D, Tol_3D, Tol_Mass;
3822   Standard_Real    aXmin, aYmin, aZmin, aXmax, aYmax, aZmax;
3823   Bnd_Box          BoundingBox;
3824   gp_Pnt           aPnt, aPnt_aWhat, tab_Pnt[2];
3825   GProp_GProps     aProps;
3826
3827   // Find the iType of the aWhat shape
3828   iType = GetTypeOfSimplePart(aWhat);
3829   if (iType == TopAbs_SHAPE) {
3830     SetErrorCode("Error: An attempt to extract a shape of not supported type.");
3831     return NULL;
3832   }
3833
3834   TopExp_Explorer Exp_aWhat  ( aWhat,  iType );
3835   TopExp_Explorer Exp_aWhere ( aWhere, iType );
3836   TopExp_Explorer Exp_Edge   ( aWhere, TopAbs_EDGE );
3837
3838   // Find the shortest edge in theShapeWhere shape
3839   BRepBndLib::Add(aWhere, BoundingBox);
3840   BoundingBox.Get(aXmin, aYmin, aZmin, aXmax, aYmax, aZmax);
3841   min_l = fabs(aXmax - aXmin);
3842   if( min_l < fabs(aYmax - aYmin) ) min_l = fabs(aYmax - aYmin);
3843   if( min_l < fabs(aZmax - aZmin) ) min_l = fabs(aZmax - aZmin);
3844   min_l /= dl_l;
3845   // Mantis issue 0020908 BEGIN
3846   if (!Exp_Edge.More()) {
3847     min_l = Precision::Confusion();
3848   }
3849   // Mantis issue 0020908 END
3850   for ( Standard_Integer nbEdge = 0; Exp_Edge.More(); Exp_Edge.Next(), nbEdge++ ) {
3851     TopExp_Explorer Exp_Vertex( Exp_Edge.Current(), TopAbs_VERTEX);
3852     for ( Standard_Integer nbVertex = 0; Exp_Vertex.More(); Exp_Vertex.Next(), nbVertex++ ) {
3853       aPnt = BRep_Tool::Pnt( TopoDS::Vertex( Exp_Vertex.Current() ) );
3854       tab_Pnt[nbVertex] = aPnt;
3855     }
3856     if ( ! tab_Pnt[0].IsEqual(tab_Pnt[1], dl_l) ) {
3857       BRepGProp::LinearProperties(Exp_Edge.Current(), aProps);
3858       if ( aProps.Mass() < min_l ) min_l = aProps.Mass();
3859     }
3860   }
3861
3862   // Compute tolerances
3863   Tol_0D = dl_l;
3864   Tol_1D = dl_l * min_l;
3865   Tol_2D = dl_l * ( min_l * min_l) * ( 2. + dl_l);
3866   Tol_3D = dl_l * ( min_l * min_l * min_l ) * ( 3. + (3 * dl_l) + (dl_l * dl_l) );
3867
3868   if (Tol_0D < Precision::Confusion()) Tol_0D = Precision::Confusion();
3869   if (Tol_1D < Precision::Confusion()) Tol_1D = Precision::Confusion();
3870   if (Tol_2D < Precision::Confusion()) Tol_2D = Precision::Confusion();
3871   if (Tol_3D < Precision::Confusion()) Tol_3D = Precision::Confusion();
3872
3873   Tol_Mass = Tol_3D;
3874   if ( iType == TopAbs_VERTEX )    Tol_Mass = Tol_0D;
3875   else if ( iType == TopAbs_EDGE ) Tol_Mass = Tol_1D;
3876   else if ( iType == TopAbs_FACE ) Tol_Mass = Tol_2D;
3877
3878   // Searching for the sub-shapes inside the ShapeWhere shape
3879   GEOMAlgo_GetInPlace aGIP;
3880   aGIP.SetTolerance(Tol_1D);
3881   aGIP.SetTolMass(Tol_Mass);
3882   aGIP.SetTolCG(Tol_1D);
3883
3884   aGIP.SetArgument(aWhat);
3885   aGIP.SetShapeWhere(aWhere);
3886
3887   aGIP.Perform();
3888   int iErr = aGIP.ErrorStatus();
3889   if (iErr) {
3890     SetErrorCode("Error in GEOMAlgo_GetInPlace");
3891     return NULL;
3892   }
3893
3894   // aGIP.IsFound() returns true only when the whole theShapeWhat
3895   // is found (as one shape or several parts). But we are also interested
3896   // in the partial result, that is why this check is commented.
3897   //if (!aGIP.IsFound()) {
3898   //  SetErrorCode(NOT_FOUND_ANY);
3899   //  return NULL;
3900   //}
3901
3902   const TopTools_DataMapOfShapeListOfShape& aDMSLS = aGIP.Images();
3903   if (!aDMSLS.IsBound(aWhat)) {
3904     SetErrorCode(NOT_FOUND_ANY);
3905     return NULL;
3906   }
3907
3908   // the list of shapes aLSA contains the shapes 
3909   // of the Shape For Search that corresponds 
3910   // to the Argument aWhat
3911   const TopTools_ListOfShape& aLSA = aDMSLS.Find(aWhat);
3912   if (aLSA.Extent() == 0) {
3913     SetErrorCode(NOT_FOUND_ANY); // Not found any Results
3914     return NULL;
3915   }
3916
3917   Handle(TColStd_HArray1OfInteger) aModifiedArray = new TColStd_HArray1OfInteger (1, aLSA.Extent());
3918   TopTools_ListIteratorOfListOfShape anIterModif (aLSA);
3919   for (Standard_Integer imod = 1; anIterModif.More(); anIterModif.Next(), imod++) {
3920     if (aWhereIndices.Contains(anIterModif.Value())) {
3921       aModifiedArray->SetValue(imod, aWhereIndices.FindIndex(anIterModif.Value()));
3922     }
3923     else {
3924       SetErrorCode("Error: wrong sub-shape returned");
3925       return NULL;
3926     }
3927   }
3928
3929   //Add a new object
3930   Handle(GEOM_Object) aResult = GetEngine()->AddSubShape(theShapeWhere, aModifiedArray);
3931   if (aResult.IsNull()) {
3932     SetErrorCode("Error in algorithm: result found, but cannot be returned.");
3933     return NULL;
3934   }
3935
3936   if (aModifiedArray->Length() > 1 || theShapeWhat->GetType() == GEOM_GROUP) {
3937     //Set a GROUP type
3938     aResult->SetType(GEOM_GROUP);
3939
3940     //Set a sub-shape type
3941     TopoDS_Shape aFirstFound = aLSA.First();
3942     TopAbs_ShapeEnum aShapeType = aFirstFound.ShapeType();
3943
3944     TDF_Label aFreeLabel = aResult->GetFreeLabel();
3945     TDataStd_Integer::Set(aFreeLabel, (Standard_Integer)aShapeType);
3946   }
3947
3948   //Make a Python command
3949   Handle(GEOM_Function) aFunction = aResult->GetFunction(1);
3950
3951   GEOM::TPythonDump(aFunction) << aResult << " = geompy.GetInPlace("
3952     << theShapeWhere << ", " << theShapeWhat << ", True)";
3953
3954   SetErrorCode(OK);
3955   return aResult;
3956 }
3957
3958 //=============================================================================
3959 /*!
3960  *  case GetInPlaceOld:
3961  *  default:
3962  */
3963 //=============================================================================
3964 Handle(GEOM_Object) GEOMImpl_IShapesOperations::GetInPlaceOld (Handle(GEOM_Object) theShapeWhere,
3965                                                                Handle(GEOM_Object) theShapeWhat)
3966 {
3967   SetErrorCode(KO);
3968
3969   if (theShapeWhere.IsNull() || theShapeWhat.IsNull()) return NULL;
3970
3971   TopoDS_Shape aWhere = theShapeWhere->GetValue();
3972   TopoDS_Shape aWhat  = theShapeWhat->GetValue();
3973   TopoDS_Shape aPntShape;
3974   TopoDS_Vertex aVertex;
3975
3976   if (aWhere.IsNull() || aWhat.IsNull()) {
3977     SetErrorCode("Error: aWhere and aWhat TopoDS_Shape are Null.");
3978     return NULL;
3979   }
3980
3981   Handle(GEOM_Function) aWhereFunction = theShapeWhere->GetLastFunction();
3982   if (aWhereFunction.IsNull()) {
3983     SetErrorCode("Error: aWhereFunction is Null.");
3984     return NULL;
3985   }
3986
3987   TopTools_IndexedMapOfShape aWhereIndices;
3988   TopExp::MapShapes(aWhere, aWhereIndices);
3989
3990   TColStd_ListOfInteger aModifiedList;
3991   Standard_Integer aWhereIndex;
3992   Handle(TColStd_HArray1OfInteger) aModifiedArray;
3993   Handle(GEOM_Object) aResult;
3994
3995   bool isFound = false;
3996   TopAbs_ShapeEnum iType = TopAbs_SOLID;
3997   //Standard_Real    aWhat_Mass = 0., aWhere_Mass = 0.;
3998   Standard_Real    tab_aWhat[4],    tab_aWhere[4];
3999   Standard_Real    dl_l = 1e-3;
4000   Standard_Real    min_l, Tol_0D, Tol_1D, Tol_2D, Tol_3D, Tol_Mass;
4001   Standard_Real    aXmin, aYmin, aZmin, aXmax, aYmax, aZmax;
4002   Bnd_Box          BoundingBox;
4003   gp_Pnt           aPnt, aPnt_aWhat, tab_Pnt[2];
4004   GProp_GProps     aProps;
4005
4006   // Find the iType of the aWhat shape
4007   /*
4008   if      ( aWhat.ShapeType() == TopAbs_VERTEX )                                         iType = TopAbs_VERTEX;
4009   else if ( aWhat.ShapeType() == TopAbs_EDGE  || aWhat.ShapeType() == TopAbs_WIRE )      iType = TopAbs_EDGE;
4010   else if ( aWhat.ShapeType() == TopAbs_FACE  || aWhat.ShapeType() == TopAbs_SHELL )     iType = TopAbs_FACE;
4011   else if ( aWhat.ShapeType() == TopAbs_SOLID || aWhat.ShapeType() == TopAbs_COMPSOLID ) iType = TopAbs_SOLID;
4012   else if ( aWhat.ShapeType() == TopAbs_COMPOUND ) {
4013     // Only the iType of the first shape in the compound is taken into account
4014     TopoDS_Iterator It (aWhat, Standard_False, Standard_False);
4015     if ( !It.More() ) {
4016       SetErrorCode("Error: theShapeWhat is an empty COMPOUND.");
4017       return NULL;
4018     }
4019     TopAbs_ShapeEnum compType = It.Value().ShapeType();
4020     if      ( compType == TopAbs_VERTEX )                               iType = TopAbs_VERTEX;
4021     else if ( compType == TopAbs_EDGE  || compType == TopAbs_WIRE )     iType = TopAbs_EDGE;
4022     else if ( compType == TopAbs_FACE  || compType == TopAbs_SHELL)     iType = TopAbs_FACE;
4023     else if ( compType == TopAbs_SOLID || compType == TopAbs_COMPSOLID) iType = TopAbs_SOLID;
4024   }
4025   else {
4026     SetErrorCode("Error: An attempt to extract a shape of not supported type.");
4027     return NULL;
4028   }
4029   */
4030   iType = GetTypeOfSimplePart(aWhat);
4031   if (iType == TopAbs_SHAPE) {
4032     SetErrorCode("Error: An attempt to extract a shape of not supported type.");
4033     return NULL;
4034   }
4035
4036   TopExp_Explorer Exp_aWhat  ( aWhat,  iType );
4037   TopExp_Explorer Exp_aWhere ( aWhere, iType );
4038   TopExp_Explorer Exp_Edge   ( aWhere, TopAbs_EDGE );
4039
4040   // Find the shortest edge in theShapeWhere shape
4041   BRepBndLib::Add(aWhere, BoundingBox);
4042   BoundingBox.Get(aXmin, aYmin, aZmin, aXmax, aYmax, aZmax);
4043   min_l = fabs(aXmax - aXmin);
4044   if( min_l < fabs(aYmax - aYmin) ) min_l = fabs(aYmax - aYmin);
4045   if( min_l < fabs(aZmax - aZmin) ) min_l = fabs(aZmax - aZmin);
4046   min_l /= dl_l;
4047   // Mantis issue 0020908 BEGIN
4048   if (!Exp_Edge.More()) {
4049     min_l = Precision::Confusion();
4050   }
4051   // Mantis issue 0020908 END
4052   for ( Standard_Integer nbEdge = 0; Exp_Edge.More(); Exp_Edge.Next(), nbEdge++ ) {
4053     TopExp_Explorer Exp_Vertex( Exp_Edge.Current(), TopAbs_VERTEX);
4054     for ( Standard_Integer nbVertex = 0; Exp_Vertex.More(); Exp_Vertex.Next(), nbVertex++ ) {
4055       aPnt = BRep_Tool::Pnt( TopoDS::Vertex( Exp_Vertex.Current() ) );
4056       tab_Pnt[nbVertex] = aPnt;
4057     }
4058     if ( ! tab_Pnt[0].IsEqual(tab_Pnt[1], dl_l) ) {
4059       BRepGProp::LinearProperties(Exp_Edge.Current(), aProps);
4060       if ( aProps.Mass() < min_l ) min_l = aProps.Mass();
4061     }
4062   }
4063
4064   // Compute tolerances
4065   Tol_0D = dl_l;
4066   Tol_1D = dl_l * min_l;
4067   Tol_2D = dl_l * ( min_l * min_l) * ( 2. + dl_l);
4068   Tol_3D = dl_l * ( min_l * min_l * min_l ) * ( 3. + (3 * dl_l) + (dl_l * dl_l) );
4069
4070   if (Tol_0D < Precision::Confusion()) Tol_0D = Precision::Confusion();
4071   if (Tol_1D < Precision::Confusion()) Tol_1D = Precision::Confusion();
4072   if (Tol_2D < Precision::Confusion()) Tol_2D = Precision::Confusion();
4073   if (Tol_3D < Precision::Confusion()) Tol_3D = Precision::Confusion();
4074
4075   //if (Tol_1D > 1.0) Tol_1D = 1.0;
4076   //if (Tol_2D > 1.0) Tol_2D = 1.0;
4077   //if (Tol_3D > 1.0) Tol_3D = 1.0;
4078
4079   Tol_Mass = Tol_3D;
4080   if ( iType == TopAbs_VERTEX )    Tol_Mass = Tol_0D;
4081   else if ( iType == TopAbs_EDGE ) Tol_Mass = Tol_1D;
4082   else if ( iType == TopAbs_FACE ) Tol_Mass = Tol_2D;
4083
4084   // Compute the ShapeWhat Mass
4085   /*
4086   for ( ; Exp_aWhat.More(); Exp_aWhat.Next() ) {
4087     if ( iType == TopAbs_VERTEX ) {
4088       aWhat_Mass += 1;
4089       continue;
4090     }
4091     else if ( iType == TopAbs_EDGE ) BRepGProp::LinearProperties(Exp_aWhat.Current(),  aProps);
4092     else if ( iType == TopAbs_FACE ) BRepGProp::SurfaceProperties(Exp_aWhat.Current(), aProps);
4093     else                             BRepGProp::VolumeProperties(Exp_aWhat.Current(),  aProps);
4094     aWhat_Mass += aProps.Mass();
4095   }
4096   */
4097
4098   // Searching for the sub-shapes inside the ShapeWhere shape
4099   TopTools_MapOfShape map_aWhere;
4100   for ( Exp_aWhere.ReInit(); Exp_aWhere.More(); Exp_aWhere.Next() ) {
4101     if (!map_aWhere.Add(Exp_aWhere.Current()))
4102       continue; // skip repeated shape to avoid mass addition
4103     GetShapeProperties( Exp_aWhere.Current(), tab_aWhere, aPnt );
4104     for ( Exp_aWhat.ReInit(); Exp_aWhat.More(); Exp_aWhat.Next() ) {
4105       GetShapeProperties( Exp_aWhat.Current(), tab_aWhat, aPnt_aWhat );
4106       if ( fabs(tab_aWhat[3] - tab_aWhere[3]) <= Tol_Mass && aPnt_aWhat.Distance(aPnt) <= Tol_1D )
4107         isFound = true;
4108       else {
4109         if ( (tab_aWhat[3] - tab_aWhere[3]) > Tol_Mass ) {
4110           aPntShape = BRepBuilderAPI_MakeVertex( aPnt ).Shape();
4111           aVertex   = TopoDS::Vertex( aPntShape );
4112           BRepExtrema_DistShapeShape aWhereDistance ( aVertex, Exp_aWhere.Current() );
4113           BRepExtrema_DistShapeShape aWhatDistance  ( aVertex, Exp_aWhat.Current() );
4114           if ( aWhereDistance.IsDone() && aWhatDistance.IsDone() &&
4115                fabs(aWhereDistance.Value() - aWhatDistance.Value()) <= Tol_1D )
4116           {
4117             // 0020162: "EDF 961 GEOM : Getinplace is getting additionnal orthogonal faces"
4118             // aVertex must be projected to the same point on Where and on What
4119             gp_Pnt pOnWhat  = aWhatDistance.PointOnShape2(1);
4120             gp_Pnt pOnWhere = aWhereDistance.PointOnShape2(1);
4121             isFound = ( pOnWhat.Distance(pOnWhere) <= Tol_1D );
4122             if ( isFound && iType == TopAbs_FACE )
4123             {
4124               // check normals at pOnWhat and pOnWhere
4125               const double angleTol = M_PI/180.;
4126               gp_Vec normToWhat  = GetNormal( TopoDS::Face(Exp_aWhat.Current()), aWhatDistance);
4127               gp_Vec normToWhere = GetNormal( TopoDS::Face(Exp_aWhere.Current()), aWhereDistance);
4128               if ( normToWhat * normToWhere < 0 )
4129                 normToWhat.Reverse();
4130               isFound = ( normToWhat.Angle( normToWhere ) < angleTol );
4131             }
4132           }
4133         }
4134       }
4135       if ( isFound ) {
4136         aWhereIndex = aWhereIndices.FindIndex(Exp_aWhere.Current());
4137         aModifiedList.Append(aWhereIndex);
4138         //aWhere_Mass += tab_aWhere[3];
4139         isFound = false;
4140         break;
4141       }
4142     }
4143     //if ( fabs( aWhat_Mass - aWhere_Mass ) <= Tol_Mass )
4144       //break;
4145   }
4146
4147   if (aModifiedList.Extent() == 0) { // Not found any Results
4148     SetErrorCode(NOT_FOUND_ANY);
4149     return NULL;
4150   }
4151
4152   aModifiedArray = new TColStd_HArray1OfInteger (1, aModifiedList.Extent());
4153   TColStd_ListIteratorOfListOfInteger anIterModif (aModifiedList);
4154   for (Standard_Integer imod = 1; anIterModif.More(); anIterModif.Next(), imod++)
4155     aModifiedArray->SetValue(imod, anIterModif.Value());
4156
4157   //Add a new object
4158   aResult = GetEngine()->AddSubShape(theShapeWhere, aModifiedArray);
4159   if (aResult.IsNull()) {
4160     SetErrorCode("Error in algorithm: result found, but cannot be returned.");
4161     return NULL;
4162   }
4163
4164   if (aModifiedArray->Length() > 1 || theShapeWhat->GetType() == GEOM_GROUP) {
4165     //Set a GROUP type
4166     aResult->SetType(GEOM_GROUP);
4167
4168     //Set a sub-shape type
4169     TopoDS_Shape aFirstFound = aWhereIndices.FindKey(aModifiedArray->Value(1));
4170     TopAbs_ShapeEnum aShapeType = aFirstFound.ShapeType();
4171
4172     TDF_Label aFreeLabel = aResult->GetFreeLabel();
4173     TDataStd_Integer::Set(aFreeLabel, (Standard_Integer)aShapeType);
4174   }
4175
4176   //Make a Python command
4177   Handle(GEOM_Function) aFunction = aResult->GetFunction(1);
4178
4179   GEOM::TPythonDump(aFunction) << aResult << " = geompy.GetInPlace("
4180     << theShapeWhere << ", " << theShapeWhat << ", False)";
4181
4182   SetErrorCode(OK);
4183   return aResult;
4184 }
4185
4186 //=======================================================================
4187 //function : GetInPlaceByHistory
4188 //purpose  :
4189 //=======================================================================
4190 Handle(GEOM_Object) GEOMImpl_IShapesOperations::GetInPlaceByHistory
4191                                           (Handle(GEOM_Object) theShapeWhere,
4192                                            Handle(GEOM_Object) theShapeWhat)
4193 {
4194   SetErrorCode(KO);
4195
4196   if (theShapeWhere.IsNull() || theShapeWhat.IsNull()) return NULL;
4197
4198   TopoDS_Shape aWhere = theShapeWhere->GetValue();
4199   TopoDS_Shape aWhat  = theShapeWhat->GetValue();
4200
4201   if (aWhere.IsNull() || aWhat.IsNull()) return NULL;
4202
4203   Handle(GEOM_Function) aWhereFunction = theShapeWhere->GetLastFunction();
4204   if (aWhereFunction.IsNull()) return NULL;
4205
4206   //Fill array of indices
4207   TopTools_IndexedMapOfShape aWhereIndices;
4208   TopExp::MapShapes(aWhere, aWhereIndices);
4209
4210   // process shape
4211   TColStd_ListOfInteger aModifiedList;
4212   bool isFound = GetInPlaceOfShape(aWhereFunction, aWhereIndices, aWhat, aModifiedList);
4213
4214   if (!isFound || aModifiedList.Extent() < 1) {
4215     SetErrorCode("Error: No history found for the sought shape or its sub-shapes.");
4216     return NULL;
4217   }
4218
4219   Handle(TColStd_HArray1OfInteger) aModifiedArray =
4220     new TColStd_HArray1OfInteger (1, aModifiedList.Extent());
4221   TColStd_ListIteratorOfListOfInteger anIterModif (aModifiedList);
4222   for (Standard_Integer imod = 1; anIterModif.More(); anIterModif.Next(), imod++) {
4223     aModifiedArray->SetValue(imod, anIterModif.Value());
4224   }
4225
4226   //Add a new object
4227   Handle(GEOM_Object) aResult = GetEngine()->AddSubShape(theShapeWhere, aModifiedArray);
4228   if (aResult.IsNull()) {
4229     SetErrorCode("Error in algorithm: result found, but cannot be returned.");
4230     return NULL;
4231   }
4232
4233   if (aModifiedArray->Length() > 1) {
4234     //Set a GROUP type
4235     aResult->SetType(GEOM_GROUP);
4236
4237     //Set a sub-shape type
4238     TopoDS_Shape aFirstFound = aWhereIndices.FindKey(aModifiedArray->Value(1));
4239     TopAbs_ShapeEnum aShapeType = aFirstFound.ShapeType();
4240
4241     TDF_Label aFreeLabel = aResult->GetFreeLabel();
4242     TDataStd_Integer::Set(aFreeLabel, (Standard_Integer)aShapeType);
4243   }
4244
4245   //Make a Python command
4246   Handle(GEOM_Function) aFunction = aResult->GetFunction(1);
4247
4248   GEOM::TPythonDump(aFunction) << aResult << " = geompy.GetInPlaceByHistory("
4249     << theShapeWhere << ", " << theShapeWhat << ")";
4250
4251   SetErrorCode(OK);
4252   return aResult;
4253 }
4254
4255 //=======================================================================
4256 //function : ShapeToDouble
4257 //purpose  : used by CompareShapes::operator()
4258 //=======================================================================
4259 std::pair<double, double> ShapeToDouble (const TopoDS_Shape& S, bool isOldSorting)
4260 {
4261   // Computing of CentreOfMass
4262   gp_Pnt GPoint;
4263   double Len;
4264
4265   if (S.ShapeType() == TopAbs_VERTEX) {
4266     GPoint = BRep_Tool::Pnt(TopoDS::Vertex(S));
4267     Len = (double)S.Orientation();
4268   }
4269   else {
4270     GProp_GProps GPr;
4271     // BEGIN: fix for Mantis issue 0020842
4272     if (isOldSorting) {
4273       BRepGProp::LinearProperties(S, GPr);
4274     }
4275     else {
4276       if (S.ShapeType() == TopAbs_EDGE || S.ShapeType() == TopAbs_WIRE) {
4277         BRepGProp::LinearProperties(S, GPr);
4278       }
4279       else if (S.ShapeType() == TopAbs_FACE || S.ShapeType() == TopAbs_SHELL) {
4280         BRepGProp::SurfaceProperties(S, GPr);
4281       }
4282       else {
4283         BRepGProp::VolumeProperties(S, GPr);
4284       }
4285     }
4286     // END: fix for Mantis issue 0020842
4287     GPoint = GPr.CentreOfMass();
4288     Len = GPr.Mass();
4289   }
4290
4291   double dMidXYZ = GPoint.X() * 999.0 + GPoint.Y() * 99.0 + GPoint.Z() * 0.9;
4292   return std::make_pair(dMidXYZ, Len);
4293 }
4294
4295 //=======================================================================
4296 //function : CompareShapes::operator()
4297 //purpose  : used by std::sort(), called from SortShapes()
4298 //=======================================================================
4299 bool GEOMImpl_IShapesOperations::CompareShapes::operator()(const TopoDS_Shape& theShape1,
4300                                                            const TopoDS_Shape& theShape2)
4301 {
4302   if (!myMap.IsBound(theShape1)) {
4303     myMap.Bind(theShape1, ShapeToDouble(theShape1, myIsOldSorting));
4304   }
4305
4306   if (!myMap.IsBound(theShape2)) {
4307     myMap.Bind(theShape2, ShapeToDouble(theShape2, myIsOldSorting));
4308   }
4309
4310   std::pair<double, double> val1 = myMap.Find(theShape1);
4311   std::pair<double, double> val2 = myMap.Find(theShape2);
4312
4313   double tol = Precision::Confusion();
4314   bool exchange = Standard_False;
4315
4316   double dMidXYZ = val1.first - val2.first;
4317   if (dMidXYZ >= tol) {
4318     exchange = Standard_True;
4319   }
4320   else if (Abs(dMidXYZ) < tol) {
4321     double dLength = val1.second - val2.second;
4322     if (dLength >= tol) {
4323       exchange = Standard_True;
4324     }
4325     else if (Abs(dLength) < tol && theShape1.ShapeType() <= TopAbs_FACE) {
4326       // PAL17233
4327       // equal values possible on shapes such as two halves of a sphere and
4328       // a membrane inside the sphere
4329       Bnd_Box box1,box2;
4330       BRepBndLib::Add(theShape1, box1);
4331       if (!box1.IsVoid()) {
4332         BRepBndLib::Add(theShape2, box2);
4333         Standard_Real dSquareExtent = box1.SquareExtent() - box2.SquareExtent();
4334         if (dSquareExtent >= tol) {
4335           exchange = Standard_True;
4336         }
4337         else if (Abs(dSquareExtent) < tol) {
4338           Standard_Real aXmin, aYmin, aZmin, aXmax, aYmax, aZmax, val1, val2;
4339           box1.Get(aXmin, aYmin, aZmin, aXmax, aYmax, aZmax);
4340           val1 = (aXmin+aXmax)*999.0 + (aYmin+aYmax)*99.0 + (aZmin+aZmax)*0.9;
4341           box2.Get(aXmin, aYmin, aZmin, aXmax, aYmax, aZmax);
4342           val2 = (aXmin+aXmax)*999.0 + (aYmin+aYmax)*99.0 + (aZmin+aZmax)*0.9;
4343           if ((val1 - val2) >= tol) {
4344             exchange = Standard_True;
4345           }
4346         }
4347       }
4348     }
4349   }
4350
4351   //return val1 < val2;
4352   return !exchange;
4353 }
4354
4355 //=======================================================================
4356 //function : SortShapes
4357 //purpose  :
4358 //=======================================================================
4359 void GEOMImpl_IShapesOperations::SortShapes(TopTools_ListOfShape& SL,
4360                                             const Standard_Boolean isOldSorting)
4361 {
4362 #ifdef STD_SORT_ALGO
4363   std::vector<TopoDS_Shape> aShapesVec;
4364   aShapesVec.reserve(SL.Extent());
4365
4366   TopTools_ListIteratorOfListOfShape it (SL);
4367   for (; it.More(); it.Next()) {
4368     aShapesVec.push_back(it.Value());
4369   }
4370   SL.Clear();
4371
4372   CompareShapes shComp (isOldSorting);
4373   std::stable_sort(aShapesVec.begin(), aShapesVec.end(), shComp);
4374   //std::sort(aShapesVec.begin(), aShapesVec.end(), shComp);
4375
4376   std::vector<TopoDS_Shape>::const_iterator anIter = aShapesVec.begin();
4377   for (; anIter != aShapesVec.end(); ++anIter) {
4378     SL.Append(*anIter);
4379   }
4380 #else
4381   // old implementation
4382   Standard_Integer MaxShapes = SL.Extent();
4383   TopTools_Array1OfShape  aShapes (1,MaxShapes);
4384   TColStd_Array1OfInteger OrderInd(1,MaxShapes);
4385   TColStd_Array1OfReal    MidXYZ  (1,MaxShapes); //X,Y,Z;
4386   TColStd_Array1OfReal    Length  (1,MaxShapes); //X,Y,Z;
4387
4388   // Computing of CentreOfMass
4389   Standard_Integer Index;
4390   GProp_GProps GPr;
4391   gp_Pnt GPoint;
4392   TopTools_ListIteratorOfListOfShape it(SL);
4393   for (Index=1;  it.More();  Index++)
4394   {
4395     TopoDS_Shape S = it.Value();
4396     SL.Remove( it ); // == it.Next()
4397     aShapes(Index) = S;
4398     OrderInd.SetValue (Index, Index);
4399     if (S.ShapeType() == TopAbs_VERTEX) {
4400       GPoint = BRep_Tool::Pnt( TopoDS::Vertex( S ));
4401       Length.SetValue( Index, (Standard_Real) S.Orientation());
4402     }
4403     else {
4404       // BEGIN: fix for Mantis issue 0020842
4405       if (isOldSorting) {
4406         BRepGProp::LinearProperties (S, GPr);
4407       }
4408       else {
4409         if (S.ShapeType() == TopAbs_EDGE || S.ShapeType() == TopAbs_WIRE) {
4410           BRepGProp::LinearProperties (S, GPr);
4411         }
4412         else if (S.ShapeType() == TopAbs_FACE || S.ShapeType() == TopAbs_SHELL) {
4413           BRepGProp::SurfaceProperties(S, GPr);
4414         }
4415         else {
4416           BRepGProp::VolumeProperties(S, GPr);
4417         }
4418       }
4419       // END: fix for Mantis issue 0020842
4420       GPoint = GPr.CentreOfMass();
4421       Length.SetValue(Index, GPr.Mass());
4422     }
4423     MidXYZ.SetValue(Index, GPoint.X()*999.0 + GPoint.Y()*99.0 + GPoint.Z()*0.9);
4424     //cout << Index << " L: " << Length(Index) << "CG: " << MidXYZ(Index) << endl;
4425   }
4426
4427   // Sorting
4428   Standard_Integer aTemp;
4429   Standard_Boolean exchange, Sort = Standard_True;
4430   Standard_Real    tol = Precision::Confusion();
4431   while (Sort)
4432   {
4433     Sort = Standard_False;
4434     for (Index=1; Index < MaxShapes; Index++)
4435     {
4436       exchange = Standard_False;
4437       Standard_Real dMidXYZ = MidXYZ(OrderInd(Index)) - MidXYZ(OrderInd(Index+1));
4438       Standard_Real dLength = Length(OrderInd(Index)) - Length(OrderInd(Index+1));
4439       if ( dMidXYZ >= tol ) {
4440 //         cout << "MidXYZ: " << MidXYZ(OrderInd(Index))<< " > " <<MidXYZ(OrderInd(Index+1))
4441 //              << " d: " << dMidXYZ << endl;
4442         exchange = Standard_True;
4443       }
4444       else if ( Abs(dMidXYZ) < tol && dLength >= tol ) {
4445 //         cout << "Length: " << Length(OrderInd(Index))<< " > " <<Length(OrderInd(Index+1))
4446 //              << " d: " << dLength << endl;
4447         exchange = Standard_True;
4448       }
4449       else if ( Abs(dMidXYZ) < tol && Abs(dLength) < tol &&
4450                 aShapes(OrderInd(Index)).ShapeType() <= TopAbs_FACE) {
4451         // PAL17233
4452         // equal values possible on shapes such as two halves of a sphere and
4453         // a membrane inside the sphere
4454         Bnd_Box box1,box2;
4455         BRepBndLib::Add( aShapes( OrderInd(Index) ), box1 );
4456         if ( box1.IsVoid() ) continue;
4457         BRepBndLib::Add( aShapes( OrderInd(Index+1) ), box2 );
4458         Standard_Real dSquareExtent = box1.SquareExtent() - box2.SquareExtent();
4459         if ( dSquareExtent >= tol ) {
4460 //           cout << "SquareExtent: " << box1.SquareExtent()<<" > "<<box2.SquareExtent() << endl;
4461           exchange = Standard_True;
4462         }
4463         else if ( Abs(dSquareExtent) < tol ) {
4464           Standard_Real aXmin, aYmin, aZmin, aXmax, aYmax, aZmax, val1, val2;
4465           box1.Get(aXmin, aYmin, aZmin, aXmax, aYmax, aZmax);
4466           val1 = (aXmin+aXmax)*999 + (aYmin+aYmax)*99 + (aZmin+aZmax)*0.9;
4467           box2.Get(aXmin, aYmin, aZmin, aXmax, aYmax, aZmax);
4468           val2 = (aXmin+aXmax)*999 + (aYmin+aYmax)*99 + (aZmin+aZmax)*0.9;
4469           //exchange = val1 > val2;
4470           if ((val1 - val2) >= tol) {
4471             exchange = Standard_True;
4472           }
4473           //cout << "box: " << val1<<" > "<<val2 << endl;
4474         }
4475       }
4476
4477       if (exchange)
4478       {
4479 //         cout << "exchange " << Index << " & " << Index+1 << endl;
4480         aTemp = OrderInd(Index);
4481         OrderInd(Index) = OrderInd(Index+1);
4482         OrderInd(Index+1) = aTemp;
4483         Sort = Standard_True;
4484       }
4485     }
4486   }
4487
4488   for (Index=1; Index <= MaxShapes; Index++)
4489     SL.Append( aShapes( OrderInd(Index) ));
4490 #endif
4491 }
4492
4493 //=======================================================================
4494 //function : CompsolidToCompound
4495 //purpose  :
4496 //=======================================================================
4497 TopoDS_Shape GEOMImpl_IShapesOperations::CompsolidToCompound (const TopoDS_Shape& theCompsolid)
4498 {
4499   if (theCompsolid.ShapeType() != TopAbs_COMPSOLID) {
4500     return theCompsolid;
4501   }
4502
4503   TopoDS_Compound aCompound;
4504   BRep_Builder B;
4505   B.MakeCompound(aCompound);
4506
4507   TopTools_MapOfShape mapShape;
4508   TopoDS_Iterator It (theCompsolid, Standard_True, Standard_True);
4509
4510   for (; It.More(); It.Next()) {
4511     TopoDS_Shape aShape_i = It.Value();
4512     if (mapShape.Add(aShape_i)) {
4513       B.Add(aCompound, aShape_i);
4514     }
4515   }
4516
4517   return aCompound;
4518 }
4519
4520 //=======================================================================
4521 //function : CheckTriangulation
4522 //purpose  :
4523 //=======================================================================
4524 bool GEOMImpl_IShapesOperations::CheckTriangulation (const TopoDS_Shape& aShape)
4525 {
4526   bool isTriangulation = true;
4527
4528   TopExp_Explorer exp (aShape, TopAbs_FACE);
4529   if (exp.More())
4530   {
4531     TopLoc_Location aTopLoc;
4532     Handle(Poly_Triangulation) aTRF;
4533     aTRF = BRep_Tool::Triangulation(TopoDS::Face(exp.Current()), aTopLoc);
4534     if (aTRF.IsNull()) {
4535       isTriangulation = false;
4536     }
4537   }
4538   else // no faces, try edges
4539   {
4540     TopExp_Explorer expe (aShape, TopAbs_EDGE);
4541     if (!expe.More()) {
4542       return false;
4543     }
4544     TopLoc_Location aLoc;
4545     Handle(Poly_Polygon3D) aPE = BRep_Tool::Polygon3D(TopoDS::Edge(expe.Current()), aLoc);
4546     if (aPE.IsNull()) {
4547       isTriangulation = false;
4548     }
4549   }
4550
4551   if (!isTriangulation) {
4552     // calculate deflection
4553     Standard_Real aDeviationCoefficient = 0.001;
4554
4555     Bnd_Box B;
4556     BRepBndLib::Add(aShape, B);
4557     Standard_Real aXmin, aYmin, aZmin, aXmax, aYmax, aZmax;
4558     B.Get(aXmin, aYmin, aZmin, aXmax, aYmax, aZmax);
4559
4560     Standard_Real dx = aXmax - aXmin, dy = aYmax - aYmin, dz = aZmax - aZmin;
4561     Standard_Real aDeflection = Max(Max(dx, dy), dz) * aDeviationCoefficient * 4;
4562     Standard_Real aHLRAngle = 0.349066;
4563
4564     BRepMesh_IncrementalMesh Inc (aShape, aDeflection, Standard_False, aHLRAngle);
4565   }
4566
4567   return true;
4568 }
4569
4570 #define MAX_TOLERANCE 1.e-7
4571
4572 //=======================================================================
4573 //function : isSameEdge
4574 //purpose  : Returns True if two edges coincide
4575 //=======================================================================
4576 static bool isSameEdge(const TopoDS_Edge& theEdge1, const TopoDS_Edge& theEdge2)
4577 {
4578   TopoDS_Vertex V11, V12, V21, V22;
4579   TopExp::Vertices(theEdge1, V11, V12);
4580   TopExp::Vertices(theEdge2, V21, V22);
4581   gp_Pnt P11 = BRep_Tool::Pnt(V11);
4582   gp_Pnt P12 = BRep_Tool::Pnt(V12);
4583   gp_Pnt P21 = BRep_Tool::Pnt(V21);
4584   gp_Pnt P22 = BRep_Tool::Pnt(V22);
4585   bool coincide = false;
4586
4587   //Check that ends of edges coincide
4588   if(P11.Distance(P21) <= MAX_TOLERANCE) {
4589     if(P12.Distance(P22) <= MAX_TOLERANCE) coincide =  true;
4590   }
4591   else if(P11.Distance(P22) <= MAX_TOLERANCE) {
4592     if(P12.Distance(P21) <= MAX_TOLERANCE) coincide = true;
4593   }
4594
4595   if(!coincide) return false;
4596
4597   if (BRep_Tool::Degenerated(theEdge1))
4598     if (BRep_Tool::Degenerated(theEdge2)) return true;
4599     else return false;
4600   else
4601     if (BRep_Tool::Degenerated(theEdge2)) return false;
4602
4603   double U11, U12, U21, U22;
4604   Handle(Geom_Curve) C1 = BRep_Tool::Curve(theEdge1, U11, U12);
4605   Handle(Geom_Curve) C2 = BRep_Tool::Curve(theEdge2, U21, U22);
4606   if(C1->DynamicType() == C2->DynamicType()) return true;
4607
4608   //Check that both edges has the same geometry
4609   double range = U12-U11;
4610   double U = U11+ range/3.0;
4611   gp_Pnt P1 = C1->Value(U);     //Compute a point on one third of the edge's length
4612   U = U11+range*2.0/3.0;
4613   gp_Pnt P2 = C1->Value(U);     //Compute a point on two thirds of the edge's length
4614
4615   if(!GeomLib_Tool::Parameter(C2, P1, MAX_TOLERANCE, U) ||  U < U21 || U > U22)
4616     return false;
4617
4618   if(P1.Distance(C2->Value(U)) > MAX_TOLERANCE) return false;
4619
4620   if(!GeomLib_Tool::Parameter(C2, P2, MAX_TOLERANCE, U) || U < U21 || U > U22)
4621     return false;
4622
4623   if(P2.Distance(C2->Value(U)) > MAX_TOLERANCE) return false;
4624
4625   return true;
4626 }
4627
4628 #include <TopoDS_TShape.hxx>
4629 //=======================================================================
4630 //function : isSameFace
4631 //purpose  : Returns True if two faces coincide
4632 //=======================================================================
4633 static bool isSameFace(const TopoDS_Face& theFace1, const TopoDS_Face& theFace2)
4634 {
4635   TopExp_Explorer E(theFace1, TopAbs_EDGE);
4636   TopTools_ListOfShape LS1, LS2;
4637   for(; E.More(); E.Next()) LS1.Append(E.Current());
4638
4639   E.Init(theFace2, TopAbs_EDGE);
4640   for(; E.More(); E.Next()) LS2.Append(E.Current());
4641
4642   //Compare the number of edges in the faces
4643   if(LS1.Extent() != LS2.Extent()) return false;
4644
4645   double aMin = RealFirst(), aMax = RealLast();
4646   double xminB1=aMax, yminB1=aMax, zminB1=aMax, xminB2=aMax, yminB2=aMax, zminB2=aMax;
4647   double xmaxB1=aMin, ymaxB1=aMin, zmaxB1=aMin, xmaxB2=aMin, ymaxB2=aMin, zmaxB2=aMin;
4648
4649   for(E.Init(theFace1, TopAbs_VERTEX); E.More(); E.Next()) {
4650     gp_Pnt P = BRep_Tool::Pnt(TopoDS::Vertex(E.Current()));
4651     if(P.X() < xminB1) xminB1 = P.X();
4652     if(P.Y() < yminB1) yminB1 = P.Y();
4653     if(P.Z() < zminB1) zminB1 = P.Z();
4654     if(P.X() > xmaxB1) xmaxB1 = P.X();
4655     if(P.Y() > ymaxB1) ymaxB1 = P.Y();
4656     if(P.Z() > zmaxB1) zmaxB1 = P.Z();
4657   }
4658
4659   for(E.Init(theFace2, TopAbs_VERTEX); E.More(); E.Next()) {
4660     gp_Pnt P = BRep_Tool::Pnt(TopoDS::Vertex(E.Current()));
4661     if(P.X() < xminB2) xminB2 = P.X();
4662     if(P.Y() < yminB2) yminB2 = P.Y();
4663     if(P.Z() < zminB2) zminB2 = P.Z();
4664     if(P.X() > xmaxB2) xmaxB2 = P.X();
4665     if(P.Y() > ymaxB2) ymaxB2 = P.Y();
4666     if(P.Z() > zmaxB2) zmaxB2 = P.Z();
4667   }
4668
4669   //Compare the bounding boxes of both faces
4670   if(gp_Pnt(xminB1, yminB1, zminB1).Distance(gp_Pnt(xminB2, yminB2, zminB2)) > MAX_TOLERANCE)
4671     return false;
4672
4673   if(gp_Pnt(xmaxB1, ymaxB1, zmaxB1).Distance(gp_Pnt(xmaxB2, ymaxB2, zmaxB2)) > MAX_TOLERANCE)
4674     return false;
4675
4676   Handle(Geom_Surface) S1 = BRep_Tool::Surface(theFace1);
4677   Handle(Geom_Surface) S2 = BRep_Tool::Surface(theFace2);
4678
4679   //Check if there a coincidence of two surfaces at least in two points
4680   double U11, U12, V11, V12, U21, U22, V21, V22;
4681   BRepTools::UVBounds(theFace1, U11, U12, V11, V12);
4682   BRepTools::UVBounds(theFace2, U21, U22, V21, V22);
4683
4684   double rangeU = U12-U11;
4685   double rangeV = V12-V11;
4686   double U = U11 + rangeU/3.0;
4687   double V = V11 + rangeV/3.0;
4688   gp_Pnt P1 = S1->Value(U, V);
4689   U = U11+rangeU*2.0/3.0;
4690   V = V11+rangeV*2.0/3.0;
4691   gp_Pnt P2 = S1->Value(U, V);
4692
4693   if (!GeomLib_Tool::Parameters(S2, P1, MAX_TOLERANCE, U, V) || U < U21 || U > U22 || V < V21 || V > V22)
4694     return false;
4695
4696   if (P1.Distance(S2->Value(U,V)) > MAX_TOLERANCE) return false;
4697
4698   if (!GeomLib_Tool::Parameters(S2, P2, MAX_TOLERANCE, U, V) || U < U21 || U > U22 || V < V21 || V > V22)
4699     return false;
4700
4701   if (P2.Distance(S2->Value(U, V)) > MAX_TOLERANCE) return false;
4702
4703   //Check that each edge of the Face1 has a counterpart in the Face2
4704   TopTools_MapOfOrientedShape aMap;
4705   TopTools_ListIteratorOfListOfShape LSI1(LS1);
4706   for(; LSI1.More(); LSI1.Next()) {
4707     TopoDS_Edge E = TopoDS::Edge(LSI1.Value());
4708     bool isFound = false;
4709     TopTools_ListIteratorOfListOfShape LSI2(LS2);
4710     for(; LSI2.More(); LSI2.Next()) {
4711       TopoDS_Shape aValue = LSI2.Value();
4712       if(aMap.Contains(aValue)) continue; //To avoid checking already found edge several times
4713       if(isSameEdge(E, TopoDS::Edge(aValue))) {
4714         aMap.Add(aValue);
4715         isFound = true;
4716         break;
4717       }
4718     }
4719     if(!isFound) return false;
4720   }
4721
4722   return true;
4723 }
4724
4725 //=======================================================================
4726 //function : isSameSolid
4727 //purpose  : Returns True if two solids coincide
4728 //=======================================================================
4729 bool isSameSolid(const TopoDS_Solid& theSolid1, const TopoDS_Solid& theSolid2)
4730 {
4731   TopExp_Explorer E(theSolid1, TopAbs_FACE);
4732   TopTools_ListOfShape LS1, LS2;
4733   for(; E.More(); E.Next()) LS1.Append(E.Current());
4734   E.Init(theSolid2, TopAbs_FACE);
4735   for(; E.More(); E.Next()) LS2.Append(E.Current());
4736
4737   if(LS1.Extent() != LS2.Extent()) return false;
4738
4739   double aMin = RealFirst(), aMax = RealLast();
4740   double xminB1=aMax, yminB1=aMax, zminB1=aMax, xminB2=aMax, yminB2=aMax, zminB2=aMax;
4741   double xmaxB1=aMin, ymaxB1=aMin, zmaxB1=aMin, xmaxB2=aMin, ymaxB2=aMin, zmaxB2=aMin;
4742
4743   for(E.Init(theSolid1, TopAbs_VERTEX); E.More(); E.Next()) {
4744     gp_Pnt P = BRep_Tool::Pnt(TopoDS::Vertex(E.Current()));
4745     if(P.X() < xminB1) xminB1 = P.X();
4746     if(P.Y() < yminB1) yminB1 = P.Y();
4747     if(P.Z() < zminB1) zminB1 = P.Z();
4748     if(P.X() > xmaxB1) xmaxB1 = P.X();
4749     if(P.Y() > ymaxB1) ymaxB1 = P.Y();
4750     if(P.Z() > zmaxB1) zmaxB1 = P.Z();
4751   }
4752
4753   for(E.Init(theSolid2, TopAbs_VERTEX); E.More(); E.Next()) {
4754     gp_Pnt P = BRep_Tool::Pnt(TopoDS::Vertex(E.Current()));
4755     if(P.X() < xminB2) xminB2 = P.X();
4756     if(P.Y() < yminB2) yminB2 = P.Y();
4757     if(P.Z() < zminB2) zminB2 = P.Z();
4758     if(P.X() > xmaxB2) xmaxB2 = P.X();
4759     if(P.Y() > ymaxB2) ymaxB2 = P.Y();
4760     if(P.Z() > zmaxB2) zmaxB2 = P.Z();
4761   }
4762
4763   //Compare the bounding boxes of both solids
4764   if(gp_Pnt(xminB1, yminB1, zminB1).Distance(gp_Pnt(xminB2, yminB2, zminB2)) > MAX_TOLERANCE)
4765     return false;
4766
4767   if(gp_Pnt(xmaxB1, ymaxB1, zmaxB1).Distance(gp_Pnt(xmaxB2, ymaxB2, zmaxB2)) > MAX_TOLERANCE)
4768     return false;
4769
4770   //Check that each face of the Solid1 has a counterpart in the Solid2
4771   TopTools_MapOfOrientedShape aMap;
4772   TopTools_ListIteratorOfListOfShape LSI1(LS1);
4773   for(; LSI1.More(); LSI1.Next()) {
4774     TopoDS_Face F = TopoDS::Face(LSI1.Value());
4775     bool isFound = false;
4776     TopTools_ListIteratorOfListOfShape LSI2(LS2);
4777     for(; LSI2.More(); LSI2.Next()) {
4778       if(aMap.Contains(LSI2.Value())) continue; //To avoid checking already found faces several times
4779       if(isSameFace(F, TopoDS::Face(LSI2.Value()))) {
4780         aMap.Add(LSI2.Value());
4781         isFound = true;
4782         break;
4783       }
4784     }
4785     if(!isFound) return false;
4786   }
4787
4788   return true;
4789 }
4790
4791 //=======================================================================
4792 //function : GetSame
4793 //purpose  :
4794 //=======================================================================
4795 Handle(GEOM_Object) GEOMImpl_IShapesOperations::GetSame(const Handle(GEOM_Object)& theShapeWhere,
4796                                                         const Handle(GEOM_Object)& theShapeWhat)
4797 {
4798   SetErrorCode(KO);
4799   if (theShapeWhere.IsNull() || theShapeWhat.IsNull()) return NULL;
4800
4801   TopoDS_Shape aWhere = theShapeWhere->GetValue();
4802   TopoDS_Shape aWhat  = theShapeWhat->GetValue();
4803
4804   if (aWhere.IsNull() || aWhat.IsNull()) return NULL;
4805
4806   int anIndex = -1;
4807   bool isFound = false;
4808   TopoDS_Shape aSubShape;
4809   TopTools_MapOfShape aMap;
4810
4811   if (aWhat.ShapeType() == TopAbs_COMPOUND || aWhat.ShapeType() == TopAbs_COMPSOLID) {
4812     TopoDS_Iterator It (aWhat, Standard_True, Standard_True);
4813     if (It.More()) aWhat = It.Value();
4814     It.Next();
4815     if (It.More()) {
4816       SetErrorCode("Compounds of two or more shapes are not allowed for aWhat argument");
4817       return NULL;
4818     }
4819   }
4820
4821   switch (aWhat.ShapeType()) {
4822     case TopAbs_VERTEX: {
4823       gp_Pnt P = BRep_Tool::Pnt(TopoDS::Vertex(aWhat));
4824       TopExp_Explorer E(aWhere, TopAbs_VERTEX);
4825       for(; E.More(); E.Next()) {
4826         if(!aMap.Add(E.Current())) continue;
4827         gp_Pnt P2 = BRep_Tool::Pnt(TopoDS::Vertex(E.Current()));
4828         if(P.Distance(P2) <= MAX_TOLERANCE) {
4829           isFound = true;
4830           aSubShape = E.Current();
4831           break;
4832         }
4833       }
4834       break;
4835                         }
4836     case TopAbs_EDGE: {
4837       TopoDS_Edge anEdge = TopoDS::Edge(aWhat);
4838       TopExp_Explorer E(aWhere, TopAbs_EDGE);
4839       for(; E.More(); E.Next()) {
4840         if(!aMap.Add(E.Current())) continue;
4841         if(isSameEdge(anEdge, TopoDS::Edge(E.Current()))) {
4842           aSubShape = E.Current();
4843           isFound = true;
4844           break;
4845         }
4846       }
4847       break;
4848                       }
4849     case TopAbs_FACE: {
4850       TopoDS_Face aFace = TopoDS::Face(aWhat);
4851       TopExp_Explorer E(aWhere, TopAbs_FACE);
4852       for(; E.More(); E.Next()) {
4853         if(!aMap.Add(E.Current())) continue;
4854         if(isSameFace(aFace, TopoDS::Face(E.Current()))) {
4855           aSubShape = E.Current();
4856           isFound = true;
4857           break;
4858         }
4859       }
4860       break;
4861                       }
4862     case TopAbs_SOLID: {
4863       TopoDS_Solid aSolid = TopoDS::Solid(aWhat);
4864       TopExp_Explorer E(aWhere, TopAbs_SOLID);
4865       for(; E.More(); E.Next()) {
4866         if(!aMap.Add(E.Current())) continue;
4867         if(isSameSolid(aSolid, TopoDS::Solid(E.Current()))) {
4868           aSubShape = E.Current();
4869           isFound = true;
4870           break;
4871         }
4872       }
4873       break;
4874                        }
4875     default:
4876       return NULL;
4877   }
4878
4879   if (isFound) {
4880     TopTools_IndexedMapOfShape anIndices;
4881     TopExp::MapShapes(aWhere, anIndices);
4882     if (anIndices.Contains(aSubShape))
4883       anIndex = anIndices.FindIndex(aSubShape);
4884   }
4885
4886   if (anIndex < 0) return NULL;
4887
4888   Handle(TColStd_HArray1OfInteger) anArray = new TColStd_HArray1OfInteger(1,1);
4889
4890   anArray->SetValue(1, anIndex);
4891
4892   Handle(GEOM_Object) aResult = GetEngine()->AddSubShape(theShapeWhere, anArray);
4893   Handle(GEOM_Function) aFunction = aResult->GetLastFunction();
4894
4895   GEOM::TPythonDump(aFunction) << aResult << " = geompy.GetSame("
4896     << theShapeWhere << ", " << theShapeWhat << ")";
4897
4898   SetErrorCode(OK);
4899
4900   return aResult;
4901 }