Salome HOME
IMPs 19766 (Wire from unconnected edges) and 20004 (NumberOfSolids)
[modules/geom.git] / src / GEOMImpl / GEOMImpl_IShapesOperations.cxx
1 //  Copyright (C) 2007-2008  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 // $Header$
27 //
28 #include <Standard_Stream.hxx>
29
30 #include "GEOMImpl_IShapesOperations.hxx"
31
32 #include "GEOMImpl_Types.hxx"
33
34 #include "GEOMImpl_VectorDriver.hxx"
35 #include "GEOMImpl_ShapeDriver.hxx"
36 #include "GEOMImpl_CopyDriver.hxx"
37 #include "GEOMImpl_GlueDriver.hxx"
38
39 #include "GEOMImpl_IVector.hxx"
40 #include "GEOMImpl_IShapes.hxx"
41 #include "GEOMImpl_IGlue.hxx"
42
43 #include "GEOMImpl_Block6Explorer.hxx"
44
45 #include "GEOM_Function.hxx"
46 #include "GEOM_ISubShape.hxx"
47 #include "GEOM_PythonDump.hxx"
48
49 #include "GEOMAlgo_FinderShapeOn1.hxx"
50 #include "GEOMAlgo_FinderShapeOnQuad.hxx"
51 #include "GEOMAlgo_FinderShapeOn2.hxx"
52 #include "GEOMAlgo_ClsfBox.hxx"
53 #include "GEOMAlgo_ClsfSolid.hxx"
54 #include "GEOMAlgo_Gluer1.hxx"
55 #include "GEOMAlgo_ListIteratorOfListOfCoupleOfShapes.hxx"
56 #include "GEOMAlgo_CoupleOfShapes.hxx"
57 #include "GEOMAlgo_ListOfCoupleOfShapes.hxx"
58
59 #include "utilities.h"
60 #include "OpUtil.hxx"
61 #include "Utils_ExceptHandlers.hxx"
62
63 #include <TFunction_DriverTable.hxx>
64 #include <TFunction_Driver.hxx>
65 #include <TFunction_Logbook.hxx>
66 #include <TDataStd_Integer.hxx>
67 #include <TDataStd_IntegerArray.hxx>
68 #include <TDF_Tool.hxx>
69
70 #include <BRepExtrema_ExtCF.hxx>
71 #include <BRepExtrema_DistShapeShape.hxx>
72
73 #include <BRep_Tool.hxx>
74 #include <BRep_Builder.hxx>
75 #include <BRepTools.hxx>
76 #include <BRepGProp.hxx>
77 #include <BRepAdaptor_Curve.hxx>
78 #include <BRepAdaptor_Surface.hxx>
79 #include <BRepBndLib.hxx>
80 #include <BRepBuilderAPI_MakeFace.hxx>
81 #include <BRepMesh_IncrementalMesh.hxx>
82
83 #include <TopAbs.hxx>
84 #include <TopExp.hxx>
85 #include <TopoDS.hxx>
86 #include <TopoDS_Shape.hxx>
87 #include <TopoDS_Solid.hxx>
88 #include <TopoDS_Face.hxx>
89 #include <TopoDS_Edge.hxx>
90 #include <TopoDS_Vertex.hxx>
91 #include <TopoDS_Compound.hxx>
92 #include <TopoDS_Iterator.hxx>
93 #include <TopExp_Explorer.hxx>
94 #include <TopLoc_Location.hxx>
95 #include <TopTools_MapOfShape.hxx>
96 #include <TopTools_MapOfOrientedShape.hxx>
97 #include <TopTools_Array1OfShape.hxx>
98 #include <TopTools_ListIteratorOfListOfShape.hxx>
99 #include <TopTools_IndexedMapOfShape.hxx>
100
101 #include <Geom_Surface.hxx>
102 #include <Geom_Plane.hxx>
103 #include <Geom_SphericalSurface.hxx>
104 #include <Geom_CylindricalSurface.hxx>
105 #include <GeomAdaptor_Surface.hxx>
106
107 #include <GeomLib_Tool.hxx>
108 #include <Geom2d_Curve.hxx>
109
110 #include <Bnd_Box.hxx>
111 #include <GProp_GProps.hxx>
112 #include <gp_Pnt.hxx>
113 #include <gp_Lin.hxx>
114 #include <TColStd_ListOfInteger.hxx>
115 #include <TColStd_ListIteratorOfListOfInteger.hxx>
116 #include <TColStd_Array1OfReal.hxx>
117 #include <TColStd_HArray1OfInteger.hxx>
118
119 #include <vector>
120
121 #include <Standard_NullObject.hxx>
122 #include <Standard_Failure.hxx>
123 #include <Standard_ErrorHandler.hxx> // CAREFUL ! position of this file is critic : see Lucien PIGNOLONI / OCC
124
125 // Includes added for GetInPlace algorithm improvement
126
127 #include <GEOMImpl_MeasureDriver.hxx>
128 #include <GEOMImpl_IMeasure.hxx>
129 #include <BRepBuilderAPI_MakeVertex.hxx>
130
131 #include <BRepClass_FaceClassifier.hxx>
132 #include <BRepClass3d_SolidClassifier.hxx>
133 #include <Precision.hxx>
134
135 //=============================================================================
136 /*!
137  *   constructor:
138  */
139 //=============================================================================
140 GEOMImpl_IShapesOperations::GEOMImpl_IShapesOperations (GEOM_Engine* theEngine, int theDocID)
141 : GEOM_IOperations(theEngine, theDocID)
142 {
143   MESSAGE("GEOMImpl_IShapesOperations::GEOMImpl_IShapesOperations");
144 }
145
146 //=============================================================================
147 /*!
148  *  destructor
149  */
150 //=============================================================================
151 GEOMImpl_IShapesOperations::~GEOMImpl_IShapesOperations()
152 {
153   MESSAGE("GEOMImpl_IShapesOperations::~GEOMImpl_IShapesOperations");
154 }
155
156 //=============================================================================
157 /*!
158  *  MakeEdge
159  */
160 //=============================================================================
161 Handle(GEOM_Object) GEOMImpl_IShapesOperations::MakeEdge
162                      (Handle(GEOM_Object) thePnt1, Handle(GEOM_Object) thePnt2)
163 {
164   SetErrorCode(KO);
165
166   if (thePnt1.IsNull() || thePnt2.IsNull()) return NULL;
167
168   //Add a new Edge object
169   Handle(GEOM_Object) anEdge = GetEngine()->AddObject(GetDocID(), GEOM_EDGE);
170
171   //Add a new Vector function
172   Handle(GEOM_Function) aFunction =
173     anEdge->AddFunction(GEOMImpl_VectorDriver::GetID(), VECTOR_TWO_PNT);
174
175   //Check if the function is set correctly
176   if (aFunction->GetDriverGUID() != GEOMImpl_VectorDriver::GetID()) return NULL;
177
178   GEOMImpl_IVector aPI (aFunction);
179
180   Handle(GEOM_Function) aRef1 = thePnt1->GetLastFunction();
181   Handle(GEOM_Function) aRef2 = thePnt2->GetLastFunction();
182   if (aRef1.IsNull() || aRef2.IsNull()) return NULL;
183
184   aPI.SetPoint1(aRef1);
185   aPI.SetPoint2(aRef2);
186
187   //Compute the Edge value
188   try {
189 #if (OCC_VERSION_MAJOR << 16 | OCC_VERSION_MINOR << 8 | OCC_VERSION_MAINTENANCE) > 0x060100
190     OCC_CATCH_SIGNALS;
191 #endif
192     if (!GetSolver()->ComputeFunction(aFunction)) {
193       SetErrorCode("Vector driver failed");
194       return NULL;
195     }
196   }
197   catch (Standard_Failure) {
198     Handle(Standard_Failure) aFail = Standard_Failure::Caught();
199     SetErrorCode(aFail->GetMessageString());
200     return NULL;
201   }
202
203   //Make a Python command
204   GEOM::TPythonDump(aFunction) << anEdge << " = geompy.MakeEdge("
205                                << thePnt1 << ", " << thePnt2 << ")";
206
207   SetErrorCode(OK);
208   return anEdge;
209 }
210
211 //=============================================================================
212 /*!
213  *  MakeWire
214  */
215 //=============================================================================
216 Handle(GEOM_Object) GEOMImpl_IShapesOperations::MakeWire
217                              (std::list<Handle(GEOM_Object)> theShapes,
218                               const Standard_Real            theTolerance)
219 {
220   SetErrorCode(KO);
221
222   //Add a new object
223   Handle(GEOM_Object) aWire = GetEngine()->AddObject(GetDocID(), GEOM_WIRE);
224
225   //Add a new function
226   Handle(GEOM_Function) aFunction =
227     aWire->AddFunction(GEOMImpl_ShapeDriver::GetID(), WIRE_EDGES);
228   if (aFunction.IsNull()) return NULL;
229
230   //Check if the function is set correctly
231   if (aFunction->GetDriverGUID() != GEOMImpl_ShapeDriver::GetID()) return NULL;
232
233   GEOMImpl_IShapes aCI (aFunction);
234   aCI.SetTolerance(theTolerance);
235
236   Handle(TColStd_HSequenceOfTransient) aShapesSeq = new TColStd_HSequenceOfTransient;
237
238   // Shapes
239   std::list<Handle(GEOM_Object)>::iterator it = theShapes.begin();
240   for (; it != theShapes.end(); it++) {
241     Handle(GEOM_Function) aRefSh = (*it)->GetLastFunction();
242     if (aRefSh.IsNull()) {
243       SetErrorCode("NULL argument shape for the shape construction");
244       return NULL;
245     }
246     aShapesSeq->Append(aRefSh);
247   }
248   aCI.SetShapes(aShapesSeq);
249
250   //Compute the shape
251   try {
252 #if (OCC_VERSION_MAJOR << 16 | OCC_VERSION_MINOR << 8 | OCC_VERSION_MAINTENANCE) > 0x060100
253     OCC_CATCH_SIGNALS;
254 #endif
255     if (!GetSolver()->ComputeFunction(aFunction)) {
256       SetErrorCode("Shape driver failed");
257       return NULL;
258     }
259   }
260   catch (Standard_Failure) {
261     Handle(Standard_Failure) aFail = Standard_Failure::Caught();
262     SetErrorCode(aFail->GetMessageString());
263     return NULL;
264   }
265
266   //Make a Python command
267   GEOM::TPythonDump pd (aFunction);
268   pd << aWire << " = geompy.MakeWire([";
269
270   // Shapes
271   it = theShapes.begin();
272   if (it != theShapes.end()) {
273     pd << (*it++);
274     while (it != theShapes.end()) {
275       pd << ", " << (*it++);
276     }
277   }
278   pd << "])";
279
280   SetErrorCode(OK);
281   return aWire;
282 }
283
284 //=============================================================================
285 /*!
286  *  MakeFace
287  */
288 //=============================================================================
289 Handle(GEOM_Object) GEOMImpl_IShapesOperations::MakeFace (Handle(GEOM_Object) theWire,
290                                                           const bool isPlanarWanted)
291 {
292   SetErrorCode(KO);
293
294   if (theWire.IsNull()) return NULL;
295
296   //Add a new Face object
297   Handle(GEOM_Object) aFace = GetEngine()->AddObject(GetDocID(), GEOM_FACE);
298
299   //Add a new Shape function for creation of a face from a wire
300   Handle(GEOM_Function) aFunction =
301     aFace->AddFunction(GEOMImpl_ShapeDriver::GetID(), FACE_WIRE);
302   if (aFunction.IsNull()) return NULL;
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) aRefWire = theWire->GetLastFunction();
310
311   if (aRefWire.IsNull()) return NULL;
312
313   aCI.SetBase(aRefWire);
314   aCI.SetIsPlanar(isPlanarWanted);
315
316   //Compute the Face value
317   try {
318 #if (OCC_VERSION_MAJOR << 16 | OCC_VERSION_MINOR << 8 | OCC_VERSION_MAINTENANCE) > 0x060100
319     OCC_CATCH_SIGNALS;
320 #endif
321     if (!GetSolver()->ComputeFunction(aFunction)) {
322       SetErrorCode("Shape driver failed to compute a face");
323       return NULL;
324     }
325   }
326   catch (Standard_Failure) {
327     Handle(Standard_Failure) aFail = Standard_Failure::Caught();
328     SetErrorCode(aFail->GetMessageString());
329     return NULL;
330   }
331
332   //Make a Python command
333   GEOM::TPythonDump(aFunction) << aFace << " = geompy.MakeFace("
334     << theWire << ", " << (int)isPlanarWanted << ")";
335
336   SetErrorCode(OK);
337   return aFace;
338 }
339
340 //=============================================================================
341 /*!
342  *  MakeFaceWires
343  */
344 //=============================================================================
345 Handle(GEOM_Object) GEOMImpl_IShapesOperations::MakeFaceWires
346                              (std::list<Handle(GEOM_Object)> theShapes,
347                               const bool isPlanarWanted)
348 {
349   SetErrorCode(KO);
350
351   //Add a new object
352   Handle(GEOM_Object) aShape = GetEngine()->AddObject(GetDocID(), GEOM_FACE);
353
354   //Add a new function
355   Handle(GEOM_Function) aFunction =
356     aShape->AddFunction(GEOMImpl_ShapeDriver::GetID(), FACE_WIRES);
357   if (aFunction.IsNull()) return NULL;
358
359   //Check if the function is set correctly
360   if (aFunction->GetDriverGUID() != GEOMImpl_ShapeDriver::GetID()) return NULL;
361
362   GEOMImpl_IShapes aCI (aFunction);
363
364   Handle(TColStd_HSequenceOfTransient) aShapesSeq = new TColStd_HSequenceOfTransient;
365
366   // Shapes
367   std::list<Handle(GEOM_Object)>::iterator it = theShapes.begin();
368   for (; it != theShapes.end(); it++) {
369     Handle(GEOM_Function) aRefSh = (*it)->GetLastFunction();
370     if (aRefSh.IsNull()) {
371       SetErrorCode("NULL argument shape for the face construction");
372       return NULL;
373     }
374     aShapesSeq->Append(aRefSh);
375   }
376   aCI.SetShapes(aShapesSeq);
377
378   aCI.SetIsPlanar(isPlanarWanted);
379
380   //Compute the shape
381   try {
382 #if (OCC_VERSION_MAJOR << 16 | OCC_VERSION_MINOR << 8 | OCC_VERSION_MAINTENANCE) > 0x060100
383     OCC_CATCH_SIGNALS;
384 #endif
385     if (!GetSolver()->ComputeFunction(aFunction)) {
386       SetErrorCode("Shape driver failed");
387       return NULL;
388     }
389   }
390   catch (Standard_Failure) {
391     Handle(Standard_Failure) aFail = Standard_Failure::Caught();
392     SetErrorCode(aFail->GetMessageString());
393     return NULL;
394   }
395
396   //Make a Python command
397   GEOM::TPythonDump pd (aFunction);
398   pd << aShape << " = geompy.MakeFaceWires([";
399
400   // Shapes
401   it = theShapes.begin();
402   if (it != theShapes.end()) {
403     pd << (*it++);
404     while (it != theShapes.end()) {
405       pd << ", " << (*it++);
406     }
407   }
408   pd << "], " << (int)isPlanarWanted << ")";
409
410   SetErrorCode(OK);
411   return aShape;
412 }
413
414 //=============================================================================
415 /*!
416  *  MakeShell
417  */
418 //=============================================================================
419 Handle(GEOM_Object) GEOMImpl_IShapesOperations::MakeShell
420                              (std::list<Handle(GEOM_Object)> theShapes)
421 {
422   return MakeShape(theShapes, GEOM_SHELL, SHELL_FACES, "MakeShell");
423 }
424
425 //=============================================================================
426 /*!
427  *  MakeSolidShells
428  */
429 //=============================================================================
430 Handle(GEOM_Object) GEOMImpl_IShapesOperations::MakeSolidShells
431                              (std::list<Handle(GEOM_Object)> theShapes)
432 {
433   return MakeShape(theShapes, GEOM_SOLID, SOLID_SHELLS, "MakeSolid");
434 }
435
436 //=============================================================================
437 /*!
438  *  MakeSolidShell
439  */
440 //=============================================================================
441 Handle(GEOM_Object) GEOMImpl_IShapesOperations::MakeSolidShell (Handle(GEOM_Object) theShell)
442 {
443   SetErrorCode(KO);
444
445   if (theShell.IsNull()) return NULL;
446
447   //Add a new Solid object
448   Handle(GEOM_Object) aSolid = GetEngine()->AddObject(GetDocID(), GEOM_SOLID);
449
450   //Add a new Solid function for creation of a solid from a shell
451   Handle(GEOM_Function) aFunction =
452     aSolid->AddFunction(GEOMImpl_ShapeDriver::GetID(), SOLID_SHELL);
453   if (aFunction.IsNull()) return NULL;
454
455   //Check if the function is set correctly
456   if (aFunction->GetDriverGUID() != GEOMImpl_ShapeDriver::GetID()) return NULL;
457
458   GEOMImpl_IShapes aCI (aFunction);
459
460   Handle(GEOM_Function) aRefShell = theShell->GetLastFunction();
461
462   if (aRefShell.IsNull()) return NULL;
463
464   aCI.SetBase(aRefShell);
465
466   //Compute the Solid value
467   try {
468 #if (OCC_VERSION_MAJOR << 16 | OCC_VERSION_MINOR << 8 | OCC_VERSION_MAINTENANCE) > 0x060100
469     OCC_CATCH_SIGNALS;
470 #endif
471     if (!GetSolver()->ComputeFunction(aFunction)) {
472       SetErrorCode("Solid driver failed");
473       return NULL;
474     }
475   }
476   catch (Standard_Failure) {
477     Handle(Standard_Failure) aFail = Standard_Failure::Caught();
478     SetErrorCode(aFail->GetMessageString());
479     return NULL;
480   }
481
482   //Make a Python command
483   GEOM::TPythonDump(aFunction) << aSolid
484     << " = geompy.MakeSolid(" << theShell << ")";
485
486   SetErrorCode(OK);
487   return aSolid;
488 }
489
490 //=============================================================================
491 /*!
492  *  MakeCompound
493  */
494 //=============================================================================
495 Handle(GEOM_Object) GEOMImpl_IShapesOperations::MakeCompound
496                              (std::list<Handle(GEOM_Object)> theShapes)
497 {
498   return MakeShape(theShapes, GEOM_COMPOUND, COMPOUND_SHAPES, "MakeCompound");
499 }
500
501 //=============================================================================
502 /*!
503  *  MakeShape
504  */
505 //=============================================================================
506 Handle(GEOM_Object) GEOMImpl_IShapesOperations::MakeShape
507                              (std::list<Handle(GEOM_Object)> theShapes,
508                               const Standard_Integer         theObjectType,
509                               const Standard_Integer         theFunctionType,
510                               const TCollection_AsciiString& theMethodName)
511 {
512   SetErrorCode(KO);
513
514   //Add a new object
515   Handle(GEOM_Object) aShape = GetEngine()->AddObject(GetDocID(), theObjectType);
516
517   //Add a new function
518   Handle(GEOM_Function) aFunction =
519     aShape->AddFunction(GEOMImpl_ShapeDriver::GetID(), theFunctionType);
520   if (aFunction.IsNull()) return NULL;
521
522   //Check if the function is set correctly
523   if (aFunction->GetDriverGUID() != GEOMImpl_ShapeDriver::GetID()) return NULL;
524
525   GEOMImpl_IShapes aCI (aFunction);
526
527   Handle(TColStd_HSequenceOfTransient) aShapesSeq = new TColStd_HSequenceOfTransient;
528
529   // Shapes
530   std::list<Handle(GEOM_Object)>::iterator it = theShapes.begin();
531   for (; it != theShapes.end(); it++) {
532     Handle(GEOM_Function) aRefSh = (*it)->GetLastFunction();
533     if (aRefSh.IsNull()) {
534       SetErrorCode("NULL argument shape for the shape construction");
535       return NULL;
536     }
537     aShapesSeq->Append(aRefSh);
538   }
539   aCI.SetShapes(aShapesSeq);
540
541   //Compute the shape
542   try {
543 #if (OCC_VERSION_MAJOR << 16 | OCC_VERSION_MINOR << 8 | OCC_VERSION_MAINTENANCE) > 0x060100
544     OCC_CATCH_SIGNALS;
545 #endif
546     if (!GetSolver()->ComputeFunction(aFunction)) {
547       SetErrorCode("Shape driver failed");
548       return NULL;
549     }
550   }
551   catch (Standard_Failure) {
552     Handle(Standard_Failure) aFail = Standard_Failure::Caught();
553     SetErrorCode(aFail->GetMessageString());
554     return NULL;
555   }
556
557   //Make a Python command
558   GEOM::TPythonDump pd (aFunction);
559   pd << aShape << " = geompy." << theMethodName.ToCString() << "([";
560
561   // Shapes
562   it = theShapes.begin();
563   if (it != theShapes.end()) {
564     pd << (*it++);
565     while (it != theShapes.end()) {
566       pd << ", " << (*it++);
567     }
568   }
569   pd << "])";
570
571   SetErrorCode(OK);
572   return aShape;
573 }
574
575 //=============================================================================
576 /*!
577  *  MakeGlueFaces
578  */
579 //=============================================================================
580 Handle(GEOM_Object) GEOMImpl_IShapesOperations::MakeGlueFaces
581                                                 (Handle(GEOM_Object) theShape,
582                                                  const Standard_Real theTolerance,
583                                                  const Standard_Boolean doKeepNonSolids)
584 {
585   SetErrorCode(KO);
586
587   if (theShape.IsNull()) return NULL;
588
589   //Add a new Glued object
590   Handle(GEOM_Object) aGlued = GetEngine()->AddObject(GetDocID(), GEOM_GLUED);
591
592   //Add a new Glue function
593   Handle(GEOM_Function) aFunction;
594   aFunction = aGlued->AddFunction(GEOMImpl_GlueDriver::GetID(), GLUE_FACES);
595   if (aFunction.IsNull()) return NULL;
596
597   //Check if the function is set correctly
598   if (aFunction->GetDriverGUID() != GEOMImpl_GlueDriver::GetID()) return NULL;
599
600   GEOMImpl_IGlue aCI (aFunction);
601
602   Handle(GEOM_Function) aRefShape = theShape->GetLastFunction();
603   if (aRefShape.IsNull()) return NULL;
604
605   aCI.SetBase(aRefShape);
606   aCI.SetTolerance(theTolerance);
607   aCI.SetKeepNonSolids(doKeepNonSolids);
608
609   //Compute the sub-shape value
610   Standard_Boolean isWarning = Standard_False;
611   try {
612 #if (OCC_VERSION_MAJOR << 16 | OCC_VERSION_MINOR << 8 | OCC_VERSION_MAINTENANCE) > 0x060100
613     OCC_CATCH_SIGNALS;
614 #endif
615     if (!GetSolver()->ComputeFunction(aFunction)) {
616       SetErrorCode("Shape driver failed to glue faces");
617       return NULL;
618     }
619   }
620   catch (Standard_Failure) {
621     Handle(Standard_Failure) aFail = Standard_Failure::Caught();
622     SetErrorCode(aFail->GetMessageString());
623     // to provide warning
624     if (!aFunction->GetValue().IsNull()) {
625       isWarning = Standard_True;
626     } else {
627       return NULL;
628     }
629   }
630
631   //Make a Python command
632   GEOM::TPythonDump(aFunction) << aGlued << " = geompy.MakeGlueFaces("
633     << theShape << ", " << theTolerance << ")";
634
635   // to provide warning
636   if (!isWarning) SetErrorCode(OK);
637   return aGlued;
638 }
639
640 //=============================================================================
641 /*!
642  *  GetGlueFaces
643  */
644 //=============================================================================
645 Handle(TColStd_HSequenceOfTransient) GEOMImpl_IShapesOperations::GetGlueFaces
646                                                 (Handle(GEOM_Object) theShape,
647                                                  const Standard_Real theTolerance)
648 {
649   SetErrorCode(KO);
650
651   if (theShape.IsNull()) return NULL;
652   TopoDS_Shape aShape = theShape->GetValue();
653   if (aShape.IsNull()) return NULL;
654
655   Handle(TColStd_HSequenceOfTransient) aSeq = new TColStd_HSequenceOfTransient;
656
657   Standard_Integer iErr;
658   TopoDS_Shape aS;
659   GEOMAlgo_Gluer1 aGluer;
660   GEOMAlgo_ListIteratorOfListOfCoupleOfShapes aItCS;
661   GEOMAlgo_CoupleOfShapes aCS;
662   GEOMAlgo_ListOfCoupleOfShapes aLCS;
663
664   //aGluer = new GEOMAlgo_Gluer1;
665   aGluer.SetShape(aShape);
666   aGluer.SetTolerance(theTolerance);
667   aGluer.Perform();
668   iErr = aGluer.ErrorStatus();
669   if (iErr) return NULL;
670
671   TopTools_ListOfShape listShape;
672   const GEOMAlgo_ListOfCoupleOfShapes& aLCSG = aGluer.GluedFaces();
673   // Access to faces
674   aItCS.Initialize(aLCSG);
675   for (; aItCS.More(); aItCS.Next()) {
676     const GEOMAlgo_CoupleOfShapes& aCSG = aItCS.Value();
677     listShape.Append(aCSG.Shape1());
678   }
679
680   TopTools_ListIteratorOfListOfShape itSub (listShape);
681   TCollection_AsciiString anAsciiList, anEntry;
682   TopTools_IndexedMapOfShape anIndices;
683   TopExp::MapShapes(aShape, anIndices);
684   Handle(TColStd_HArray1OfInteger) anArray;
685   Handle(GEOM_Object) anObj;
686   for (int index = 1; itSub.More(); itSub.Next(), ++index) {
687     TopoDS_Shape aValue = itSub.Value();
688     anArray = new TColStd_HArray1OfInteger(1,1);
689     anArray->SetValue(1, anIndices.FindIndex(aValue));
690     anObj = GetEngine()->AddSubShape(theShape, anArray);
691     if (!anObj.IsNull()) {
692       aSeq->Append(anObj);
693
694       // for python command
695       TDF_Tool::Entry(anObj->GetEntry(), anEntry);
696       anAsciiList += anEntry;
697       anAsciiList += ",";
698     }
699   }
700
701   //Make a Python command
702   if(anAsciiList.Length()>0)
703     anAsciiList.Trunc(anAsciiList.Length() - 1);
704   Handle(GEOM_Function) aFunction = theShape->GetLastFunction();
705   GEOM::TPythonDump pd (aFunction, /*append=*/true);
706   pd << "[" << anAsciiList.ToCString();
707   pd << "] = geompy.GetGlueFaces(" << theShape << ", " << theTolerance << ")";
708
709   SetErrorCode(OK);
710
711   return aSeq;
712 }
713
714 //=============================================================================
715 /*!
716  *  MakeGlueFacesByList
717  */
718 //=============================================================================
719 Handle(GEOM_Object) GEOMImpl_IShapesOperations::MakeGlueFacesByList
720                                                 (Handle(GEOM_Object) theShape,
721                                                  const Standard_Real theTolerance,
722                                                  std::list<Handle(GEOM_Object)> theFaces,
723                                                  const Standard_Boolean doKeepNonSolids)
724 {
725   SetErrorCode(KO);
726
727   if (theShape.IsNull()) return NULL;
728
729   //Add a new Glued object
730   Handle(GEOM_Object) aGlued = GetEngine()->AddObject(GetDocID(), GEOM_GLUED);
731
732   //Add a new Glue function
733   Handle(GEOM_Function) aFunction;
734   aFunction = aGlued->AddFunction(GEOMImpl_GlueDriver::GetID(), GLUE_FACES_BY_LIST);
735   if (aFunction.IsNull()) return NULL;
736
737   //Check if the function is set correctly
738   if (aFunction->GetDriverGUID() != GEOMImpl_GlueDriver::GetID()) return NULL;
739
740   GEOMImpl_IGlue aCI (aFunction);
741
742   Handle(GEOM_Function) aRefShape = theShape->GetLastFunction();
743   if (aRefShape.IsNull()) return NULL;
744
745   aCI.SetBase(aRefShape);
746   aCI.SetTolerance(theTolerance);
747   aCI.SetKeepNonSolids(doKeepNonSolids);
748
749   Handle(TColStd_HSequenceOfTransient) aFaces = new TColStd_HSequenceOfTransient;
750   std::list<Handle(GEOM_Object)>::iterator it = theFaces.begin();
751   for (; it != theFaces.end(); it++) {
752     Handle(GEOM_Function) aRefSh = (*it)->GetLastFunction();
753     if (aRefSh.IsNull()) {
754       SetErrorCode("NULL argument shape for the shape construction");
755       return NULL;
756     }
757     aFaces->Append(aRefSh);
758   }
759   aCI.SetFaces(aFaces);
760
761   //Compute the sub-shape value
762   Standard_Boolean isWarning = Standard_False;
763   try {
764 #if (OCC_VERSION_MAJOR << 16 | OCC_VERSION_MINOR << 8 | OCC_VERSION_MAINTENANCE) > 0x060100
765     OCC_CATCH_SIGNALS;
766 #endif
767     if (!GetSolver()->ComputeFunction(aFunction)) {
768       SetErrorCode("Shape driver failed to glue faces");
769       return NULL;
770     }
771   }
772   catch (Standard_Failure) {
773     Handle(Standard_Failure) aFail = Standard_Failure::Caught();
774     SetErrorCode(aFail->GetMessageString());
775     // to provide warning
776     if (!aFunction->GetValue().IsNull()) {
777       isWarning = Standard_True;
778     } else {
779       return NULL;
780     }
781   }
782
783   //Make a Python command
784
785   GEOM::TPythonDump pd(aFunction);
786   pd << aGlued << " = geompy.MakeGlueFacesByList("
787      << theShape << ", " << theTolerance << ", [";
788   // Faces
789   it = theFaces.begin();
790   if (it != theFaces.end()) {
791     pd << (*it++);
792     while (it != theFaces.end()) {
793       pd << ", " << (*it++);
794     }
795   }
796   pd << "])";
797
798   // to provide warning
799   if (!isWarning) SetErrorCode(OK);
800   return aGlued;
801 }
802
803 //=============================================================================
804 /*!
805  *  MakeExplode
806  */
807 //=============================================================================
808 Handle(TColStd_HSequenceOfTransient) GEOMImpl_IShapesOperations::MakeExplode
809                                           (Handle(GEOM_Object)    theShape,
810                                            const Standard_Integer theShapeType,
811                                            const Standard_Boolean isSorted)
812 {
813   SetErrorCode(KO);
814
815   if (theShape.IsNull()) return NULL;
816   TopoDS_Shape aShape = theShape->GetValue();
817   if (aShape.IsNull()) return NULL;
818
819   Handle(GEOM_Function) aMainShape = theShape->GetLastFunction();
820
821   Handle(TColStd_HSequenceOfTransient) aSeq = new TColStd_HSequenceOfTransient;
822   Handle(GEOM_Object) anObj;
823   TopTools_MapOfShape mapShape;
824   TopTools_ListOfShape listShape;
825
826   if (aShape.ShapeType() == TopAbs_COMPOUND &&
827       (TopAbs_ShapeEnum(theShapeType) == TopAbs_SHAPE ||
828        TopAbs_ShapeEnum(theShapeType) == TopAbs_COMPSOLID ||
829        TopAbs_ShapeEnum(theShapeType) == TopAbs_COMPOUND)) {
830     TopoDS_Iterator It (aShape, Standard_True, Standard_True);
831     for (; It.More(); It.Next()) {
832       if (mapShape.Add(It.Value())) {
833         if (TopAbs_ShapeEnum(theShapeType) == TopAbs_SHAPE ||
834             TopAbs_ShapeEnum(theShapeType) == It.Value().ShapeType()) {
835           listShape.Append(It.Value());
836         }
837       }
838     }
839   } else {
840     TopExp_Explorer exp (aShape, TopAbs_ShapeEnum(theShapeType));
841     for (; exp.More(); exp.Next())
842       if (mapShape.Add(exp.Current()))
843         listShape.Append(exp.Current());
844   }
845
846   if (listShape.IsEmpty()) {
847     //SetErrorCode("The given shape has no sub-shapes of the requested type");
848     SetErrorCode(NOT_FOUND_ANY); // NPAL18017
849     return aSeq;
850   }
851
852   if (isSorted)
853     SortShapes(listShape);
854
855   TopTools_IndexedMapOfShape anIndices;
856   TopExp::MapShapes(aShape, anIndices);
857   Handle(TColStd_HArray1OfInteger) anArray;
858
859   TopTools_ListIteratorOfListOfShape itSub (listShape);
860   TCollection_AsciiString anAsciiList, anEntry;
861   for (int index = 1; itSub.More(); itSub.Next(), ++index)
862   {
863     TopoDS_Shape aValue = itSub.Value();
864     anArray = new TColStd_HArray1OfInteger(1,1);
865     anArray->SetValue(1, anIndices.FindIndex(aValue));
866
867     //anObj = GetEngine()->AddSubShape(theShape, anArray);
868     {
869       anObj = GetEngine()->AddObject(GetDocID(), GEOM_SUBSHAPE);
870       Handle(GEOM_Function) aFunction = anObj->AddFunction(GEOM_Object::GetSubShapeID(), 1);
871       if (aFunction.IsNull()) return aSeq;
872
873       GEOM_ISubShape aSSI (aFunction);
874       aSSI.SetMainShape(aMainShape);
875       aSSI.SetIndices(anArray);
876
877       // Set function value directly, as we know it.
878       // Usage of Solver here would lead to significant loss of time,
879       // because GEOM_SubShapeDriver will build TopTools_IndexedMapOfShape
880       // on the main shape for each being calculated sub-shape separately.
881       aFunction->SetValue(aValue);
882     }
883
884     if (!anObj.IsNull()) {
885       aSeq->Append(anObj);
886
887       // for python command
888       TDF_Tool::Entry(anObj->GetEntry(), anEntry);
889       anAsciiList += anEntry;
890       anAsciiList += ",";
891     }
892   }
893
894   //Make a Python command
895   anAsciiList.Trunc(anAsciiList.Length() - 1);
896
897   GEOM::TPythonDump pd (aMainShape, /*append=*/true);
898   pd << "[" << anAsciiList.ToCString();
899   pd << "] = geompy.SubShapeAll" << (isSorted ? "Sorted(" : "(");
900   pd << theShape << ", " << TopAbs_ShapeEnum(theShapeType) << ")";
901
902   SetErrorCode(OK);
903
904   return aSeq;
905 }
906
907 //=============================================================================
908 /*!
909  *  SubShapeAllIDs
910  */
911 //=============================================================================
912 Handle(TColStd_HSequenceOfInteger) GEOMImpl_IShapesOperations::SubShapeAllIDs
913                                           (Handle(GEOM_Object)    theShape,
914                                            const Standard_Integer theShapeType,
915                                            const Standard_Boolean isSorted)
916 {
917   SetErrorCode(KO);
918
919   if (theShape.IsNull()) return NULL;
920   TopoDS_Shape aShape = theShape->GetValue();
921   if (aShape.IsNull()) return NULL;
922
923   Handle(TColStd_HSequenceOfInteger) aSeq = new TColStd_HSequenceOfInteger;
924   TopTools_MapOfShape mapShape;
925   TopTools_ListOfShape listShape;
926
927   if (aShape.ShapeType() == TopAbs_COMPOUND &&
928       (TopAbs_ShapeEnum(theShapeType) == TopAbs_SHAPE ||
929        TopAbs_ShapeEnum(theShapeType) == TopAbs_COMPSOLID ||
930        TopAbs_ShapeEnum(theShapeType) == TopAbs_COMPOUND)) {
931     TopoDS_Iterator It (aShape, Standard_True, Standard_True);
932     for (; It.More(); It.Next()) {
933       if (mapShape.Add(It.Value())) {
934         if (TopAbs_ShapeEnum(theShapeType) == TopAbs_SHAPE ||
935             TopAbs_ShapeEnum(theShapeType) == It.Value().ShapeType()) {
936           listShape.Append(It.Value());
937         }
938       }
939     }
940   } else {
941     TopExp_Explorer exp (aShape, TopAbs_ShapeEnum(theShapeType));
942     for (; exp.More(); exp.Next())
943       if (mapShape.Add(exp.Current()))
944         listShape.Append(exp.Current());
945   }
946
947   if (listShape.IsEmpty()) {
948     //SetErrorCode("The given shape has no sub-shapes of the requested type");
949     SetErrorCode(NOT_FOUND_ANY); // NPAL18017
950     return aSeq;
951   }
952
953   if (isSorted)
954     SortShapes(listShape);
955
956   TopTools_IndexedMapOfShape anIndices;
957   TopExp::MapShapes(aShape, anIndices);
958   Handle(TColStd_HArray1OfInteger) anArray;
959
960   TopTools_ListIteratorOfListOfShape itSub (listShape);
961   for (int index = 1; itSub.More(); itSub.Next(), ++index) {
962     TopoDS_Shape aValue = itSub.Value();
963     aSeq->Append(anIndices.FindIndex(aValue));
964   }
965
966   Handle(GEOM_Function) aFunction = theShape->GetLastFunction();
967
968   //Make a Python command
969   GEOM::TPythonDump pd (aFunction, /*append=*/true);
970   pd << "listSubShapeIDs = geompy.SubShapeAll";
971   pd << (isSorted ? "SortedIDs(" : "IDs(");
972   pd << theShape << ", " << TopAbs_ShapeEnum(theShapeType) << ")";
973
974   SetErrorCode(OK);
975   return aSeq;
976 }
977
978 //=============================================================================
979 /*!
980  *  GetSubShape
981  */
982 //=============================================================================
983 Handle(GEOM_Object) GEOMImpl_IShapesOperations::GetSubShape
984                                           (Handle(GEOM_Object)    theMainShape,
985                                            const Standard_Integer theID)
986 {
987   SetErrorCode(KO);
988
989   if (theMainShape.IsNull()) return NULL;
990
991   Handle(TColStd_HArray1OfInteger) anArray = new TColStd_HArray1OfInteger(1,1);
992   anArray->SetValue(1, theID);
993   Handle(GEOM_Object) anObj = GetEngine()->AddSubShape(theMainShape, anArray,true);
994   if (anObj.IsNull()) {
995     SetErrorCode("Can not get a sub-shape with the given ID");
996     return NULL;
997   }
998
999   Handle(GEOM_Function) aFunction = anObj->GetLastFunction();
1000
1001   //Make a Python command
1002   GEOM::TPythonDump(aFunction) << anObj << " = geompy.GetSubShape("
1003                                << theMainShape << ", [" << theID << "])";
1004
1005   SetErrorCode(OK);
1006   return anObj;
1007 }
1008
1009 //=============================================================================
1010 /*!
1011  *  GetSubShapeIndex
1012  */
1013 //=============================================================================
1014 Standard_Integer GEOMImpl_IShapesOperations::GetSubShapeIndex (Handle(GEOM_Object) theMainShape,
1015                                                                Handle(GEOM_Object) theSubShape)
1016 {
1017   SetErrorCode(KO);
1018
1019   TopoDS_Shape aMainShape = theMainShape->GetValue();
1020   TopoDS_Shape aSubShape = theSubShape->GetValue();
1021
1022   if (aMainShape.IsNull() || aSubShape.IsNull()) return -1;
1023
1024   TopTools_IndexedMapOfShape anIndices;
1025   TopExp::MapShapes(aMainShape, anIndices);
1026   if (anIndices.Contains(aSubShape)) {
1027     SetErrorCode(OK);
1028     return anIndices.FindIndex(aSubShape);
1029   }
1030
1031   return -1;
1032 }
1033
1034 //=============================================================================
1035 /*!
1036  *  GetTopologyIndex
1037  */
1038 //=============================================================================
1039 Standard_Integer GEOMImpl_IShapesOperations::GetTopologyIndex (Handle(GEOM_Object) theMainShape,
1040                                                                Handle(GEOM_Object) theSubShape)
1041 {
1042   SetErrorCode(OK);
1043
1044   TopoDS_Shape aMainShape = theMainShape->GetValue();
1045   TopoDS_Shape aSubShape = theSubShape->GetValue();
1046
1047   if (aMainShape.IsNull() || aSubShape.IsNull()) {
1048     SetErrorCode("Null argument shape given");
1049     return -1;
1050   }
1051
1052   int index = 1;
1053   if (aSubShape.ShapeType() == TopAbs_COMPOUND) {
1054     TopoDS_Iterator it;
1055     TopTools_ListOfShape CL;
1056     CL.Append(aMainShape);
1057     TopTools_ListIteratorOfListOfShape itC;
1058     for (itC.Initialize(CL); itC.More(); itC.Next()) {
1059       for (it.Initialize(itC.Value()); it.More(); it.Next()) {
1060         if (it.Value().ShapeType() == TopAbs_COMPOUND) {
1061           if (it.Value().IsSame(aSubShape))
1062             return index;
1063           else
1064             index++;
1065           CL.Append(it.Value());
1066         }
1067       }
1068     }
1069   } else {
1070     TopExp_Explorer anExp (aMainShape, aSubShape.ShapeType());
1071     TopTools_MapOfShape M;
1072     for (; anExp.More(); anExp.Next()) {
1073       if (M.Add(anExp.Current())) {
1074         if (anExp.Current().IsSame(aSubShape))
1075           return index;
1076         index++;
1077       }
1078     }
1079   }
1080
1081   SetErrorCode("The sub-shape does not belong to the main shape");
1082   return -1;
1083 }
1084
1085 //=============================================================================
1086 /*!
1087  *  GetShapeTypeString
1088  */
1089 //=============================================================================
1090 TCollection_AsciiString GEOMImpl_IShapesOperations::GetShapeTypeString (Handle(GEOM_Object) theShape)
1091 {
1092   SetErrorCode(KO);
1093
1094   TCollection_AsciiString aTypeName ("Null Shape");
1095
1096   TopoDS_Shape aShape = theShape->GetValue();
1097   if (aShape.IsNull())
1098     return aTypeName;
1099
1100   switch (aShape.ShapeType() )
1101   {
1102   case TopAbs_COMPOUND:
1103     aTypeName = "Compound";
1104     break;
1105   case  TopAbs_COMPSOLID:
1106     aTypeName = "Compound Solid";
1107     break;
1108   case TopAbs_SOLID:
1109     aTypeName = "Solid";
1110     break;
1111   case TopAbs_SHELL:
1112     aTypeName = "Shell";
1113     break;
1114   case TopAbs_FACE:
1115     {
1116       BRepAdaptor_Surface surf (TopoDS::Face(aShape));
1117       if (surf.GetType() == GeomAbs_Plane)
1118         aTypeName = "Plane";
1119       else if (surf.GetType() == GeomAbs_Cylinder)
1120         aTypeName = "Cylindrical Face";
1121       else if (surf.GetType() == GeomAbs_Sphere)
1122         aTypeName = "Spherical Face";
1123       else if (surf.GetType() == GeomAbs_Torus)
1124         aTypeName = "Toroidal Face";
1125       else if (surf.GetType() == GeomAbs_Cone)
1126         aTypeName = "Conical Face";
1127       else
1128         aTypeName = "GEOM::FACE";
1129     }
1130     break;
1131   case TopAbs_WIRE:
1132     aTypeName = "Wire";
1133     break;
1134   case TopAbs_EDGE:
1135     {
1136       BRepAdaptor_Curve curv (TopoDS::Edge(aShape));
1137       if (curv.GetType() == GeomAbs_Line) {
1138         if ((Abs(curv.FirstParameter()) >= 1E6) ||
1139             (Abs(curv.LastParameter()) >= 1E6))
1140           aTypeName = "Line";
1141         else
1142           aTypeName = "Edge";
1143       } else if (curv.GetType() == GeomAbs_Circle) {
1144         if (curv.IsClosed())
1145           aTypeName = "Circle";
1146         else
1147           aTypeName = "Arc";
1148       } else {
1149         aTypeName = "Edge";
1150       }
1151     }
1152     break;
1153   case TopAbs_VERTEX:
1154     aTypeName = "Vertex";
1155     break;
1156   case TopAbs_SHAPE:
1157     aTypeName = "Shape";
1158     break;
1159   default:
1160     aTypeName = "Shape of unknown type";
1161   }
1162
1163   return aTypeName;
1164 }
1165
1166 //=============================================================================
1167 /*!
1168  *  NumberOfSubShapes
1169  */
1170 //=============================================================================
1171 Standard_Integer GEOMImpl_IShapesOperations::NumberOfSubShapes
1172                                           (Handle(GEOM_Object)    theShape,
1173                                            const Standard_Integer theShapeType)
1174 {
1175   SetErrorCode(KO);
1176   Standard_Integer nbShapes = 0;
1177
1178   if (theShape.IsNull()) return -1;
1179   TopoDS_Shape aShape = theShape->GetValue();
1180   if (aShape.IsNull()) return -1;
1181
1182   /*
1183   TopTools_MapOfShape mapShape;
1184
1185   if (aShape.ShapeType() == TopAbs_COMPOUND &&
1186       (TopAbs_ShapeEnum(theShapeType) == TopAbs_SHAPE ||
1187        TopAbs_ShapeEnum(theShapeType) == TopAbs_COMPSOLID ||
1188        TopAbs_ShapeEnum(theShapeType) == TopAbs_COMPOUND)) {
1189     TopoDS_Iterator It (aShape, Standard_True, Standard_True);
1190     for (; It.More(); It.Next()) {
1191       if (mapShape.Add(It.Value())) {
1192         if (TopAbs_ShapeEnum(theShapeType) == TopAbs_SHAPE ||
1193             TopAbs_ShapeEnum(theShapeType) == It.Value().ShapeType()) {
1194           nbShapes++;
1195         }
1196       }
1197     }
1198   } else {
1199     TopExp_Explorer exp (aShape, TopAbs_ShapeEnum(theShapeType));
1200     for (; exp.More(); exp.Next())
1201       if (mapShape.Add(exp.Current()))
1202         nbShapes++;
1203   }
1204   */
1205
1206   try {
1207 #if (OCC_VERSION_MAJOR << 16 | OCC_VERSION_MINOR << 8 | OCC_VERSION_MAINTENANCE) > 0x060100
1208     OCC_CATCH_SIGNALS;
1209 #endif
1210     int iType, nbTypes [TopAbs_SHAPE];
1211     for (iType = 0; iType < TopAbs_SHAPE; ++iType)
1212       nbTypes[iType] = 0;
1213     nbTypes[aShape.ShapeType()]++;
1214
1215     TopTools_MapOfShape aMapOfShape;
1216     aMapOfShape.Add(aShape);
1217     TopTools_ListOfShape aListOfShape;
1218     aListOfShape.Append(aShape);
1219
1220     TopTools_ListIteratorOfListOfShape itL (aListOfShape);
1221     for (; itL.More(); itL.Next()) {
1222       TopoDS_Iterator it (itL.Value());
1223       for (; it.More(); it.Next()) {
1224         TopoDS_Shape s = it.Value();
1225         if (aMapOfShape.Add(s)) {
1226           aListOfShape.Append(s);
1227           nbTypes[s.ShapeType()]++;
1228         }
1229       }
1230     }
1231
1232     if (TopAbs_ShapeEnum(theShapeType) == TopAbs_SHAPE)
1233       nbShapes = aMapOfShape.Extent();
1234     else
1235       nbShapes = nbTypes[theShapeType];
1236   }
1237   catch (Standard_Failure) {
1238     Handle(Standard_Failure) aFail = Standard_Failure::Caught();
1239     SetErrorCode(aFail->GetMessageString());
1240     return -1;
1241   }
1242
1243   SetErrorCode(OK);
1244   return nbShapes;
1245 }
1246
1247 //=============================================================================
1248 /*!
1249  *  ReverseShape
1250  */
1251 //=============================================================================
1252 Handle(GEOM_Object) GEOMImpl_IShapesOperations::ReverseShape(Handle(GEOM_Object) theShape)
1253 {
1254   SetErrorCode(KO);
1255
1256   if (theShape.IsNull()) return NULL;
1257
1258   //Add a new reversed object
1259   Handle(GEOM_Object) aReversed = GetEngine()->AddObject(GetDocID(), theShape->GetType());
1260
1261   //Add a new Revese function
1262   Handle(GEOM_Function) aFunction;
1263   aFunction = aReversed->AddFunction(GEOMImpl_ShapeDriver::GetID(), REVERSE_ORIENTATION);
1264   if (aFunction.IsNull()) return NULL;
1265
1266   //Check if the function is set correctly
1267   if (aFunction->GetDriverGUID() != GEOMImpl_ShapeDriver::GetID()) return NULL;
1268
1269   GEOMImpl_IShapes aSI (aFunction);
1270
1271   Handle(GEOM_Function) aRefShape = theShape->GetLastFunction();
1272   if (aRefShape.IsNull()) return NULL;
1273
1274   aSI.SetBase(aRefShape);
1275
1276   //Compute the sub-shape value
1277   try {
1278 #if (OCC_VERSION_MAJOR << 16 | OCC_VERSION_MINOR << 8 | OCC_VERSION_MAINTENANCE) > 0x060100
1279     OCC_CATCH_SIGNALS;
1280 #endif
1281     if (!GetSolver()->ComputeFunction(aFunction)) {
1282       SetErrorCode("Shape driver failed to reverse shape");
1283       return NULL;
1284     }
1285   }
1286   catch (Standard_Failure) {
1287     Handle(Standard_Failure) aFail = Standard_Failure::Caught();
1288     SetErrorCode(aFail->GetMessageString());
1289     return NULL;
1290   }
1291
1292   //Make a Python command
1293   GEOM::TPythonDump(aFunction) << aReversed
1294     << " = geompy.ChangeOrientation(" << theShape << ")";
1295
1296   SetErrorCode(OK);
1297   return aReversed;
1298 }
1299
1300 //=============================================================================
1301 /*!
1302  *  GetFreeFacesIDs
1303  */
1304 //=============================================================================
1305 Handle(TColStd_HSequenceOfInteger) GEOMImpl_IShapesOperations::GetFreeFacesIDs
1306                                                  (Handle(GEOM_Object) theShape)
1307 {
1308   SetErrorCode(KO);
1309
1310   if (theShape.IsNull()) return NULL;
1311   TopoDS_Shape aShape = theShape->GetValue();
1312   if (aShape.IsNull()) return NULL;
1313
1314   Handle(TColStd_HSequenceOfInteger) aSeq = new TColStd_HSequenceOfInteger;
1315
1316   TopTools_IndexedDataMapOfShapeListOfShape mapFaceBlocks;
1317   GEOMImpl_Block6Explorer::MapShapesAndAncestors
1318     (aShape, TopAbs_FACE, TopAbs_SOLID, mapFaceBlocks);
1319
1320   Standard_Integer ind = 1, nbFaces = mapFaceBlocks.Extent();
1321
1322   if (nbFaces == 0) {
1323     SetErrorCode("The given shape has no faces");
1324     return aSeq;
1325   }
1326
1327   TopTools_IndexedMapOfShape anIndices;
1328   TopExp::MapShapes(aShape, anIndices);
1329
1330   Standard_Integer id;
1331   for (; ind <= nbFaces; ind++) {
1332     if (mapFaceBlocks.FindFromIndex(ind).Extent() != 2) {
1333       id = anIndices.FindIndex(mapFaceBlocks.FindKey(ind));
1334       aSeq->Append(id);
1335     }
1336   }
1337
1338   //The explode doesn't change object so no new function is required.
1339   Handle(GEOM_Function) aFunction = theShape->GetLastFunction();
1340
1341   //Make a Python command
1342   GEOM::TPythonDump(aFunction, /*append=*/true)
1343     << "listFreeFacesIDs = geompy.GetFreeFacesIDs(" << theShape << ")";
1344
1345   SetErrorCode(OK);
1346   return aSeq;
1347 }
1348
1349 //=======================================================================
1350 //function : GetSharedShapes
1351 //purpose  :
1352 //=======================================================================
1353 Handle(TColStd_HSequenceOfTransient) GEOMImpl_IShapesOperations::GetSharedShapes
1354                                                 (Handle(GEOM_Object)    theShape1,
1355                                                  Handle(GEOM_Object)    theShape2,
1356                                                  const Standard_Integer theShapeType)
1357 {
1358   SetErrorCode(KO);
1359
1360   if (theShape1.IsNull() || theShape2.IsNull()) return NULL;
1361
1362   TopoDS_Shape aShape1 = theShape1->GetValue();
1363   TopoDS_Shape aShape2 = theShape2->GetValue();
1364
1365   if (aShape1.IsNull() || aShape2.IsNull()) return NULL;
1366
1367   TopTools_IndexedMapOfShape anIndices;
1368   TopExp::MapShapes(aShape1, anIndices);
1369   Handle(TColStd_HArray1OfInteger) anArray;
1370
1371   TopTools_IndexedMapOfShape mapShape1;
1372   TopExp::MapShapes(aShape1, TopAbs_ShapeEnum(theShapeType), mapShape1);
1373
1374   Handle(GEOM_Object) anObj;
1375   Handle(TColStd_HSequenceOfTransient) aSeq = new TColStd_HSequenceOfTransient;
1376   TCollection_AsciiString anAsciiList, anEntry;
1377
1378   TopTools_MapOfShape mapShape2;
1379   TopExp_Explorer exp (aShape2, TopAbs_ShapeEnum(theShapeType));
1380   for (; exp.More(); exp.Next()) {
1381     TopoDS_Shape aSS = exp.Current();
1382     if (mapShape2.Add(aSS) && mapShape1.Contains(aSS)) {
1383       anArray = new TColStd_HArray1OfInteger(1,1);
1384       anArray->SetValue(1, anIndices.FindIndex(aSS));
1385       anObj = GetEngine()->AddSubShape(theShape1, anArray);
1386       aSeq->Append(anObj);
1387
1388       // for python command
1389       TDF_Tool::Entry(anObj->GetEntry(), anEntry);
1390       anAsciiList += anEntry;
1391       anAsciiList += ",";
1392     }
1393   }
1394
1395   if (aSeq->IsEmpty()) {
1396     SetErrorCode("The given shapes have no shared sub-shapes of the requested type");
1397     return aSeq;
1398   }
1399
1400   //Make a Python command
1401   anAsciiList.Trunc(anAsciiList.Length() - 1);
1402
1403   Handle(GEOM_Function) aFunction = anObj->GetLastFunction();
1404
1405   GEOM::TPythonDump(aFunction) << "[" << anAsciiList.ToCString()
1406     << "] = geompy.GetSharedShapes(" << theShape1 << ", "
1407       << theShape2 << ", " << TopAbs_ShapeEnum(theShapeType) << ")";
1408
1409   SetErrorCode(OK);
1410   return aSeq;
1411 }
1412
1413 //=============================================================================
1414 /*!
1415  *
1416  */
1417 //=============================================================================
1418 static GEOM::TPythonDump& operator<< (GEOM::TPythonDump&   theDump,
1419                                       const GEOMAlgo_State theState)
1420 {
1421   switch (theState) {
1422   case GEOMAlgo_ST_IN:
1423     theDump << "geompy.GEOM.ST_IN";
1424     break;
1425   case GEOMAlgo_ST_OUT:
1426     theDump << "geompy.GEOM.ST_OUT";
1427     break;
1428   case GEOMAlgo_ST_ON:
1429     theDump << "geompy.GEOM.ST_ON";
1430     break;
1431   case GEOMAlgo_ST_ONIN:
1432     theDump << "geompy.GEOM.ST_ONIN";
1433     break;
1434   case GEOMAlgo_ST_ONOUT:
1435     theDump << "geompy.GEOM.ST_ONOUT";
1436     break;
1437   default:
1438     theDump << "geompy.GEOM.ST_UNKNOWN";
1439     break;
1440   }
1441   return theDump;
1442 }
1443
1444 //=======================================================================
1445 //function : checkTypeShapesOn
1446 /*!
1447  * \brief Checks if theShapeType parameter of GetShapesOnXXX() is OK
1448  * \param theShapeType - the shape type to check
1449  * \retval bool  - result of the check
1450  */
1451 //=======================================================================
1452 bool GEOMImpl_IShapesOperations::checkTypeShapesOn(const Standard_Integer theShapeType)
1453 {
1454   if (theShapeType != TopAbs_VERTEX &&
1455       theShapeType != TopAbs_EDGE &&
1456       theShapeType != TopAbs_FACE &&
1457       theShapeType != TopAbs_SOLID) {
1458     SetErrorCode("Only solids, vertices, edges or faces can be found by this method");
1459     return false;
1460   }
1461   return true;
1462 }
1463
1464 //=======================================================================
1465 //function : makePlane
1466   /*!
1467    * \brief Creates Geom_Plane
1468     * \param theAx1 - shape object defining plane parameters
1469     * \retval Handle(Geom_Surface) - resulting surface
1470    */
1471 //=======================================================================
1472 Handle(Geom_Surface) GEOMImpl_IShapesOperations::makePlane(const TopoDS_Shape& anAx1)
1473 {
1474   if (anAx1.ShapeType() != TopAbs_EDGE) return NULL;
1475   TopoDS_Edge anEdge = TopoDS::Edge(anAx1);
1476   TopoDS_Vertex V1, V2;
1477   TopExp::Vertices(anEdge, V1, V2, Standard_True);
1478   if (V1.IsNull() || V2.IsNull()) {
1479     SetErrorCode("Bad edge given for the plane normal vector");
1480     return NULL;
1481   }
1482   gp_Pnt aLoc = BRep_Tool::Pnt(V1);
1483   gp_Vec aVec (aLoc, BRep_Tool::Pnt(V2));
1484   if (aVec.Magnitude() < Precision::Confusion()) {
1485     SetErrorCode("Vector with null magnitude given");
1486     return NULL;
1487   }
1488   return new Geom_Plane(aLoc, aVec);
1489 }
1490
1491 //=======================================================================
1492 //function : makeCylinder
1493   /*!
1494    * \brief Creates Geom_CylindricalSurface
1495     * \param theAx1 - edge defining cylinder axis
1496     * \param theRadius - cylinder radius
1497     * \retval Handle(Geom_Surface) - resulting surface
1498    */
1499 //=======================================================================
1500 Handle(Geom_Surface) GEOMImpl_IShapesOperations::makeCylinder(const TopoDS_Shape& anAxis,
1501                                                               const Standard_Real theRadius)
1502 {
1503   //Axis of the cylinder
1504   if (anAxis.ShapeType() != TopAbs_EDGE) {
1505     SetErrorCode("Not an edge given for the axis");
1506     return NULL;
1507   }
1508   TopoDS_Edge anEdge = TopoDS::Edge(anAxis);
1509   TopoDS_Vertex V1, V2;
1510   TopExp::Vertices(anEdge, V1, V2, Standard_True);
1511   if (V1.IsNull() || V2.IsNull()) {
1512     SetErrorCode("Bad edge given for the axis");
1513     return NULL;
1514   }
1515   gp_Pnt aLoc = BRep_Tool::Pnt(V1);
1516   gp_Vec aVec (aLoc, BRep_Tool::Pnt(V2));
1517   if (aVec.Magnitude() < Precision::Confusion()) {
1518     SetErrorCode("Vector with null magnitude given");
1519     return NULL;
1520   }
1521
1522   gp_Ax3 anAx3 (aLoc, aVec);
1523   return new Geom_CylindricalSurface(anAx3, theRadius);
1524 }
1525
1526 //=======================================================================
1527 //function : getShapesOnBoxIDs
1528   /*!
1529    * \brief Find IDs of subshapes complying with given status about surface
1530     * \param theBox - the box to check state of subshapes against
1531     * \param theShape - the shape to explore
1532     * \param theShapeType - type of subshape of theShape
1533     * \param theState - required state
1534     * \retval Handle(TColStd_HSequenceOfInteger) - IDs of found subshapes
1535    */
1536 //=======================================================================
1537 Handle(TColStd_HSequenceOfInteger)
1538   GEOMImpl_IShapesOperations::getShapesOnBoxIDs(const Handle(GEOM_Object)& theBox,
1539                                                 const Handle(GEOM_Object)& theShape,
1540                                                 const Standard_Integer theShapeType,
1541                                                 GEOMAlgo_State theState)
1542 {
1543   Handle(TColStd_HSequenceOfInteger) aSeqOfIDs;
1544
1545   TopoDS_Shape aBox = theBox->GetValue();
1546   TopoDS_Shape aShape = theShape->GetValue();
1547
1548   // Check presence of triangulation, build if need
1549   if (!CheckTriangulation(aShape)) {
1550     SetErrorCode("Cannot build triangulation on the shape");
1551     return aSeqOfIDs;
1552   }
1553
1554   // Call algo
1555   GEOMAlgo_FinderShapeOn2 aFinder;
1556   Standard_Real aTol = 0.0001; // default value
1557
1558   Handle(GEOMAlgo_ClsfBox) aClsfBox = new GEOMAlgo_ClsfBox;
1559   aClsfBox->SetBox(aBox);
1560
1561   aFinder.SetShape(aShape);
1562   aFinder.SetTolerance(aTol);
1563   aFinder.SetClsf(aClsfBox);
1564   aFinder.SetShapeType( (TopAbs_ShapeEnum)theShapeType );
1565   aFinder.SetState(theState);
1566   aFinder.Perform();
1567
1568   // Interprete results
1569   Standard_Integer iErr = aFinder.ErrorStatus();
1570   // the detailed description of error codes is in GEOMAlgo_FinderShapeOn1.cxx
1571   if (iErr) {
1572     MESSAGE(" iErr : " << iErr);
1573     TCollection_AsciiString aMsg (" iErr : ");
1574     aMsg += TCollection_AsciiString(iErr);
1575     SetErrorCode(aMsg);
1576     return aSeqOfIDs;
1577   }
1578   Standard_Integer iWrn = aFinder.WarningStatus();
1579   // the detailed description of warning codes is in GEOMAlgo_FinderShapeOn1.cxx
1580   if (iWrn) {
1581     MESSAGE(" *** iWrn : " << iWrn);
1582   }
1583
1584   const TopTools_ListOfShape& listSS = aFinder.Shapes(); // the result
1585
1586   if (listSS.Extent() < 1) {
1587     //SetErrorCode("Not a single sub-shape of the requested type found on the given surface");
1588     SetErrorCode(NOT_FOUND_ANY); // NPAL18017
1589     return aSeqOfIDs;
1590   }
1591
1592   // Fill sequence of object IDs
1593   aSeqOfIDs = new TColStd_HSequenceOfInteger;
1594
1595   TopTools_IndexedMapOfShape anIndices;
1596   TopExp::MapShapes(aShape, anIndices);
1597
1598   TopTools_ListIteratorOfListOfShape itSub (listSS);
1599   for (int index = 1; itSub.More(); itSub.Next(), ++index) {
1600     int id = anIndices.FindIndex(itSub.Value());
1601     aSeqOfIDs->Append(id);
1602   }
1603
1604   return aSeqOfIDs;
1605 }
1606
1607 //=======================================================================
1608 //function : GetShapesOnBoxIDs
1609 /*!
1610    * \brief Find subshapes complying with given status about surface
1611     * \param theBox - the box to check state of subshapes against
1612     * \param theShape - the shape to explore
1613     * \param theShapeType - type of subshape of theShape
1614     * \param theState - required state
1615     * \retval Handle(TColStd_HSequenceOfInteger) - IDs of found subshapes
1616  */
1617 //=======================================================================
1618 Handle(TColStd_HSequenceOfInteger)
1619     GEOMImpl_IShapesOperations::GetShapesOnBoxIDs(const Handle(GEOM_Object)& theBox,
1620                                                   const Handle(GEOM_Object)& theShape,
1621                                                   const Standard_Integer theShapeType,
1622                                                   GEOMAlgo_State theState)
1623 {
1624   // Find subshapes ids
1625   Handle(TColStd_HSequenceOfInteger) aSeqOfIDs =
1626     getShapesOnBoxIDs (theBox, theShape, theShapeType, theState);
1627   if ( aSeqOfIDs.IsNull()  || aSeqOfIDs->Length() == 0 )
1628     return NULL;
1629
1630   // The GetShapesOnBox() doesn't change object so no new function is required.
1631   Handle(GEOM_Function) aFunction = GEOM::GetCreatedLast(theShape,theBox)->GetLastFunction();
1632
1633   // Make a Python command
1634   GEOM::TPythonDump(aFunction)
1635     << "listShapesOnBoxIDs = geompy.GetShapesOnBoxIDs("
1636     << theBox << ", "
1637     << theShape << ", "
1638     << TopAbs_ShapeEnum(theShapeType) << ", "
1639     << theState << ")";
1640
1641   SetErrorCode(OK);
1642   return aSeqOfIDs;
1643 }
1644
1645 //=======================================================================
1646 //function : GetShapesOnBox
1647 /*!
1648    * \brief Find subshapes complying with given status about surface
1649     * \param theBox - the box to check state of subshapes against
1650     * \param theShape - the shape to explore
1651     * \param theShapeType - type of subshape of theShape
1652     * \param theState - required state
1653     * \retval Handle(TColStd_HSequenceOfTransient) - found subshapes
1654  */
1655 //=======================================================================
1656 Handle(TColStd_HSequenceOfTransient)
1657     GEOMImpl_IShapesOperations::GetShapesOnBox(const Handle(GEOM_Object)& theBox,
1658                                                const Handle(GEOM_Object)&  theShape,
1659                                                const Standard_Integer theShapeType,
1660                                                GEOMAlgo_State theState)
1661 {
1662   // Find subshapes ids
1663   Handle(TColStd_HSequenceOfInteger) aSeqOfIDs =
1664     getShapesOnBoxIDs (theBox, theShape, theShapeType, theState);
1665   if ( aSeqOfIDs.IsNull()  || aSeqOfIDs->Length() == 0 )
1666     return NULL;
1667
1668   // Find objects by indices
1669   TCollection_AsciiString anAsciiList;
1670   Handle(TColStd_HSequenceOfTransient) aSeq;
1671   aSeq = getObjectsShapesOn( theShape, aSeqOfIDs, anAsciiList );
1672   if ( aSeq.IsNull() || aSeq->IsEmpty() )
1673     return NULL;
1674
1675   // Make a Python command
1676
1677   Handle(GEOM_Object) anObj = Handle(GEOM_Object)::DownCast( aSeq->Value( 1 ));
1678   Handle(GEOM_Function) aFunction = anObj->GetLastFunction();
1679
1680   GEOM::TPythonDump(aFunction)
1681     << "[" << anAsciiList.ToCString() << "] = geompy.GetShapesOnBox("
1682     << theBox << ", "
1683     << theShape << ", "
1684     << TopAbs_ShapeEnum(theShapeType) << ", "
1685     << theState << ")";
1686
1687   SetErrorCode(OK);
1688   return aSeq;
1689 }
1690
1691 //=======================================================================
1692 //function : getShapesOnShapeIDs
1693 /*!
1694  * \brief Find IDs of subshapes complying with given status about surface
1695  * \param theCheckShape - the shape to check state of subshapes against
1696  * \param theShape - the shape to explore
1697  * \param theShapeType - type of subshape of theShape
1698  * \param theState - required state
1699  * \retval Handle(TColStd_HSequenceOfInteger) - IDs of found subshapes
1700  */
1701 //=======================================================================
1702 Handle(TColStd_HSequenceOfInteger)
1703   GEOMImpl_IShapesOperations::getShapesOnShapeIDs
1704                                  (const Handle(GEOM_Object)& theCheckShape,
1705                                   const Handle(GEOM_Object)& theShape,
1706                                   const Standard_Integer theShapeType,
1707                                   GEOMAlgo_State theState)
1708 {
1709   Handle(TColStd_HSequenceOfInteger) aSeqOfIDs;
1710
1711   TopoDS_Shape aCheckShape = theCheckShape->GetValue();
1712   TopoDS_Shape aShape = theShape->GetValue();
1713   TopTools_ListOfShape res;
1714
1715   // Check presence of triangulation, build if need
1716   if (!CheckTriangulation(aShape)) {
1717     SetErrorCode("Cannot build triangulation on the shape");
1718     return aSeqOfIDs;
1719   }
1720
1721   // Call algo
1722   GEOMAlgo_FinderShapeOn2 aFinder;
1723   Standard_Real aTol = 0.0001; // default value
1724
1725   Handle(GEOMAlgo_ClsfSolid) aClsfSolid = new GEOMAlgo_ClsfSolid;
1726   aClsfSolid->SetShape(aCheckShape);
1727
1728   aFinder.SetShape(aShape);
1729   aFinder.SetTolerance(aTol);
1730   aFinder.SetClsf(aClsfSolid);
1731   aFinder.SetShapeType( (TopAbs_ShapeEnum)theShapeType );
1732   aFinder.SetState(theState);
1733   aFinder.Perform();
1734
1735   // Interprete results
1736   Standard_Integer iErr = aFinder.ErrorStatus();
1737   // the detailed description of error codes is in GEOMAlgo_FinderShapeOn1.cxx
1738   if (iErr) {
1739     MESSAGE(" iErr : " << iErr);
1740     TCollection_AsciiString aMsg (" iErr : ");
1741     aMsg += TCollection_AsciiString(iErr);
1742     SetErrorCode(aMsg);
1743     return aSeqOfIDs;
1744   }
1745   Standard_Integer iWrn = aFinder.WarningStatus();
1746   // the detailed description of warning codes is in GEOMAlgo_FinderShapeOn1.cxx
1747   if (iWrn) {
1748     MESSAGE(" *** iWrn : " << iWrn);
1749   }
1750
1751   const TopTools_ListOfShape& listSS = aFinder.Shapes(); // the result
1752
1753   if (listSS.Extent() < 1) {
1754     //SetErrorCode("Not a single sub-shape of the requested type found on the given surface");
1755     SetErrorCode(NOT_FOUND_ANY); // NPAL18017
1756   }
1757
1758   // Fill sequence of object IDs
1759   aSeqOfIDs = new TColStd_HSequenceOfInteger;
1760
1761   TopTools_IndexedMapOfShape anIndices;
1762   TopExp::MapShapes(aShape, anIndices);
1763
1764   TopTools_ListIteratorOfListOfShape itSub (listSS);
1765   for (int index = 1; itSub.More(); itSub.Next(), ++index) {
1766     int id = anIndices.FindIndex(itSub.Value());
1767     aSeqOfIDs->Append(id);
1768   }
1769
1770   return aSeqOfIDs;
1771 }
1772
1773 //=======================================================================
1774 //function : GetShapesOnShapeIDs
1775 /*!
1776  * \brief Find subshapes complying with given status about surface
1777  * \param theCheckShape - the shape to check state of subshapes against
1778  * \param theShape - the shape to explore
1779  * \param theShapeType - type of subshape of theShape
1780  * \param theState - required state
1781  * \retval Handle(TColStd_HSequenceOfInteger) - IDs of found subshapes
1782  */
1783 //=======================================================================
1784 Handle(TColStd_HSequenceOfInteger)
1785     GEOMImpl_IShapesOperations::GetShapesOnShapeIDs
1786                             (const Handle(GEOM_Object)& theCheckShape,
1787                              const Handle(GEOM_Object)& theShape,
1788                              const Standard_Integer theShapeType,
1789                              GEOMAlgo_State theState)
1790 {
1791   Handle(TColStd_HSequenceOfInteger) aSeqOfIDs =
1792     getShapesOnShapeIDs (theCheckShape, theShape, theShapeType, theState);
1793
1794   if ( aSeqOfIDs.IsNull()  || aSeqOfIDs->Length() == 0 )
1795     return NULL;
1796
1797   // The GetShapesOnShape() doesn't change object so no new function is required.
1798   Handle(GEOM_Function) aFunction =
1799     GEOM::GetCreatedLast(theShape,theCheckShape)->GetLastFunction();
1800
1801   // Make a Python command
1802   GEOM::TPythonDump(aFunction)
1803     << "listShapesOnBoxIDs = geompy.GetShapesOnShapeIDs("
1804     << theCheckShape << ", "
1805     << theShape << ", "
1806     << TopAbs_ShapeEnum(theShapeType) << ", "
1807     << theState << ")";
1808
1809   SetErrorCode(OK);
1810   return aSeqOfIDs;
1811 }
1812
1813 //=======================================================================
1814 //function : GetShapesOnShape
1815 /*!
1816  * \brief Find subshapes complying with given status about surface
1817  * \param theCheckShape - the shape to check state of subshapes against
1818  * \param theShape - the shape to explore
1819  * \param theShapeType - type of subshape of theShape
1820  * \param theState - required state
1821  * \retval Handle(TColStd_HSequenceOfTransient) - found subshapes
1822  */
1823 //=======================================================================
1824 Handle(TColStd_HSequenceOfTransient)
1825   GEOMImpl_IShapesOperations::GetShapesOnShape
1826                              (const Handle(GEOM_Object)& theCheckShape,
1827                               const Handle(GEOM_Object)&  theShape,
1828                               const Standard_Integer theShapeType,
1829                               GEOMAlgo_State theState)
1830 {
1831   Handle(TColStd_HSequenceOfInteger) aSeqOfIDs =
1832     getShapesOnShapeIDs (theCheckShape, theShape, theShapeType, theState);
1833   if ( aSeqOfIDs.IsNull()  || aSeqOfIDs->Length() == 0 )
1834     return NULL;
1835
1836   // Find objects by indices
1837   TCollection_AsciiString anAsciiList;
1838   Handle(TColStd_HSequenceOfTransient) aSeq;
1839   aSeq = getObjectsShapesOn( theShape, aSeqOfIDs, anAsciiList );
1840
1841   if ( aSeq.IsNull() || aSeq->IsEmpty() )
1842     return NULL;
1843
1844   // Make a Python command
1845
1846   Handle(GEOM_Object) anObj = Handle(GEOM_Object)::DownCast( aSeq->Value( 1 ));
1847   Handle(GEOM_Function) aFunction = anObj->GetLastFunction();
1848
1849   GEOM::TPythonDump(aFunction)
1850     << "[" << anAsciiList.ToCString() << "] = geompy.GetShapesOnShape("
1851     << theCheckShape << ", "
1852     << theShape << ", "
1853     << TopAbs_ShapeEnum(theShapeType) << ", "
1854     << theState << ")";
1855
1856   SetErrorCode(OK);
1857   return aSeq;
1858 }
1859
1860 //=======================================================================
1861 //function : GetShapesOnShapeAsCompound
1862 //=======================================================================
1863 Handle(GEOM_Object) GEOMImpl_IShapesOperations::GetShapesOnShapeAsCompound
1864                              (const Handle(GEOM_Object)& theCheckShape,
1865                               const Handle(GEOM_Object)&  theShape,
1866                               const Standard_Integer theShapeType,
1867                               GEOMAlgo_State theState)
1868 {
1869   Handle(TColStd_HSequenceOfInteger) aSeqOfIDs =
1870     getShapesOnShapeIDs (theCheckShape, theShape, theShapeType, theState);
1871
1872   if ( aSeqOfIDs.IsNull()  || aSeqOfIDs->Length() == 0 )
1873     return NULL;
1874
1875   // Find objects by indices
1876   TCollection_AsciiString anAsciiList;
1877   Handle(TColStd_HSequenceOfTransient) aSeq;
1878   aSeq = getObjectsShapesOn( theShape, aSeqOfIDs, anAsciiList );
1879
1880   if ( aSeq.IsNull() || aSeq->IsEmpty() )
1881     return NULL;
1882
1883   TopoDS_Compound aCompound;
1884   BRep_Builder B;
1885   B.MakeCompound(aCompound);
1886   int i = 1;
1887   for(; i<=aSeq->Length(); i++) {
1888     Handle(GEOM_Object) anObj = Handle(GEOM_Object)::DownCast(aSeq->Value(i));
1889     TopoDS_Shape aShape_i = anObj->GetValue();
1890     B.Add(aCompound,aShape_i);
1891   }
1892
1893   //Add a new result object
1894   Handle(GEOM_Object) aRes = GetEngine()->AddObject(GetDocID(), GEOM_SHAPES_ON_SHAPE);
1895   Handle(GEOM_Function) aFunction =
1896     aRes->AddFunction(GEOMImpl_ShapeDriver::GetID(), SHAPES_ON_SHAPE);
1897   aFunction->SetValue(aCompound);
1898
1899   GEOM::TPythonDump(aFunction)
1900     << aRes << " = geompy.GetShapesOnShapeAsCompound("
1901     << theCheckShape << ", "
1902     << theShape << ", "
1903     << TopAbs_ShapeEnum(theShapeType) << ", "
1904     << theState << ")";
1905
1906   SetErrorCode(OK);
1907
1908   return aRes;
1909 }
1910
1911 //=======================================================================
1912 //function : getShapesOnSurfaceIDs
1913   /*!
1914    * \brief Find IDs of subshapes complying with given status about surface
1915     * \param theSurface - the surface to check state of subshapes against
1916     * \param theShape - the shape to explore
1917     * \param theShapeType - type of subshape of theShape
1918     * \param theState - required state
1919     * \retval Handle(TColStd_HSequenceOfInteger) - IDs of found subshapes
1920    */
1921 //=======================================================================
1922 Handle(TColStd_HSequenceOfInteger)
1923   GEOMImpl_IShapesOperations::getShapesOnSurfaceIDs(const Handle(Geom_Surface)& theSurface,
1924                                                     const TopoDS_Shape&         theShape,
1925                                                     TopAbs_ShapeEnum            theShapeType,
1926                                                     GEOMAlgo_State              theState)
1927 {
1928   Handle(TColStd_HSequenceOfInteger) aSeqOfIDs;
1929
1930   // Check presence of triangulation, build if need
1931   if (!CheckTriangulation(theShape)) {
1932     SetErrorCode("Cannot build triangulation on the shape");
1933     return aSeqOfIDs;
1934   }
1935
1936   // Call algo
1937   GEOMAlgo_FinderShapeOn1 aFinder;
1938   Standard_Real aTol = 0.0001; // default value
1939
1940   aFinder.SetShape(theShape);
1941   aFinder.SetTolerance(aTol);
1942   aFinder.SetSurface(theSurface);
1943   aFinder.SetShapeType(theShapeType);
1944   aFinder.SetState(theState);
1945
1946   // Sets the minimal number of inner points for the faces that do not have own
1947   // inner points at all (for e.g. rectangular planar faces have just 2 triangles).
1948   // Default value=3
1949   aFinder.SetNbPntsMin(3);
1950   // Sets the maximal number of inner points for edges or faces.
1951   // It is usefull for the cases when this number is very big (e.g =2000) to improve
1952   // the performance. If this value =0, all inner points will be taken into account.
1953   // Default value=0
1954   aFinder.SetNbPntsMax(100);
1955
1956   aFinder.Perform();
1957
1958   // Interprete results
1959   Standard_Integer iErr = aFinder.ErrorStatus();
1960   // the detailed description of error codes is in GEOMAlgo_FinderShapeOn1.cxx
1961   if (iErr) {
1962     MESSAGE(" iErr : " << iErr);
1963     TCollection_AsciiString aMsg (" iErr : ");
1964     aMsg += TCollection_AsciiString(iErr);
1965     SetErrorCode(aMsg);
1966     return aSeqOfIDs;
1967   }
1968   Standard_Integer iWrn = aFinder.WarningStatus();
1969   // the detailed description of warning codes is in GEOMAlgo_FinderShapeOn1.cxx
1970   if (iWrn) {
1971     MESSAGE(" *** iWrn : " << iWrn);
1972   }
1973
1974   const TopTools_ListOfShape& listSS = aFinder.Shapes(); // the result
1975
1976   if (listSS.Extent() < 1) {
1977     //SetErrorCode("Not a single sub-shape of the requested type found on the given surface");
1978     SetErrorCode(NOT_FOUND_ANY); // NPAL18017
1979     return aSeqOfIDs;
1980   }
1981
1982   // Fill sequence of object IDs
1983   aSeqOfIDs = new TColStd_HSequenceOfInteger;
1984
1985   TopTools_IndexedMapOfShape anIndices;
1986   TopExp::MapShapes(theShape, anIndices);
1987
1988   TopTools_ListIteratorOfListOfShape itSub (listSS);
1989   for (int index = 1; itSub.More(); itSub.Next(), ++index) {
1990     int id = anIndices.FindIndex(itSub.Value());
1991     aSeqOfIDs->Append(id);
1992   }
1993
1994   return aSeqOfIDs;
1995 }
1996
1997 //=======================================================================
1998 //function : getObjectsShapesOn
1999 /*!
2000  * \brief Find shape objects and their entries by their ids
2001  * \param theShapeIDs - incoming shape ids
2002  * \param theShapeEntries - outgoing entries like "entry1, entry2, ..."
2003  * \retval Handle(TColStd_HSequenceOfTransient) - found shape objects
2004  */
2005 //=======================================================================
2006 Handle(TColStd_HSequenceOfTransient) GEOMImpl_IShapesOperations::
2007  getObjectsShapesOn(const Handle(GEOM_Object)&                theShape,
2008                     const Handle(TColStd_HSequenceOfInteger)& theShapeIDs,
2009                     TCollection_AsciiString &                 theShapeEntries)
2010 {
2011   Handle(TColStd_HSequenceOfTransient) aSeq;
2012
2013   if ( !theShapeIDs.IsNull() && theShapeIDs->Length() > 0 )
2014   {
2015     aSeq = new TColStd_HSequenceOfTransient;
2016     Handle(TColStd_HArray1OfInteger) anArray = new TColStd_HArray1OfInteger(1,1);
2017     TCollection_AsciiString anEntry;
2018     for ( int i = 1; i <= theShapeIDs->Length(); ++i )
2019     {
2020       anArray->SetValue(1, theShapeIDs->Value( i ));
2021       Handle(GEOM_Object) anObj = GetEngine()->AddSubShape(theShape, anArray);
2022       aSeq->Append( anObj );
2023
2024       TDF_Tool::Entry(anObj->GetEntry(), anEntry);
2025       if ( i != 1 ) theShapeEntries += ",";
2026       theShapeEntries += anEntry;
2027     }
2028   }
2029   return aSeq;
2030 }
2031
2032 //=======================================================================
2033 //function : getShapesOnSurface
2034 /*!
2035    * \brief Find subshapes complying with given status about surface
2036     * \param theSurface - the surface to check state of subshapes against
2037     * \param theShape - the shape to explore
2038     * \param theShapeType - type of subshape of theShape
2039     * \param theState - required state
2040     * \param theShapeEntries - outgoing entries like "entry1, entry2, ..."
2041     * \retval Handle(TColStd_HSequenceOfInteger) - IDs of found subshapes
2042  */
2043 //=======================================================================
2044 Handle(TColStd_HSequenceOfTransient)
2045     GEOMImpl_IShapesOperations::getShapesOnSurface(const Handle(Geom_Surface)& theSurface,
2046                                                    const Handle(GEOM_Object)&  theShape,
2047                                                    TopAbs_ShapeEnum            theShapeType,
2048                                                    GEOMAlgo_State              theState,
2049                                                    TCollection_AsciiString &   theShapeEntries)
2050 {
2051   // Find subshapes ids
2052   Handle(TColStd_HSequenceOfInteger) aSeqOfIDs =
2053     getShapesOnSurfaceIDs (theSurface, theShape->GetValue(), theShapeType, theState);
2054   if ( aSeqOfIDs.IsNull()  || aSeqOfIDs->Length() == 0 )
2055     return NULL;
2056
2057   return getObjectsShapesOn( theShape, aSeqOfIDs, theShapeEntries );
2058 }
2059
2060 //=============================================================================
2061 /*!
2062  *  GetShapesOnPlane
2063  */
2064 //=============================================================================
2065 Handle(TColStd_HSequenceOfTransient) GEOMImpl_IShapesOperations::GetShapesOnPlane
2066                                         (const Handle(GEOM_Object)& theShape,
2067                                          const Standard_Integer     theShapeType,
2068                                          const Handle(GEOM_Object)& theAx1,
2069                                          const GEOMAlgo_State       theState)
2070 {
2071   SetErrorCode(KO);
2072
2073   if (theShape.IsNull() || theAx1.IsNull()) return NULL;
2074
2075   TopoDS_Shape aShape = theShape->GetValue();
2076   TopoDS_Shape anAx1  = theAx1->GetValue();
2077
2078   if (aShape.IsNull() || anAx1.IsNull()) return NULL;
2079
2080   TopAbs_ShapeEnum aShapeType = TopAbs_ShapeEnum(theShapeType);
2081   if ( !checkTypeShapesOn( theShapeType ))
2082     return NULL;
2083
2084   // Create plane
2085   Handle(Geom_Surface) aPlane = makePlane( anAx1 );
2086   if ( aPlane.IsNull() )
2087     return NULL;
2088
2089   // Find objects
2090   TCollection_AsciiString anAsciiList;
2091   Handle(TColStd_HSequenceOfTransient) aSeq;
2092   aSeq = getShapesOnSurface( aPlane, theShape, aShapeType, theState, anAsciiList );
2093   if ( aSeq.IsNull() || aSeq->Length() == 0 )
2094     return NULL;
2095
2096   // Make a Python command
2097
2098   Handle(GEOM_Object) anObj = Handle(GEOM_Object)::DownCast( aSeq->Value( 1 ));
2099   Handle(GEOM_Function) aFunction = anObj->GetLastFunction();
2100
2101   GEOM::TPythonDump(aFunction) << "[" << anAsciiList.ToCString()
2102     << "] = geompy.GetShapesOnPlane(" << theShape << ", "
2103       << aShapeType << ", " << theAx1 << ", " << theState << ")";
2104
2105   SetErrorCode(OK);
2106   return aSeq;
2107 }
2108
2109 //=============================================================================
2110 /*!
2111  *  GetShapesOnPlaneWithLocation
2112  */
2113 //=============================================================================
2114 Handle(TColStd_HSequenceOfTransient) GEOMImpl_IShapesOperations::GetShapesOnPlaneWithLocation
2115                                         (const Handle(GEOM_Object)& theShape,
2116                                          const Standard_Integer     theShapeType,
2117                                          const Handle(GEOM_Object)& theAx1,
2118                                          const Handle(GEOM_Object)& thePnt,
2119                                          const GEOMAlgo_State       theState)
2120 {
2121   SetErrorCode(KO);
2122
2123   if (theShape.IsNull() || theAx1.IsNull() || thePnt.IsNull()) return NULL;
2124
2125   TopoDS_Shape aShape = theShape->GetValue();
2126   TopoDS_Shape anAx1  = theAx1->GetValue();
2127   TopoDS_Shape anPnt = thePnt->GetValue();
2128
2129   if (aShape.IsNull() || anAx1.IsNull() || anPnt.IsNull()) return NULL;
2130
2131   TopAbs_ShapeEnum aShapeType = TopAbs_ShapeEnum(theShapeType);
2132   if ( !checkTypeShapesOn( theShapeType ))
2133     return NULL;
2134
2135   // Create plane
2136   if ( anAx1.ShapeType() != TopAbs_EDGE || anPnt.ShapeType() != TopAbs_VERTEX ) return NULL;
2137   TopoDS_Vertex V1, V2, V3;
2138   TopoDS_Edge anEdge = TopoDS::Edge(anAx1);
2139   TopExp::Vertices(anEdge, V1, V2, Standard_True);
2140
2141   if (V1.IsNull() || V2.IsNull()) {
2142     SetErrorCode("Bad edge given for the plane normal vector");
2143     return NULL;
2144   }
2145   V3 = TopoDS::Vertex(anPnt);
2146
2147   if(V3.IsNull()) {
2148     SetErrorCode("Bad vertex given for the plane location");
2149       return NULL;
2150   }
2151   gp_Pnt aLoc = BRep_Tool::Pnt(V3);
2152   gp_Vec aVec(BRep_Tool::Pnt(V1),BRep_Tool::Pnt(V2));
2153
2154   if (aVec.Magnitude() < Precision::Confusion()) {
2155      SetErrorCode("Vector with null magnitude given");
2156     return NULL;
2157   }
2158   Handle(Geom_Surface) aPlane = new Geom_Plane(aLoc, aVec);
2159
2160   if ( aPlane.IsNull() )
2161     return NULL;
2162
2163   // Find objects
2164   TCollection_AsciiString anAsciiList;
2165   Handle(TColStd_HSequenceOfTransient) aSeq;
2166   aSeq = getShapesOnSurface( aPlane, theShape, aShapeType, theState, anAsciiList );
2167   if ( aSeq.IsNull() || aSeq->Length() == 0 )
2168     return NULL;
2169
2170   // Make a Python command
2171
2172   Handle(GEOM_Object) anObj = Handle(GEOM_Object)::DownCast( aSeq->Value( 1 ));
2173   Handle(GEOM_Function) aFunction = anObj->GetLastFunction();
2174
2175   GEOM::TPythonDump(aFunction) << "[" << anAsciiList.ToCString()
2176     << "] = geompy.GetShapesOnPlaneWithLocation(" << theShape << ", "
2177     << aShapeType << ", " << theAx1 << ", "<< thePnt <<", " << theState << ")";
2178
2179   SetErrorCode(OK);
2180   return aSeq;
2181 }
2182
2183 //=============================================================================
2184 /*!
2185  *  GetShapesOnCylinder
2186  */
2187 //=============================================================================
2188 Handle(TColStd_HSequenceOfTransient) GEOMImpl_IShapesOperations::GetShapesOnCylinder
2189                                           (const Handle(GEOM_Object)& theShape,
2190                                            const Standard_Integer     theShapeType,
2191                                            const Handle(GEOM_Object)& theAxis,
2192                                            const Standard_Real        theRadius,
2193                                            const GEOMAlgo_State       theState)
2194 {
2195   SetErrorCode(KO);
2196
2197   if (theShape.IsNull() || theAxis.IsNull()) return NULL;
2198
2199   TopoDS_Shape aShape = theShape->GetValue();
2200   TopoDS_Shape anAxis = theAxis->GetValue();
2201
2202   if (aShape.IsNull() || anAxis.IsNull()) return NULL;
2203
2204   TopAbs_ShapeEnum aShapeType = TopAbs_ShapeEnum(theShapeType);
2205   if ( !checkTypeShapesOn( aShapeType ))
2206     return NULL;
2207
2208   // Create a cylinder surface
2209   Handle(Geom_Surface) aCylinder = makeCylinder( anAxis, theRadius );
2210   if ( aCylinder.IsNull() )
2211     return NULL;
2212
2213   // Find objects
2214   TCollection_AsciiString anAsciiList;
2215   Handle(TColStd_HSequenceOfTransient) aSeq;
2216   aSeq = getShapesOnSurface( aCylinder, theShape, aShapeType, theState, anAsciiList );
2217   if ( aSeq.IsNull() || aSeq->Length() == 0 )
2218     return NULL;
2219
2220   // Make a Python command
2221
2222   Handle(GEOM_Object) anObj = Handle(GEOM_Object)::DownCast( aSeq->Value( 1 ));
2223   Handle(GEOM_Function) aFunction = anObj->GetLastFunction();
2224
2225   GEOM::TPythonDump(aFunction) << "[" << anAsciiList.ToCString()
2226     << "] = geompy.GetShapesOnCylinder(" << theShape << ", " << aShapeType
2227       << ", " << theAxis << ", " << theRadius << ", " << theState << ")";
2228
2229   SetErrorCode(OK);
2230   return aSeq;
2231 }
2232
2233 //=============================================================================
2234 /*!
2235  *  GetShapesOnSphere
2236  */
2237 //=============================================================================
2238 Handle(TColStd_HSequenceOfTransient) GEOMImpl_IShapesOperations::GetShapesOnSphere
2239                                           (const Handle(GEOM_Object)& theShape,
2240                                            const Standard_Integer     theShapeType,
2241                                            const Handle(GEOM_Object)& theCenter,
2242                                            const Standard_Real        theRadius,
2243                                            const GEOMAlgo_State       theState)
2244 {
2245   SetErrorCode(KO);
2246
2247   if (theShape.IsNull() || theCenter.IsNull()) return NULL;
2248
2249   TopoDS_Shape aShape  = theShape->GetValue();
2250   TopoDS_Shape aCenter = theCenter->GetValue();
2251
2252   if (aShape.IsNull() || aCenter.IsNull()) return NULL;
2253
2254   TopAbs_ShapeEnum aShapeType = TopAbs_ShapeEnum(theShapeType);
2255   if ( !checkTypeShapesOn( aShapeType ))
2256     return NULL;
2257
2258   // Center of the sphere
2259   if (aCenter.ShapeType() != TopAbs_VERTEX) return NULL;
2260   gp_Pnt aLoc = BRep_Tool::Pnt(TopoDS::Vertex(aCenter));
2261
2262   gp_Ax3 anAx3 (aLoc, gp::DZ());
2263   Handle(Geom_SphericalSurface) aSphere =
2264     new Geom_SphericalSurface(anAx3, theRadius);
2265
2266   // Find objects
2267   TCollection_AsciiString anAsciiList;
2268   Handle(TColStd_HSequenceOfTransient) aSeq;
2269   aSeq = getShapesOnSurface( aSphere, theShape, aShapeType, theState, anAsciiList );
2270   if ( aSeq.IsNull() || aSeq->Length() == 0 )
2271     return NULL;
2272
2273   // Make a Python command
2274
2275   Handle(GEOM_Object) anObj = Handle(GEOM_Object)::DownCast( aSeq->Value( 1 ));
2276   Handle(GEOM_Function) aFunction = anObj->GetLastFunction();
2277
2278   GEOM::TPythonDump(aFunction) << "[" << anAsciiList.ToCString()
2279     << "] = geompy.GetShapesOnSphere(" << theShape << ", " << aShapeType
2280       << ", " << theCenter << ", " << theRadius << ", " << theState << ")";
2281
2282   SetErrorCode(OK);
2283   return aSeq;
2284 }
2285
2286 //=============================================================================
2287 /*!
2288  *  GetShapesOnPlaneIDs
2289  */
2290 //=============================================================================
2291 Handle(TColStd_HSequenceOfInteger) GEOMImpl_IShapesOperations::GetShapesOnPlaneIDs
2292                                         (const Handle(GEOM_Object)& theShape,
2293                                          const Standard_Integer     theShapeType,
2294                                          const Handle(GEOM_Object)& theAx1,
2295                                          const GEOMAlgo_State       theState)
2296 {
2297   SetErrorCode(KO);
2298
2299   if (theShape.IsNull() || theAx1.IsNull()) return NULL;
2300
2301   TopoDS_Shape aShape = theShape->GetValue();
2302   TopoDS_Shape anAx1  = theAx1->GetValue();
2303
2304   if (aShape.IsNull() || anAx1.IsNull()) return NULL;
2305
2306   TopAbs_ShapeEnum aShapeType = TopAbs_ShapeEnum(theShapeType);
2307   if ( !checkTypeShapesOn( aShapeType ))
2308     return NULL;
2309
2310   // Create plane
2311   Handle(Geom_Surface) aPlane = makePlane( anAx1 );
2312   if ( aPlane.IsNull() )
2313     return NULL;
2314
2315   // Find object IDs
2316   Handle(TColStd_HSequenceOfInteger) aSeq;
2317   aSeq = getShapesOnSurfaceIDs( aPlane, aShape, aShapeType, theState );
2318
2319   // The GetShapesOnPlaneIDs() doesn't change object so no new function is required.
2320   Handle(GEOM_Function) aFunction = GEOM::GetCreatedLast(theShape,theAx1)->GetLastFunction();
2321
2322   // Make a Python command
2323   GEOM::TPythonDump(aFunction, /*append=*/true)
2324     << "listShapesOnPlane = geompy.GetShapesOnPlaneIDs"
2325     << "(" << theShape << "," << aShapeType << "," << theAx1 << "," << theState << ")";
2326
2327   SetErrorCode(OK);
2328   return aSeq;
2329 }
2330
2331 //=============================================================================
2332 /*!
2333  *  GetShapesOnPlaneWithLocationIDs
2334  */
2335 //=============================================================================
2336 Handle(TColStd_HSequenceOfInteger) GEOMImpl_IShapesOperations::GetShapesOnPlaneWithLocationIDs
2337                                         (const Handle(GEOM_Object)& theShape,
2338                                          const Standard_Integer     theShapeType,
2339                                          const Handle(GEOM_Object)& theAx1,
2340                                          const Handle(GEOM_Object)& thePnt,
2341                                          const GEOMAlgo_State       theState)
2342 {
2343   SetErrorCode(KO);
2344
2345   if (theShape.IsNull() || theAx1.IsNull() || thePnt.IsNull()) return NULL;
2346
2347   TopoDS_Shape aShape = theShape->GetValue();
2348   TopoDS_Shape anAx1  = theAx1->GetValue();
2349   TopoDS_Shape anPnt  = thePnt->GetValue();
2350
2351   if (aShape.IsNull() || anAx1.IsNull() || anPnt.IsNull()) return NULL;
2352
2353   TopAbs_ShapeEnum aShapeType = TopAbs_ShapeEnum(theShapeType);
2354   if ( !checkTypeShapesOn( aShapeType ))
2355     return NULL;
2356
2357   // Create plane
2358   if (anAx1.ShapeType() != TopAbs_EDGE || anPnt.ShapeType() != TopAbs_VERTEX) return NULL;
2359   TopoDS_Edge anEdge = TopoDS::Edge(anAx1);
2360   TopoDS_Vertex V1, V2, V3;
2361   TopExp::Vertices(anEdge, V1, V2, Standard_True);
2362   if (V1.IsNull() || V2.IsNull()) {
2363     SetErrorCode("Bad edge given for the plane normal vector");
2364     return NULL;
2365   }
2366   V3 = TopoDS::Vertex(anPnt);
2367   if(V3.IsNull()) {
2368     SetErrorCode("Bad vertex given for the plane location");
2369       return NULL;
2370   }
2371   gp_Pnt aLoc = BRep_Tool::Pnt(V3);
2372   gp_Vec aVec(BRep_Tool::Pnt(V1),BRep_Tool::Pnt(V2));
2373   if (aVec.Magnitude() < Precision::Confusion()) {
2374     SetErrorCode("Vector with null magnitude given");
2375     return NULL;
2376   }
2377
2378   Handle(Geom_Surface) aPlane = new Geom_Plane(aLoc, aVec);
2379   if ( aPlane.IsNull() )
2380     return NULL;
2381
2382   // Find object IDs
2383   Handle(TColStd_HSequenceOfInteger) aSeq;
2384   aSeq = getShapesOnSurfaceIDs( aPlane, aShape, aShapeType, theState );
2385
2386   // The GetShapesOnPlaneIDs() doesn't change object so no new function is required.
2387   Handle(GEOM_Function) aFunction = GEOM::GetCreatedLast(theShape,theAx1)->GetLastFunction();
2388
2389   // Make a Python command
2390   GEOM::TPythonDump(aFunction, /*append=*/true)
2391     << "listShapesOnPlane = geompy.GetShapesOnPlaneWithLocationIDs"
2392     << "(" << theShape << ", " << aShapeType << ", " << theAx1 << ", "<< thePnt << ", "  << theState << ")";
2393
2394   SetErrorCode(OK);
2395   return aSeq;
2396 }
2397
2398 //=============================================================================
2399 /*!
2400  *  GetShapesOnCylinderIDs
2401  */
2402 //=============================================================================
2403 Handle(TColStd_HSequenceOfInteger) GEOMImpl_IShapesOperations::GetShapesOnCylinderIDs
2404                                           (const Handle(GEOM_Object)& theShape,
2405                                            const Standard_Integer     theShapeType,
2406                                            const Handle(GEOM_Object)& theAxis,
2407                                            const Standard_Real        theRadius,
2408                                            const GEOMAlgo_State       theState)
2409 {
2410   SetErrorCode(KO);
2411
2412   if (theShape.IsNull() || theAxis.IsNull()) return NULL;
2413
2414   TopoDS_Shape aShape = theShape->GetValue();
2415   TopoDS_Shape anAxis = theAxis->GetValue();
2416
2417   if (aShape.IsNull() || anAxis.IsNull()) return NULL;
2418
2419   TopAbs_ShapeEnum aShapeType = TopAbs_ShapeEnum(theShapeType);
2420   if ( !checkTypeShapesOn( aShapeType ))
2421     return NULL;
2422
2423   // Create a cylinder surface
2424   Handle(Geom_Surface) aCylinder = makeCylinder( anAxis, theRadius );
2425   if ( aCylinder.IsNull() )
2426     return NULL;
2427
2428   // Find object IDs
2429   Handle(TColStd_HSequenceOfInteger) aSeq;
2430   aSeq = getShapesOnSurfaceIDs( aCylinder, aShape, aShapeType, theState );
2431
2432   // The GetShapesOnCylinder() doesn't change object so no new function is required.
2433   Handle(GEOM_Function) aFunction = GEOM::GetCreatedLast(theShape,theAxis)->GetLastFunction();
2434
2435   // Make a Python command
2436   GEOM::TPythonDump(aFunction, /*append=*/true)
2437     << "listShapesOnCylinder = geompy.GetShapesOnCylinderIDs"
2438     << "(" << theShape << ", " << aShapeType << ", " << theAxis << ", "
2439     << theRadius << ", " << theState << ")";
2440
2441   SetErrorCode(OK);
2442   return aSeq;
2443 }
2444
2445 //=============================================================================
2446 /*!
2447  *  GetShapesOnSphereIDs
2448  */
2449 //=============================================================================
2450 Handle(TColStd_HSequenceOfInteger) GEOMImpl_IShapesOperations::GetShapesOnSphereIDs
2451                                           (const Handle(GEOM_Object)& theShape,
2452                                            const Standard_Integer     theShapeType,
2453                                            const Handle(GEOM_Object)& theCenter,
2454                                            const Standard_Real        theRadius,
2455                                            const GEOMAlgo_State       theState)
2456 {
2457   SetErrorCode(KO);
2458
2459   if (theShape.IsNull() || theCenter.IsNull()) return NULL;
2460
2461   TopoDS_Shape aShape  = theShape->GetValue();
2462   TopoDS_Shape aCenter = theCenter->GetValue();
2463
2464   if (aShape.IsNull() || aCenter.IsNull()) return NULL;
2465
2466   TopAbs_ShapeEnum aShapeType = TopAbs_ShapeEnum(theShapeType);
2467   if ( !checkTypeShapesOn( aShapeType ))
2468     return NULL;
2469
2470   // Center of the sphere
2471   if (aCenter.ShapeType() != TopAbs_VERTEX) return NULL;
2472   gp_Pnt aLoc = BRep_Tool::Pnt(TopoDS::Vertex(aCenter));
2473
2474   gp_Ax3 anAx3 (aLoc, gp::DZ());
2475   Handle(Geom_SphericalSurface) aSphere =
2476     new Geom_SphericalSurface(anAx3, theRadius);
2477
2478   // Find object IDs
2479   Handle(TColStd_HSequenceOfInteger) aSeq;
2480   aSeq = getShapesOnSurfaceIDs( aSphere, aShape, aShapeType, theState );
2481
2482   // The GetShapesOnSphere() doesn't change object so no new function is required.
2483   Handle(GEOM_Function) aFunction = GEOM::GetCreatedLast(theShape,theCenter)->GetLastFunction();
2484
2485   // Make a Python command
2486   GEOM::TPythonDump(aFunction, /*append=*/true)
2487     << "listShapesOnCylinder = geompy.GetShapesOnCylinderIDs"
2488     << "(" << theShape << ", " << aShapeType << ", " << theCenter << ", "
2489     << theRadius << ", " << theState << ")";
2490
2491   SetErrorCode(OK);
2492   return aSeq;
2493 }
2494
2495 //=======================================================================
2496 //function : getShapesOnQuadrangleIDs
2497   /*!
2498    * \brief Find IDs of subshapes complying with given status about quadrangle
2499     * \param theShape - the shape to explore
2500     * \param theShapeType - type of subshape of theShape
2501     * \param theTopLeftPoint - top left quadrangle corner
2502     * \param theTopRigthPoint - top right quadrangle corner
2503     * \param theBottomLeftPoint - bottom left quadrangle corner
2504     * \param theBottomRigthPoint - bottom right quadrangle corner
2505     * \param theState - required state
2506     * \retval Handle(TColStd_HSequenceOfInteger) - IDs of found subshapes
2507    */
2508 //=======================================================================
2509 Handle(TColStd_HSequenceOfInteger)
2510   GEOMImpl_IShapesOperations::getShapesOnQuadrangleIDs (const Handle(GEOM_Object)& theShape,
2511                                                         const Standard_Integer     theShapeType,
2512                                                         const Handle(GEOM_Object)& theTopLeftPoint,
2513                                                         const Handle(GEOM_Object)& theTopRigthPoint,
2514                                                         const Handle(GEOM_Object)& theBottomLeftPoint,
2515                                                         const Handle(GEOM_Object)& theBottomRigthPoint,
2516                                                         const GEOMAlgo_State       theState)
2517 {
2518   SetErrorCode(KO);
2519
2520   if ( theShape.IsNull() ||
2521        theTopLeftPoint.IsNull() ||
2522        theTopRigthPoint.IsNull() ||
2523        theBottomLeftPoint.IsNull() ||
2524        theBottomRigthPoint.IsNull() )
2525     return NULL;
2526
2527   TopoDS_Shape aShape = theShape->GetValue();
2528   TopoDS_Shape aTL = theTopLeftPoint->GetValue();
2529   TopoDS_Shape aTR = theTopRigthPoint->GetValue();
2530   TopoDS_Shape aBL = theBottomLeftPoint->GetValue();
2531   TopoDS_Shape aBR = theBottomRigthPoint->GetValue();
2532
2533   if (aShape.IsNull() ||
2534       aTL.IsNull() ||
2535       aTR.IsNull() ||
2536       aBL.IsNull() ||
2537       aBR.IsNull() ||
2538       aTL.ShapeType() != TopAbs_VERTEX ||
2539       aTR.ShapeType() != TopAbs_VERTEX ||
2540       aBL.ShapeType() != TopAbs_VERTEX ||
2541       aBR.ShapeType() != TopAbs_VERTEX )
2542     return NULL;
2543
2544   TopAbs_ShapeEnum aShapeType = TopAbs_ShapeEnum(theShapeType);
2545   if ( !checkTypeShapesOn( aShapeType ))
2546     return NULL;
2547
2548   Handle(TColStd_HSequenceOfInteger) aSeqOfIDs;
2549
2550   // Check presence of triangulation, build if need
2551   if (!CheckTriangulation(aShape)) {
2552     SetErrorCode("Cannot build triangulation on the shape");
2553     return aSeqOfIDs;
2554   }
2555
2556   // Call algo
2557   gp_Pnt aPntTL = BRep_Tool::Pnt(TopoDS::Vertex(aTL));
2558   gp_Pnt aPntTR = BRep_Tool::Pnt(TopoDS::Vertex(aTR));
2559   gp_Pnt aPntBL = BRep_Tool::Pnt(TopoDS::Vertex(aBL));
2560   gp_Pnt aPntBR = BRep_Tool::Pnt(TopoDS::Vertex(aBR));
2561
2562   GEOMAlgo_FinderShapeOnQuad aFinder( aPntTL, aPntTR, aPntBL, aPntBR );
2563   Standard_Real aTol = 0.0001; // default value
2564
2565   aFinder.SetShape(aShape);
2566   aFinder.SetTolerance(aTol);
2567   //aFinder.SetSurface(theSurface);
2568   aFinder.SetShapeType(aShapeType);
2569   aFinder.SetState(theState);
2570
2571   // Sets the minimal number of inner points for the faces that do not have own
2572   // inner points at all (for e.g. rectangular planar faces have just 2 triangles).
2573   // Default value=3
2574   aFinder.SetNbPntsMin(3);
2575   // Sets the maximal number of inner points for edges or faces.
2576   // It is usefull for the cases when this number is very big (e.g =2000) to improve
2577   // the performance. If this value =0, all inner points will be taken into account.
2578   // Default value=0
2579   aFinder.SetNbPntsMax(100);
2580
2581   aFinder.Perform();
2582
2583   // Interprete results
2584   Standard_Integer iErr = aFinder.ErrorStatus();
2585   // the detailed description of error codes is in GEOMAlgo_FinderShapeOn1.cxx
2586   if (iErr) {
2587     MESSAGE(" iErr : " << iErr);
2588     TCollection_AsciiString aMsg (" iErr : ");
2589     aMsg += TCollection_AsciiString(iErr);
2590     SetErrorCode(aMsg);
2591     return aSeqOfIDs;
2592   }
2593   Standard_Integer iWrn = aFinder.WarningStatus();
2594   // the detailed description of warning codes is in GEOMAlgo_FinderShapeOn1.cxx
2595   if (iWrn) {
2596     MESSAGE(" *** iWrn : " << iWrn);
2597   }
2598
2599   const TopTools_ListOfShape& listSS = aFinder.Shapes(); // the result
2600
2601   if (listSS.Extent() < 1) {
2602     //SetErrorCode("Not a single sub-shape of the requested type found on the given surface");
2603     SetErrorCode(NOT_FOUND_ANY); // NPAL18017
2604     return aSeqOfIDs;
2605   }
2606
2607   // Fill sequence of object IDs
2608   aSeqOfIDs = new TColStd_HSequenceOfInteger;
2609
2610   TopTools_IndexedMapOfShape anIndices;
2611   TopExp::MapShapes(aShape, anIndices);
2612
2613   TopTools_ListIteratorOfListOfShape itSub (listSS);
2614   for (int index = 1; itSub.More(); itSub.Next(), ++index) {
2615     int id = anIndices.FindIndex(itSub.Value());
2616     aSeqOfIDs->Append(id);
2617   }
2618   return aSeqOfIDs;
2619 }
2620
2621 //=======================================================================
2622 //function : GetShapesOnQuadrangle
2623   /*!
2624    * \brief Find subshapes complying with given status about quadrangle
2625     * \param theShape - the shape to explore
2626     * \param theShapeType - type of subshape of theShape
2627     * \param theTopLeftPoint - top left quadrangle corner
2628     * \param theTopRigthPoint - top right quadrangle corner
2629     * \param theBottomLeftPoint - bottom left quadrangle corner
2630     * \param theBottomRigthPoint - bottom right quadrangle corner
2631     * \param theState - required state
2632     * \retval Handle(TColStd_HSequenceOfInteger) - IDs of found subshapes
2633    */
2634 //=======================================================================
2635 Handle(TColStd_HSequenceOfTransient)
2636     GEOMImpl_IShapesOperations::GetShapesOnQuadrangle (const Handle(GEOM_Object)& theShape,
2637                                                        const Standard_Integer     theShapeType,
2638                                                        const Handle(GEOM_Object)& theTopLeftPoint,
2639                                                        const Handle(GEOM_Object)& theTopRigthPoint,
2640                                                        const Handle(GEOM_Object)& theBottomLeftPoint,
2641                                                        const Handle(GEOM_Object)& theBottomRigthPoint,
2642                                                        const GEOMAlgo_State       theState)
2643 {
2644   // Find indices
2645   Handle(TColStd_HSequenceOfInteger) aSeqOfIDs =
2646     getShapesOnQuadrangleIDs( theShape,
2647                               theShapeType,
2648                               theTopLeftPoint,
2649                               theTopRigthPoint,
2650                               theBottomLeftPoint,
2651                               theBottomRigthPoint,
2652                               theState);
2653   if ( aSeqOfIDs.IsNull() || aSeqOfIDs->IsEmpty() )
2654     return NULL;
2655
2656   // Find objects by indices
2657   TCollection_AsciiString anAsciiList;
2658   Handle(TColStd_HSequenceOfTransient) aSeq;
2659   aSeq = getObjectsShapesOn( theShape, aSeqOfIDs, anAsciiList );
2660   if ( aSeq.IsNull() || aSeq->IsEmpty() )
2661     return NULL;
2662
2663   // Make a Python command
2664
2665   Handle(GEOM_Object) anObj = Handle(GEOM_Object)::DownCast( aSeq->Value( 1 ));
2666   Handle(GEOM_Function) aFunction = anObj->GetLastFunction();
2667
2668   GEOM::TPythonDump(aFunction)
2669     << "[" << anAsciiList.ToCString() << "] = geompy.GetShapesOnQuadrangle("
2670     << theShape << ", "
2671     << TopAbs_ShapeEnum(theShapeType) << ", "
2672     << theTopLeftPoint << ", "
2673     << theTopRigthPoint << ", "
2674     << theBottomLeftPoint << ", "
2675     << theBottomRigthPoint << ", "
2676     << theState << ")";
2677
2678   SetErrorCode(OK);
2679   return aSeq;
2680 }
2681
2682 //=======================================================================
2683 //function : GetShapesOnQuadrangleIDs
2684   /*!
2685    * \brief Find IDs of subshapes complying with given status about quadrangle
2686     * \param theShape - the shape to explore
2687     * \param theShapeType - type of subshape of theShape
2688     * \param theTopLeftPoint - top left quadrangle corner
2689     * \param theTopRigthPoint - top right quadrangle corner
2690     * \param theBottomLeftPoint - bottom left quadrangle corner
2691     * \param theBottomRigthPoint - bottom right quadrangle corner
2692     * \param theState - required state
2693     * \retval Handle(TColStd_HSequenceOfInteger) - IDs of found subshapes
2694    */
2695 //=======================================================================
2696 Handle(TColStd_HSequenceOfInteger)
2697   GEOMImpl_IShapesOperations::GetShapesOnQuadrangleIDs (const Handle(GEOM_Object)& theShape,
2698                                                         const Standard_Integer     theShapeType,
2699                                                         const Handle(GEOM_Object)& theTopLeftPoint,
2700                                                         const Handle(GEOM_Object)& theTopRigthPoint,
2701                                                         const Handle(GEOM_Object)& theBottomLeftPoint,
2702                                                         const Handle(GEOM_Object)& theBottomRigthPoint,
2703                                                         const GEOMAlgo_State       theState)
2704 {
2705   // Find indices
2706   Handle(TColStd_HSequenceOfInteger) aSeqOfIDs =
2707     getShapesOnQuadrangleIDs( theShape,
2708                               theShapeType,
2709                               theTopLeftPoint,
2710                               theTopRigthPoint,
2711                               theBottomLeftPoint,
2712                               theBottomRigthPoint,
2713                               theState);
2714   if ( aSeqOfIDs.IsNull() || aSeqOfIDs->IsEmpty() )
2715     return NULL;
2716
2717   // Make a Python command
2718
2719   // The GetShapesOnCylinder() doesn't change object so no new function is required.
2720   Handle(GEOM_Object) lastObj = GEOM::GetCreatedLast(theShape,theTopLeftPoint);
2721   lastObj = GEOM::GetCreatedLast(lastObj,theTopRigthPoint);
2722   lastObj = GEOM::GetCreatedLast(lastObj,theBottomRigthPoint);
2723   lastObj = GEOM::GetCreatedLast(lastObj,theBottomLeftPoint);
2724   Handle(GEOM_Function) aFunction = lastObj->GetLastFunction();
2725
2726   GEOM::TPythonDump(aFunction, /*append=*/true)
2727     << "listShapesOnQuadrangle = geompy.GetShapesOnQuadrangleIDs("
2728     << theShape << ", "
2729     << TopAbs_ShapeEnum(theShapeType) << ", "
2730     << theTopLeftPoint << ", "
2731     << theTopRigthPoint << ", "
2732     << theBottomLeftPoint << ", "
2733     << theBottomRigthPoint << ", "
2734     << theState << ")";
2735
2736   SetErrorCode(OK);
2737   return aSeqOfIDs;
2738 }
2739
2740 //=============================================================================
2741 /*!
2742  *  GetInPlaceOfShape
2743  */
2744 //=============================================================================
2745 static bool GetInPlaceOfShape (const Handle(GEOM_Function)& theWhereFunction,
2746                                const TopTools_IndexedMapOfShape& theWhereIndices,
2747                                const TopoDS_Shape& theWhat,
2748                                TColStd_ListOfInteger& theModifiedList)
2749 {
2750   if (theWhereFunction.IsNull() || theWhat.IsNull()) return false;
2751
2752   if (theWhereIndices.Contains(theWhat)) {
2753     // entity was not changed by the operation
2754     Standard_Integer aWhatIndex = theWhereIndices.FindIndex(theWhat);
2755     theModifiedList.Append(aWhatIndex);
2756     return true;
2757   }
2758
2759   // try to find in history
2760   TDF_Label aHistoryLabel = theWhereFunction->GetHistoryEntry(Standard_False);
2761
2762   // search in history for all argument shapes
2763   Standard_Boolean isFound = Standard_False;
2764   Standard_Boolean isGood = Standard_False;
2765
2766   TDF_LabelSequence aLabelSeq;
2767   theWhereFunction->GetDependency(aLabelSeq);
2768   Standard_Integer nbArg = aLabelSeq.Length();
2769
2770   for (Standard_Integer iarg = 1; iarg <= nbArg && !isFound; iarg++) {
2771
2772     TDF_Label anArgumentRefLabel = aLabelSeq.Value(iarg);
2773
2774     Handle(GEOM_Object) anArgumentObject = GEOM_Object::GetReferencedObject(anArgumentRefLabel);
2775     TopoDS_Shape anArgumentShape = anArgumentObject->GetValue();
2776
2777     TopTools_IndexedMapOfShape anArgumentIndices;
2778     TopExp::MapShapes(anArgumentShape, anArgumentIndices);
2779
2780     if (anArgumentIndices.Contains(theWhat)) {
2781       isFound = Standard_True;
2782       Standard_Integer aWhatIndex = anArgumentIndices.FindIndex(theWhat);
2783
2784       // Find corresponding label in history
2785       TDF_Label anArgumentHistoryLabel =
2786         theWhereFunction->GetArgumentHistoryEntry(anArgumentRefLabel, Standard_False);
2787       if (anArgumentHistoryLabel.IsNull()) {
2788         // Lost History of operation argument. Possibly, all its entities was removed.
2789         isGood = Standard_True;
2790       }
2791       else {
2792         TDF_Label aWhatHistoryLabel = anArgumentHistoryLabel.FindChild(aWhatIndex, Standard_False);
2793
2794         if (aWhatHistoryLabel.IsNull()) {
2795           // Removed entity ? Compound ? Compsolid ? Shell ? Wire
2796           isGood = Standard_False;
2797         } else {
2798           Handle(TDataStd_IntegerArray) anIntegerArray;
2799           if (!aWhatHistoryLabel.FindAttribute(TDataStd_IntegerArray::GetID(), anIntegerArray)) {
2800             //Error: Empty modifications history for the sought shape.
2801             isGood = Standard_False;
2802           }
2803           else {
2804             isGood = Standard_True;
2805             Standard_Integer imod, aModifLen = anIntegerArray->Array()->Length();
2806             for (imod = 1; imod <= aModifLen; imod++) {
2807               theModifiedList.Append(anIntegerArray->Array()->Value(imod));
2808             }
2809           }
2810         }
2811       }
2812     }
2813   }
2814
2815   isFound = isGood;
2816
2817   if (!isFound) {
2818     // try compound/compsolid/shell/wire element by element
2819     bool isFoundAny = false;
2820     TopTools_MapOfShape mapShape;
2821
2822     if (theWhat.ShapeType() == TopAbs_COMPOUND ||
2823         theWhat.ShapeType() == TopAbs_COMPSOLID) {
2824       // recursive processing of compound/compsolid
2825       TopoDS_Iterator anIt (theWhat, Standard_True, Standard_True);
2826       for (; anIt.More(); anIt.Next()) {
2827         if (mapShape.Add(anIt.Value())) {
2828           TopoDS_Shape curWhat = anIt.Value();
2829           isFoundAny = GetInPlaceOfShape(theWhereFunction, theWhereIndices, curWhat, theModifiedList);
2830           if (isFoundAny) isFound = Standard_True;
2831         }
2832       }
2833     }
2834     else if (theWhat.ShapeType() == TopAbs_SHELL) {
2835       // try to replace a shell by its faces images
2836       TopExp_Explorer anExp (theWhat, TopAbs_FACE);
2837       for (; anExp.More(); anExp.Next()) {
2838         if (mapShape.Add(anExp.Current())) {
2839           TopoDS_Shape curWhat = anExp.Current();
2840           isFoundAny = GetInPlaceOfShape(theWhereFunction, theWhereIndices, curWhat, theModifiedList);
2841           if (isFoundAny) isFound = Standard_True;
2842         }
2843       }
2844     }
2845     else if (theWhat.ShapeType() == TopAbs_WIRE) {
2846       // try to replace a wire by its edges images
2847       TopExp_Explorer anExp (theWhat, TopAbs_EDGE);
2848       for (; anExp.More(); anExp.Next()) {
2849         if (mapShape.Add(anExp.Current())) {
2850           TopoDS_Shape curWhat = anExp.Current();
2851           isFoundAny = GetInPlaceOfShape(theWhereFunction, theWhereIndices, curWhat, theModifiedList);
2852           if (isFoundAny) isFound = Standard_True;
2853         }
2854       }
2855     }
2856     else {
2857       // Removed entity
2858     }
2859   }
2860
2861   return isFound;
2862 }
2863
2864 //=============================================================================
2865 /*!
2866  *  GetShapeProperties
2867  */
2868 //=============================================================================
2869 void GEOMImpl_IShapesOperations::GetShapeProperties( const TopoDS_Shape aShape, Standard_Real tab[],
2870                                                      gp_Pnt & aVertex )
2871 {
2872   GProp_GProps theProps;
2873   gp_Pnt aCenterMass;
2874   //TopoDS_Shape aPntShape;
2875   Standard_Real aShapeSize;
2876
2877   if      (aShape.ShapeType() == TopAbs_EDGE) BRepGProp::LinearProperties(aShape,  theProps);
2878   else if (aShape.ShapeType() == TopAbs_FACE) BRepGProp::SurfaceProperties(aShape, theProps);
2879   else                                        BRepGProp::VolumeProperties(aShape,  theProps);
2880
2881   aCenterMass = theProps.CentreOfMass();
2882   aShapeSize  = theProps.Mass();
2883
2884 //   aPntShape = BRepBuilderAPI_MakeVertex(aCenterMass).Shape();
2885 //   aVertex   = BRep_Tool::Pnt( TopoDS::Vertex( aPntShape ) );
2886   aVertex = aCenterMass;
2887   tab[0] = aVertex.X();
2888   tab[1] = aVertex.Y();
2889   tab[2] = aVertex.Z();
2890   tab[3] = aShapeSize;
2891   return;
2892 }
2893
2894 namespace {
2895
2896   //================================================================================
2897   /*!
2898    * \brief Return normal to face at extrema point
2899    */
2900   //================================================================================
2901
2902   gp_Vec GetNormal(const TopoDS_Face& face, const BRepExtrema_DistShapeShape& extrema)
2903   {
2904     gp_Vec defaultNorm(1,0,0); // to have same normals on different faces
2905     try {
2906       // get UV at extrema point
2907       Standard_Real u,v, f,l;
2908       switch ( extrema.SupportTypeShape2(1) ) {
2909       case BRepExtrema_IsInFace: {
2910         extrema.ParOnFaceS2(1, u, v );
2911         break;
2912       }
2913       case BRepExtrema_IsOnEdge: {
2914         TopoDS_Edge edge = TopoDS::Edge( extrema.SupportOnShape2(1));
2915         Handle(Geom2d_Curve) pcurve = BRep_Tool::CurveOnSurface( edge, face, f,l );
2916         extrema.ParOnEdgeS2( 1, u );
2917         gp_Pnt2d uv = pcurve->Value( u );
2918         u = uv.Coord(1);
2919         v = uv.Coord(2);
2920         break;
2921       }
2922       case BRepExtrema_IsVertex: return defaultNorm;
2923       }
2924       // get derivatives
2925       BRepAdaptor_Surface surface( face, false );
2926       gp_Vec du, dv; gp_Pnt p;
2927       surface.D1( u, v, p, du, dv );
2928
2929       return du ^ dv;
2930
2931     } catch (Standard_Failure ) {
2932     }
2933     return defaultNorm;
2934   }
2935 }
2936
2937 //=============================================================================
2938 /*!
2939     case GetInPlace:
2940     default:
2941  */
2942 //=============================================================================
2943 Handle(GEOM_Object) GEOMImpl_IShapesOperations::GetInPlace (Handle(GEOM_Object) theShapeWhere,
2944                                                             Handle(GEOM_Object) theShapeWhat)
2945 {
2946   SetErrorCode(KO);
2947
2948   if (theShapeWhere.IsNull() || theShapeWhat.IsNull()) return NULL;
2949
2950   TopoDS_Shape aWhere = theShapeWhere->GetValue();
2951   TopoDS_Shape aWhat  = theShapeWhat->GetValue();
2952   TopoDS_Shape aPntShape;
2953   TopoDS_Vertex aVertex;
2954
2955   if (aWhere.IsNull() || aWhat.IsNull()) {
2956     SetErrorCode("Error: aWhere and aWhat TopoDS_Shape are Null.");
2957     return NULL;
2958   }
2959
2960   Handle(GEOM_Function) aWhereFunction = theShapeWhere->GetLastFunction();
2961   if (aWhereFunction.IsNull()) {
2962     SetErrorCode("Error: aWhereFunction is Null.");
2963     return NULL;
2964   }
2965
2966   TopTools_IndexedMapOfShape aWhereIndices;
2967   TopExp::MapShapes(aWhere, aWhereIndices);
2968
2969   TColStd_ListOfInteger aModifiedList;
2970   Standard_Integer aWhereIndex;
2971   Handle(TColStd_HArray1OfInteger) aModifiedArray;
2972   Handle(GEOM_Object) aResult;
2973
2974   bool isFound = false;
2975   Standard_Integer iType = TopAbs_SOLID;
2976   Standard_Integer compType = TopAbs_SOLID;
2977   Standard_Real    aWhat_Mass = 0., aWhere_Mass = 0.;
2978   Standard_Real    tab_aWhat[4],    tab_aWhere[4];
2979   Standard_Real    dl_l = 1e-3;
2980   Standard_Real    min_l, Tol_1D, Tol_2D, Tol_3D, Tol_Mass;
2981   Standard_Real    aXmin, aYmin, aZmin, aXmax, aYmax, aZmax;
2982   Bnd_Box          BoundingBox;
2983   gp_Pnt           aPnt, aPnt_aWhat, tab_Pnt[2];
2984   GProp_GProps     aProps;
2985
2986   // Find the iType of the aWhat shape
2987   if      ( aWhat.ShapeType() == TopAbs_EDGE  || aWhat.ShapeType() == TopAbs_WIRE )      iType = TopAbs_EDGE;
2988   else if ( aWhat.ShapeType() == TopAbs_FACE  || aWhat.ShapeType() == TopAbs_SHELL )     iType = TopAbs_FACE;
2989   else if ( aWhat.ShapeType() == TopAbs_SOLID || aWhat.ShapeType() == TopAbs_COMPSOLID ) iType = TopAbs_SOLID;
2990   else if ( aWhat.ShapeType() == TopAbs_COMPOUND ) {
2991     // Only the iType of the first shape in the compound is taken into account
2992     TopoDS_Iterator It (aWhat, Standard_False, Standard_False);
2993     if ( !It.More() ) {
2994       SetErrorCode("Error: theShapeWhat is an empty COMPOUND.");
2995       return NULL;
2996     }
2997     compType = It.Value().ShapeType();
2998     if      ( compType == TopAbs_EDGE  || compType == TopAbs_WIRE )     iType = TopAbs_EDGE;
2999     else if ( compType == TopAbs_FACE  || compType == TopAbs_SHELL)     iType = TopAbs_FACE;
3000     else if ( compType == TopAbs_SOLID || compType == TopAbs_COMPSOLID) iType = TopAbs_SOLID;
3001   }
3002   else {
3003     SetErrorCode("Error: An attempt to extract a shape of not supported type.");
3004     return NULL;
3005   }
3006
3007   TopExp_Explorer Exp_aWhat( aWhat,   TopAbs_ShapeEnum( iType ) );
3008   TopExp_Explorer Exp_aWhere( aWhere, TopAbs_ShapeEnum( iType ) );
3009   TopExp_Explorer Exp_Edge( aWhere,   TopAbs_EDGE );
3010
3011   // Find the shortest edge in theShapeWhere shape
3012   BRepBndLib::Add(aWhere, BoundingBox);
3013   BoundingBox.Get(aXmin, aYmin, aZmin, aXmax, aYmax, aZmax);
3014   min_l = fabs(aXmax - aXmin);
3015   if( min_l < fabs(aYmax - aYmin) ) min_l = fabs(aYmax - aYmin);
3016   if( min_l < fabs(aZmax - aZmin) ) min_l = fabs(aZmax - aZmin);
3017   min_l /= dl_l;
3018   for ( Standard_Integer nbEdge = 0; Exp_Edge.More(); Exp_Edge.Next(), nbEdge++ ) {
3019     TopExp_Explorer Exp_Vertex( Exp_Edge.Current(), TopAbs_VERTEX);
3020     for ( Standard_Integer nbVertex = 0; Exp_Vertex.More(); Exp_Vertex.Next(), nbVertex++ ) {
3021       aPnt = BRep_Tool::Pnt( TopoDS::Vertex( Exp_Vertex.Current() ) );
3022       tab_Pnt[nbVertex] = aPnt;
3023     }
3024     if ( ! tab_Pnt[0].IsEqual(tab_Pnt[1], dl_l) ) {
3025       BRepGProp::LinearProperties(Exp_Edge.Current(), aProps);
3026       if ( aProps.Mass() < min_l ) min_l = aProps.Mass();
3027     }
3028   }
3029
3030   // Compute tolerances
3031   Tol_1D = dl_l * min_l;
3032   Tol_2D = dl_l * ( min_l * min_l) * ( 2. + dl_l);
3033   Tol_3D = dl_l * ( min_l * min_l * min_l ) * ( 3. + (3 * dl_l) + (dl_l * dl_l) );
3034
3035   if (Tol_1D < Precision::Confusion()) Tol_1D = Precision::Confusion();
3036   if (Tol_2D < Precision::Confusion()) Tol_2D = Precision::Confusion();
3037   if (Tol_3D < Precision::Confusion()) Tol_3D = Precision::Confusion();
3038
3039   Tol_Mass = Tol_3D;
3040   if      ( iType == TopAbs_EDGE ) Tol_Mass = Tol_1D;
3041   else if ( iType == TopAbs_FACE ) Tol_Mass = Tol_2D;
3042
3043   // Compute the ShapeWhat Mass
3044   for ( ; Exp_aWhat.More(); Exp_aWhat.Next() ) {
3045     if      ( iType == TopAbs_EDGE ) BRepGProp::LinearProperties(Exp_aWhat.Current(),  aProps);
3046     else if ( iType == TopAbs_FACE ) BRepGProp::SurfaceProperties(Exp_aWhat.Current(), aProps);
3047     else                             BRepGProp::VolumeProperties(Exp_aWhat.Current(),  aProps);
3048     aWhat_Mass += aProps.Mass();
3049   }
3050
3051   // Searching for the sub-shapes inside the ShapeWhere shape
3052   TopTools_MapOfShape map_aWhere;
3053   for ( Exp_aWhere.ReInit(); Exp_aWhere.More(); Exp_aWhere.Next() ) {
3054     if (!map_aWhere.Add(Exp_aWhere.Current()))
3055       continue; // skip repeated shape to avoid mass addition
3056     GetShapeProperties( Exp_aWhere.Current(), tab_aWhere, aPnt );
3057     for ( Exp_aWhat.ReInit(); Exp_aWhat.More(); Exp_aWhat.Next() ) {
3058       GetShapeProperties( Exp_aWhat.Current(), tab_aWhat, aPnt_aWhat );
3059       if ( fabs(tab_aWhat[3] - tab_aWhere[3]) <= Tol_Mass && aPnt_aWhat.Distance(aPnt) <= Tol_1D )
3060         isFound = true;
3061       else {
3062         if ( (tab_aWhat[3] - tab_aWhere[3]) > Tol_Mass ) {
3063           aPntShape = BRepBuilderAPI_MakeVertex( aPnt ).Shape();
3064           aVertex   = TopoDS::Vertex( aPntShape );
3065           BRepExtrema_DistShapeShape aWhereDistance ( aVertex, Exp_aWhere.Current() );
3066           BRepExtrema_DistShapeShape aWhatDistance  ( aVertex, Exp_aWhat.Current() );
3067           if ( aWhereDistance.IsDone() && aWhatDistance.IsDone() &&
3068                fabs(aWhereDistance.Value() - aWhatDistance.Value()) <= Tol_1D )
3069           {
3070             // 0020162: "EDF 961 GEOM : Getinplace is getting additionnal orthogonal faces"
3071             // aVertex must be projected to the same point on Where and on What
3072             gp_Pnt pOnWhat  = aWhatDistance.PointOnShape2(1);
3073             gp_Pnt pOnWhere = aWhereDistance.PointOnShape2(1);
3074             isFound = ( pOnWhat.Distance(pOnWhere) <= Tol_1D );
3075             if ( isFound && iType == TopAbs_FACE )
3076             {
3077               // check normals at pOnWhat and pOnWhere
3078               const double angleTol = PI/180.;
3079               gp_Vec normToWhat  = GetNormal( TopoDS::Face(Exp_aWhat.Current()), aWhatDistance);
3080               gp_Vec normToWhere = GetNormal( TopoDS::Face(Exp_aWhere.Current()), aWhereDistance);
3081               if ( normToWhat * normToWhere < 0 )
3082                 normToWhat.Reverse();
3083               isFound = ( normToWhat.Angle( normToWhere ) < angleTol );
3084             }
3085           }
3086         }
3087       }
3088       if ( isFound ) {
3089         aWhereIndex = aWhereIndices.FindIndex(Exp_aWhere.Current());
3090         aModifiedList.Append(aWhereIndex);
3091         aWhere_Mass += tab_aWhere[3];
3092         isFound = false;
3093         break;
3094       }
3095     }
3096     if ( fabs( aWhat_Mass - aWhere_Mass ) <= Tol_Mass ) break;
3097   }
3098
3099   if (aModifiedList.Extent() == 0) { // Not found any Results
3100     SetErrorCode(NOT_FOUND_ANY);
3101     return NULL;
3102   }
3103
3104   aModifiedArray = new TColStd_HArray1OfInteger (1, aModifiedList.Extent());
3105   TColStd_ListIteratorOfListOfInteger anIterModif (aModifiedList);
3106   for (Standard_Integer imod = 1; anIterModif.More(); anIterModif.Next(), imod++)
3107     aModifiedArray->SetValue(imod, anIterModif.Value());
3108
3109   //Add a new object
3110   aResult = GetEngine()->AddSubShape(theShapeWhere, aModifiedArray);
3111   if (aResult.IsNull()) {
3112     SetErrorCode("Error in algorithm: result found, but cannot be returned.");
3113     return NULL;
3114   }
3115
3116   if (aModifiedArray->Length() > 1) {
3117     //Set a GROUP type
3118     aResult->SetType(GEOM_GROUP);
3119
3120     //Set a sub shape type
3121     TopoDS_Shape aFirstFound = aWhereIndices.FindKey(aModifiedArray->Value(1));
3122     TopAbs_ShapeEnum aShapeType = aFirstFound.ShapeType();
3123
3124     TDF_Label aFreeLabel = aResult->GetFreeLabel();
3125     TDataStd_Integer::Set(aFreeLabel, (Standard_Integer)aShapeType);
3126   }
3127
3128   //Make a Python command
3129   Handle(GEOM_Function) aFunction = aResult->GetFunction(1);
3130
3131   GEOM::TPythonDump(aFunction) << aResult << " = geompy.GetInPlace("
3132     << theShapeWhere << ", " << theShapeWhat << ")";
3133
3134   SetErrorCode(OK);
3135   return aResult;
3136 }
3137
3138 //=======================================================================
3139 //function : GetInPlaceByHistory
3140 //purpose  :
3141 //=======================================================================
3142 Handle(GEOM_Object) GEOMImpl_IShapesOperations::GetInPlaceByHistory
3143                                           (Handle(GEOM_Object) theShapeWhere,
3144                                            Handle(GEOM_Object) theShapeWhat)
3145 {
3146   SetErrorCode(KO);
3147
3148   if (theShapeWhere.IsNull() || theShapeWhat.IsNull()) return NULL;
3149
3150   TopoDS_Shape aWhere = theShapeWhere->GetValue();
3151   TopoDS_Shape aWhat  = theShapeWhat->GetValue();
3152
3153   if (aWhere.IsNull() || aWhat.IsNull()) return NULL;
3154
3155   Handle(GEOM_Function) aWhereFunction = theShapeWhere->GetLastFunction();
3156   if (aWhereFunction.IsNull()) return NULL;
3157
3158   //Fill array of indices
3159   TopTools_IndexedMapOfShape aWhereIndices;
3160   TopExp::MapShapes(aWhere, aWhereIndices);
3161
3162   // process shape
3163   TColStd_ListOfInteger aModifiedList;
3164   bool isFound = GetInPlaceOfShape(aWhereFunction, aWhereIndices, aWhat, aModifiedList);
3165
3166   if (!isFound || aModifiedList.Extent() < 1) {
3167     SetErrorCode("Error: No history found for the sought shape or its sub-shapes.");
3168     return NULL;
3169   }
3170
3171   Handle(TColStd_HArray1OfInteger) aModifiedArray =
3172     new TColStd_HArray1OfInteger (1, aModifiedList.Extent());
3173   TColStd_ListIteratorOfListOfInteger anIterModif (aModifiedList);
3174   for (Standard_Integer imod = 1; anIterModif.More(); anIterModif.Next(), imod++) {
3175     aModifiedArray->SetValue(imod, anIterModif.Value());
3176   }
3177
3178   //Add a new object
3179   Handle(GEOM_Object) aResult = GetEngine()->AddSubShape(theShapeWhere, aModifiedArray);
3180   if (aResult.IsNull()) {
3181     SetErrorCode("Error in algorithm: result found, but cannot be returned.");
3182     return NULL;
3183   }
3184
3185   if (aModifiedArray->Length() > 1) {
3186     //Set a GROUP type
3187     aResult->SetType(GEOM_GROUP);
3188
3189     //Set a sub shape type
3190     TopoDS_Shape aFirstFound = aWhereIndices.FindKey(aModifiedArray->Value(1));
3191     TopAbs_ShapeEnum aShapeType = aFirstFound.ShapeType();
3192
3193     TDF_Label aFreeLabel = aResult->GetFreeLabel();
3194     TDataStd_Integer::Set(aFreeLabel, (Standard_Integer)aShapeType);
3195   }
3196
3197   //Make a Python command
3198   Handle(GEOM_Function) aFunction = aResult->GetFunction(1);
3199
3200   GEOM::TPythonDump(aFunction) << aResult << " = geompy.GetInPlaceByHistory("
3201     << theShapeWhere << ", " << theShapeWhat << ")";
3202
3203   SetErrorCode(OK);
3204   return aResult;
3205 }
3206
3207 //=======================================================================
3208 //function : SortShapes
3209 //purpose  :
3210 //=======================================================================
3211 void GEOMImpl_IShapesOperations::SortShapes(TopTools_ListOfShape& SL)
3212 {
3213   Standard_Integer MaxShapes = SL.Extent();
3214   TopTools_Array1OfShape  aShapes (1,MaxShapes);
3215   TColStd_Array1OfInteger OrderInd(1,MaxShapes);
3216   TColStd_Array1OfReal    MidXYZ  (1,MaxShapes); //X,Y,Z;
3217   TColStd_Array1OfReal    Length  (1,MaxShapes); //X,Y,Z;
3218
3219   // Computing of CentreOfMass
3220   Standard_Integer Index;
3221   GProp_GProps GPr;
3222   gp_Pnt GPoint;
3223   TopTools_ListIteratorOfListOfShape it(SL);
3224   for (Index=1;  it.More();  Index++)
3225   {
3226     TopoDS_Shape S = it.Value();
3227     SL.Remove( it ); // == it.Next()
3228     aShapes(Index) = S;
3229     OrderInd.SetValue (Index, Index);
3230     if (S.ShapeType() == TopAbs_VERTEX)
3231     {
3232       GPoint = BRep_Tool::Pnt( TopoDS::Vertex( S ));
3233       Length.SetValue( Index, (Standard_Real) S.Orientation());
3234     }
3235     else
3236     {
3237       BRepGProp::LinearProperties (S, GPr);
3238       GPoint = GPr.CentreOfMass();
3239       Length.SetValue( Index, GPr.Mass() );
3240     }
3241     MidXYZ.SetValue(Index,
3242                     GPoint.X()*999 + GPoint.Y()*99 + GPoint.Z()*0.9);
3243     //cout << Index << " L: " << Length(Index) << "CG: " << MidXYZ(Index) << endl;
3244   }
3245
3246   // Sorting
3247   Standard_Integer aTemp;
3248   Standard_Boolean exchange, Sort = Standard_True;
3249   Standard_Real    tol = Precision::Confusion();
3250   while (Sort)
3251   {
3252     Sort = Standard_False;
3253     for (Index=1; Index < MaxShapes; Index++)
3254     {
3255       exchange = Standard_False;
3256       Standard_Real dMidXYZ = MidXYZ(OrderInd(Index)) - MidXYZ(OrderInd(Index+1));
3257       Standard_Real dLength = Length(OrderInd(Index)) - Length(OrderInd(Index+1));
3258       if ( dMidXYZ >= tol ) {
3259 //         cout << "MidXYZ: " << MidXYZ(OrderInd(Index))<< " > " <<MidXYZ(OrderInd(Index+1))
3260 //              << " d: " << dMidXYZ << endl;
3261         exchange = Standard_True;
3262       }
3263       else if ( Abs(dMidXYZ) < tol && dLength >= tol ) {
3264 //         cout << "Length: " << Length(OrderInd(Index))<< " > " <<Length(OrderInd(Index+1))
3265 //              << " d: " << dLength << endl;
3266         exchange = Standard_True;
3267       }
3268       else if ( Abs(dMidXYZ) < tol && Abs(dLength) < tol &&
3269                 aShapes(OrderInd(Index)).ShapeType() <= TopAbs_FACE) {
3270         // PAL17233
3271         // equal values possible on shapes such as two halves of a sphere and
3272         // a membrane inside the sphere
3273         Bnd_Box box1,box2;
3274         BRepBndLib::Add( aShapes( OrderInd(Index) ), box1 );
3275         if ( box1.IsVoid() ) continue;
3276         BRepBndLib::Add( aShapes( OrderInd(Index+1) ), box2 );
3277         Standard_Real dSquareExtent = box1.SquareExtent() - box2.SquareExtent();
3278         if ( dSquareExtent >= tol ) {
3279 //           cout << "SquareExtent: " << box1.SquareExtent()<<" > "<<box2.SquareExtent() << endl;
3280           exchange = Standard_True;
3281         }
3282         else if ( Abs(dSquareExtent) < tol ) {
3283           Standard_Real aXmin, aYmin, aZmin, aXmax, aYmax, aZmax, val1, val2;
3284           box1.Get(aXmin, aYmin, aZmin, aXmax, aYmax, aZmax);
3285           val1 = (aXmin+aXmax)*999 + (aYmin+aYmax)*99 + (aZmin+aZmax)*0.9;
3286           box2.Get(aXmin, aYmin, aZmin, aXmax, aYmax, aZmax);
3287           val2 = (aXmin+aXmax)*999 + (aYmin+aYmax)*99 + (aZmin+aZmax)*0.9;
3288           //exchange = val1 > val2;
3289           if ((val1 - val2) >= tol) {
3290             exchange = Standard_True;
3291           }
3292           //cout << "box: " << val1<<" > "<<val2 << endl;
3293         }
3294       }
3295
3296       if (exchange)
3297       {
3298 //         cout << "exchange " << Index << " & " << Index+1 << endl;
3299         aTemp = OrderInd(Index);
3300         OrderInd(Index) = OrderInd(Index+1);
3301         OrderInd(Index+1) = aTemp;
3302         Sort = Standard_True;
3303       }
3304     }
3305   }
3306
3307   for (Index=1; Index <= MaxShapes; Index++)
3308     SL.Append( aShapes( OrderInd(Index) ));
3309 }
3310
3311 //=======================================================================
3312 //function : CompsolidToCompound
3313 //purpose  :
3314 //=======================================================================
3315 TopoDS_Shape GEOMImpl_IShapesOperations::CompsolidToCompound (const TopoDS_Shape& theCompsolid)
3316 {
3317   if (theCompsolid.ShapeType() != TopAbs_COMPSOLID) {
3318     return theCompsolid;
3319   }
3320
3321   TopoDS_Compound aCompound;
3322   BRep_Builder B;
3323   B.MakeCompound(aCompound);
3324
3325   TopTools_MapOfShape mapShape;
3326   TopoDS_Iterator It (theCompsolid, Standard_True, Standard_True);
3327
3328   for (; It.More(); It.Next()) {
3329     TopoDS_Shape aShape_i = It.Value();
3330     if (mapShape.Add(aShape_i)) {
3331       B.Add(aCompound, aShape_i);
3332     }
3333   }
3334
3335   return aCompound;
3336 }
3337
3338 //=======================================================================
3339 //function : CheckTriangulation
3340 //purpose  :
3341 //=======================================================================
3342 bool GEOMImpl_IShapesOperations::CheckTriangulation (const TopoDS_Shape& aShape)
3343 {
3344   bool isTriangulation = true;
3345
3346   TopExp_Explorer exp (aShape, TopAbs_FACE);
3347   if (exp.More())
3348   {
3349     TopLoc_Location aTopLoc;
3350     Handle(Poly_Triangulation) aTRF;
3351     aTRF = BRep_Tool::Triangulation(TopoDS::Face(exp.Current()), aTopLoc);
3352     if (aTRF.IsNull()) {
3353       isTriangulation = false;
3354     }
3355   }
3356   else // no faces, try edges
3357   {
3358     TopExp_Explorer expe (aShape, TopAbs_EDGE);
3359     if (!expe.More()) {
3360       return false;
3361     }
3362     TopLoc_Location aLoc;
3363     Handle(Poly_Polygon3D) aPE = BRep_Tool::Polygon3D(TopoDS::Edge(expe.Current()), aLoc);
3364     if (aPE.IsNull()) {
3365       isTriangulation = false;
3366     }
3367   }
3368
3369   if (!isTriangulation) {
3370     // calculate deflection
3371     Standard_Real aDeviationCoefficient = 0.001;
3372
3373     Bnd_Box B;
3374     BRepBndLib::Add(aShape, B);
3375     Standard_Real aXmin, aYmin, aZmin, aXmax, aYmax, aZmax;
3376     B.Get(aXmin, aYmin, aZmin, aXmax, aYmax, aZmax);
3377
3378     Standard_Real dx = aXmax - aXmin, dy = aYmax - aYmin, dz = aZmax - aZmin;
3379     Standard_Real aDeflection = Max(Max(dx, dy), dz) * aDeviationCoefficient * 4;
3380     Standard_Real aHLRAngle = 0.349066;
3381
3382     BRepMesh_IncrementalMesh Inc (aShape, aDeflection, Standard_False, aHLRAngle);
3383   }
3384
3385   return true;
3386 }
3387
3388 #define MAX_TOLERANCE 1.e-7
3389
3390 //=======================================================================
3391 //function : isSameEdge
3392 //purpose  : Returns True if two edges coincide
3393 //=======================================================================
3394 static bool isSameEdge(const TopoDS_Edge& theEdge1, const TopoDS_Edge& theEdge2)
3395 {
3396   TopoDS_Vertex V11, V12, V21, V22;
3397   TopExp::Vertices(theEdge1, V11, V12);
3398   TopExp::Vertices(theEdge2, V21, V22);
3399   gp_Pnt P11 = BRep_Tool::Pnt(V11);
3400   gp_Pnt P12 = BRep_Tool::Pnt(V12);
3401   gp_Pnt P21 = BRep_Tool::Pnt(V21);
3402   gp_Pnt P22 = BRep_Tool::Pnt(V22);
3403   bool coincide = false;
3404
3405   //Check that ends of edges coincide
3406   if(P11.Distance(P21) <= MAX_TOLERANCE) {
3407     if(P12.Distance(P22) <= MAX_TOLERANCE) coincide =  true;
3408   }
3409   else if(P11.Distance(P22) <= MAX_TOLERANCE) {
3410     if(P12.Distance(P21) <= MAX_TOLERANCE) coincide = true;
3411   }
3412
3413   if(!coincide) return false;
3414
3415   if (BRep_Tool::Degenerated(theEdge1))
3416     if (BRep_Tool::Degenerated(theEdge2)) return true;
3417     else return false;
3418   else
3419     if (BRep_Tool::Degenerated(theEdge2)) return false;
3420
3421   double U11, U12, U21, U22;
3422   Handle(Geom_Curve) C1 = BRep_Tool::Curve(theEdge1, U11, U12);
3423   Handle(Geom_Curve) C2 = BRep_Tool::Curve(theEdge2, U21, U22);
3424   if(C1->DynamicType() == C2->DynamicType()) return true;
3425
3426   //Check that both edges has the same geometry
3427   double range = U12-U11;
3428   double U = U11+ range/3.0;
3429   gp_Pnt P1 = C1->Value(U);     //Compute a point on one third of the edge's length
3430   U = U11+range*2.0/3.0;
3431   gp_Pnt P2 = C1->Value(U);     //Compute a point on two thirds of the edge's length
3432
3433   if(!GeomLib_Tool::Parameter(C2, P1, MAX_TOLERANCE, U) ||  U < U21 || U > U22)
3434     return false;
3435
3436   if(P1.Distance(C2->Value(U)) > MAX_TOLERANCE) return false;
3437
3438   if(!GeomLib_Tool::Parameter(C2, P2, MAX_TOLERANCE, U) || U < U21 || U > U22)
3439     return false;
3440
3441   if(P2.Distance(C2->Value(U)) > MAX_TOLERANCE) return false;
3442
3443   return true;
3444 }
3445
3446 #include <TopoDS_TShape.hxx>
3447 //=======================================================================
3448 //function : isSameFace
3449 //purpose  : Returns True if two faces coincide
3450 //=======================================================================
3451 static bool isSameFace(const TopoDS_Face& theFace1, const TopoDS_Face& theFace2)
3452 {
3453   TopExp_Explorer E(theFace1, TopAbs_EDGE);
3454   TopTools_ListOfShape LS1, LS2;
3455   for(; E.More(); E.Next()) LS1.Append(E.Current());
3456
3457   E.Init(theFace2, TopAbs_EDGE);
3458   for(; E.More(); E.Next()) LS2.Append(E.Current());
3459
3460   //Compare the number of edges in the faces
3461   if(LS1.Extent() != LS2.Extent()) return false;
3462
3463   double aMin = RealFirst(), aMax = RealLast();
3464   double xminB1=aMax, yminB1=aMax, zminB1=aMax, xminB2=aMax, yminB2=aMax, zminB2=aMax;
3465   double xmaxB1=aMin, ymaxB1=aMin, zmaxB1=aMin, xmaxB2=aMin, ymaxB2=aMin, zmaxB2=aMin;
3466
3467   for(E.Init(theFace1, TopAbs_VERTEX); E.More(); E.Next()) {
3468     gp_Pnt P = BRep_Tool::Pnt(TopoDS::Vertex(E.Current()));
3469     if(P.X() < xminB1) xminB1 = P.X();
3470     if(P.Y() < yminB1) yminB1 = P.Y();
3471     if(P.Z() < zminB1) zminB1 = P.Z();
3472     if(P.X() > xmaxB1) xmaxB1 = P.X();
3473     if(P.Y() > ymaxB1) ymaxB1 = P.Y();
3474     if(P.Z() > zmaxB1) zmaxB1 = P.Z();
3475   }
3476
3477   for(E.Init(theFace2, TopAbs_VERTEX); E.More(); E.Next()) {
3478     gp_Pnt P = BRep_Tool::Pnt(TopoDS::Vertex(E.Current()));
3479     if(P.X() < xminB2) xminB2 = P.X();
3480     if(P.Y() < yminB2) yminB2 = P.Y();
3481     if(P.Z() < zminB2) zminB2 = P.Z();
3482     if(P.X() > xmaxB2) xmaxB2 = P.X();
3483     if(P.Y() > ymaxB2) ymaxB2 = P.Y();
3484     if(P.Z() > zmaxB2) zmaxB2 = P.Z();
3485   }
3486
3487   //Compare the bounding boxes of both faces
3488   if(gp_Pnt(xminB1, yminB1, zminB1).Distance(gp_Pnt(xminB2, yminB2, zminB2)) > MAX_TOLERANCE)
3489     return false;
3490
3491   if(gp_Pnt(xmaxB1, ymaxB1, zmaxB1).Distance(gp_Pnt(xmaxB2, ymaxB2, zmaxB2)) > MAX_TOLERANCE)
3492     return false;
3493
3494   Handle(Geom_Surface) S1 = BRep_Tool::Surface(theFace1);
3495   Handle(Geom_Surface) S2 = BRep_Tool::Surface(theFace2);
3496
3497   //Check if there a coincidence of two surfaces at least in two points
3498   double U11, U12, V11, V12, U21, U22, V21, V22;
3499   BRepTools::UVBounds(theFace1, U11, U12, V11, V12);
3500   BRepTools::UVBounds(theFace2, U21, U22, V21, V22);
3501
3502   double rangeU = U12-U11;
3503   double rangeV = V12-V11;
3504   double U = U11 + rangeU/3.0;
3505   double V = V11 + rangeV/3.0;
3506   gp_Pnt P1 = S1->Value(U, V);
3507   U = U11+rangeU*2.0/3.0;
3508   V = V11+rangeV*2.0/3.0;
3509   gp_Pnt P2 = S1->Value(U, V);
3510
3511   if (!GeomLib_Tool::Parameters(S2, P1, MAX_TOLERANCE, U, V) || U < U21 || U > U22 || V < V21 || V > V22)
3512     return false;
3513
3514   if (P1.Distance(S2->Value(U,V)) > MAX_TOLERANCE) return false;
3515
3516   if (!GeomLib_Tool::Parameters(S2, P2, MAX_TOLERANCE, U, V) || U < U21 || U > U22 || V < V21 || V > V22)
3517     return false;
3518
3519   if (P2.Distance(S2->Value(U, V)) > MAX_TOLERANCE) return false;
3520
3521   //Check that each edge of the Face1 has a counterpart in the Face2
3522   TopTools_MapOfOrientedShape aMap;
3523   TopTools_ListIteratorOfListOfShape LSI1(LS1);
3524   for(; LSI1.More(); LSI1.Next()) {
3525     TopoDS_Edge E = TopoDS::Edge(LSI1.Value());
3526     bool isFound = false;
3527     TopTools_ListIteratorOfListOfShape LSI2(LS2);
3528     for(; LSI2.More(); LSI2.Next()) {
3529       TopoDS_Shape aValue = LSI2.Value();
3530       if(aMap.Contains(aValue)) continue; //To avoid checking already found edge several times
3531       if(isSameEdge(E, TopoDS::Edge(aValue))) {
3532         aMap.Add(aValue);
3533         isFound = true;
3534         break;
3535       }
3536     }
3537     if(!isFound) return false;
3538   }
3539
3540   return true;
3541 }
3542
3543 //=======================================================================
3544 //function : isSameSolid
3545 //purpose  : Returns True if two solids coincide
3546 //=======================================================================
3547 bool isSameSolid(const TopoDS_Solid& theSolid1, const TopoDS_Solid& theSolid2)
3548 {
3549   TopExp_Explorer E(theSolid1, TopAbs_FACE);
3550   TopTools_ListOfShape LS1, LS2;
3551   for(; E.More(); E.Next()) LS1.Append(E.Current());
3552   E.Init(theSolid2, TopAbs_FACE);
3553   for(; E.More(); E.Next()) LS2.Append(E.Current());
3554
3555   if(LS1.Extent() != LS2.Extent()) return false;
3556
3557   double aMin = RealFirst(), aMax = RealLast();
3558   double xminB1=aMax, yminB1=aMax, zminB1=aMax, xminB2=aMax, yminB2=aMax, zminB2=aMax;
3559   double xmaxB1=aMin, ymaxB1=aMin, zmaxB1=aMin, xmaxB2=aMin, ymaxB2=aMin, zmaxB2=aMin;
3560
3561   for(E.Init(theSolid1, TopAbs_VERTEX); E.More(); E.Next()) {
3562     gp_Pnt P = BRep_Tool::Pnt(TopoDS::Vertex(E.Current()));
3563     if(P.X() < xminB1) xminB1 = P.X();
3564     if(P.Y() < yminB1) yminB1 = P.Y();
3565     if(P.Z() < zminB1) zminB1 = P.Z();
3566     if(P.X() > xmaxB1) xmaxB1 = P.X();
3567     if(P.Y() > ymaxB1) ymaxB1 = P.Y();
3568     if(P.Z() > zmaxB1) zmaxB1 = P.Z();
3569   }
3570
3571   for(E.Init(theSolid2, TopAbs_VERTEX); E.More(); E.Next()) {
3572     gp_Pnt P = BRep_Tool::Pnt(TopoDS::Vertex(E.Current()));
3573     if(P.X() < xminB2) xminB2 = P.X();
3574     if(P.Y() < yminB2) yminB2 = P.Y();
3575     if(P.Z() < zminB2) zminB2 = P.Z();
3576     if(P.X() > xmaxB2) xmaxB2 = P.X();
3577     if(P.Y() > ymaxB2) ymaxB2 = P.Y();
3578     if(P.Z() > zmaxB2) zmaxB2 = P.Z();
3579   }
3580
3581   //Compare the bounding boxes of both solids
3582   if(gp_Pnt(xminB1, yminB1, zminB1).Distance(gp_Pnt(xminB2, yminB2, zminB2)) > MAX_TOLERANCE)
3583     return false;
3584
3585   if(gp_Pnt(xmaxB1, ymaxB1, zmaxB1).Distance(gp_Pnt(xmaxB2, ymaxB2, zmaxB2)) > MAX_TOLERANCE)
3586     return false;
3587
3588   //Check that each face of the Solid1 has a counterpart in the Solid2
3589   TopTools_MapOfOrientedShape aMap;
3590   TopTools_ListIteratorOfListOfShape LSI1(LS1);
3591   for(; LSI1.More(); LSI1.Next()) {
3592     TopoDS_Face F = TopoDS::Face(LSI1.Value());
3593     bool isFound = false;
3594     TopTools_ListIteratorOfListOfShape LSI2(LS2);
3595     for(; LSI2.More(); LSI2.Next()) {
3596       if(aMap.Contains(LSI2.Value())) continue; //To avoid checking already found faces several times
3597       if(isSameFace(F, TopoDS::Face(LSI2.Value()))) {
3598         aMap.Add(LSI2.Value());
3599         isFound = true;
3600         break;
3601       }
3602     }
3603     if(!isFound) return false;
3604   }
3605
3606   return true;
3607 }
3608
3609 //=======================================================================
3610 //function : GetSame
3611 //purpose  :
3612 //=======================================================================
3613 Handle(GEOM_Object) GEOMImpl_IShapesOperations::GetSame(const Handle(GEOM_Object)& theShapeWhere,
3614                                                         const Handle(GEOM_Object)& theShapeWhat)
3615 {
3616   SetErrorCode(KO);
3617   if (theShapeWhere.IsNull() || theShapeWhat.IsNull()) return NULL;
3618
3619   TopoDS_Shape aWhere = theShapeWhere->GetValue();
3620   TopoDS_Shape aWhat  = theShapeWhat->GetValue();
3621
3622   if (aWhere.IsNull() || aWhat.IsNull()) return NULL;
3623
3624   int anIndex = -1;
3625   bool isFound = false;
3626   TopoDS_Shape aSubShape;
3627   TopTools_MapOfShape aMap;
3628
3629   switch(aWhat.ShapeType()) {
3630     case TopAbs_VERTEX: {
3631       gp_Pnt P = BRep_Tool::Pnt(TopoDS::Vertex(aWhat));
3632       TopExp_Explorer E(aWhere, TopAbs_VERTEX);
3633       for(; E.More(); E.Next()) {
3634         if(!aMap.Add(E.Current())) continue;
3635         gp_Pnt P2 = BRep_Tool::Pnt(TopoDS::Vertex(E.Current()));
3636         if(P.Distance(P2) <= MAX_TOLERANCE) {
3637           isFound = true;
3638           aSubShape = E.Current();
3639           break;
3640         }
3641       }
3642       break;
3643                         }
3644     case TopAbs_FACE: {
3645       TopoDS_Face aFace = TopoDS::Face(aWhat);
3646       TopExp_Explorer E(aWhere, TopAbs_FACE);
3647       for(; E.More(); E.Next()) {
3648         if(!aMap.Add(E.Current())) continue;
3649         if(isSameFace(aFace, TopoDS::Face(E.Current()))) {
3650           aSubShape = E.Current();
3651           isFound = true;
3652           break;
3653         }
3654       }
3655       break;
3656                       }
3657     case TopAbs_EDGE: {
3658       TopoDS_Edge anEdge = TopoDS::Edge(aWhat);
3659       TopExp_Explorer E(aWhere, TopAbs_EDGE);
3660       for(; E.More(); E.Next()) {
3661         if(!aMap.Add(E.Current())) continue;
3662         if(isSameEdge(anEdge, TopoDS::Edge(E.Current()))) {
3663           aSubShape = E.Current();
3664           isFound = true;
3665           break;
3666         }
3667       }
3668       break;
3669                       }
3670     case TopAbs_SOLID: {
3671       TopoDS_Solid aSolid = TopoDS::Solid(aWhat);
3672       TopExp_Explorer E(aWhere, TopAbs_SOLID);
3673       for(; E.More(); E.Next()) {
3674         if(!aMap.Add(E.Current())) continue;
3675         if(isSameSolid(aSolid, TopoDS::Solid(E.Current()))) {
3676           aSubShape = E.Current();
3677           isFound = true;
3678           break;
3679         }
3680       }
3681       break;
3682                        }
3683     default:
3684       return NULL;
3685   }
3686
3687   if(isFound) {
3688     TopTools_IndexedMapOfShape anIndices;
3689     TopExp::MapShapes(aWhere, anIndices);
3690     if (anIndices.Contains(aSubShape))
3691       anIndex = anIndices.FindIndex(aSubShape);
3692   }
3693
3694   if(anIndex < 0) return NULL;
3695
3696   Handle(TColStd_HArray1OfInteger) anArray = new TColStd_HArray1OfInteger(1,1);
3697
3698   anArray->SetValue(1, anIndex);
3699
3700   Handle(GEOM_Object) aResult = GetEngine()->AddSubShape(theShapeWhere, anArray);
3701   Handle(GEOM_Function) aFunction = aResult->GetLastFunction();
3702
3703   GEOM::TPythonDump(aFunction) << aResult << " = geompy.GetSame("
3704     << theShapeWhere << ", " << theShapeWhat << ")";
3705
3706   SetErrorCode(OK);
3707
3708   return aResult;
3709 }